nginx详细的配置和用途

文章目录
  1. 1. return 301 http://8.136.132.68:8081/404.html;
    1. 1.0.1. server模块
  2. 1.1. 关于server_name
  3. 1.2. 关于root和alias的区别
  4. 1.3. 关于error_page
  5. 1.4. location模块
  6. 1.5. upstream模块
  7. 1.6. include
  8. 1.7. 关于 mime.types:
  9. 1.8. 关于 vhost/*.conf :
  10. 1.9. gzip
  11. 1.10. rewrite模块(ngx_http_rewrite_mode)
  12. 1.11. break
  13. 1.12. if
  14. 1.13. return
  15. 1.14. rewrite

2022-03-23补充————
后置代理和从定向

location /api/test.html {

return 301 http://8.136.132.68:8081/404.html;

return 301 $scheme://$host:$server_port/404.html;
}

location /stg/swagger-ui.html {
proxy_pass http://$host:$server_port/404.html;

}

2022-1-20———————

在 Nginx 中配置二级域名 - Mincong Huang

目前ss证书都是Let’s Encrypt 和cloudflare

,image-20220123144802723

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
26
27
28
29
30
31
32
33
34
35
36
37
  # 配置证书地址
ssl_certificate /etc/nginx/imlike.cc.pem;
ssl_certificate_key /etc/nginx/imlike.cc.key;
server{
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _;
location / {
# 一些基本反向代理配置以及获取请求真是IP地址
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://8.136.132.68:5212/;
}
# access_log /home/wwwlogs/git.aboutme.ink.log;
}
# 监听80端口,提供本地静态服务
server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# 监听80的配置 跳转到对应HTTPS
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}

如果出现下图的问题,需要看看后置代理的服务是否有问题和nginx日志

image-20220120172354834

curl -iL file.imlike.cc

2021-12-31补充

image-20211231134646924

1
2
3
4
5
6
7
8
gzip on;  #是否开启gzip模块 on表示开启 off表示关闭
gzip_static on;
gzip_buffers 4 16k; #设置压缩所需要的缓冲区大小
gzip_comp_level 6; #压缩级别1-9,数字越大压缩的越好,也越占用CPU时间
gzip_min_length 1k; #设置允许压缩的最小字节
gzip_http_version 1.0; #设置压缩http协议的版本,默认是1.1
gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php image/jpeg image/gif image/png application/octet-stream application/javascript; #设置压缩的文件类型
gzip_vary on; #加上http头信息Vary: Accept-Encoding给后端代理服务器识别是否启用 gzip 压缩

2021-12-17补充使用nginx来代理并替换内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
location /uu/ {
# 添加gzip的支持 否则geoserver返回的内容不能被替换
proxy_set_header Accept-Encoding "";
# 你想要代理的地址
proxy_pass http://192.168.11.20:8080/geoserver/;

# sub_filter_types text/html;
# 参数分别为 on(一次),off(全部替换)
sub_filter_once off;
# 需要替换的内容,就是网页的内容
sub_filter 'http://127.0.0.1/geoserver/' 'http://127.0.0.1:8088/uu/';



proxy_redirect default;

# 返回重定向的
# proxy_set_header Host $host;
# proxy_set_header Host $host:$server_port;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

tips

  • nginx -V 查看是否支持 http_sub_module 否则不会替换
  • sub_filter 只支持替换,不支持正则表达式,复杂的需要使用第三方的库
  • {IP}:{PORT}/uu/ 才能被识别 但是geoserver通常访问是 xxx/geoserver/web 所以代理后是 xxx/uu/web/ 否则跳转不过去

2021-08-20 补充nginx使用和配置

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
重定向后找不到 host/uu/geoserver -> host/uu/geoserver/web/ ->  host/uu/geoserver/index.html
/ 是相对路径 没有 / 绝对路径

配置文件
location /uts/ {
proxy_pass http://192.168.11.20:90/uu/;
proxy_redirect default;
proxy_set_header Host $host;
}
location /uu/ {

sub_filter_once off;
# sub_filter_types text/html;
sub_filter "http://192.168.11.20:8080/geoserver/" "http://127.0.0.1/uu/";

proxy_pass http://192.168.11.20:8080/geoserver/;
proxy_redirect default;

# 返回重定向的
# proxy_set_header Host $host;
# proxy_set_header Host $proxy_host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}






location /uts {
proxy_host 192.168.11.20:8080
} http://127.0.0.1/uts/ /uts/ http://127.0.0.1/uts/configDetail /uts/configDetail

location /uts/ {
proxy_host 192.168.11.20:8080/
} http://127.0.0.1/uts/ / http://127.0.0.1/uts/configDetail configDetail

location /uts/ {
proxy_host 192.168.11.20:8080/ss/
} http://127.0.0.1/uts/ / http://127.0.0.1/uts/configDetail configDetail

location /uts/ {
proxy_host 192.168.11.20:8080
} http://127.0.0.1/uts/ /uts/ http://127.0.0.1/uts/configDetail /uts/configDetail



location /uts {
proxy_host 192.168.11.20:8080/
} http://127.0.0.1/uts/ // http://127.0.0.1/uts/configDetail //configDetail

2021-7-29补充

root alias区别

同样配置nginx目录

alias的路径只用于 url 不会根据这个去, 其配置的文件夹来找寻具体目录地址,同时如果在alias的根路径下还会显示 路径下所有文件.相当于 alias设置虚拟目录

但是root不是它会匹配,同样的如果root配置的location对应 文件夹不存在那就会包404

借鉴下面博文https://www.cnblogs.com/kevingrace/p/6187482.html

1)alias指定的目录是准确的,即location匹配访问的path目录下的文件直接是在alias目录下查找的;
2)root指定的目录是location匹配访问的path目录的上一级目录,这个path目录一定要是真实存在root指定目录下的;
3)使用alias标签的目录块中不能使用rewrite的break(具体原因不明);另外,alias指定的目录后面必须要加上”/“符号!!
4)alias虚拟目录配置中,location匹配的path目录如果后面不带”/“,那么访问的url地址中这个path目录后面加不加”/“不影响访问,访问时它会自动加上”/“;
但是如果location匹配的path目录后面加上”/“,那么访问的url地址中这个path目录必须要加上”/“,访问时它不会自动加上”/“。如果不加上”/“,访问就会失败!
5)root目录配置中,location匹配的path目录后面带不带”/“,都不会影响访问。

举例说明(比如nginx配置的域名是www.wangshibo.com):
示例一
location /huan/ {
alias /home/www/huan/;
}

在上面alias虚拟目录配置下,访问http://www.wangshibo.com/huan/a.html实际指定的是/home/www/huan/a.html。
注意:alias指定的目录后面必须要加上”/“,即/home/www/huan/不能改成/home/www/huan

上面的配置也可以改成root目录配置,如下,这样nginx就会去/home/www/huan下寻找http://www.wangshibo.com/huan的访问资源,两者配置后的访问效果是一样的!
location /huan/ {
root /home/www/;
}

http://blackwolfsec.cc/2018/05/23/Nginx_alias_misconfig_path_traversle/ 借鉴下

img

补充域名相关的知识

1
www.xxx.com` ,`www.zzz.xxx.com`,`www.xxx.com/getName

www: World Wide Web 万维网

xxx: 注册的名称

zzz: 子域名(Second-level domain;英文缩写:SLD)

com:顶级域名(Top-level domains)是org,

URL: http://www.example.net/index.html,www.xxx.com/getName

对于第三个需要配置 server->多个location配置

对于第二中需要配置多个server,或者server->server_name

转载地址nginx 常用配置记录-知乎专栏


server模块

server模块是http的子模块,它用来定义一个虚拟主机

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name localhost www.example.com;
root /Users/yangyi/www;# 全局定义,表示在该server下web的根目录
client_max_body_size 100M;
keepalive_timeout 20;
index index.php index.html index.htm;
charset utf-8;
access_log logs/host.access.log main; #用来指定此虚拟主机的访问日志存放路径,输出格式为main。
error_log logs/host.error.log error; #错误日志存放路径,输出格式为error。
error_page 404 /404.html; #状态码为404时的时候的网页地址,还可定义500,502之类的
....
}

以上一些配置为在该server下具有全局性,例如 root,可在location中重新定义root

关于server_name

用来指定IP地址或者域名,多个域名之间用空格分开

当我们想定义多个server监听同一个端口但访问的host不一样时,server_name就派上用场了。nginx会根据HTTP请求的header Host选择nginx配置文件里符合条件的server_name的server配置

匹配顺序如下

  1. 完全匹配的server_name;
  2. 后缀匹配: *.example.com;
  3. 前缀匹配: www.example.*;
  4. 正则匹配: ~\w+.com;
  5. listen指令里配置了default或default_server的server;如`listen 80 default`
  6. 第一个匹配上listen的server。

所以当我们监听的的端口只有一个server配置的时候,server_name 可以不填

关于root和alias的区别

两者作用差不多,区别在于最终映射的地址不同,例:

1
2
3
4
5
6
7
location /request_path/image/ {
# 如果现在访问 /request_path/image/a/b.jpg,root映
# 射的地址为/local_path/image/request_path/image/a/b.jpg,
# 而alias为/local_path/image/a/b.jpg
root /local_path/image/;
alias /local_path/image/;
}

关于error_page

语法:error_page code … [=[response]] uri
使用字段: http, server, location, if in location

产生的效果为内部跳转(internal redirect),即用户页面地址不变,但内容实际上为设置的uri对应的内容
我们也可以自定义设置返回的状态码,如:
error_page 502 503 =200 /50x.html;
这样用户访问产生502 、503的时候给用户的返回状态是200,内容是50x.html。
还有一种写法是 = 后面不带状态码,是针对相应的内容不是一个静态的页面,最终返回的状态码取决于对应url服务返回的状态码。

location模块

最主要和最复杂的配置,通过定位和解析url,判断该选择什么配置,支持正则和条件判断;

简单例子,匹配所有请求

1
2
3
4
location / {
root /home/www/html;
index index.php index.html index.htm;
}

一个正则匹配的例子:

1
2
3
4
# 匹配.php结尾的请求
location ~ \.php$ {
....
}

一个反向代理的例子:

1
2
3
4
5
6
7
8
9
10
# 匹配到/api开头的路由时候,将请求转发到http://192.168.0.1,但是通常不是直接填写地址,而是设置一个`upstream`配置,后面会提到
location /api {
proxy_pass http://192.168.0.1; #请求转向地址192.168.0.1
#不修改被代理服务器返回的响应头中的location头
proxy_redirect off;
#使用nginx反向代理后,如果要使服务获取真实的用户信息,用以下的设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

vue-router、react-router等路由框架要开启history模式可以选择的nginx配置的例子

1
2
3
4
location / {
alias static/;
try_files $uri $uri/ /index.html;
}

location的匹配规则和顺序

  1. 第一种是 = 类型,表示精确匹配,优先级最高,一旦匹配到忽略之后的正则匹配
  2. ^~ 类型,表示前缀匹配,是字符串开头匹配而非正则匹配,当匹配到该规则时,停止往下面的搜索,所以如果存在两个^~ 匹配的时候要注意有顺序之分。优先级比正则高。
  3. ~~*,正则匹配,两者区别是后者不区分大小写。有顺序之分,匹配到第一个正则停止搜索。
  4. /uri,普通字符串匹配,无顺序之分,会选择匹配长度最长的配置。
  5. / 通用匹配,匹配所有请求

还有一种特殊匹配类型 @url,只用于nginx内部跳转,例:

1
2
3
4
5
6
7
location / {
root /var/www/html;
error_page 404 @40x;
}
location @40x {
root /var/www/errors/40x.html;
}

upstream模块

upstream后端服务器提供简单的负载均衡(轮循调度和客户端 IP)。

例子:

1
2
3
4
5
6
7
8
9
10
11
upstream backend  {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;
}

server {
location / {
proxy_pass http://backend;
}
}

有常用两种负载均衡支持调度算法,分别是 weightip_hash 。weight 模式下可以为每个 server 设置weight值,weight值越大,分配到的访问机率越高,ip_hash 为同一个ip的
分配同一个后端服务器,这样我们不用解决session共享问题。

include

include指令 使nginx配置更加灵活,将部分配置直接拆分出来,分成不同的配置文件

例子:

1
http {    include mime.types;    include vhost/*.conf; # 虚拟主机配置}

关于 mime.types:

mime type 和 文件扩展名的对应关系一般放在 mime.types 里,然后 用 include mime.types;
mime.types作用:通过文件的扩展名设置了Content-Type,Nginx如果没找到对应文件的扩展名的话,就使用默认的Type,默认Type通用 default_type 定义,比如 default_type application/octet-stream ;
完整的 mime.types 配置:https://github.com/h5bp/server-configs-nginx/blob/master/mime.types

关于 vhost/*.conf :

一个虚拟主机对一个文件配置,放到vhost文件夹下面,然后通过include指令包含进来,这样更便于维护和管理

gzip

gzip 压缩,用来对静态资源进行压缩,需要客户端同时支持才有效。

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http {
#开启gzip压缩
gzip on;
#IE6的某些版本对gzip的压缩支持很不好,故关闭
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
#HTTP1.0以上的版本都启动gzip
gzip_http_version 1.0;
#指定哪些类型的相应才启用gzip压缩,多个用空格分隔
gzip_types
application/javascript
application/json
text/css
text/plain;
# 压缩等级,可选1-9,值越大压缩时间越长压缩率越高,
# 通常选5,能压缩到原来的1/4
gzip_comp_level 5;
}

rewrite模块(ngx_http_rewrite_mode)

rewrite模块配合很多模块一起使用,包含几个指令:

  1. break
  2. if
  3. return
  4. rewrite
  5. rewrite_log
  6. set
  7. uninitialized_variable_warn

这里简单介绍下break、if、return,重点介绍 rewrite

break

语法: break;
使用字段: server, location, if
此指令的意思是停止执行当前虚拟主机的后续rewrite指令集

例子

1
2
3
4
5
# 如果访问的文件名不存在,反向代理到localhost 。这里的break也是停止rewrite检查
if (!-f $request_filename) {
break;
proxy_pass http://127.0.0.1;
}

if

语法: if (condition) { … }
使用字段: server, location
if 判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。

条件(conditon)可以是如下任何操作:

  1. 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false;
  2. 使用“=”和“!=”比较一个变量和字符串;
  3. 使用“”做正则表达式匹配,“*”做不区分大小写的正则匹配,“!~”做区分大小写的正则不匹配;
  4. 使用“-f”和“!-f” 检查一个文件是否存在;
  5. 使用“-d”和“!-d”检查一个目录是否存在;
  6. 使用“-e”和“!-e”检查一个文件、目录、符号链接是否存在;
  7. 使用“-x”和“ !-x”检查一个文件是否可执行;
1
2
3
4
# 如果提交方法为POST,则返回状态405(Method not allowed)
if ($request_method = POST) {
return 405;
}

return

语法: return code [text];
return code URL;
return URL;
使用字段: server, location, if
停止处理并为客户端返回状态码,非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头部值。没有状态码的URL将被视为一个302状态码,这种情况下URL需要以“http://”, “https://”, 或者 “$scheme”开头。

rewrite

语法: rewrite regex replacement [flag];
使用字段: server, location, if
使用nginx提供的全局变量或自己设置的变量,然后结合正则表达式和标志位实现url重写以及重定向。多条 rewrite 顺序靠前且匹配的优先执行。可以通过设置 flag 停止继续处理。如果replacement 以“http://”, “https://”, 或者 “$scheme”开头,那么将立即停止处理并临时重定向给客户端。

flag可以是如下参数:

  • last,完成该rewrite规则的执行后,停止处理后续rewrite指令集;然后查找匹配改变后URI的新location;
  • break,完成该rewrite规则的执行后,停止处理后续rewrite指令集,并不再重新查找;但是当前location内剩余非rewrite语句和location外的的非rewrite语句可以执行;
  • redirect,返回302临时重定向,地址栏会显示跳转后的地址;
  • permanent,返回301永久重定向,地址栏会显示跳转后的地址;即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。

因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。两种重定向的方式对客户端来说是一样的,就是重新加载另外一个url。我们在实际设置中推荐只使用永久重定向,因为临时重定向可能造成在url为A页面,但显示的是B页面的内容,造成网址劫持。

比较难以理解的是 last 和 break,让我们先了解 nginx 运行的11个阶段,注意到第四阶段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef enum {  
NGX_HTTP_POST_READ_PHASE = 0, //读取请求头

NGX_HTTP_SERVER_REWRITE_PHASE, //执行rewrite

NGX_HTTP_FIND_CONFIG_PHASE, //根据uri替换location
NGX_HTTP_REWRITE_PHASE, //根据替换结果继续执行rewrite
NGX_HTTP_POST_REWRITE_PHASE, //执行rewrite后处理

NGX_HTTP_PREACCESS_PHASE, //认证预处理 请求限制,连接限制

NGX_HTTP_ACCESS_PHASE, //认证处理
NGX_HTTP_POST_ACCESS_PHASE, //认证后处理, 认证不通过, 丢包

NGX_HTTP_TRY_FILES_PHASE, //尝试try标签
NGX_HTTP_CONTENT_PHASE, //内容处理

NGX_HTTP_LOG_PHASE //日志处理
} ngx_http_phases;

所以我们再来理解last与break的区别:
last: 停止当前这个请求,并根据rewrite匹配的规则重新发起一个请求。新请求又从第一阶段开始执行…
break:相对last,break并不会重新发起一个请求,只是跳过当前的rewrite阶段,并执行本请求后续的执行阶段…

通过实例会更加清晰的理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80 default_server;
server_name dcshi.com;
root www;

location /break/ {
rewrite ^/break/(.*) /test/$1 break;
echo "break page";
}

location /last/ {
rewrite ^/last/(.*) /test/$1 last;
echo "last page";
}

location /test/ {
echo "test page";
}
}

请求:http://dcshi.com/break/***
输出: break page
分析:正如上面讨论所说,break是跳过当前请求的rewrite阶段,并继续执行本请求的其他阶段,很明显,对于/foo 对应的content阶段的输出为 echo “break page”; (content阶段,可以简单理解为产生数据输出的阶段,如返回静态页面内容也是在content阶段;echo指令也是运行在content阶段,一般情况下content阶段只能对应一个输出指令,如同一个location配置两个echo,最终只会有一个echo指令被执行);当然如果你把/break/里的echo 指令注释,然后再次访问/break/xx会报404,这也跟我们预期一样:虽然/break/xx被重定向到/test/xx,但是break指令不会重新开启一个新的请求继续匹配,所以nginx是不会匹配到下面的/test/这个location;在echo指令被注释的情况下,/break/ 这location里只能执行nginx默认的content指令,即尝试找/test/xx这个html页面并输出起内容,事实上,这个页面不存在,所以会报404的错误。

请求: http://dcshi.com/last/***
输出: test page
分析: last与break最大的不同是,last会重新发起一个新请求,并重新匹配location,所以对于/last,重新匹配请求以后会匹配到/test/,所以最终对应的content阶段的输出是test page;

解释完了 last 和 break ,我们再写一个实例用来说明 rewrite 可以做什么事情。通过rewrite将不带www的请求统一转向为www:

1
2
3
4
5
6
7
8
9
10
server {
# ........
server_name www.abc.com ;//只留一个
# ......


server {
server_name abc.com;
rewrite ^(.*)$ http://www.abc.com$1 permanent;
}

或者是:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name abc.com www.abc.com;
if ( $host != 'www.abc.com' ) {
rewrite ^/(.*) http://www.abc.com/$1 permanent;
}
location / {
root /data/www/www;
index index.html index.htm;
}
}

参考:

在线文档-nginx-zh

WEB请求处理二:Nginx请求反向代理

http://blog.sina.com.cn/s/blog_4f9fc6e10102ux0w.html