我的 Nginx 配置

本文记录了本站服务端的相关配置,都是基于 Nginx 的 HTTPS 和 HTTP/2 的配置,记录下来作为自己的备份,方便日后参考。

安全测试和评分

一切妥当后,推荐使用以下两个在线服务来检测站点 HTTPS 配置:

1)Qualys SSL Labs's SSL Server Test

测试地址:SSL Labs,以下是本博客测试结果截图:

查看本站完整测试结果>>

2)HTTP Security Report

测试地址:HTTP Security Report,以下是本博客测试结果截图:

查看本站完整测试结果>>

安装依赖

我的 VPS 系统是 Debian 10,并且使用了 Oneinstack 一键安装工具进行整体管理,如果你使用的是其它发行版或一键包,有关的命令和路径请自行调整

获取必要组件

由于本站使用了 Oneinstack 一键安装工具,以下组件统一放在 /root/oneinstack/src/ 下,请自行调整相关路径。

ngx_brotli

本站支持 Google 开发的 Brotli 压缩格式,它通过内置分析大量网页得出的字典,实现了更高的压缩比率,同时几乎不影响压缩和解压速度。

获取 ngx_brotli 源码:

git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli

git submodule update --init

cd ../

编译并安装 Nginx

接着就可以获取 Nginx 源码:

wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar xzf nginx-1.18.0.tar.gz

cd nginx-1.18.0/

cd ../

基于 oneinstack 的编译和安装:

cd nginx-1.18.0/

./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-openssl=../openssl-1.1.1g --with-pcre=../pcre-8.44 --with-pcre-jit --with-ld-opt=-ljemalloc

make
make install

Nginx 全局配置

到此为止,Nginx 已经安装完毕。再来修改一下它的全局配置,打开 /usr/local/nginx/conf/nginx.conf,在 http 段新增或修改以下内容:

http {

  #... ...#
  
# 如果编译时添加了 ngx_brotli 模块,需要增加 brotli 相关配置
  brotli_static on;
  brotli on;
  brotli_types *;
  brotli_buffers 16 8k;
  brotli_comp_level 6;
  brotli_window 512k;
  brotli_min_length 20;
  
  #... ...#
}

要让网站支持浏览器通过 HTTP/2 访问必须先部署 HTTPS,要部署 HTTPS 必须先有合法的证书。

WEB 站点配置

以下是本博客站点完整配置(注意配置条目有一些重复,暂时没有找到很好的方法合并第二和第三段):

server {
    listen 80;
    # listen [::]:80;

    server_name uskvm.com www.uskvm.com;
    return 301 https://www.uskvm.com$request_uri;

    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 444;
    }
    location /nginx_status {
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

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

    server_name uskvm.com;
    return 301 https://www.uskvm.com$request_uri;

    ssl_certificate /usr/local/nginx/conf/ssl/uskvm.crt;
    ssl_certificate_key /usr/local/nginx/conf/ssl/uskvm.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /usr/local/nginx/conf/ssl/root.crt;
    resolver 119.29.29.29 223.5.5.5 1.1.1.1 8.8.8.8 valid=60s;
    resolver_timeout 60s;

    if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$ ) {
        return 444;
    }
    location /nginx_status {
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

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

    server_name www.uskvm.com;
    root /data/wwwroot/uskvm;
    index index.html index.htm index.php;
    access_log /data/wwwlogs/www.uskvm.com_nginx.log combined;
    error_log /data/wwwlogs/www.uskvm.com_nginx_error.log error;
    include /usr/local/nginx/conf/rewrite/typecho.conf;

    ssl_certificate /usr/local/nginx/conf/ssl/uskvm.crt;
    ssl_certificate_key /usr/local/nginx/conf/ssl/uskvm.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /usr/local/nginx/conf/ssl/root.crt;
    resolver 119.29.29.29 223.5.5.5 1.1.1.1 8.8.8.8 valid=60s;
    resolver_timeout 60s;

    if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$ ) {
        return 444;
    }
    location ~ [^/]\.php(/|$) {
        #fastcgi_pass remote_php_ip:9000;
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico|eot|ttf|otf|woff|svg)$ {
        expires 30d;
        access_log off;
    }
    location ~ .*\.(js|css)?$ {
        expires 7d;
        access_log off;
    }
    location ~ /\.ht {
        deny all;
    }
    location /nginx_status {
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

日志自动切分

上一节中,我在 Nginx 的站点配置中通过 access_log 指定了访问日志的存放位置。Nginx 启动后,会持续往这个文件写入访问日志。如果网站访问量很大,最好能按照指定大小或者时间间隔切分日志,便于后期管理和排查问题。注:Oneinstack 一键工具已经内置了这部分。

虽然本站访问量不大,但我也使用了 logrotate 工具对访问日志进行了按天切分。大多数 Linux 发行版都内置了 logrotate,只需新建一个配置文件即可,例如:

vi /etc/logrotate.d/nginx

/data/wwwlogs/*nginx.log {
  daily
  rotate 5
  missingok
  dateext
  compress
  notifempty
  sharedscripts
  postrotate
    [ -e /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
  endscript
}

配置中具体指令的含义可以查看 手册。配置好之后,可以手动执行一下,看是否正常:

/usr/sbin/logrotate -f /etc/logrotate.d/nginx

如果一切无误,后续 Nginx 的访问日志就会自动按天切分,并以年月日做为文件后缀,一目了然。

标签: Nginx

发表评论: