自从10年前接触nginx后,就对它爱不释手,最近两年运维实战也是大量使用,下面就nginx的一些使用经验和常用配置进行一下总结:

常用命令

安装

centos直接命令:yum install nginx
其他系统请参考官网指引,这里不做详述。

配置管理

建议每个监听端口和域名都单独一个配置,放在/etc/nginx/conf.d目录下,以port_domain.conf格式命名,以便管理。

加载配置

生产环境修改配置需要慎重,配置修改完成后先测试一下/usr/sbin/nginx -t,确保配置正确后再通过/usr/sbin/nginx -s reload动态加载配置实现用户无感切换,慎用service nginx restart

Location

语法规则: location [=|~|~*|^~] /uri/ { … } ,不同语法的location匹配顺序:

  1. 精确匹配:= :如:location = /
  2. 有修饰符前缀匹配:^~ : 如:location ^~ /api
  3. 正则匹配: ~ (区分大小写),~*(不区分大小写)如:location ~ \.html$
  4. 无修饰符前缀匹配:如:location /api
  5. 通用匹配: / ,如:location /

常用配置

HTTP代理转发

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server {
        listen       80;#监听端口
        server_name  localhost liming.pub;#监听域名或IP

        location / {
            proxy_pass http://xxx.xxx.xxx.xxx:8888;
            proxy_set_header Host $host:$server_port;#第一层代理,拿到监听端口
            #proxy_set_header Host $http_host;#非首层代理,一直传下去
            proxy_set_header X-Real-IP $remote_addr;#第一层代理,拿到真实IP
            #proxy_set_header X-Real-IP $http_x_real_ip; #非首层以后的代理,一直传下去
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #附件大小限制
            client_max_body_size 100m;
        }

    }

NOTE: * $proxy_add_x_forwarded_for 会累加代理层的IP向后传递 * $http_x_forwarded_for 仅仅是上层传过来的值

HTTPS代理转发

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
    listen 443;
    server_name liming.pub;
    ssl on;
    ssl_certificate   cert/liming.pub.pem;#证书
    ssl_certificate_key  cert/liming.pub.key;#证书秘钥
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
            proxy_pass http://127.0.0.1:8080;
            #代理配置
            proxy_set_header Host $host:$server_port;#第一层代理,拿到监听端口
            #proxy_set_header Host $http_host;#非首层代理,一直传下去
            proxy_set_header X-Real-IP $remote_addr;#第一层代理,拿到真实IP
            #proxy_set_header X-Real-IP $http_x_real_ip; #非首层以后的代理,一直传下去
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #HTTPS代理配置
            proxy_set_header X-Forwarded-Proto  https;
            proxy_set_header X-Forwarded-Ssl on;
            #附件大小限制
            client_max_body_size 100m;
        }
}

静态资源跨域配置

vi /etc/nginx/conf.d/static.conf`

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
server {
    location /static/  {
        root   /var/www/liming/static/;
        if ($request_method = 'GET') {
            #跨域支持
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        }
    }
}

配置tcp转发

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
stream {
    upstream tcp_a{
        server  xxx.xxx.xxx.xxx:$端口;
    }
 
    server {
        listen $监听端口;
        proxy_pass tcp_a;
    }
}

例如:

  1. mysql转发

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    #Mysql转发
    stream {
    server {
        listen 3306;
        proxy_pass xxx.xxx.xxx.xxx:3306;
    
        # 也支持socket
        # proxy_pass unix:/var/lib/mysql/mysql.socket;
    }
    }
  2. SSH转发

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    stream {
    upstream ssh {
        server xxx.xxx.xxx.xxx:22;
    }
    server {
        listen $监听端口;
        proxy_pass ssh;
        proxy_connect_timeout 1h;
        proxy_timeout 1h;
    }
    }

设置用户名密码

1
2
cd /etc/nginx
printf "用户名:$(openssl passwd -crypt 密码)\n" >htpasswd

或者使用htpasswd命令

1
2
3
4
# 创建文件
htpasswd -c /etc/nginx/htpasswd user
# 新增用户
htpasswd -c /etc/nginx/htpasswd user
1
2
3
4
5
6
        location /admin {
            root   /var/log/admin;
            auth_basic "用户名";
            auth_basic_user_file htpasswd;
            autoindex on;
        }

负载均衡

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
upstream liming-pub-server {
    server 192.168.1.1:8080 weight=4;
    server 192.168.1.2:8081 weight=5;
}

server {
    location / {
        proxy_pass http://liming-pub-server;
        # 其他配置
    }
    
}

https跳转改写

1
2
        proxy_redirect http:// $scheme://;
        port_in_redirect on;

官网配置

  1. 默认HTTP

    1
    2
    3
    4
    5
    
    server {
        listen       443;
        server_name  www.liming.pub liming.pub;
        return 301 http://$host$request_uri;
    }
  2. 默认HTTPS

    1
    2
    3
    4
    5
    
    server {
    listen       80;
    server_name  www.liming.pub liming.pub;
    return 301 https://$host$request_uri;    
    }
  3. 默认二级域名

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    server {
        listen       80;
        server_name  www.liming.pub liming.pub;
    
        if ($host = www.liming.pub) {
            return 301 http://liming.pub$request_uri;
        }
    
        location /  {
            root   /var/www/liming;
        }
    }

防止图片盗链

1
2
3
4
5
6
location ~* \.(gif|jpg)$ {
    valid_referers none blocked www.liming.pub liming.pub;
    if ($invalid_referer) {
       rewrite ^/ http://$host/logo.png;
    }
}

安全相关

  1. nginx目录及目录下的所有文件,属主不能是nginx,目录权限只能744,文件权限只能是644;
  2. 当根目录下没有申明的索引文件时,也会报403错误,不一定是目录权限的问题;
  3. 隐藏nginx版本号,在http节点增加 server_tokens off;
  4. location uri配置中 uri需要带 / ,防止任意文件读取;
  5. 使用 $request_uri 代替 $uri
  6. 第一层nginx中,用$server_name代替$host,防止客户端修改host值导致跳转url错误;
  7. 禁用不必要的Http请求方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    if ($request_method !~ ^(GET|POST|PATCH|DELETE)$) {
        return 405;
    }
    
    error_page 405 /405.json;
    location = /405.json {
        add_header Content-Type application/problem+json;
        return 405 '{"title": "Method_Not_Allowed","status": 405,"detail": "不支持的HTTP方法请求"}';
    }

超时处理

nginx默认的超时时间都是60秒,有些场景,比如导出,下载等很容易超时,这时可以设置如下几个变量。

1
2
3
4
5
6
# 后端服务器连接的超时时间
proxy_connect_timeout 10s;
# 连接成功后_等候后端服务器响应时间
proxy_send_timeout 600s;
# 后端服务器数据回传时间
proxy_read_timeout 2000s;

其他

将共性配置往上提

如:

  1. root /var/www/html-default/; 配置在server节点,这样所有location不用配置。
  2. index index.htm index.html; 配置在http节点,这样所有的server也不用配置。
  3. 减少使用 if , 借助于重定向301和try_files,如 try_files $uri $uri/index.html /v2/$uri /v2/$uri/index.html =404;,注意try_files的最后一个是内部重定向,前面的值是相对root目录的文件路径。