使用ActionCable将Rails部署到在生产中通过HTTPS运行的Nginx / Puma

时间:2017-06-07 08:51:29

标签: ruby-on-rails nginx capistrano3 puma actioncable

我正在尝试将Rails 5.0.1应用程序部署到运行Ubuntu,Nginx和Puma以及Capistrano的生产服务器。在我们添加ActionCable之前,该应用程序曾经运行良好。所有东西(包括ActionCable)在开发环境中都能很好地工作,但是当应用程序部署到生产环境时,ActionCable就不会连接。

我已按照this tutorial进行基本设置...

问题:

问题是每次浏览器尝试WebSocket握手时,请求都会被重定向...

浏览器JavaScript控制台反馈:

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

Nginx访问日志反馈:

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

设置:

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

如果有更多信息有用,请告诉我们!

我们非常感谢任何建议。

由于

1 个答案:

答案 0 :(得分:0)

有同样的问题,最终还是复制了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;
}

重新启动了nginx和puma,它开始工作了。

我还明确地在config.action_cable.url = 'wss://example.com/cable'中设置了config.action_cable.allowed_request_origins = [ 'https://example.com' ]config/environments/production.rb,你没有提及,但这是在我让nginx工作之前的方式,所以不确定是否真的有必要。