note

📝 Web 开发笔记

View project on GitHub

Nginx 使用指南

读音 Engine X

  • https://www.zhihu.com/question/19739907
  • https://segmentfault.com/q/1010000002432695

安装 Nginx

安装 nginx/Windows,需要下载 1.3.11 或以上版本

  • http://nginx.org/en/download.html
  • https://nginx.org/download/

CentOS

sudo yum install yum-utils

/etc/yum.repos.d/nginx.repo

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
sudo yum-config-manager --enable nginx-mainline

sudo yum install nginx

启动Nginx并设置开机自动运行

sudo systemctl start nginx.service

sudo systemctl enable nginx.service

服务的启动/停止/刷新配置文件/查看状态

systemctl start nginx.service

systemctl stop nginx.service

systemctl restart nginx.service

systemctl list-units --type=service

systemctl status nginx.service

systemctl enable nginx.service

systemctl disable nginx.service
参考:
C:\Users\Administrator>g:
G:\>cd G:\Program_Files\nginx-1.11.12
G:\Program_Files\nginx-1.11.12>start nginx

命令行

D:\ProgramFiles\nginx-1.13.10>nginx -h
nginx version: nginx/1.13.10
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: NONE)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

查看进程

tasklist /fi "imagename eq nginx.exe"

nginx/Windows作为标准控制台应用运行,而不是系统服务。可以用下面的命令控制:

nginx -s stop	# 快速退出
nginx -s quit	# 优雅退出
nginx -s reload	# 更换配置,启动新的工作进程,优雅的关闭以往的工作进程
nginx -s reopen	# 重新打开日志文件

配置

配置文件中的目录请使用“/”,而不是“\”做目录分隔

工具:
  • https://nginxconfig.io/
    • https://www.digitalocean.com/community/tools/nginx#?
  • https://www.tools4nerds.com/online-tools/nginx-conf-generator
参考:

虚拟主机

虚拟主机名

可以使用确切的名字,通配符,或者是正则表达式来定义:

# 不含“Host”字段的请求,需要指定一个空名字
# 可以将IP地址作为虚拟主机名
# 特殊的虚拟主机名“$hostname”
server {
    listen       80;
    server_name  example.org  www.example.org "" 192.168.1.1;
    ...
}

server {
    listen       80;
    server_name  *.example.org;
    ...
}

server {
    listen       80;
    server_name  mail.*;
    ...
}

server {
    listen       80;
    server_name  ~^(?<user>.+)\.example\.net$;
    ...
}
  • 通配符名字只可以在名字的起始处或结尾处包含一个星号,并且星号与其他字符之间用点分隔。
  • 有一种形如“.example.org”的特殊通配符
  • 为了使用正则表达式,虚拟主机名必须以波浪线“~”起始。正则表达式是一个一个串行的测试,所以是最慢的
  • 命名的正则表达式捕获组在后面可以作为变量使用: ```sh server { server_name ~^(www.)?(?.+)$;

    location / { root /sites/$domain; } }

server { server_name ~^(www.)?(.+)$;

location / {
    root   /sites/$2;
} } ``` - 在匹配所有的服务器的例子中,可以见到一个奇怪的名字“_”: ```sh server {
listen       80  default_server;
server_name  _;
return       444; } ``` 如果定义了大量名字,或者定义了非常长的名字,那可能需要在http配置块中使用server_names_hash_max_size和server_names_hash_bucket_size指令进行调整。

默认虚拟主机

  • 第一个被列出的虚拟主机即nginx的默认虚拟主机
  • default_server 显式地设置某个主机为默认虚拟主机,捕获组也可以以数字方式引用: ```sh server { listen 192.168.1.1:80 default_server; server_name example.net www.example.net; … }

server { listen [::]:80 default_server; server_name example.com www.example.com; … }

请注意"default_server"是监听端口的属性,而不是主机名的属性。



## 虚拟目录

location /path/ { root html }

实际访问 html/path/

location /paths/ { alias html/paths/ }

路径结尾必须加斜杠




## 进程

工作进程数量需要不少于可用CPU的个数

worker_processes 2;

- 虽然可以启动若干工作进程运行,实际上只有一个进程在处理请求所有请求。
- 一个工作进程只能处理不超过1024个并发连接。

## 日志

error_log logs/error.log debug;

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 logs/access.log main;

如果日志文件不存在,那失败原因会记录在Windows事件日志中。

access_log off; error_log /dev/null crit;




##### 参考:
- [nginx的error.log日志常见的几个错误解决方法](https://blog.51cto.com/chenx1242/1769724)

## 错误页面

error_page 500 502 503 504 /50x.html; location = /50x.html { root html; }


## SSL证书安装

##### 参考:
- https://cloud.tencent.com/document/product/400/4143
- [HTTPS 简介及使用官方工具 Certbot 配置 Let’s Encrypt SSL 安全证书详细教程](https://linuxstory.org/deploy-lets-encrypt-ssl-certificate-with-certbot/)

server { listen 80; # 合并HTTP/HTTPS主机 listen 443 ssl; server_name urlnk.host;

ssl_certificate K:\env\win\ProgramData/nginx\conf\cert\urlnk.host.crt; ssl_certificate_key K:\env\win\ProgramData/nginx\conf\cert\urlnk.host.key;

# HTTPS服务器优化 keepalive_timeout 70; ssl_session_cache shared:SSL:10m; # 共享会话缓存 ssl_session_timeout 10m; # 缓存超时(分钟)

ssl_ciphers HIGH:!aNULL:!MD5; # 1.0.5及以后版本,默认SSL密码算法 ssl_prefer_server_ciphers on;

location / { root D:\www\work\cdn; index index.html index.htm; autoindex on; } }


### HTTP/2

server { listen 443 ssl http2; server_name www.urlnk.com; }



## 自定义变量

全局有效,不可以和自带变量重名
```sh
set $doc_root /srv/www/htdocs;
fastcgi_param  DOCUMENT_ROOT      $doc_root;

运行 php

https://www.nginx.com/resources/wiki/start/topics/examples/phpfastcgionwindows/

try_files 和 QUERY_STRING

location / {
  root   K:/env/win/ProgramData/nginx/html;
  index  index.html index.php;
  autoindex on;
  try_files   $uri $uri/ /index.php$uri$is_args$args;
}

FastCGI

location ~ \.php($|/) {
  root           K:/env/win/ProgramData/nginx/html;
  fastcgi_pass   fastcgi_backend;
  fastcgi_read_timeout 150;
  fastcgi_index  index.php;
  fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

  fastcgi_split_path_info  ^(.+\.php)(/.*)$;
  fastcgi_param  PATH_INFO $fastcgi_path_info;
  fastcgi_param  RUNTIME_ENVIROMENT 'PRO';

  include        fastcgi_params;
}

使用 PATH_INFO

fastcgi_split_path_info  ^(.+\.php)(/.*)$;
fastcgi_param  PATH_INFO $fastcgi_path_info;

php 使用远程服务器

  1. 相对路径 nginx 和 php-fpm 启动程序的命令行初始目录,php-fpm.conf 可以改 chdir 选项
    fastcgi_param  SCRIPT_FILENAME  html$fastcgi_script_name;
    
  2. 绝对路径 更改 root 文档根路径不会影响远程 php-fpm 运行
    root html;
    fastcgi_param  SCRIPT_FILENAME  $doc_root$fastcgi_script_name;
    

参考:

跨域

add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";

80 转 443

server {
    listen       80;
    server_name  example.org;
    return       301 https://www.example.org$request_uri;
}

# 或者
server {
    listen 80;
    server_name localhost;
    rewrite ^(.*)$ https://${server_name}$1 permanent;
}

${server_name} 可以换成 $host

HTTP 压缩

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
参考:

反向代理

# 配置 Apache 虚拟主机 
<VirtualHost *:8080>
  ServerAdmin webmaster@dummy-host2.example.com
  DocumentRoot "/usr/local/nginx/html"
  ServerName "192.168.80.22"
  ErrorLog "logs/dummy-host2.example.com-error_log"
  CustomLog "logs/dummy-host2.example.com-access_log" common
</VirtualHost>
# 设置权限
<Directory />
  Options FollowSymLinks
  AllowOverride None
  Order deny,allow
  Allow from all
</Directory>

# 设置 Nginx 配置文件 .php 文件让 Apache 来解析
location ~ \.php$ {
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_pass   http://192.168.80.22:8080;
}

负载均衡

upstream fastcgi_backend {
  server 127.0.0.1:9001;
  server 127.0.0.1:9002;
}

location / {
  proxy_pass http://fastcgi_backend;
}

expires 缓存

# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
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 font/ttf font/otf image/svg+xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

# 开启缓存
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ { 
    access_log   off; 
    expires      30d;
}

location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
    access_log   off;
    expires      24h;
}

location ~* ^.+\.(html|htm)$ {
    expires      1h;
}

location ~* ^.+\.(eot|ttf|otf|woff|svg)$ {
    access_log   off;
    expires max;
}

# 格式
# expires 30s;
# expires 30m;
# expires 2h;
# expires 30d;
参考:

常见问题

bind() to 0.0.0.0:443 failed

netstat -aon|findstr "443"
tasklist|findstr "1408" 
taskkill /F /pid 1408

可能和已经运行的 nginx (cmd 下通过运行 .bat 启动,进程可能是 RuntimeBroker.exe) 或 httpd 冲突;

也可能是 vmware-hostd.exe (需要停止 VMware 所有服务,并将启动类型设置为手动)

sublime_text.exe 也会

VPS 遇到:

控制面板\网络和 Internet\网络连接\传入的连接

右键菜单属性:虚拟专用网络不要勾选

参考:

could not build server_names_hash, you should increase server_names_hash_bucket_size: 32

http {
	server_names_hash_bucket_size 512;

值为 32 的倍数

WSASocketW() failed (10106: The requested service provider could not be loaded or initialized)

以管理员身份打开命令提示符

netsh winsock reset

SSL: error:0200107B:system library:fopen:Unknown error:fopen

SSL 证书必须放 conf 目录下,用相对路径,如:cert/example.com.crt

开机自启动

创建快捷方式放到

%programdata%\Microsoft\Windows\Start Menu\Programs\Startup

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

shell:startup
shell:Common Startup

C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

参考文档

  • Nginx 入门指南
  • [nginx安装配置 nginx负载均衡 nginx反向代理 gzip压缩 expires缓存](https://segmentfault.com/a/1190000011489789)
  • https://nginx.org/en/docs/ => http://tengine.taobao.org/nginx_docs/cn/
  • https://wizardforcel.gitbooks.io/nginx-doc <=> https://www.kancloud.cn/wizardforcel/nginx-doc
  • https://www.yiibai.com/nginx/
  • Nginx 烹调书
  • Nginx完全配置指南