1

I'm currently trying to deploy a Rails 5 app to production on a local server (not a VPS!). I decided to go for Puma as application server and nginx as reverse proxy. In development, everything of the Rails app is working fine. The app also includes one subpage using ActionCable to send updates to the client, which are shown in a log there. The app does not use a database, as there is no need to store something in it. Additionally the project needs to use SSL.

When I try to launch it with the current settings, opening the URL of the website gets me the message of not being able to establish a connection to the server. But in the logs I can actually see the requests getting handled by nginx, just nothing happens afterwards. I'm not very familiar with nginx and puma, but from the log I would guess that ActionCable might be the problem here?


Update 29th of march:

This information might be helping: The system on the server is Debian 9, the nginx version is 1.10.3, rails 5.1.4 and puma 3.9.1.

I also have some more for nginx. I did a strace for the nginx worker while I was trying to access the website:

>>> strace -f -s 512 -a 512 -o /tmp/nginx.out -p 23518ls

23518 recvfrom(11, "\26", 1, MSG_PEEK, NULL, NULL) = 1
23518 read(11, "\26\3\1\2\0\1\0\1\374\3\3\250\365,\30\333\35\37\26\1\240R\25\246\310\10\356\20z\357M\n)\356\364E\26\350L\336\266k\364 \267\23\322\2666\20\23H\257\274U\0\227}PH_\340\352\342\245\263\215:1\"\326U\1773\202\227\0\36\300+\300/\314\251\314\250\300,\3000\300\n\300\t\300\23\300\24\0003\0009\0/\0005\0\n\1\0\1\225\0\0\0$\0\"\0\0\37website-url-was-here.com\0\27\0\0\377\1\0\1\0\0\n\0\n\0\10\0\35\0\27\0\30\0\31\0\v\0\2\1\0\0#\0\340\236L\256\5\352\303t\10R\33L\200L\253n\363\1\24:\250\4\231\204\242\3769\273\326\35C\202\25\234R\35\343\0bYM\341\214\256\4S\32\32\2542V\313\3658G\320\215\314\273\323\243\327:N\200\227\266\212\2463\311\36_\31sy\3\347\31@\327\254k\300\344\215\336\263\207\376|30Z\317:r;~#4\34\340\37sy$\231\310\240\217\266\222\311(\372r\213_\"\220W.\343\363\214+/%p\25\272\6\365\227t\221\303\256\33Q\21\344k\372\334\343W[\206\235\300\332\276{\3205#\253\351bh\3629j\231\276\216\325-M\233\224Q\323i\347\312Tt\366h\277_\223\331\236\22\372\350\324j6R\3164X\312F\362OF\7\365\225\3272\353D4\353O@\370\37\345\260b*\200\37\242\247\31p\0\20\0\16\0\f\2h2\10http/1.1\0\5\0\5\1\0\0\0\0\0\r\0\30\0\26\4\3\5\3\6\3\10\4\10\5\10\6\4\1\5\1\6\1\2\3\2\1\0\25\0001\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 16709) = 517
23518 getpid()  = 23518
23518 getpid()  = 23518
23518 write(11, "\26\3\3\0d\2\0\0`\3\3a\274\256\7\v\303\275\327\v\21gPo\1\342\311e\303\310\252,]\213\223+\332\325\221\324\327S\371 \267\23\322\2666\20\23H\257\274U\0\227}PH_\340\352\342\245\263\215:1\"\326U\1773\202\227\300/\0\0\30\377\1\0\1\0\0\27\0\0\0\20\0\v\0\t\10http/1.1\24\3\3\0\1\1\26\3\3\0(\372)\17\301\347\237c\204\321\32_J\371i\31\332N\252R\227\220\22e\0109Y3\344]?\207\31\240Ya\377S\231\31r", 156)   = 156
23518 read(11, 0x55f00c064ec3, 16709)    = -1 EAGAIN (Resource temporarily unavailable)
23518 epoll_wait(8, [{EPOLLIN, {u32=2553787544, u64=140520998810776}}], 512, 58183)  = 1
23518 read(11, "\24\3\3\0\1\1\26\3\3\0(\0\0\0\0\0\0\0\0yR\24\270\26\34x\264?\250\251\0344m\350c\210\357/da#C\261\211\37\335\351J\342\213\34", 16709) = 51
23518 read(11, 0x55f00c05f963, 16709)  = -1 EAGAIN (Resource temporarily unavailable)
23518 epoll_wait(8, [{EPOLLIN|EPOLLOUT, {u32=2553787080, u64=140520998810312}}], 512, 58182)    = 1
23518 recvfrom(10, "\201${\"type\":\"ping\",\"message\":1522309419}", 4096, 0, NULL, NULL)        = 38
23518 write(3, "\27\3\3\0>\235\365\306=\362$44K\3429\240\322\262\246D\24M\271\371=\334\236\202\373\30TDI-'\225\v\343\37\341\224[\351\342NZ\340\335\355\274d~\351Z\312@\326\240\275\234g\312X\3517w", 67)   = 67
23518 recvfrom(10, 0x55f00c054ec0, 4096, 0, NULL, NULL)  = -1 EAGAIN (Resource temporarily unavailable)
23518 epoll_wait(8, [{EPOLLIN|EPOLLOUT, {u32=2553787080, u64=140520998810312}}], 512, 58817)    = 1
23518 recvfrom(10, "\201${\"type\":\"ping\",\"message\":1522309422}", 4096, 0, NULL, NULL)   = 38
23518 write(3, "\27\3\3\0>\235\365\306=\362$45\3245\275\352S~\330m\244\312{\346\267\217\347\335\224\323\324n\276\304\220D\255K\16\217\317\25\322&\325J\346AV\1c\277,2\334\363\344\241\342*\367Db\361\37\216", 67) = 67
23518 recvfrom(10, 0x55f00c054ec0, 4096, 0, NULL, NULL)  = -1 EAGAIN (Resource temporarily unavailable)
23518 epoll_wait(8,  <detached ...>

Maybe this is helping? Also I found this in the puma error log:

=== puma startup: 2018-03-29 09:34:16 +0200 ===
[2018-03-29 09:34:24.505] ERROR -- Specified 'redis' for Action Cable pubsub adapter, but the gem is not loaded. Add `gem 'redis'` to your Gemfile (and ensure its version is at the minimum required by Action Cable).: nil

Doesn't ActionCable also work without redis? I do not have it installed.


This is from the logs:

172.19.28.1 - - [27/Mar/2018:16:13:49 +0200] "GET /cable HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"

and

host, request: "GET /cable HTTP/1.1", upstream: "http://unix:/path/to/app/shared/sockets/puma.sock:/500.html", host: "hips-wordpress.helmholtz-hzi.de:9292"
2018/03/27 15:36:06 [error] 15944#15944: *154 connect() to unix:/path/to/app/shared/sockets/puma.sock failed (111: Connection refused) while connecting to upstream, client: 172.19.28.1, server: local

config/environments/production.rb:

[...]
# Mount Action Cable outside main process or domain
config.action_cable.url = [/ws:\/\/*/, /wss:\/\/*/]
config.action_cable.allowed_request_origins = [/http:\/\/*/, /https:\/\/*/]

#Use of SSL
config.force_ssl = false
[...]

config/puma.rb:

#!/usr/bin/env puma
# directory '/path/to/app/'
# Change to match your CPU core count
workers 2

# Min and Max threads per worker
threads 0, 1

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"

# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restartq

config/nginx.cfg:

events {
        worker_connections 1024;
}

http {
        upstream app {
        # Path to Puma SOCK file, as defined previously
        server unix:/path/to/app/shared/sockets/puma.sock;
        }

        server {
        listen 9292 ssl;
        server_name app.de ;
        ssl_certificate  /path/to/app/config/cert/certificate.pem ;
        ssl_certificate_key /path/to/app/config/cert/public_key.key;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        root /path/to/app;

        try_files $uri/index.html $uri @app;

        location @app {
         proxy_redirect off;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_set_header  X-Real-IP $remote_addr;
         proxy_pass http://app;
        }

        location /cable {
         proxy_pass http://app;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
        }

         error_page 500 502 503 504 /500.html;
         client_max_body_size 4G;
        keepalive_timeout 10;
        }

}

To start everything I use a startup script:

#!/bin/bash

PATH=/path/to/app
cd $PATH
nginx -c config/nginx.cfg

export SECRET_KEY_BASE= <secret_key_base>
export RAILS_SERVE_STATIC_FILES=true

RAILS_ENV=production rails assets:precompile

puma -vvv -C config/puma.rb

At this point I tried to fix several things already, which is why the configs are partly assembled from different tutorials and stackoverflow questions. To my understanding, SSL shouldn't be the problem, at least not from the nginx side. puma seems to never receive any requests, as the logs stay empty. and nginx seems to not be able to redirect the /cable request to puma (which is the url to subscribe to the ActionCable Channel). Did I do something wrong with the configs for ActionCable? I'm not really able to find a tutorial about how to setup a rails app using ActionCable and SSL in production with nginx/puma combination.

If you need any other information, I will include it in the question.

AlexB
  • 11
  • 6
  • does this even exist? path/to/app/shared/sockets/puma.sock. Also where is your rails app stored? Do you use capistano or something ? – GorillaApe Mar 29 '18 at 06:14
  • @GorillaApe yes, the .sock file does exist. I develop the rails app in a Amzaon C9 IDE, push it to a repo on bitbucket using git and pull from there to the local server where it should be deployed for production. Does this answer your questions? Im also about to update the question with some more info obtained this morning. – AlexB Mar 29 '18 at 07:52
  • which version of redis do you have? Try updating to 5.1.5 rails. I assume you have bundle install too (normally it should be installed in deployment mode) – GorillaApe Mar 29 '18 at 08:25
  • @GorillaApe I don't think that I can update to Rails 5.1.5, because when I do I also would need to update some more gems. But some of them, e.g. coffee-rails gem are not updated yet with new versions to match 5.1.5, they still want rails 5.1.4 (or rather actionpack 5.1.4). I do not have redis installed, as far as I know ActionCable should also work without it [as stated here](https://stackoverflow.com/a/43181668/9391351). – AlexB Mar 29 '18 at 08:53
  • Dependencies are resolved through bundler 5.1.4 to 5.1.5 isn't a major difference. However in production actioncable might be configured to your system to use redis. You could use postgresql though – GorillaApe Mar 29 '18 at 10:54

0 Answers0