web-dev-qa-db-ja.com

Nginx SSL構成でGunicornアップストリームを実行するにはどうすればよいですか?

SSL証明書がインストールされたnginxサーバーがあります。 0.0.0.0:8000で実行しているGunicornサーバーにアップストリームの要求を渡したいです。ただし、Gunicornサーバーを実行すると、リダイレクトループが多すぎるというエラーが表示されます。 httpsでgunicornを実行すると、接続は安全になりますが、gunicornサーバーに接続せず、bad gatewayと表示されます。また、httpsでgunicornを実行しているときに接続しようとすると、次のエラーが発生します。

Traceback (most recent call last):
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 515, in spawn_worker
    worker.init_process()
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.run()
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 119, in run
    self.run_for_one(timeout)
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 66, in run_for_one
    self.accept(listener)
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 30, in accept
    self.handle(listener, client, addr)
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 141, in handle
    self.handle_error(req, client, addr, e)
  File "/opt/bitnami/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 213, in handle_error
    self.log.exception("Error handling request %s", req.uri)
AttributeError: 'NoneType' object has no attribute 'uri'
[2016-01-01 15:37:45 +0000] [935] [INFO] Worker exiting (pid: 935)
[2016-01-01 20:37:45 +0000] [938] [INFO] Booting worker with pid: 938
[2016-01-01 15:37:46 +0000] [938] [ERROR] Exception in worker process:

これが私のnginx設定です:

  server {
    # port to listen on. Can also be set to an IP:PORT
    listen 80;
    listen 443 ssl;
    ssl_certificate /etc/ssl/pyhub_crt.crt;
    ssl_certificate_key /etc/ssl/pyhub.key;
    server_name www.pyhub.co;
    server_name_in_redirect off;
    access_log /opt/bitnami/nginx/logs/access.log;
    error_log /opt/bitnami/nginx/logs/error.log;
    location /E0130777F7D5B855A4C5DEB138808515.txt {
        root /home/bitnami;
    }

    location / {
    proxy_pass_header Server;
    proxy_set_header Host $Host;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-SSL-Protocal $ssl_protocol;
    proxy_connect_timeout 10;
    proxy_read_timeout 10;
    proxy_redirect http:// $scheme://;
    proxy_pass http://localhost:8000;
    }
6
Dorian Dore

Gunicornが0.0.0.0にバインドされている場合、すべてのインターフェースにバインドされているため、すでに外部インターフェースに公開されています。 nginxが同じポート上の任意のインターフェースにバインドしようとすると、失敗します。

Gunicornは特定のIP以上の127.0.0.1にバインドする必要があるため、内部IPにのみバインドされます。

Sesond、あなたはhttpsをgunicornに渡したいと言いますが、トラフィックは証明書を持っているプロキシ、つまりngninxへのSSLで保護されています。その後、gunicornでSSLを設定していない限り、トラフィックは内部で明らかです(つまり、httpです)。

したがって、nginx設定には次のものが必要です。

  • Ip 127.0.0.1ポート8080またはあなたが望むものを使ってgunicornの上流サーバー。
  • Httpはポート80、httpsは443でリッスンするサーバーディレクティブ
  • アップストリームに転送するサーバーブロックのプロキシパスディレクティブ

sSLのnginxプロキシ設定は次のようなものです。

upstream website    {
    ip_hash;                        # for sticky sessions, more below
    server                          website:8000 max_fails=1 fail_timeout=10s;
}

server {
    # only listen to https here
    listen                          443 ssl http2;
    listen                          [::]:443 ssl http2;
    server_name                     yourdomain.here.com;

    access_log                      /var/log/nginx/yourdomain.here.com.access.log;
    error_log                       /var/log/nginx/yourdomain.here.com.error.log;
    ssl                             on;
    ssl_certificate                 /etc/nginx/certs/ca-cert.chained.crt;
    ssl_certificate_key             /etc/nginx/certs/cert.key;
    ssl_session_cache               shared:SSL:5m;
    ssl_session_timeout             10m;
    ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers       on;
    #ssl_dhparam                     /etc/nginx/certs/dhparams.pem;
    # use the line above if you generated a dhparams file 
    ssl_ciphers                     'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_buffer_size                 8k;

    location / {
        proxy_pass                  http://website;
        proxy_set_header            Host $Host;
        proxy_set_header            X-Real-IP $remote_addr;
        proxy_http_version          1.1;

        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header            X-Forwarded-Proto http;
        proxy_redirect              http:// $scheme://;
    }
}

# redirect http to https here
server {
    listen                          80;
    listen                          [::]:80;
    server_name                     yourdomain.here.com;
    return                          301 https://$server_name/;
}
6
MrE

これを試して:

upstream app_server {
    server 127.0.0.1:8000 fail_timeout=0;
}

server {
    # port to listen on. Can also be set to an IP:PORT
    listen 80;
    listen 443 ssl;

    ssl_certificate /etc/ssl/pyhub_crt.crt;
    ssl_certificate_key /etc/ssl/pyhub.key;

    server_name www.pyhub.co;
    server_name_in_redirect off;

    access_log /opt/bitnami/nginx/logs/access.log;
    error_log /opt/bitnami/nginx/logs/error.log;

    location /E0130777F7D5B855A4C5DEB138808515.txt {
        root /home/bitnami;
    }

    location / {
        try_files @proxy_to_app;
    }

    location @proxy_to_app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_Host;
        proxy_redirect off;

        proxy_pass http://app_server;

        proxy_pass_header Server;
        proxy_set_header Host $Host;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-SSL-Protocol $ssl_protocol;
    }
}

これにより、SSLがnginxではなくgunicornで(適切に)終了することに注意してください。 X-SSL-ProtocalProtocalのスペルも間違っています。私の例で修正:)

gunicornnginxをデプロイするための正規の情報については、 ここ を参照してください。

4
Will

私はかなり長い間、自分のサイトを機能させてきたので、私はずっと前にこの答えを投稿するべきでした。しかし、これが私の設定を機能させる方法です。

Nginxの設定をいじくり回した後、私はかなりイライラしてあきらめました。そこで、私はそのサーバーを削除し、すべてを新規にインストールして新しいサーバーを作成し、それをホストするリポジトリーから私のWebサイトのソース・コードを複製しました。これを行った後、このNginx構成を使用して機能しました。

  upstream djangosite {
    server 127.0.0.1:8000 fail_timeout=2s;
  }
  server {
    # port to listen on. Can also be set to an IP:PORT
    listen 443 ssl;
    server_name pyhub.co;
    ssl_certificate /etc/ssl/pyhub.crt;
    ssl_certificate_key /etc/ssl/pyhub.key;
    location / {
      proxy_pass http://djangosite;
    }
  server {
    listen 80;
    server_name pyhub.co;
    return 301 https://$server_name$request_uri;
  }

今日まで、私は自分の構成に問題を引き起こしている原因や、完全に新規インストールした別のサーバーを取得する必要がある理由をまだ知りませんが、それが機能してうれしいです。私はすでに提供されている2つの優れた回答のうち1つを選択しますが、どれも私に解決策を与えてくれませんでした。自分自身を選択したくありません。私が抱えていた問題の具体的すぎると考え、この回答を選択する可能性があるからです。将来多くの人を助けることができない。

2
Dorian Dore