初始化1

This commit is contained in:
zg
2026-07-16 13:03:11 +08:00
parent 0bdfcbc1c8
commit e6b0f287cc
100 changed files with 12184 additions and 0 deletions

View 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 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: 准备工作
在新服务器上执行:
```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.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.conf``http {}` 块)。迁移时注意 `include /etc/nginx/conf.d/*.conf;` 不要丢失。