Nginx

时常会用到Nginx,一直没有好好的梳理下,以后更新在这里.

关于Nginx性能优化见另一篇文章: Nginx调优

基础使用

安装

官方教程 来就好,没啥好说的.

# CentOS中 $releasever替换为主版本号,比如7; $basearch 替换为架构, 用arch命令查看
sudo tee /etc/yum.repos.d/nginx.repo <<-'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
EOF
# /etc/apt/sources.list.d/nginx.list
deb https://nginx.org/packages/ubuntu/ $release nginx
deb-src https://nginx.org/packages/ubuntu/ $release nginx

sudo apt update
# Ubuntu中 用以下命令修复错误: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY $key;
# sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $key 
sudo apt install nginx

sudo systemctl start nginx

Mac安装

brew install nginx
# 以服务的形式随系统启动
brew services start nginx
# 主要配置目录
/usr/local/var/www  # Doc Root
/usr/local/etc/nginx/nginx.conf
/usr/local/etc/nginx/servers/  ## 虚拟server 

Windows使用服务

借助于 winsw 可以把Nginx安装成服务.

winsw.exe install/uninstall/start/stop/restart/status

常用命令

# 手动启动
/etc/init.d/nginx start
# 开机启动服务
chkconfig nginx on
# 修改配置文件后,验证语法正确
nginx -t

# 重新加载配置让修改立即生效
sudo nginx -s reload

# 查看当前版本信息
nginx -V

配置

  • /etc/nginx/nginx.conf
  • 默认常用Document Root : /var/www/, /srv, /usr/share/www

http 常用设置

    # 设置客户端上传文件大小限制,默认1m太小
    # 否则报错 413 – Request Entity Too Large
    client_max_body_size 50m;

指令:

Location

  • 使用正则:必须以下面2种前缀开始
    • “~” 大小写匹配
    • “~*” 忽略大小写匹配
    • 不做匹配检查使用空block,即 “/ /”
  • 不使用正则(literal): 逐字匹配,一旦匹配停止继续检索
    • = 前缀强制URI和Location参数的匹配

正则备忘: ^ 代表以xx开始, $代表以xx结尾

location  = / {
# 只匹配 / 查询
}
location /test {
# 开启目录自动索引
    autoindex on;
}

文件名后缀

  • 以/结尾的location认为是目录,默认去找index.html文件,找不到返回404
server {
  location / {
  }
  
  location /images/ {
    autoindex on;
    index index.htm index.html;
  }
  
  locaiton ~ \.(mp3|mp4) {
    root /www/media;
  }
  
}

root和alias区别

  • 直接含义
    • root: 最上层目录. 适用于http{}, server{}, location{}
    • alias: 目录别名
  • 如何解释uri
    • root结果: root路径 + location路径
    • alias结果: 使用alias路径替换location路径

URL重写

rewrite (PCRE, perl兼容正则)

try_files

# 首先找相应的URI
# 如果没有,尝试添加/作为目录去匹配
# 如果还是找不到,转发给代理
try_files $uri $uri/ @proxy;

主要变量:

  • $server_name : 虚拟主机名

日志

默认的错误日志位于/var/log/nginx/error.log

# 开启debug日志对调试很有用
error_log /var/log/nginx/error.log debug;

Troubleshooting

bind() to 0.0.0.0:8443 failed, Permission denied

在CentOS安装完,绑定端口出错.

原因: SELinux 阻止了连接 解决1: semanage port -a -t http_port_t -p tcp 8443 解决2: tsebool httpd_can_network_connect on -P

# 辅助调试命令
sestatus
tail -f /var/log/audit/audit.log
semanage port -l | grep http_port_t
getsebool -a | grep httpd
# 如果找不到semanage命令:
yum provides /usr/sbin/semanage
yum -y install policycoreutils-python

403 Forbidden , 13: Permission denied

error.log 可找到 open() failed (13: Permission denied)

# 确保nginx对于静态文件的父级目录也有执行权限x
# 检查权限
namei -om /path/to/www

# Ubuntu /etc/nginx/nginx.conf 修改user为启动用户
user root;


# CentOS
# 可能原因为SELinux
setsebool -P httpd_can_network_connect on
# 检查Enforcing  
getenforce
chcon -Rt httpd_sys_content_t /path/to/www

说明: If the master process is run as root, then nginx will setuid()/setgid() to USER/GROUP. If GROUP is not specified, then nginx uses the same name as USER. By default, it’s nobody user and nobody or nogroup group or the –user=USER and –group=GROUP from the ./configure script. 不指定默认是nobody。

# 如果非root,
# user nginx;
chown -R nginx:nginx /app
chmod -R 755 /app
chown -R nginx:nginx /var/cache/nginx
chown -R nginx:nginx /var/log/nginx
chown -R nginx:nginx /etc/nginx/conf.d

touch /var/run/nginx.pid
chown -R nginx:nginx /var/run/nginx.pid

常见配置场景

Location用法

下载apk

location /apk {
    default_type application/octet-stream;
    alias /var/www/apk;
}
# 这种方式没有试过
# /etc/nginx/mime.types
application/vnd.android.package-archive apk;

# conf
location ~* \.(apk)$ {
  add_header Content-Type application/vnd.android.package-archive;
}

端口重定向

    location /test {
        # 重写URLs,把请求/testXXXX转换成/XXXX交给AppServer.
        rewrite ^/test(.*) /$1 break;
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
    }

启用HTTPS

各主流中间件容器对于ssl的配置可参考Mozilla自动生成网站

# 利用多核
worker_processes auto;

http {
# 缓存ssl session以提高性能
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    server {
        listen              443 ssl;
        ssl_certificate     /etc/ssl/xulizhao.com.crt;
        ssl_certificate_key /etc/ssl/xulizhao.com.key;

        # 优先采用server端算法
        ssl_prefer_server_ciphers   on;
    ...
# 生成曲线参数
openssl dhparam -out dhparam.pem 2048
# 列出支持的曲线算法
openssl ecparam -list_curves

# 查看系统ssl版本
rpm -qa openssl
# 关于椭圆曲线配置
ssl_dhparam /path/to/dhparam.pem;
ssl_ecdh_curve secp384r1;

对某路径启用认证密码保护

# 使用htpasswd工具加密密码
sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd admin
# 编辑配置,添加
sudo vi /etc/nginx/sites-available/default
    auth_basic "Private Property";
    auth_basic_user_file /etc/nginx/.htpasswd;
sudo service nginx reload

修改超时设置

Nginx连接Tomcat的默认超时是1分钟

vi /etc/nginx/conf.d/default.conf
# 修改proxy_read_timeout的值
location / {
        proxy_pass  http://127.0.0.1:8080;
        proxy_read_timeout 180;
    }

状态页

location /nginx_status {
        stub_status on;
        access_log   off;
        # Security
        allow 192.168.1.100;
        deny all;
   }

blog 二级域名与子目录映射

location / {  
        rewrite ^/(.*)$ /blog/$1 last;  
    }  
location ~* ^/blog/.*$ {  
        proxy_pass http://127.0.0.1:8080;  
    }  

mock服务URL重写

基于RAP2的REST API mock服务

# rap-mock.conf
upstream mock_server {
 server localhost:38080;
}

server {
    listen       38082;
    server_name  192.168.10.1;

 location ^~/sys-app/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
 
    rewrite ^/sys-app/(.*)$ /$1 break;
    proxy_pass http://mock_server/app/mock/16/sys-app/$1;
 }
}

日志记录响应时间

# 在预制格式combined的最后
# 添加 $request_time 和 $upstream_response_time
log_format  combined_timed  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" $request_time $upstream_response_time';
access_log  /var/log/nginx/access.log  combined_timed;

安全相关

server_tokens off;

支持 websocket

# 在location /添加
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

支持php

# 添加以下内容
location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
}

资源