博客迁移到阿里云 ECS 后,接着把 HTTPS 和 gzip 配上。HTTPS 用来加密浏览器与服务器之间的通信,gzip 则可以压缩 HTML、CSS 和 JavaScript,减少传输内容的大小。

申请并上传证书

在阿里云证书服务中申请免费 DV SSL 证书,补全域名信息,使用系统生成的 CSR,并通过 DNS 完成域名验证。审核通过后下载 Nginx 格式的证书,压缩包中包含 .pem 证书文件和 .key 私钥文件。

把证书放到单独的目录:

mkdir -p /etc/nginx/ssl
chmod 700 /etc/nginx/ssl

下面统一使用这两个文件名,实际使用时替换成下载后的文件:

/etc/nginx/ssl/<domain>.pem
/etc/nginx/ssl/<domain>.key

私钥文件不能公开,上传后限制读取权限:

chmod 600 /etc/nginx/ssl/<domain>.key

如果主域名和 www 都要支持 HTTPS,申请证书时必须让证书同时包含 <domain> 和 www.<domain>。浏览器会先完成 TLS 握手,再收到 HTTP 跳转;证书不包含 www 时,请求会先出现证书错误,无法依靠 301 跳转解决。

配置 HTTPS

在 Nginx 的 http 配置块中增加公共 TLS 配置:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

再修改博客的站点配置。80 端口只负责跳转到主域名的 HTTPS 地址:

server {
    listen 80;
    server_name <domain> www.<domain>;
    return 301 https://<domain>$request_uri;
}

主域名使用 443 端口提供博客内容,原有的 root、PHP-FPM 和 Typecho 固定链接配置继续保留:

server {
    listen 443 ssl;
    server_name <domain>;

    ssl_certificate /etc/nginx/ssl/<domain>.pem;
    ssl_certificate_key /etc/nginx/ssl/<domain>.key;

    root /usr/share/nginx/html/blog;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }
}

www 的 HTTPS 请求也需要单独监听 443,然后跳转到主域名:

server {
    listen 443 ssl;
    server_name www.<domain>;

    ssl_certificate /etc/nginx/ssl/<domain>.pem;
    ssl_certificate_key /etc/nginx/ssl/<domain>.key;

    return 301 https://<domain>$request_uri;
}

这里使用 listen 443 ssl,不再单独写 ssl on。确认阿里云安全组已经允许 443 端口后,检查配置并重新加载 Nginx:

nginx -t
systemctl reload nginx

分别检查四种访问方式:

curl -I http://<domain>
curl -I http://www.<domain>
curl -I https://www.<domain>
curl -I https://<domain>

前三个地址应该跳转到 https://<domain>,最后一个地址正常返回博客内容。

开启 gzip

在 /etc/nginx/nginx.conf 的 http 配置块中增加:

gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_vary on;
gzip_proxied any;
gzip_types
    text/plain
    text/css
    application/json
    application/javascript
    application/xml
    text/xml
    image/svg+xml;

几个主要参数的作用:

  • gzip_min_length:响应内容超过 1 KB 时再压缩,小文件没有必要额外消耗 CPU。
  • gzip_comp_level:压缩级别范围为 1 到 9,级别越高压缩率越高,CPU 消耗也越大。这里使用 6。
  • gzip_vary:在响应中增加 Vary: Accept-Encoding,让缓存区分压缩和未压缩版本。
  • gzip_types:除了默认的 text/html,再指定需要压缩的文本类型。JPEG、PNG 等已经压缩过的图片不需要加入。

再次检查并重新加载 Nginx:

nginx -t
systemctl reload nginx

发送带有 Accept-Encoding: gzip 的请求:

curl -H 'Accept-Encoding: gzip' -s -D - -o /dev/null https://<domain>/

响应头中出现下面的内容,说明 gzip 已经生效:

Content-Encoding: gzip
Vary: Accept-Encoding

HTTPS 和 gzip 配好以后,HTTP、www 和主域名的入口统一到了同一个 HTTPS 地址,文本资源也会在传输前压缩。Nginx 的配置规则可以参考 HTTPS 配置说明 和 gzip 模块文档。

最后修改:2017 年 09 月 01 日
如果觉得我的文章对你有用,请随意赞赏