nginx之ERR_EMPTY_RESPONSE 与 Ghost 0.7.5、Nginx 1.9、HTTPS 和 HTTP/2

zfyouxi 阅读:47 2025-06-02 22:19:02 评论:0

问题

当我点击 kevinsuttle.com 时,我得到了

"No data received ERR_EMPTY_RESPONSE". 

当我点击 https://kevinsuttle.com 时,我得到了网站。

Ghost 0.7.5
nginx 1.4 => 1.9.9
letsencrypt 0.2.0

digital ocean :Ubuntu 14.04 Ghost 1-click droplet

Networking > Domains 下,我将 kevinsuttle.comwww.kevinsuttle.com 作为 A指向服务器 IP 地址的记录 (@)。

DNS简单记录

| Type  | Name                  | TTL               | Content                   | 
|------ |---------------------  |---------------    |------------------------   | 
| URL   | www.kevinsuttle.com   | 3600 (1 hour)     | http://kevinsuttle.com    |   

The only modified portion in Ghost's config.js is my domain.

url: 'http://kevinsuttle.com', 

Nginx 1.9

nginx 1.9 默认不创建以下目录:
/etc/nginx/可用站点
/etc/nginx/sites-enabled

通常的 default conf 不会在这些目录中创建。

取而代之的是 etc/nginx/conf.d/default.conf 和重要的 etc/nginx/conf.d/nginx.conf。你会看到很多教程告诉你删除 default.conf,这似乎没问题,但无论你做什么,不要删除 nginx.conf

此外,您应该将 ghost.conf 移动/创建到 /etc/nginx/conf.d/ 目录中。这就是解决我的一个问题的原因,因为 etc/nginx/conf.d/nginx.conf 的最后一行在 /conf.d/ 目录中包含任何内容那里的文件:include/etc/nginx/conf.d/*.conf;

这是我的 /etc/nginx/conf.d/ghost.conf 文件:

  server { 
  root /usr/share/nginx/html; 
  index index.html index.htm; 
 
  listen 443 ssl http2; 
 
  server_name kevinsuttle.com www.kevinsuttle.com; 
    ssl_certificate /etc/letsencrypt/live/kevinsuttle.com/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/kevinsuttle.com/privkey.pem; 
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
    ssl_prefer_server_ciphers on; 
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; 
 
  location ~ /.well-known { 
      allow all; 
      root /var/www/; 
  }  
 
  location / { 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header HOST $http_host; 
        proxy_set_header X-NginX-Proxy true; 
 
        proxy_pass http://127.0.0.1:2368; 
        proxy_redirect off; 
        root /var/www/; 
    } 
      location /.well-known/ { 
        root /var/www/; 
    } 
} 
 
server { 
    listen 80 ssl http2; 
    server_name kevinsuttle.com; 
    return 301 https://$host$request_uri; 
} 

现在,我让这一切工作正常,并尝试将 nginx 升级到 1.9+,以便通过 http/2 提供服务。 DigitalOcean 的一键式 Ghost droplet 默认使用 nginx 1.4。

长话短说,我一直收到这个错误:

dpkg: error processing archive /var/cache/apt/archives/nginx_1.9.9-1~trusty_amd64.deb (--unpack): 

我找到的唯一解决方案是

apt-get purge nginx nginx-common 

然后我可以通过将以下行添加到我的 /etc/apt/source.list 文件来安装 nginx 1.9。

deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx 
deb-src http://nginx.org/packages/mainline/ubuntu/ trusty nginx 

现在我只需添加 listen 80 ssl http2;listen 443 ssl http2;,http/2 就可以正常工作了。但仅当明确输入 https:// URL 时。

我找到了 some evidence这表明 express 不支持 http/2,但我不是 100% 支持这一点。

任何想法将不胜感激。

请您参考如下方法:

我认为这不是 Ghost 或 DNS 的问题。

您可以排除 DNS,因为 www 和非 www 都解析为配置的 IP。

➜  ~  dig kevinsuttle.com +short 
162.243.4.120 
➜  ~  dig www.kevinsuttle.com +short 
162.243.4.120 

DNS 协议(protocol)工作在比 HTTP 更低的级别,它不关心 HTTP 版本或您使用的是 HTTP 还是 HTTPS。因此,我们可以排除 DNS 并转移到检查更高级别的协议(protocol)。

我也排除了 Ghost/Express 的问题,因为我可以在使用 HTTPS 时向您的博客发送 HTTP/2 请求。

➜  ~  curl --http2 -I https://kevinsuttle.com/ 
HTTP/2.0 200 
server:nginx/1.9.9 
date:Sun, 24 Jan 2016 19:34:30 GMT 
content-type:text/html; charset=utf-8 
content-length:13594 
x-powered-by:Express 
cache-control:public, max-age=0 
etag:W/"351a-fflrj9kHHJyvRRSahEc8JQ" 
vary:Accept-Encoding 

只要我使用站点的 HTTP 版本,我也可以回退到 HTTP 1.1。

➜  ~  curl -I https://kevinsuttle.com/ 
HTTP/1.1 200 OK 
Server: nginx/1.9.9 
Date: Sun, 24 Jan 2016 19:35:36 GMT 
Content-Type: text/html; charset=utf-8 
Content-Length: 13594 
Connection: keep-alive 
X-Powered-By: Express 
Cache-Control: public, max-age=0 
ETag: W/"351a-fflrj9kHHJyvRRSahEc8JQ" 
Vary: Accept-Encoding 

因此,问题出在Nginx配置上。具体来说,问题在于 HTTP-only block 的 Nginx 配置。

我现在无法尝试,但我个人认为问题出在这一行:

listen 80 ssl http2; 

应该是

listen 80; 

ssl 指令用于强制监听套接字理解ssl。但是,在您的情况下,让套接字监听 80 以使用 HTTPS 是没有意义的。此外,使用 ssl 的套接字必须声明关联的 SSL 配置(也就是至少一个有效的证书和 key )。

通常,您使用 ssl 来配置处理 HTTP 和 HTTPS 请求的单个服务器:

server { 
    listen              80; 
    listen              443 ssl; 
    server_name         www.example.com; 
    ssl_certificate     www.example.com.crt; 
    ssl_certificate_key www.example.com.key; 
    ... 
} 

另请注意,作为 explained in the Nginx documentation

The use of the ssl directive in modern versions is thus discouraged.

http2 与非 https 套接字结合使用也可能导致麻烦。

引用 this article :

While the spec doesn’t force anyone to implement HTTP/2 over TLS but allows you to do it over clear text TCP, representatives from both the Firefox and the Chrome development teams have expressed their intents to only implement HTTP/2 over TLS. This means HTTPS:// URLs are the only ones that will enable HTTP/2 for these browsers.

因此,假设有可能,通过 HTTP/2 为非 https 站点提供服务可能没有用。实际上,考虑到 issue described in this ticket,我怀疑它在今天是否可能。这似乎符合您的问题。

总结一下,简单的改

server { 
    listen 80 ssl http2; 
    server_name kevinsuttle.com; 
    return 301 https://$host$request_uri; 
} 

server { 
    listen 80; 
    server_name kevinsuttle.com; 
    return 301 https://$host$request_uri; 
} 


标签:nginx
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号