Ghost 博客的 Nginx 配置优化

以下是本站的 Nginx 配置,这个配置主要干了以下的事情:

  • 静态资源的 Cache 设为 30 天。
  • 200 Response 的 Cache 设为 30 分钟。
  • 400 Response 的 Cache 设为 1 分钟。
  • 禁止特殊链接(管理页面、预览页面、登出连接)的 Cache。
  • 打开了 Gzip。
  • 使用 Keepalive TCP 转发 Request 至 Ghost Service
  • 打开了 Proxy Buffer 做 Response Cache。
  • 强制支持基于 Let's Encrypt CA 的 SSL。

Nginx 配置设置参考:

以下是 /etc/nginx/sites-available/ghost 的完整配置。Nginx 配置的语法与使用方法不在本文的讨论范围,请阅读上面我列出来的 Nginx 配置设置参考

client_body_buffer_size 10K;  
client_header_buffer_size 1k;  
client_max_body_size 50m;  
large_client_header_buffers 2 1k;

proxy_cache_path /var/run/cache levels=1:2 keys_zone=STATIC:75m inactive=24h max_size=512m;

upstream ghost_upstream {  
  server 127.0.0.1:2368;
  keepalive 64;
}

server {  
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;
  server_name huntzhan.org www.huntzhan.org;

  # redirect to https.
  location / {
    return 301 https://$server_name$request_uri;
  }

  # letsencrypt.
  location ~ ^/.well-known {
    root /var/www/ghost;
  }
}

server {  
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;

  ssl on;
  include snippets/ssl-huntzhan.org.conf;
  include snippets/ssl-params.conf;

  # cache state.
  add_header X-Cache-Status $upstream_cache_status;

  # gzip
  gzip on;
  gzip_vary on;

  gzip_comp_level 5;
  gzip_min_length 256;

  gzip_proxied any;
  gzip_disable "msie6";

  gzip_types application/atom+xml
             application/javascript
             application/json
             application/rss+xml
             application/vnd.ms-fontobject
             application/x-font-ttf
             application/x-web-app-manifest+json
             application/xhtml+xml
             application/xml
             font/opentype
             image/svg+xml
             image/x-icon
             text/css
             text/plain
             text/x-component;

  location / {
    proxy_pass http://ghost_upstream;

    # enable keepalive.
    proxy_http_version 1.1;
    proxy_set_header Connection "";

    # cache.
    proxy_cache STATIC;
    proxy_cache_valid 200 30m;
    proxy_cache_valid 404 1m;
    # response header.
    expires 15m;

    # clean up headers.
    proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
    proxy_hide_header Set-Cookie;
    proxy_hide_header X-powered-by;

    # set headers.
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;

    # buffer.
    proxy_buffering on;
    proxy_buffers 32 16k;
  }

  # static resource: images.
  location /content/images {
    alias /var/www/ghost/content/images;
    access_log off;
    expires 30d;
  }
  # static resource: casper-gfw theme.
  location /assets {
    alias /var/www/ghost/content/themes/casper-gfw/assets;
    access_log off;
    expires 30d;
  }

  # disable cache for:
  # * /ghost/xxx, site management.
  # * /p/xxx, page preview.
  # * /signout
  location ~ ^/(ghost/|p/|signout) { 
    proxy_pass http://ghost_upstream;

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;

    add_header Cache-Control "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0";
  }
}

以下是 SSL 相关的配置,主要是从 How To Secure Nginx with Let's Encrypt on Ubuntu 16.04 | DigitalOcean 直接抄过来的。

# /etc/nginx/snippets/ssl-huntzhan.org.conf
ssl_certificate /etc/letsencrypt/live/huntzhan.org/fullchain.pem;  
ssl_certificate_key /etc/letsencrypt/live/huntzhan.org/privkey.pem;  
# /etc/nginx/snippets/ssl-params.conf

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  
ssl_prefer_server_ciphers on;  
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";  
ssl_ecdh_curve secp384r1;  
ssl_session_cache shared:SSL:10m;  
ssl_session_tickets off;  
ssl_stapling on;  
ssl_stapling_verify on;  
resolver 8.8.8.8 8.8.4.4 valid=300s;  
resolver_timeout 5s;  
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";  
add_header X-Frame-Options DENY;  
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;