速查

配置文件路径:/etc/nginx/nginx.conf

日志路径:/var/log/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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
user  root;
worker_processes 1;

# 这里写成绝对路径,因为编译生成的 prefix 错误,如果写相对路径,会报错找不到日志文件
error_log /var/log/nginx/error.log;
error_log /var/log/nginx/error.log notice;
error_log /var/log/nginx/error.log info;

# pid logs/nginx.pid;


events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;

# $scheme 表示 access 时的协议
log_format main '$scheme - '
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;

tcp_nopush on;

keepalive_timeout 65;

gzip on;

# 前端 nginx 只配了 http,然后配置 cdn + https,这样也可以用 https 来访问
server {
listen 80;
server_name api.danmoits.com;
return 301 https://$host$request_uri;
}

server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
server_name api.danmoits.com;
index index.js;
root /home/Milestone-be/be/src;

location /milestone/ {
proxy_pass http://127.0.0.1:8080/;
}
# 核心,证书配置
ssl_certificate /etc/nginx/cert/api.danmoits.com.pem;
ssl_certificate_key /etc/nginx/cert/api.danmoits.com.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCSHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
}

server {
listen 80;
server_name milestone.danmoits.com;
index index.html;
root /home/Milestone-fe;

location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
}


server {
listen 80;
server_name zichen.danmoits.com;
index index.html;
root /home/remote-sensing;

location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
}
}

location路径替换

我只需要购买一个域名,创建很多二级域名,每个二级域名映射到服务器的一个端口上。实现起来,就是在server_name处写上域名,再在下面location中的proxy_pass指明代理到哪个端口。当然只有后端服务才需要这么做,前端只需要把静态资源放上去,指明 server_name 就行了,不需要配置反向代理。

问题:当我请求 api/danmoits.com/milestone/post 时,我希望后端那边收到的请求不带 milestone。

参考: nginx中proxy_pass的使用

假设http的请求路径为:http://123.25.95.148:9998/nginx/hello?name=taolong

1
2
3
4
5
6
#匹配规则
location /nginx {
#注意这里是“/”结尾,请求url中未匹配的内容:/hello?name=taolong
proxy_pass http://123.25.95.148:10010/;
}
#此时上面输出的结果:http://123.25.95.148:10010/hello?name=taolong

所以我只需要在 /nginx 处写成 /milestone/ (此处必须加 /,不然后端会多一个/,如 //post

proxy_pass 处写成 http:127.0.0.1/ (以 / 结尾)

这样就会把未匹配内容加在 http:127.0.0.1/ 后面

try_files

踩坑:刚进入页面时正常,刷新后显示404

由于nginx本质上还是一个托管静态资源的web服务器,当访问domain/url时,会去我指定的root目录下查找是否有资源。

比如说,milestone.danmoits.com/posts?page=0,我指定的root是服务器的/home/Milestone-fe,那么会找/home/Milestone-fe/posts?page=0,很显然此时找不到,那么就会报404。

为什么刚进入页面时不报404呢?因为我一开始访问的是根目录,请求会打到index.html上,随后前端把url重定向,而/home/Milestone-fe/index.html是真实存在的,所以没有404,这里的前端重定向,被学长称作’fake router’。

因此,需要配置try_files:

1
try_files $uri $uri/ /index.html;

当用户请求 http://localhost/example 时,这里的 $uri 就是 /example,try_files 会到硬盘里尝试找这个文件;
如果存在名为 /$root/example(其中 $root 是项目代码安装目录)的文件,就直接把这个文件的内容发送给用户;

如果这样写,其实try_files前面的$uri做的事和上边描述的一样,关键在于最后的参数。

如果给出的file都没有匹配到,则会进行一个内部重定向到最后一个参数给定的uri,就是新的location匹配。

即前面都没匹配到,就会去找/index.html,而它是能找到的,就不会报404了。

https

前端配置 https 借助来 cdn,而后端只能配 nginx.conf。

前端需要明白 cdn 的原理,我们要访问的域名配置了 CNAME 解析,从而访问 cdn 域名,我们发送 https 请求是向 cdn 服务器发送 https 请求,cdn 可能会回源,此时我配置回源协议是 http,所以 nginx 这边就不用配 https 了,当然也可以配,这样的话回源协议需要设置为 https。

以前用 certbot 生成的一份配置:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
user  root;
worker_processes auto;

# error_log logs/error.log;
# error_log logs/error.log notice;
# error_log logs/error.log info;

events {
accept_mutex on;
multi_accept on;
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

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 /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;

##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;

gzip on;

#################
# milestone
#################
server {
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
server_name milestone.danmoits.com;
ssl_certificate /etc/letsencrypt/live/milestone.danmoits.com/fullchain.pem; # managed by Certbot

include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

root /home/Milestone-fe;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}

}
server {
listen 80;
listen [::]:80;

server_name milestone.danmoits.com;
if ($host = milestone.danmoits.com) {
return 301 https://$host$request_uri;
} # managed by Certbot

return 404; # managed by Certbot
}

#################
# API
#################

server {
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
server_name api.danmoits.com;

ssl_certificate /etc/letsencrypt/live/api.danmoits.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.danmoits.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

index index.js;
root /home/Milestone-be/be/src;
location /milestone/ {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080/;
}
}

server {
listen 80;
listen [::]:80;

server_name api.danmoits.com;
if ($host = api.danmoits.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
return 404; # managed by Certbot
}

#################
# cmind
#################
server {
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
server_name cmind.danmoits.com;

ssl_certificate /etc/letsencrypt/live/cmind.danmoits.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cmind.danmoits.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

root /home/cMind;
location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
}

server {
listen 80;
listen [::]:80;

server_name cmind.danmoits.com;
if ($host = cmind.danmoits.com) {
return 301 https://$host$request_uri;
} # managed by Certbot

return 404; # managed by Certbot
}

}


后来自己尝试配 https,参考以下资料:

Configuring HTTPS servers

在Nginx或Tengine服务器上安装证书

然后就有了开头那份 nginx.conf。