nginx 个人理解
服务日志都要配上哈
这份文档主要就是看例子,理解几种最常见的 nginx 写法。
1. 静态网站怎么写
例子
直接用端口访问
server { listen 8123; listen [::]:8123;
access_log /var/log/nginx/hexo_8123_access.log; error_log /var/log/nginx/hexo_8123_error.log warn;
root /data/hexo; index index.html;
location / { try_files $uri $uri/ /index.html; } }
|
说明
这段配置表示:
nginx 监听 8123
- 网站目录是
/data/hexo
- 找不到文件时回退到
/index.html
适合:
如果:
- nginx 已启动
- 端口
8123 已放行
/data/hexo/index.html 存在
那就可以直接通过:
访问。
如果你是普通静态网站,不需要回退到首页,也可以写成:
location / { try_files $uri $uri/ =404; }
|
静态网站走域名
HTTP
server { listen 80; listen [::]:80; server_name blog.example.com;
access_log /var/log/nginx/blog_http_access.log; error_log /var/log/nginx/blog_http_error.log warn;
root /data/hexo; index index.html;
location / { try_files $uri $uri/ /index.html; } }
|
这表示:
- 域名
blog.example.com 访问这个站点
- 走的是 HTTP
- 不需要 SSL 证书
访问方式:
HTTPS
server { listen 80; listen [::]:80; server_name blog.example.com; return 301 https://$host$request_uri; }
server { listen 443 ssl; listen [::]:443 ssl; server_name blog.example.com;
access_log /var/log/nginx/blog_https_access.log; error_log /var/log/nginx/blog_https_error.log warn;
ssl_certificate /etc/nginx/ssl/blog.example.com.crt; ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;
root /data/hexo; index index.html;
location / { try_files $uri $uri/ /index.html; } }
|
这表示:
80 负责跳转到 HTTPS
443 正式提供静态网站
- 这里必须配置 SSL 证书
访问方式:
屏蔽直接 IP 访问
就在正式域名站点的基础上,再额外补一个默认兜底站点。
HTTP 场景
server { listen 80; listen [::]:80; server_name blog.example.com;
root /data/hexo; index index.html;
location / { try_files $uri $uri/ /index.html; } }
server { listen 80 default_server; listen [::]:80 default_server; server_name _; access_log /var/log/nginx/default_http_drop_access.log; error_log /var/log/nginx/default_http_drop_error.log warn; return 444; }
|
HTTPS 场景
server { listen 80; listen [::]:80; server_name blog.example.com; access_log /var/log/nginx/blog_http_redirect_access.log; error_log /var/log/nginx/blog_http_redirect_error.log warn; return 301 https://$host$request_uri; }
server { listen 80 default_server; listen [::]:80 default_server; server_name _; access_log /var/log/nginx/default_http_drop_access.log; error_log /var/log/nginx/default_http_drop_error.log warn; return 444; }
server { listen 443 ssl; listen [::]:443 ssl; server_name blog.example.com;
access_log /var/log/nginx/blog_https_access.log; error_log /var/log/nginx/blog_https_error.log warn;
ssl_certificate /etc/nginx/ssl/blog.example.com.crt; ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;
root /data/hexo; index index.html;
location / { try_files $uri $uri/ /index.html; } }
server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _;
access_log /var/log/nginx/default_https_drop_access.log; error_log /var/log/nginx/default_https_drop_error.log warn;
ssl_certificate /etc/nginx/ssl/blog.example.com.crt; ssl_certificate_key /etc/nginx/ssl/blog.example.com.key;
return 444; }
|
这表示:
- 正式域名访问正常返回
- 直接访问 IP 或错误 Host 的请求直接丢掉
2. 反向代理怎么写
例子
server { listen 80; listen [::]:80; server_name api.example.com;
access_log /var/log/nginx/api_http_access.log; error_log /var/log/nginx/api_http_error.log warn;
location / { proxy_pass http://127.0.0.1:8000; 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-Forwarded-Proto $scheme; } }
|
说明
这表示:
- 用户访问
api.example.com
- 请求先到 nginx
- nginx 再把请求转发给本机
127.0.0.1:8000
适合:
- FastAPI
- Flask
- Django
- Node
- Java 服务
也就是说:
- 对外入口是 nginx
- 真正处理业务的是本地服务端口
如果想屏蔽直接 IP 访问
就在反向代理站点基础上,再额外补默认兜底站点。
server { listen 80; listen [::]:80; server_name api.example.com;
access_log /var/log/nginx/api_http_access.log; error_log /var/log/nginx/api_http_error.log warn;
location / { proxy_pass http://127.0.0.1:8000; 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-Forwarded-Proto $scheme; } }
server { listen 80 default_server; listen [::]:80 default_server; server_name _; access_log /var/log/nginx/default_http_drop_access.log; error_log /var/log/nginx/default_http_drop_error.log warn; return 444; }
|
3. HTTPS + 反向代理怎么写
例子
server { listen 80; listen [::]:80; server_name api.example.com; access_log /var/log/nginx/api_http_redirect_access.log; error_log /var/log/nginx/api_http_redirect_error.log warn; return 301 https://$host$request_uri; }
server { listen 80 default_server; listen [::]:80 default_server; server_name _; access_log /var/log/nginx/default_http_drop_access.log; error_log /var/log/nginx/default_http_drop_error.log warn; return 444; }
server { listen 443 ssl; listen [::]:443 ssl; server_name api.example.com;
access_log /var/log/nginx/api_https_access.log; error_log /var/log/nginx/api_https_error.log warn;
ssl_certificate /etc/nginx/ssl/api.example.com.crt; ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
location / { proxy_pass http://127.0.0.1:8000; 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-Forwarded-Proto $scheme; } }
server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _;
access_log /var/log/nginx/default_https_drop_access.log; error_log /var/log/nginx/default_https_drop_error.log warn;
ssl_certificate /etc/nginx/ssl/api.example.com.crt; ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
return 444; }
|
说明
这表示:
80 正式域名跳转到 HTTPS
80 default_server 丢弃其他访问
443 正式域名做反向代理
443 default_server 丢弃其他访问
所以外部用户实际访问的是:
而不是:
4. 负载均衡怎么写
例子
upstream api_backend { server 127.0.0.1:8001; server 127.0.0.1:8002; }
server { listen 80; listen [::]:80; server_name api.example.com;
access_log /var/log/nginx/api_lb_access.log; error_log /var/log/nginx/api_lb_error.log warn;
location / { proxy_pass http://api_backend; 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-Forwarded-Proto $scheme; } }
|
说明
这表示:
- 后端不是一台服务,而是两台
- nginx 先定义一个
upstream
- 然后把请求交给这个服务组
常见理解就是:
如果想带 HTTPS,也是在这个基础上继续套上前面的 80 -> 443 和 443 ssl 写法。
5. 同一个域名按路径分发到不同服务怎么写
例子
例如你想要:
web.dostorm.com/v1 访问 127.0.0.1:8001
web.dostorm.com/v2 访问 127.0.0.1:8002
可以这样写:
server { listen 80; listen [::]:80; server_name web.dostorm.com;
access_log /var/log/nginx/web_router_access.log; error_log /var/log/nginx/web_router_error.log warn;
location /v1/ { proxy_pass http://127.0.0.1:8001/; 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-Forwarded-Proto $scheme; }
location /v2/ { proxy_pass http://127.0.0.1:8002/; 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-Forwarded-Proto $scheme; } }
|
说明
这表示:
web.dostorm.com/v1/... 转发到 127.0.0.1:8001/...
web.dostorm.com/v2/... 转发到 127.0.0.1:8002/...
这里最后那个 / 要注意:
proxy_pass http://127.0.0.1:8001/;
|
这种写法通常表示:
- 把
/v1/ 这个前缀替换掉
- 再把剩余路径转给后端
例如:
- 用户访问:
web.dostorm.com/v1/users
- 后端
8001 实际收到的通常是:
/users
如果你希望后端保留 /v1/ 这个前缀,那常见写法就是不要在 proxy_pass 后面加最后这个 /:
location /v1/ { proxy_pass http://127.0.0.1:8001; }
|
这时后端更可能收到:
6. 一个子域名对应一个服务怎么写
例子
这也是很常见的一种写法,只不过它不是按路径分发,而是按子域名分发。
例如你有多个本地服务:
- 博客前端:
127.0.0.1:8123
- API 服务:
127.0.0.1:8000
- 管理后台:
127.0.0.1:9000
然后你想分别对外提供:
blog.example.com
api.example.com
admin.example.com
那就可以这样写:
server { listen 80; listen [::]:80; server_name blog.example.com;
access_log /var/log/nginx/blog_subdomain_access.log; error_log /var/log/nginx/blog_subdomain_error.log warn;
location / { proxy_pass http://127.0.0.1:8123; 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-Forwarded-Proto $scheme; } }
server { listen 80; listen [::]:80; server_name api.example.com;
access_log /var/log/nginx/api_subdomain_access.log; error_log /var/log/nginx/api_subdomain_error.log warn;
location / { proxy_pass http://127.0.0.1:8000; 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-Forwarded-Proto $scheme; } }
server { listen 80; listen [::]:80; server_name admin.example.com;
access_log /var/log/nginx/admin_subdomain_access.log; error_log /var/log/nginx/admin_subdomain_error.log warn;
location / { proxy_pass http://127.0.0.1:9000; 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-Forwarded-Proto $scheme; } }
|
说明
这表示:
- 一个子域名对应一个本地服务
- 所有请求先到 nginx
- nginx 再按
server_name 分别转发到不同端口
这种方式特别适合:
- 博客
- 接口服务
- 管理后台
- 不同系统之间想彻底隔离入口
也就是说,子域名本身就是服务入口。
如果后面都要上 HTTPS,也是在这个基础上,分别给每个子域名继续加:
80 -> 443 跳转
443 ssl
- 对应证书