初始化1
This commit is contained in:
536
docs/nginxLinux服务器迁移手册.md
Normal file
536
docs/nginxLinux服务器迁移手册.md
Normal file
@@ -0,0 +1,536 @@
|
||||
# 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 安装软件清单
|
||||
|
||||
```bash
|
||||
# 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 clone,get.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 API(acme.sh + DNS 管理) |
|
||||
| 出站 | letsencrypt.org:443 | Let's Encrypt 证书签发/续期 |
|
||||
|
||||
---
|
||||
|
||||
## 三、迁移步骤
|
||||
|
||||
### Step 0: 准备工作
|
||||
|
||||
在新服务器上执行:
|
||||
|
||||
```bash
|
||||
# 创建目录结构
|
||||
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: 安装软件
|
||||
|
||||
```bash
|
||||
# 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: 配置防火墙
|
||||
|
||||
```bash
|
||||
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 代码
|
||||
|
||||
```bash
|
||||
# 从旧服务器拷贝整个目录
|
||||
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 证书目录
|
||||
|
||||
```bash
|
||||
# ⚠️ 关键:内部 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 配置
|
||||
|
||||
```bash
|
||||
# 主配置
|
||||
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
|
||||
|
||||
```bash
|
||||
rsync -avz root@10.1.1.160:/root/.acme.sh/ /root/.acme.sh/
|
||||
```
|
||||
|
||||
### Step 7: 迁移环境变量
|
||||
|
||||
将以下内容追加到 `/root/.bashrc`:
|
||||
|
||||
```bash
|
||||
export Ali_Key="LTAI5t98jUxLUadZM1LkaSa8"
|
||||
export Ali_Secret="K2HyLLXizAgvOMOa0Mzc7ebs4gbAZs"
|
||||
```
|
||||
|
||||
然后执行:
|
||||
```bash
|
||||
source /root/.bashrc
|
||||
```
|
||||
|
||||
### Step 8: 安装 systemd 服务
|
||||
|
||||
创建 `/etc/systemd/system/nginx-api.service`:
|
||||
|
||||
```ini
|
||||
[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
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable nginx-api
|
||||
systemctl start nginx-api
|
||||
```
|
||||
|
||||
### Step 9: 迁移 crontab
|
||||
|
||||
```bash
|
||||
# 查看旧服务器 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: 验证
|
||||
|
||||
```bash
|
||||
# 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`
|
||||
|
||||
```nginx
|
||||
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`
|
||||
|
||||
```python
|
||||
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`):
|
||||
```nginx
|
||||
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`):
|
||||
```nginx
|
||||
# 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.py` 的 `init_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.com` 和 `www.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 用,Python 不直连) |
|
||||
| 新服务器 → | Java 后端 | 10.10.1.170 | 4002 | Java 调用 Python API 的反向 |
|
||||
| Java 后端 → | 新服务器 | 新IP | 5000 | **需要更新 Java 配置中的 python-api.base-url** |
|
||||
| 新服务器 → | 阿里云 DNS | alidns.aliyuncs.com | 443 | DNS 管理 + LE 验证 |
|
||||
| 新服务器 → | 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 | ✅ | — |
|
||||
|
||||
### 常用命令
|
||||
|
||||
```bash
|
||||
# 查看所有服务状态
|
||||
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.6,Flask 最高只支持到 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-Plus(2026-06-12),新服务器上 Python API 代码已包含 `list_certs()` 修复(扫描全部 .pem)。
|
||||
|
||||
6. **Nginx gzip**: 主配置中包含全局 gzip 压缩(`/etc/nginx/nginx.conf` 中 `http {}` 块)。迁移时注意 `include /etc/nginx/conf.d/*.conf;` 不要丢失。
|
||||
Reference in New Issue
Block a user