配置nginx代理瘦和Rails ActionCable

时间:2015-09-01 02:32:05

标签: ruby-on-rails nginx websocket thin ruby-on-rails-5

我正在尝试使用ActionCable(主要是复制DHH example)并尝试让它在具有瘦(在端口8443上)和nginx的Ubuntu服务器上运行。一切都在本地工作正常但是,当我尝试在实时服务器上代理它时,我收到此错误响应:failed: Error during WebSocket handshake: Unexpected response code: 301

这是我的nginx配置的相关部分:

server {
  listen 80;

  server_name _not_;
  root /home/ubuntu/www/;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream websocket {
  server 127.0.0.1:8443;
}

server {

  listen 80;

  ...

  location /websocket/ {
    proxy_pass http://127.0.0.1:8443;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_redirect off;
  }

  ...

}

我在这里与nginx联盟有点 - 我错过了什么或者出错了?

2 个答案:

答案 0 :(得分:1)

我在一个月后回到这里,发现问题不在于nginx配置,而是与瘦身有关。我做了三件事:

(1)配置精简以使用the Faye adapter

# config.ru

require 'faye'
Faye::WebSocket.load_adapter('thin')

require ::File.expand_path('../config/environment',  __FILE__)

use Faye::RackAdapter, mount: '/faye', timeout: 25

run Rails.application

(2)切换到在routes.rb中挂载ActionCable,而不是尝试运行它as a standalone

#routes.rb

MyAwesomeApp::Application.routes.draw do

  ...

  match "/websocket", to: ActionCable.server, via: [:get, :post]

end

(3)返回到我的正常nginx配置,上游瘦的websockets(如网络服务器那样:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close; }

upstream thin { 
    server 127.0.0.1:3000;
}

server {
  ...

  location /websocket {
    proxy_pass http://thin;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;   }

  ...
}

所以,我道歉nginx,我为你赦免 - 似乎问题主要与瘦身有关。

编辑:我添加了在路由中安装后返回的旧nginx配置。另外值得注意的是,对于那些使用SSL的人来说,config.force_ssl会破坏安全的wss websocket。相反,您应该在控制器级别as recommended here上执行force_ssl,并配置nginx以重写任何到HTTPS的HTTP路由。

答案 1 :(得分:1)

这个帖子对我很有帮助,但我选择将AC进程分成一个单独的puma实例,这样我就可以单独配置worker等。我后来从nginx添加了SSL代理,以确保使用最新的密码等。这避免了rails / puma / AC不必担心SSL与非SSL的关系;服务器实例中的所有内容都是非SSL的。

这是AC的服务器部分:

 x = read_port();
 y = read_port();

 if( x == y )
    return x;

 for(;;) {
    z = read_port();
    if( z == x || z == y )
        return z;
    x = y;
    y = z;
 }

请注意此github issue:您需要确保您的AC配置允许您的域名作为来源:

server {
   listen 881 ssl;


   ssl_certificate /etc/nginx/ssl/server.crt;
   ssl_certificate_key /etc/nginx/ssl/server.key;

   ssl_prefer_server_ciphers on;
   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';


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