跳转至

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

::: warning

启动容器前,先创建好一些必要的文件夹,不然可能启动不成功

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.cnwww.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;
}

::: warning

  1. server_name部分最好写上带www不带www两个域名,这样不管怎么访问都可以正确访问到主站。
  2. 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;
}

编写反向代理时,需要注意两个地方,如下:

  1. 指明要代理的地址
  2. 资源请求全都交给代理的地址处理

    在大型项目中,这样处理可能会导致性能下降,但是可以无脑解决资源转发的问题,不然你可能部署了一个网页,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/后台服务

::: caution 这个搞不定,首页能正确代理,但是各种资源无法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;
}

::: warning

如果路径有中文,要在 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,写入如下内容:

::: tabs

@tab 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 点自动执行

::: tabs

@tab 添加计划任务

  1. 编辑 crontab 文件
crontab -e

添加以下内容,00 点执行 updateLogDate.sh 脚本:

0 0 * * * /root/docker/01nginx/updateLogDate.sh

::: note 在 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

:::

评论