简体   繁体   中英

Deploying Rails with ActionCable to Nginx/Puma running over HTTPS in production

I am trying to deploy a Rails 5.0.1 application to a production server running Ubuntu, Nginx and Puma with Capistrano. The app used to work great until we added ActionCable. Everything (including ActionCable) works perfectly in the development environment but ActionCable just won't connect when the application is deployed to production.

I have followed this tutorial to get the basic setup...

The problem:

The issue is that every time a browser attempts a WebSocket handshake, the request is 301 redirected...

Browser JavaScript Console feedback:

WebSocket connection to 'wss://app.example.com/cable' failed: Unexpected response code: 301

Nginx access log feedback:

XXX.XXX.XXX.XXX - - [07/Jun/2017:17:16:22 +0800] "GET /cable HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4"

$ curl -v https://app.example.com/cable :

*   Trying XXX.XXX.XXX.XXX...
* TCP_NODELAY set
* Connected to app.example.com (XXX.XXX.XXX.XXX) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: app.example.com
* Server certificate: COMODO RSA Domain Validation Secure Server CA
* Server certificate: COMODO RSA Certification Authority
> GET /cable HTTP/1.1
> Host: app.example.com
> User-Agent: curl/7.51.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.4.6 (Ubuntu)
< Date: Wed, 07 Jun 2017 11:42:27 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: https://puma/cable
< 
* Curl_http_done: called premature == 0
* Connection #0 to host app.example.com left intact

The setup:

nginx.conf :

upstream puma {
  server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}

server { # Primary server block
  # Bind port(s)
  listen  80;
  # listen  [::]:80;
  listen  443 ssl;

  # Bind domain(s)
  server_name app.example.com;

  # Bind certificate(s)
  ssl_certificate       /etc/nginx/ssl/app.example.com/ssl-bundle.crt;
  ssl_certificate_key   /etc/nginx/ssl/app.example.com/app.example.com.key;

  root /home/deploy/apps/appname/current/public;
  access_log /home/deploy/apps/appname/current/log/nginx.access.log;
  error_log /home/deploy/apps/appname/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  # ActionCable
  location /cable {
    proxy_pass http://puma;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # proxy_set_header X-Forwarded-Proto $scheme;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    # Let Rails see current protocol
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_pass http://puma;
  }

  error_page 500 502 503 504 /500.html;
  #error_page 503 /503.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}

cable.yml :

development:
  adapter: async

test:
  adapter: async

production:
  adapter: redis
  url: redis://localhost:6379/1

If any more information would be helpful, let me know!

Any suggestions would be much appreciated.

Thanks

Had the same issue, eventually copied in a few more directives from here :

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

  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_set_header X-Forwarded-Proto https;
  proxy_redirect off;
}

Restarted nginx and puma and it started working.

I also explicitly set config.action_cable.url = 'wss://example.com/cable' and config.action_cable.allowed_request_origins = [ 'https://example.com' ] in config/environments/production.rb , which you don't mention, but that was way before I got nginx working so not sure if actually necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM