包括常用的一些 Nginx 示例和使用技巧,如果你在使用中遇到问题,欢迎去提 Issue 。
Nginx 状态码配置和错误文件
server {
# 配置访问 /test.js 时报 403 错
location /test.js {
return 403;
}
# 配置访问 /404 时报 404 错
location /404 {
return 404;
}
# 配置访问 /500 时报 500 错
location /500 {
return 500;
}
# 把指定状态码指向这个文件 uri
error_page 500 502 503 504 /status.html;
error_page 404 /status.html;
}
如:
server {
listen 80;
server_name test.me;
root /Users/xiaowu/work/test.me;
# 用if匹配任何以 403 开头的,会匹配到 /4034444
if ($request_uri ~* ^/403) {
return 403;
}
# 用location匹配 /500/ /500,但不匹配 /500/1
location ~* "^/500/?$" {
return 500;
}
# 用if匹配以 /501/ 开头的,匹配 /501/1,/501/1/2 但不匹配 /501
if ($request_uri ~* ^/501/) {
return 501;
}
# 用location匹配 /502/ /502 /502/1 /502/1/2
location ~* "^/502(/.*)?$" {
return 502;
}
# 用location只匹配 /503
location = /503 {
return 503;
}
}
#error_page配置小提示
注意 error_page
配置时加 = 和不加 = 的区别,加了 = 表示响应为指定的 http status code
,默认为 200,不加 = 为原错误的状态码~
# 这样可以访问错误页面时 http status 为 404 ,并且页面内容是 404.html 的内容
error_page 404 /404.html
error_page 404 500 /404.html;
# 这样配置访问错误页面时 http status 为 200 ,但页面内容是 404.html 的内容
error_page 404 500 = /404.html;
# 这样配置访问错误页面时 http status 为 404 ,但页面内容是 404.html 的内容
error_page 404 500 =404 /404.html;
# 也可以把404请求直接301到某个域上
error_page 404 =301 https://xuexb.com/404;
这样就可以根据自己需求配置错误页为指定的状态码,因为非 200 的状态码可能会被浏览器拦截。
主域301重定向
你的网站可能有多个域名访问,比如:www.xuexb.com
、xuexb.com
等,设置主域意思是不管用户输入哪个域名,都会 301
重定向到主域上,设置主域可以对 SEO 更友好,比如:
以xuexb.com为主域
www.xuexb.com => xuexb.com
www.xuexb.com/search/xxoo => xuexb.com/search/xxoo
www.xuexb.com/a/b/c/404.html => xuexb.com/a/b/c/404.html
配置文件核心:
server {
# 设置多个域名
server_name www.xuexb.com xuexb.com;
# 判断host是不是xuexb.com,如果不是则直接301重定向,permanent表示301
if ( $host != 'xuexb.com' ){
rewrite ^/(.*)$ http://xuexb.com/$1 permanent;
}
# 其他规则
}
Node.js 反向代理
服务端如果使用nodejs
运行服务,由于端口不能同时多个服务占用,而服务器中可能又是多个网站,那么可以使用 Nginx 做反向代理,比如有这些网站域名和端口:
域名 | 端口 |
---|---|
www.xxoo.com | 8001 |
www.xo.com | 8002 |
www.xo.cn | 8003 |
当然一个服务器上的网站可能还有更多,可以通过配置 Nginx 转发来代理这些端口分发,如:
server {
server_name www.xxoo.com;
listen 80;
# 设置这个网站的根目录
root /wwwroot/www.xxoo.com/;
# 由于下面配置了文件不存在则代码到 Node.js 中,那么直接访问目录(不带默认主页)的话会有问题,这里做下判断
# 如果访问目录下有 index.html 文件,则直接重写到该文件
# break 表示重写且停止,但 url 不变,而 permanent 表示301重定向,url 会更新
if ( -f $request_filename/index.html ){
rewrite (.*) $1/index.html break;
}
# 如果请求的文件不存在,则代理到 Node.js
if ( !-f $request_filename ){
rewrite (.*) /index.js;
}
# 代理node服务 8001
location = /index.js {
# 设置一些代理的header信息,这些信息将被透传到 Node.js 服务的header信息里
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# 代理服务
proxy_pass http://127.0.0.1:8001$request_uri;
# 忽略其他重写
proxy_redirect off;
}
}
配置之后,比如你网站根目录里有 index.html
文件,访问 url
如:
访问链接 | 解析过程 | 备注 |
---|---|---|
www.xxoo.com/index.html | Nginx | 由于文件存在,直接使用 Nginx 输出 |
www.xxoo.com | Nginx | 由于判断该目录下有 index.html 文件,则自动重写到该文件,但 url 不变 |
www.xxoo.com/xx.html | Nginx → Node.js:8001 | 由于文件不存在,使用 Nginx 代理到 Node.js 的 8001 端口 |
www.xxoo.com/xxoo/ | Nginx → Node.js:8001 | 首先判断该目录是否存在 如果存在再判断是否有 index.html 文件 一旦不成立,直接代理到 Node.js |
配置图片防盗链
防盗链是指当图片不是自己网站打开时返回 403 或者指定图片,是通过请求的来路判断是否是自己的站点来设置响应。
#语法
valid_referers none | blocked | server_names | string
none
:表示没有来路blocked
:表示有来路server_names
:来路里包含当前域名string
:(忽略端口)- 如果是字符串:一个域名验证的规则,
*
表示通配符 - 如果是以
~
开头:正则表达式,排除https://或http://开头的字符串
- 如果是字符串:一个域名验证的规则,
以上参数可以叠加一起使用。
#例子
server {
# 配置所有图片
location ~* \.(gif|jpg|png|bmp)$ {
# 验证可以是没有来路、或者有来路时来路匹配xuexb.com、或者匹配当前域名
valid_referers none blocked *.xuexb.com server_names;
# 如果验证不通过则返回403
if ($invalid_referer) {
return 403;
}
}
}
配置 HTTPS
首先配置支持 HTTPS 必须让 Nginx 开启 http_ssl_module
模块,点击查看nginx编译安装参数 ,可以使用nginx -V
查看是否开启TLS SNI support enabled
。
购买/生成 SSL 证书,可以使用免费的证书,比如:Let’s Encrypt,免费好用的 HTTPS 证书 。
# 配置 HTTPS
# 配置个http的站点,用来做重定向,当然如果你不需要把 HTTP->HTTPS 可以把这个配置删了
server {
listen 80;
# 配置域名
server_name www.xxoo.com xxoo.com;
# 添加 STS, 并让所有子域支持, 开启需慎重
add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';
# 配置让这些 HTTP 的访问全部 301 重定向到 HTTPS 的
rewrite ^(.*) https://www.xxoo.com$1 permanent;
}
# 配置 HTTPS
server {
# 配置域名
server_name www.xxoo.com xxoo.com;
# https默认端口
listen 443;
# 添加STS, 并让所有子域支持, 开启需慎重
add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';
# https配置
ssl on;
ssl_certificate /xxoo/www.xxoo.com.crt;
ssl_certificate_key /xxoo/www.xxoo.com.key;
# 其他按正常配置处理即可...
}
注意,这里证书的格式是
.crt
的。
#配置后的访问规则
#强烈推荐
使用 https://github.com/Neilpang/acme.sh 支持泛域名证书申请了,好赞。
配置泛域名转发
有的时候,我们需要配置一些自定义的子域名,如:
xuexb.user.demo.com
a01.user.demo.com
这时候就需要域名的 DNS 解析一个泛域名 *.user.demo.com
到服务器,Nginx 可以配置如下:
#子域名转发到子目录
server {
listen 80;
server_name ~^([\w-]+)\.user\.demo\.com$;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/$1$request_uri;
}
}
以上配置表示:
xuexb.user.demo.com/path?a=1
→127.0.0.1:8080/xuexb/path?a=1
a01.user.demo.com/path?a=1
→127.0.0.1:8080/a01/path?a=1
这样后端就可以根据子目录解析不同的规则,甚至 Nginx 可以再进行链接重写。
#子域名配置不同的目录
server {
listen 80;
server_name ~^([\w-]+)\.user\.demo\.com$;
root /home/user/wwwroot/user/$1;
}
以上配置可以把不同的子域名分发到不同的目录中,做到路径分离的功能,如:
xuexb.user.demo.com
→/home/user/wwwroot/user/xuexb
;a01.user.demo.com
→/home/user/wwwroot/user/a01
;
配置浏览器缓存
使用 expires
参数。
#不缓存
server {
expires -1;
}
输出Response Headers:
Cache-Control:no-cache
当文件没有变更时会返回 304 ,有变更时会是 200 ,如果强制命中 200 可以再添加: if_modified_since off;
忽略 Request Headers 里的 If-Modified-Since
字段。
#缓存
server {
expires 1d;
}
1d为1天,单位如下:
ms milliseconds
s seconds
m minutes
h hours
d days
w weeks
M months,30 days
y years,365 days
如果希望最大缓存可以:
server {
expires max;
}
输出Response Headers:
Cache-Control:max-age=315360000
#根据链接设置缓存时间
server {
# 设置为1月
set $expires_time 1M;
# 针对后台不缓存
if ($request_uri ~* ^/admin(\/.*)?$) {
set $expires_time -1;
}
# 针对静态文件缓存最大
if ($request_uri ~* ^/static(\/.*)?$) {
set $expires_time max;
}
# 设置吧
expires $expires_time;
}
配置默认主页、目录浏览
设置默认主页
直接可以使用目录形式打开的页面称为默认主页,一般常见的有: index.html
、index.htm
、index.php
这些,要吧通过配置来完成,如:
server {
root /网站根目录;
# 设置默认主页,支持多个,按优先级来,空格分格
index index.html index.htm index.php;
}
#设置目录浏览
当一个目录内没有默认主页的文件时,直接访问目录会报 403 Forbidden
错误,而启用目录浏览功能后可以直接列出当前目录下的文件、文件夹,如:
server {
root /网站根目录;
# 优先使用默认主页
index index.html index.htm;
# 当默认主页不存在时直接列出目录内文件树
autoindex on;
}
但多 autoindex
相关可官方文档: http://nginx.org/en/docs/http/ngx_http_autoindex_module.html
注意,线上运行环境最好别开启该配置,因为这将直接暴露你的文件~