Files
nginxserver/docs/nginxLinux服务器迁移手册.md
2026-07-16 13:03:11 +08:00

14 KiB
Raw Blame History

NginxLinux 服务器迁移手册

服务器: 10.1.1.160 (linuxNginx) 系统: Rocky Linux 8.10 更新日期: 2026-06-12 用途: Nginx 域名转发管理平台 — Python API + Nginx 反向代理


一、迁移概览

需要迁移以下内容到新服务器:

类别 内容 位置
目录 Python API 项目 /opt/nginx-api/
目录 SSL 证书 + 内部 CA /etc/nginx/ssl/
目录 Nginx 转发配置 /etc/nginx/conf.d/
目录 acme.sh /root/.acme.sh/
文件 Nginx 主配置 /etc/nginx/nginx.conf
文件 systemd 服务 /etc/systemd/system/nginx-api.service
文件 环境变量 /root/.bashrc (Ali_Key / Ali_Secret)
文件 Gunicorn 配置 /opt/nginx-api/gunicorn_config.py
定时任务 acme.sh 自动续期 cron crontab -l

二、新服务器环境要求

2.1 操作系统

  • Rocky Linux 8.x / CentOS 8.x / RHEL 8.x或其他 systemd Linux 发行版)
  • 最小磁盘: 20G当前使用 3.6G
  • 内存: 2G+(当前 1.7G,用 ~350M

2.2 安装软件清单

# 1. Nginx (dnf 安装)
dnf install -y nginx

# 2. Python 3 (系统自带 ≥ 3.6)
# Rocky 8 自带 Python 3.6.8,无需额外安装

# 3. pip 包
pip3 install flask==2.0.3 gunicorn==21.2.0
# 注: Python 3.6 不支持 Flask 3.x实际安装 2.0.x

# 4. acme.sh (从 GitHub cloneget.acme.sh 可能被墙)
git clone https://github.com/acmesh-official/acme.sh.git /root/.acme.sh
cd /root/.acme.sh && ./acme.sh --install --home /root/.acme.sh

# 5. 设置默认 CA
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

2.3 需要开放的网络

方向 端口/地址 用途
入站 22/tcp SSH 管理
入站 80/tcp HTTP 转发
入站 443/tcp HTTPS 转发
入站 5000/tcp Python API仅 Java 后端访问)
出站 alidns.aliyuncs.com:443 阿里云 DNS APIacme.sh + DNS 管理)
出站 letsencrypt.org:443 Let's Encrypt 证书签发/续期

三、迁移步骤

Step 0: 准备工作

在新服务器上执行:

# 创建目录结构
mkdir -p /etc/nginx/ssl/ca
mkdir -p /etc/nginx/conf.d
mkdir -p /opt/nginx-api/services

# 创建 nginx-api 用户(可选,当前用 root
useradd -r -s /sbin/nologin nginx-api || true

Step 1: 安装软件

# Nginx
dnf install -y nginx
systemctl enable nginx
systemctl start nginx

# Python pip 包
pip3 install flask==2.0.3 gunicorn==21.2.0

# acme.sh
git clone https://github.com/acmesh-official/acme.sh.git /root/.acme.sh
/root/.acme.sh/acme.sh --install --home /root/.acme.sh
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

Step 2: 配置防火墙

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=5000/tcp
firewall-cmd --reload

# SELinux
setsebool -P httpd_can_network_connect 1

Step 3: 迁移 Python API 代码

# 从旧服务器拷贝整个目录
rsync -avz root@10.1.1.160:/opt/nginx-api/ /opt/nginx-api/

# 或手动拷贝文件:
# /opt/nginx-api/
#   app.py              — Flask 主入口
#   gunicorn_config.py  — Gunicorn 配置
#   deploy.sh           — 部署脚本
#   requirements.txt    — Python 依赖
#   services/
#     __init__.py
#     nginx_service.py  — Nginx 配置读写
#     ssl_service.py    — 证书签发管理
#     dns_service.py    — DNS 解析管理
#     cert_notifier.py  — 邮件通知脚本

Step 4: 迁移 SSL 证书目录

# ⚠️ 关键:内部 CA 私钥必须保留
rsync -avz root@10.1.1.160:/etc/nginx/ssl/ /etc/nginx/ssl/

# 确保证书权限正确
chmod 700 /etc/nginx/ssl/ca
chmod 600 /etc/nginx/ssl/ca/ca.key
chmod 644 /etc/nginx/ssl/ca/ca.crt
chmod 600 /etc/nginx/ssl/*.key
chmod 644 /etc/nginx/ssl/*.pem

Step 5: 迁移 Nginx 配置

# 主配置
rsync -avz root@10.1.1.160:/etc/nginx/nginx.conf /etc/nginx/nginx.conf

# 所有域名转发配置
rsync -avz root@10.1.1.160:/etc/nginx/conf.d/ /etc/nginx/conf.d/

# 验证配置
nginx -t

# 重载
systemctl reload nginx

Step 6: 迁移 acme.sh

rsync -avz root@10.1.1.160:/root/.acme.sh/ /root/.acme.sh/

Step 7: 迁移环境变量

将以下内容追加到 /root/.bashrc

export Ali_Key="LTAI5t98jUxLUadZM1LkaSa8"
export Ali_Secret="K2HyLLXizAgvOMOa0Mzc7ebs4gbAZs"

然后执行:

source /root/.bashrc

Step 8: 安装 systemd 服务

创建 /etc/systemd/system/nginx-api.service

[Unit]
Description=Nginx Manager Python API
After=network.target nginx.service

[Service]
Type=simple
User=root
WorkingDirectory=/opt/nginx-api
Environment=Ali_Key=LTAI5t98jUxLUadZM1LkaSa8
Environment=Ali_Secret=K2HyLLXizAgvOMOa0Mzc7ebs4gbAZs
ExecStart=/usr/bin/python3 -m gunicorn -c gunicorn_config.py app:app
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable nginx-api
systemctl start nginx-api

Step 9: 迁移 crontab

# 查看旧服务器 crontab
crontab -l

# 添加 acme.sh 自动续期(每天 19:01
echo '1 19 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null' | crontab -

Step 10: 验证

# 1. 服务状态
systemctl status nginx nginx-api

# 2. 端口监听
ss -tlnp | grep -E ":(80|443|5000)"

# 3. Nginx 配置语法
nginx -t

# 4. Python API 健康检查
curl http://localhost:5000/api/nginx/health

# 5. 证书列表
curl http://localhost:5000/api/nginx/certs

# 6. acme.sh 版本
/root/.acme.sh/acme.sh --version

四、完整配置文件参考

4.1 Nginx 主配置 /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/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;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 4096;

    # 全局 gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_types text/plain text/css text/xml application/json
               application/javascript text/javascript application/xml+rss
               application/x-font-ttf image/svg+xml;

    # 包含所有域名转发配置
    include /etc/nginx/conf.d/*.conf;
}

4.2 Gunicorn 配置 /opt/nginx-api/gunicorn_config.py

import os

bind = "0.0.0.0:5000"
pidfile = "gunicorn.pid"
workers = int(os.environ.get('GUNICORN_WORKERS', 2))
worker_class = "sync"
timeout = 300
graceful_timeout = 10
accesslog = "-"
errorlog = "-"
loglevel = "info"
proc_name = "nginx-manager-api"
daemon = False

4.3 域名转发配置模板

HTTP (/etc/nginx/conf.d/<domain>.conf):

server {
    listen 80;
    server_name <domain>;

    # 静态资源缓存
    location ~* \.(js|css|svg|woff2|png|jpg|ico)$ {
        proxy_pass <target>;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    location / {
        proxy_pass <target>;
        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;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

HTTPS (/etc/nginx/conf.d/<domain>.conf):

# HTTP → HTTPS 重定向
server {
    listen 80;
    server_name <domain>;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name <domain>;

    ssl_certificate /etc/nginx/ssl/<domain>.pem;
    ssl_certificate_key /etc/nginx/ssl/<domain>.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 静态资源缓存
    location ~* \.(js|css|svg|woff2|png|jpg|ico)$ {
        proxy_pass <target>;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    location / {
        proxy_pass <target>;
        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;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

五、证书体系

5.1 双层证书架构

类型 适用域名 签发方式 有效期 续期方式
内部 CA 非 zgitm 域名 OpenSSL 自签 365天 重新签发
Let's Encrypt *.zgitm.com acme.sh DNS-01 90天 自动续期(每天cron)

5.2 内部 CA

/etc/nginx/ssl/ca/
  ca.key   (600) — 根CA私钥 (RSA 2048)
  ca.crt   (644) — 根CA证书 (有效期10年, 至约2036年)
  ca.srl        — 序列号文件

首次启动时由 ssl_service.pyinit_ca() 方法自动生成。迁移时必须保留此目录,否则所有内部 CA 签发的域名的 SSL 证书将不被信任。

5.3 Let's Encrypt (acme.sh)

  • 安装目录: /root/.acme.sh/
  • 证书存放: /etc/nginx/ssl/<domain>.pem + .key
  • 自动续期 cron: 1 19 * * * (每天)
  • DNS 验证: 阿里云 DNS API (dns_ali)
  • 阿里云 AccessKey 环境变量: Ali_Key / Ali_Secret
  • 当前已签发: zgitm.com, www.zgitm.com (到期 2026-09-09)

5.4 系统保护域名

zgitm.comwww.zgitm.com 为系统内置域名,不允许在转发规则页面创建/修改/删除。三层拦截:

  1. 前端: 操作按钮置灰
  2. Java: ForwardingRuleService.SYSTEM_DOMAINS
  3. Python: ssl_service.is_system_domain()

六、Python API 端点参考

基地址: http://10.1.1.160:5000

转发规则

GET    /api/nginx/health              → 健康检查
GET    /api/nginx/rules               → 规则列表
GET    /api/nginx/rules/<domain>       → 规则详情
POST   /api/nginx/rules               → 新增规则  {domain, protocol, target}
PUT    /api/nginx/rules/<domain>       → 修改规则  {domain, protocol, target}
DELETE /api/nginx/rules/<domain>       → 删除规则
POST   /api/nginx/reload              → 重载 Nginx

证书管理

GET    /api/nginx/certs               → 证书列表(扫描所有 .pem排除 ca.*
GET    /api/nginx/certs/<domain>       → 证书详情
POST   /api/nginx/certs/<domain>/issue → 签发 LE 证书
POST   /api/nginx/certs/<domain>/renew → 续期 LE 证书

DNS 管理

GET    /api/nginx/dns/records?zone=    → DNS 记录列表
POST   /api/nginx/dns/records          → 添加 DNS 记录
PUT    /api/nginx/dns/records/<id>     → 修改 DNS 记录
DELETE /api/nginx/dns/records/<id>     → 删除 DNS 记录

七、外部依赖关系

迁移后需要确保以下连通性:

从 → 到 地址 端口 用途
新服务器 MySQL 10.1.1.122 3306
新服务器 → Java 后端 10.10.1.170 4002
Java 后端 → 新服务器 新IP 5000
新服务器 → 阿里云 DNS alidns.aliyuncs.com 443
新服务器 → Let's Encrypt acme-v02.api.letsencrypt.org 443

⚠️ 迁移后必须更新的配置

  1. Java application-qa.yml / application-prod.yml: 修改 python-api.base-url 为新服务器 IP
  2. 前端 .env.production: 如果 Nginx 入口域名换了需更新 VITE_API_BASE_URL
  3. DNS 解析: 如果 nginx.server.zgitm.com 指向旧服务器 IP需更新 DNS 记录

八、服务清单

服务 systemd unit 开机自启 端口
Nginx nginx.service 80, 443
Python API nginx-api.service 5000
SSH sshd.service 22
Firewalld firewalld.service

常用命令

# 查看所有服务状态
systemctl status nginx nginx-api

# 重载 Nginx不中断连接
systemctl reload nginx

# 重启 Python API
systemctl restart nginx-api

# 查看日志
journalctl -u nginx-api -f
journalctl -u nginx -f

# 测试 Nginx 配置
nginx -t

# 手动签发证书LE 测试)
/root/.acme.sh/acme.sh --issue --dns dns_ali -d test.zgitm.com --staging

# 手动续期
/root/.acme.sh/acme.sh --renew -d zgitm.com --force

九、当前服务器资源使用

指标
磁盘 17G 总量, 3.6G 已用 (22%)
内存 1.7G 总量, ~350M 已用
Python API 大小 152K
acme.sh 大小 3.5M
Nginx 配置+证书 376K
证书文件数 20+ .pem
转发规则数 17 .conf

十、已知注意事项

  1. Python 3.6 兼容性: Rocky 8 自带 Python 3.6Flask 最高只支持到 2.0.x。requirements.txt 写的 flask==3.1.0 实际上被降级安装为 2.0.3。如果新服务器用 Python 3.9+,可以安装 Flask 3.x

  2. acme.sh 安装方式: curl https://get.acme.sh | sh 可能被墙,建议用 git clone 方式安装。

  3. 内部 CA 私钥: /etc/nginx/ssl/ca/ca.key 是安全敏感文件迁移时不要通过不安全渠道传输。RSYNC/SCP 直接传输是安全的。

  4. 阿里云 AccessKey: 存储在 /root/.bashrc 环境变量中systemd service 文件中也硬编码了一份(Environment=),两处都需要更新。

  5. Java 后端 MyBatis-Plus: 已从 JPA 迁移到 MyBatis-Plus2026-06-12新服务器上 Python API 代码已包含 list_certs() 修复(扫描全部 .pem

  6. Nginx gzip: 主配置中包含全局 gzip 压缩(/etc/nginx/nginx.confhttp {} 块)。迁移时注意 include /etc/nginx/conf.d/*.conf; 不要丢失。