Nginx 常用配置
为什么写这篇文章?
- 在工作中发现很多开发者只关注于开发,认为 nginx 属于运维的事,然而无论大小公司,开发中都会涉及到一部分服务器配置,小公司基本都是开发和运维一体。即使是大公司可能也会涉及到一些 cors、特殊 http 头配置问题。尤其是 cors,很多人不知道完整的 http 配置
- 一些人想搭建自己的服务器,但是服务器不太会配置
- 记录,供日后查看(由于涉及内容太多,只写关键内容,如需要更详细内容,还请搜索关键词,确实有必要,可以留言添加)
我的配置
nginx.conf
user web_admin; # 一般网站出现403之类的,可能是nginx 网站文件夹权限配置错误,或者是这个配的用户错误
worker_processes 1; # 一般设置成逻辑CPU的数量
error_log /var/log/nginx/error.log warn; # 错误日志,
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
index index.html;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # 访问日志,格式采用上面定义的 main
sendfile on;
tcp_nopush on;
etag on;
expires 3d; # 缓存
server_names_hash_bucket_size 128;
keepalive_timeout 65;
# gzip config
gzip on;
gzip_min_length 1k; # 小于 1kb 的内容可能压缩完体积更大
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\."; # 现在加不加这个无所谓了,因为IE6早就没了
include /etc/nginx/conf.d/*.conf; # 导入/etc/nginx/conf.d 下面的所有.conf 配置文件
}
AI 代码解读
yingyj.com.conf
server {
server_name yingyj.com www.yingyj.com;
listen 443 ssl http2;
include /etc/nginx/ssl/options-ssl-nginx.conf;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
root /home/web_admin/www/yingyj.com;
#charset koi8-r;
access_log /var/log/nginx/yingyj.com.access.log main;
location / {
autoindex on;
autoindex_exact_size off;
index index.html;
}
location = /50x.html {
root /usr/share/nginx/html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
}
# 完全不使用 http 可以采用下面的配置,将本机80 端口转到要访问的 https 网址
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
AI 代码解读
ssl/options-ssl-nginx.conf
# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.
ssl on;
ssl_session_cache shared:le_nginx_SSL:20m;
ssl_session_timeout 60m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
# 这个参数会影响浏览器兼容性
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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_certificate /etc/nginx/ssl/yingyj.com/fullchain.cer; # 不用这个
ssl_certificate_key /etc/nginx/ssl/yingyj.com/yingyj.com.key;
# ssl_trusted_certificate /etc/nginx/ssl/yingyj.com/fullchain.cer;
AI 代码解读
关于安装
公司使用建议自己编译,有利于优化,个人小站点不想折腾可以直接 使用 linux 的包管理工具安装。笔者的服务器采用编译安装,主要是想尝试下 TLS 1.3,编译教程参考imququ.com
HTTPS
个人站点直接使用 letsencrypt (支持泛域名),然后采用定时任务自动续签证书。笔者看到国外有些企业也是使用 letsencrypt,而国内公司都是采用付费证书。
证书配置完成之后可以用 ssllabs 检查,有问题的项会高亮显示,兼容和安全有时候需要取舍。
其中 ssl_ciphers 决定启用哪些 Cipher suites
,会影响浏览器兼容,具体请看 wiki
HSTS 不正确配置会导致网址无法访问,使用之后只能使用https访问网站,一定程度保证安全性。chrome等浏览器,会将正确设置了HSTS add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
的网址加入硬编码。
使用 HTTP2 的前提的 开始HTTPS, listen 443 ssl http2;
不用HTTPS?,难道你想要你的网站被窜改?比如突然弹个广告、比如恶意链接、如果打赏二维码换成别人的 :)
cors
笔者更意向于将必要资源使用 nginx 放到一个域名,不存在跨域,自然也就没有cors需求。
cors 涉及的 http header
- Access-Control-Allow-Origin: | 使用 虽然可以适用大部分情景,但是他不够安全,部分场景(如支付相关逻辑层面不允许使用 *)
- Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header 让服务器把允许浏览器访问的头放入白名单
- Access-Control-Max-Age: 指定了preflight请求的结果能够被缓存多久
- Access-Control-Allow-Credentials: true 是否允许携带cookie
- Access-Control-Allow-Methods: [, ]* 涉及到复杂请求需要使用 OPTIONS 请求,大部分公司使用 GET, POST, OPTIONS
- Access-Control-Allow-Headers: [, ]* 指明了实际请求中允许携带的HTTP header, 有时候使用CDN,需要携带特殊的CDN头,否者无法请求
缓存
缓存分以下几类:
- 服务器缓存(如 Redis 之类)
- CDN 缓存,部分 CDN 文件更新之后无法立即生效
- 浏览器缓存(强缓存、协商缓存、ServiceWorker?)
其中1、2和本文无关,暂不言表。
强缓存和HTTP header 的Cache-Control 和
Expires 有关,
Cache-Control优先级高于
Expires`。若本地有对应文件缓存且缓存还在有效期,则直接使用本地缓存。
协商缓存和多个 成对的 http 头有关,分别是:
-
Etag
和If-None-Match
优先级高于第二个 (nginx 开启etag on;
) -
Last-Modified
和If-Modified-Since
Vary
完全禁用缓存:Cache-Control: no-cache, no-store, must-revalidate
对于不放cdn的文件,一般来说,我们可以将永远不会变的文件设置很长时间的强缓存(比如 js 插件)。而现在的前端文件,一般都是 hash 文件名,除了html 文件,所以我们只需要根据需求设置好 html 文件缓存,其他文件可以强缓存。
有时候遇到前端文件全部放cdn,导致 index.html 文件被错误缓存了,可以考虑将 index.html 单独提取出来。
本文章使用 markdown 编辑器 Typora 编辑,推荐使用。