Nginx笔记
之前一直在用 NginxProxyManager 来做 Nginx 的反向代理,但 NginxProxyManager 有时候会有些问题,还占用资源,我最近折腾各种反向代理,后面发现 NginxProxyManager 登录不上去了,,,于是下定决心,抛弃这些可视化的,重新学 Nginx 配置文件的编写。
Nginx 的安装
Nginx 原生安装也挺简单,用 docker 安装是怕玩坏了,可以随时重头再来。
docker-compose.yml
内容如下:
version: "3"
services:
web:
container_name: nginx
image: nginx
ports:
- 80:80
- 443:443
volumes:
- ./html:/usr/share/nginx/html
- ./conf/nginx.conf:/etc/nginx/nginx.conf
- ./conf.d:/etc/nginx/conf.d
- ./logs:/var/log/nginx
- ./docs:/docs # 这是我自己准备的目录,可选
- ./ssl:/ssl_cert # 这是我自己准备的目录,可选
restart: always
deploy:
resources:
limits:
memory: 100M # 设置最大内存
cpus: "0.5" # 限制容器使用 1 个 CPU 核心
reservations:
memory: 50M # 设置预留内存
cpus: "0.5" # 设置 CPU 预留(预留 0.5 个 CPU 核心
networks:
default:
ipv4_address: 172.32.0.2
networks:
default:
external: true
name: web_net
注意
启动容器前,先创建好一些必要的文件夹,不然可能启动不成功
mkdir html
mkdir conf
mkdir conf.d
mkdir logs
创建好docker-compose.yml
文件以及相应的文件夹,使用docker-compose up -d
启动 docker 就行
Nginx 反向代理配置的编写
conf/nginx.conf
默认内容如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
# HTTPS server
# 引入扩展配置(可以细分服务nginx)
include /etc/nginx/conf.d/*.conf;
}
一般这个文件我都不会动它,这个文件最后一行include /etc/nginx/conf.d/*.conf;
表示会识别conf.d
文件夹下的所有.conf
文件,因此每个服务,我都是单独创建一个.conf
文件,这样方便管理。
1.主站文件配置(强制 https)
效果: 访问xxx.cn
和www.xxx.cn
默认访问的网站根目录/usr/share/nginx/html
。
在conf.d
文件夹下有一个Default.conf
的文件,写入内容如下:
# 配置HTTP服务器(端口80)
server {
listen 80; # 监听80端口
server_name www.xxx.cn xxx.cn; # 支持的域名
# 强制将HTTP流量重定向到HTTPS,在443服务那边去写网站根目录
return 301 https://$host$request_uri;
}
# 配置HTTPS服务器(端口443)
server {
listen 443 ssl;
http2 on;
server_name www.xxx.cn xxx.cn; # 支持的域名
# 网站内容配置
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm;
}
# 指定SSL证书和私钥文件路径
ssl_certificate /ssl_cert/nginx.crt; # 替换为你的证书文件路径
ssl_certificate_key /ssl_cert/nginx.key; # 替换为你的私钥文件路径
# SSL配置优化
ssl_protocols TLSv1.2 TLSv1.3; # 仅启用安全的协议
ssl_ciphers HIGH:!aNULL:!MD5; # 启用强大的加密算法
ssl_session_cache shared:SSL:1m; # SSL会话缓存
ssl_session_timeout 5m;
# HSTS(强制HTTPS访问)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
注意
server_name
部分最好写上带www
和不带www
两个域名,这样不管怎么访问都可以正确访问到主站。- location 部分注意事项
# 网站内容配置
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm;
}
这里网站根目录,其实是写 docker 容器内的绝对路径,这里指定根目录是/usr/share/nginx/html
,然后我docker-compose.yml
文件又把/usr/share/nginx/html
映射到本机的./html
,因此我上传文件到本机的./html
,就是上传到容器内的/usr/share/nginx/html
。
强调这一点,是想说明:编写 Nginx 配置时,所有路径都是应该是写容器内的路径,怎么映射出来,应该写在docker-compose.yml
文件。
2.二级域名反向代理后端服务
效果:访问二级域名sub.xxx.cn
,自动代理到http://192.168.32.10:8080
,浏览器地址栏显示sub.xxx.cn
。
在conf.d
目录下新建一个sub.xxx.cn.conf
文件(一般我就用域名当文件名),编写该.conf
文件内容如下:
server {
listen 80;
server_name sub.xxx.cn;
# 强制https
return 301 https://$host$request_uri;
}
# 配置HTTPS服务器(端口443)
server {
listen 443 ssl;
http2 on;
server_name xxx.yanggenjie.cn; # 支持的域名
set $myproxy_host http://192.168.32.10:8080;
location = / {
proxy_pass $myproxy_host; # 目标地址
proxy_set_header Host $host; # 传递原始 Host 头
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递转发信息
proxy_set_header X-Forwarded-Proto $scheme; # 传递协议信息
}
#解决js css 访问不到的问题
location ~ .* {
proxy_pass $myproxy_host;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forw $proxy_add_x_forwarded_for;
}
# 指定SSL证书和私钥文件路径
ssl_certificate /ssl_cert/nginx.crt; # 替换为你的证书文件路径
ssl_certificate_key /ssl_cert/nginx.key; # 替换为你的私钥文件路径
# SSL配置优化
ssl_protocols TLSv1.2 TLSv1.3; # 仅启用安全的协议
ssl_ciphers HIGH:!aNULL:!MD5; # 启用强大的加密算法
ssl_session_cache shared:SSL:1m; # SSL会话缓存
ssl_session_timeout 5m;
# HSTS(强制HTTPS访问)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
编写反向代理时,需要注意两个地方,如下:
- 指明要代理的地址
- 资源请求全都交给代理的地址处理
在大型项目中,这样处理可能会导致性能下降,但是可以无脑解决资源转发的问题,不然你可能部署了一个网页,css,js,png 等资源都无法正确转发。
# 这我只是定义了一个变量叫myproxy_host,方便后面调用而已
set $myproxy_host http://192.168.32.10:8080;
# 这里是指明要转发到后台那个地址服务
location = / {
proxy_pass $myproxy_host; # 目标地址
proxy_set_header Host $host; # 传递原始 Host 头
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递转发信息
proxy_set_header X-Forwarded-Proto $scheme; # 传递协议信息
}
# 这里是把所有的请求原封不动转发给后台的服务,让它自己处理,
# 这样能解决js css等 访问不到的问题
location ~ .* {
proxy_pass $myproxy_host;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forw $proxy_add_x_forwarded_for;
}
3. 二级目录反向代理到后端服务
有时候不想申请太多的二级域名,就想着直接用二级目录来访问后端服务。
效果:访问xxx.cn/后台服务
时,自动代理到http://192.168.32.2:8080
,浏览器地址栏显示xxx.cn/后台服务
。
警告
这个搞不定,首页能正确代理,但是各种资源无法v正确代理转发。放弃这个二级目录,使用二级域名来替代
4. 二级域名反向代理到磁盘的任意目录
效果:访问sub.xxx.cn
时,自动代理到 docs 目录下的我的笔记.html
文件,即/docs/我的笔记.html
,浏览器地址栏应该还是显示sub.xxx.cn
。
同样在conf.d
目录下新建一个新的.conf
文件,编写内容如下:
# 配置HTTP服务器(端口80)
server {
listen 80; # 监听80端口
server_name sub.xxx.cn; # 支持的域名
# 强制将HTTP流量重定向到HTTPS
return 301 https://$host$request_uri;
}
# 配置HTTPS服务器(端口443)
server {
listen 443 ssl;
http2 on;
server_name hintcad.xxx.cn; # 支持的域名
# 网站内容配置
location / {
root /docs; # 网站根目录
index 我的笔记.html ;
charset utf-8;
}
# 指定SSL证书和私钥文件路径
ssl_certificate /ssl_cert/nginx.crt; # 替换为你的证书文件路径
ssl_certificate_key /ssl_cert/nginx.key; # 替换为你的私钥文件路径
# SSL配置优化
ssl_protocols TLSv1.2 TLSv1.3; # 仅启用安全的协议
ssl_ciphers HIGH:!aNULL:!MD5; # 启用强大的加密算法
ssl_session_cache shared:SSL:1m; # SSL会话缓存
ssl_session_timeout 5m;
# HSTS(强制HTTPS访问)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
注意
如果路径有中文,要在 http 和 server 块加上 charset utf-8;
5. 二级域名反向代理到某个域名的二级目录(即子目录)
效果:访问sub.xxx.cn
时,自动代理到xxx.cn/我的笔记.html
,但是浏览器地址栏应该还是显示sub.xxx.cn
。
这个,先不折腾了,这个其实可以用第四条来替代,就是写绝对路径,而不是域名+子目录
,因为能访问到子目录的,基本都是在磁盘上有这个静态资源的,但是也不排除只能通过域名访问的情况,这个可以参照上面的几个写法,来写一下。
Nginx 日志按天分割日志文件
因为我是 docker 部署的 nginx,用各种工具不太方便,就用最原始的,修改 Nginx 的配置文件。
基本思路就是修改nginx.conf
配置文件,
# 省略
error_log /var/log/nginx/error_2025-02-23.log;
# 省略
http {
# ...省略
access_log /var/log/nginx/accesss_2025-02-23.log;
# ...省略
}
直接强行指定为某一天的路径就行了,但是不可能每天都打开服务器去修改,所以写个定时脚本,自动获取当天的日期,然后自动打开这个配置文件修改一下这个配置文件,然后重启 Nginx 就行。
新建一个 Shell 脚本文件/root/docker/01nginx/updateLogDate.sh
,写入如下内容:
#!/bin/bash
# 使用sed匹配到配置文件的error_log、access_log这两行,然后替换为当天的日期
TODAY=$(date +%Y-%m-%d)
sed -i "s|access_log /var/log/nginx/access[^;]*.log;|access_log /var/log/nginx/accesss_${TODAY}.log;|" /root/docker/01nginx/conf/nginx.conf
sed -i "s|error_log /var/log/nginx/error[^;]*.log;|error_log /var/log/nginx/error_${TODAY}.log;|" /root/docker/01nginx/conf/nginx.conf
# 强制重建容器
cd /root/docker/01nginx
docker-compose up -d --force-recreate
然后添加到计划任务,每天 00 点自动执行
- 编辑 crontab 文件
crontab -e
添加以下内容,00 点执行 updateLogDate.sh 脚本:
0 0 * * * /root/docker/01nginx/updateLogDate.sh
注
在 cronab 文件中,你可以添加一行来定义任务的执行时间和脚本路径。格式:
* * * * * command_to_execute
- 第一个
*
:分钟(0-59) - 第二个
*
:小时(0-23) - 第三个
*
:日期(1-31) - 第四个
*
:月份(1-12) - 第五个
*
:星期几(0-7,其中 0 和 7 都表示星期天) 例如,如果你想每天凌晨 2 点运行一个名为 backup.sh 的脚本,可以这样写:
0 2 * * * /path/to/backup.sh
2.确保脚本可执行:
chmod +x /root/docker/01nginx/updateLogDate.sh
:::