This commit is contained in:
2026-05-08 06:19:59 -07:00
parent 7d2f98b7c9
commit f946504cb8
12 changed files with 1493 additions and 140 deletions
+306
View File
@@ -0,0 +1,306 @@
# PPanel 香港区新 AWS 账号部署说明
本目录用于在 **新 AWS 账号** 中按 **香港区 `ap-east-1`** 重建一套全新空环境。
目标架构:
`DNS -> ALB -> WAF -> EC2(Nginx + ppanel-server + observability) -> RDS MySQL + ElastiCache Redis`
## 1. 资源清单
按下面顺序创建资源:
1. VPC
2. 2 个公有子网 + 2 个私有子网
3. Internet Gateway
4. 公有 / 私有路由表
5. 安全组
6. RDS MySQL
7. ElastiCache Redis OSS
8. EC2
9. ACM 证书
10. ALB + Target Group
11. WAF Web ACL
12. 平行环境域名
建议命名:
- VPC: `ppanel-hk-prod`
- EC2: `ppanel-app-hk-01`
- RDS: `ppanel-mysql-hk`
- Redis: `ppanel-redis-hk`
- ALB: `ppanel-alb-hk`
- WAF: `ppanel-waf-hk`
## 2. 默认规格
### EC2
- Region: `ap-east-1`
- OS: Ubuntu 24.04 LTS
- Instance type: `t4g.large` 起步
- Disk: `gp3 80GB`
- Public subnet: 是
- IAM Role: 允许读取 CloudWatch / SSM(如使用)
### RDS MySQL
- Engine: MySQL 8.0
- Class: `db.r7g.xlarge`
- Storage: `gp3 100GB`
- DB name: `hifast`
- Username: `admin`
- Public access: `No`
- Charset: `utf8mb4`
- Backup: `7-14 days`
### ElastiCache Redis OSS
- Engine: Redis OSS 7.x
- Node type: `cache.m7g.large`
- Cluster mode: disabled
- Multi-AZ: 按预算决定,正式环境建议开启
- Public access: 不开放
- TLS: 当前模板按 **关闭** 规划
## 3. 网络与安全组
### 子网布局
- `public-a`, `public-b`: ALB / EC2
- `private-a`, `private-b`: RDS / Redis
### 安全组建议
#### `sg-alb`
- Inbound
- `80/tcp` from `0.0.0.0/0`
- `443/tcp` from `0.0.0.0/0`
- Outbound
- `80/tcp` to `sg-ec2`
#### `sg-ec2`
- Inbound
- `80/tcp` from `sg-alb`
- `22/tcp` from `你的固定运维 IP`
- Outbound
- all
说明:
- 应用容器监听 `127.0.0.1:8080`
- EC2 对外只让 Nginx 监听 `80`
- Grafana / Prometheus / Tempo 仅监听 `127.0.0.1`
#### `sg-rds`
- Inbound
- `3306/tcp` from `sg-ec2`
#### `sg-redis`
- Inbound
- `6379/tcp` from `sg-ec2`
## 4. ALB / Target Group / 健康检查
### Target Group
- Type: `Instance`
- Protocol: `HTTP`
- Port: `80`
- Health check path: `/v1/common/heartbeat`
- Success code: `200`
这个路径已由项目现有接口提供,无需额外改代码。
### ALB 监听器
- `80` -> redirect to `443`
- `443` -> forward 到 target group
### ACM
-`ap-east-1` 申请证书
- 先给平行环境域名,例如:
- `api-new.hifast.biz`
- `logs-new.hifast.biz`
## 5. WAF 规则
首版至少启用:
1. `AWSManagedRulesCommonRuleSet`
2. `AWSManagedRulesKnownBadInputsRuleSet`
3. `AWSManagedRulesAmazonIpReputationList`
4. 全站 rate-based rule
5. 针对高风险路径的 rate-based rule
建议的第一版限流:
- 全站:每 IP `2000 / 5 分钟`
- `/v1/public/user/subscribe`:每 IP `300 / 5 分钟`
- 登录 / 注册 / 验证码接口:每 IP `100 / 5 分钟`
节点上报接口建议后续补:
- `/v1/server/status`
- `/v1/server/online`
- `/v1/server/traffic`
优先用节点出口 IP 白名单;没有固定出口 IP 的节点暂时保留 `secret_key`,但不要把它当成唯一防线。
## 6. EC2 文件落地
在 EC2 上建议使用:
- 应用目录:`/opt/ppanel`
- Nginx 配置:`/etc/nginx/sites-available/ppanel-api.conf`
需要上传这些文件 / 目录:
- `docker-compose.cloud.yml`
- `deploy/aws/ap-east-1/configs/ppanel.yaml.example` -> 重命名为 `configs/ppanel.yaml`
- `deploy/aws/ap-east-1/nginx/ppanel-api.conf`
- `grafana/`
- `loki/`
- `prometheus/`
- `tempo/`
- `.env.example` -> 重命名为 `.env`
目标目录示例:
```text
/opt/ppanel/
docker-compose.cloud.yml
.env
configs/ppanel.yaml
grafana/
loki/
prometheus/
tempo/
logs/
cache/
tempo_data/
```
## 7. 应用配置
基线模板见:
- [`configs/ppanel.yaml.example`](./configs/ppanel.yaml.example)
- [`nginx/ppanel-api.conf`](./nginx/ppanel-api.conf)
关键值必须替换:
- `MySQL.Addr`
- `MySQL.Password`
- `Redis.Host`
- `JwtAuth.AccessSecret`
- `Administrator.Email`
- `Administrator.Password`
- `AppSignature.AppSecrets.*`
- `device.security_secret`
- `Site.Host`
- `Site.SiteName`
Redis 约定保持不变:
- 业务缓存:DB `0`
- AsynqDB `5`(代码内部已固定使用)
## 8. 部署步骤
### 8.1 初始化 EC2
把脚本上传到 EC2 后执行:
```bash
chmod +x deploy/scripts/bootstrap_aws_ec2.sh
sudo APP_DIR=/opt/ppanel deploy/scripts/bootstrap_aws_ec2.sh
```
### 8.2 安装 Nginx 配置
```bash
sudo cp deploy/aws/ap-east-1/nginx/ppanel-api.conf /etc/nginx/sites-available/ppanel-api.conf
sudo ln -sf /etc/nginx/sites-available/ppanel-api.conf /etc/nginx/sites-enabled/ppanel-api.conf
sudo nginx -t
sudo systemctl reload nginx
```
### 8.3 启动容器
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d
```
### 8.4 预检
```bash
chmod +x deploy/scripts/preflight_aws_hk.sh
APP_DIR=/opt/ppanel \
RDS_HOST=<new-rds-endpoint> \
REDIS_HOST=<new-redis-endpoint> \
deploy/scripts/preflight_aws_hk.sh
```
## 9. 平行环境验证
先验证 `api-new.hifast.biz`,不要直接切正式域名。
必测项:
1. `ALB target` 为 healthy
2. `GET /v1/common/heartbeat` 返回 200
3. 管理员登录
4. 用户注册 / 登录
5. 订阅查询
6. 节点上报 `/v1/server/status`
7. Redis 可写缓存
8. Asynq 可入队并消费
## 10. 正式切换
切换前检查:
1. ALB 5xx 为 0
2. EC2 CPU / Memory 正常
3. RDS CPU / Connections 正常
4. Redis CPU / Connections / Memory 正常
5. WAF 已挂到 ALB
6. EC2 安全组没有对公网放 `8080/3333/9090/4317`
切换方式:
1. 保持新环境先跑平行域名
2. 正式域名切到新 ALB
3. 观察至少 1 小时
4. 确认无误后再处理旧环境
## 11. 监控建议
至少建这些 CloudWatch / Grafana 观测项:
- ALB `RequestCount`, `HTTPCode_ELB_5XX_Count`, `TargetResponseTime`
- EC2 `CPUUtilization`, `NetworkIn`, `NetworkOut`, `StatusCheckFailed`
- RDS `CPUUtilization`, `DatabaseConnections`, `ReadLatency`, `WriteLatency`
- Redis `EngineCPUUtilization`, `CurrConnections`, `BytesUsedForCache`
## 12. 这次方案的边界
本目录交付的是:
- 香港区新账号的部署模板
- 新空环境启动与验证流程
- ALB / WAF / EC2 / RDS / Redis 的落地约定
不包含:
- 旧数据迁移
- Terraform / CloudFormation 自动建资源
- Redis TLS 改造
- 多活 / 自动扩缩容
@@ -0,0 +1,111 @@
Host: 0.0.0.0
Port: 8080
Debug: false
JwtAuth:
AccessSecret: CHANGE_ME_TO_A_LONG_RANDOM_SECRET
AccessExpire: 604800
Logger:
ServiceName: PPanel
Mode: console
Encoding: plain
TimeFormat: "2006-01-02 15:04:05.000"
Path: logs
Level: info
MaxContentLength: 0
Compress: false
Stat: true
KeepDays: 7
StackCooldownMillis: 100
MaxBackups: 7
MaxSize: 100
Rotation: daily
FileTimeFormat: "2006-01-02T15:04:05.000Z07:00"
MySQL:
Addr: YOUR_RDS_ENDPOINT:3306
Dbname: hifast
Username: admin
Password: CHANGE_ME_TO_RDS_PASSWORD
Config: charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
MaxIdleConns: 10
MaxOpenConns: 100
SlowThreshold: 1000
Redis:
Host: YOUR_REDIS_PRIMARY_ENDPOINT:6379
Pass:
DB: 0
PoolSize: 100
MinIdleConns: 10
MaxRetries: 3
PoolTimeout: 4
IdleTimeout: 300
MaxConnAge: 0
DialTimeout: 5
ReadTimeout: 3
WriteTimeout: 3
Trace:
Name: ppanel-server
Endpoint: 127.0.0.1:4317
Sampler: 0.1
Batcher: otlpgrpc
Site:
Host: api-new.hifast.biz
SiteName: HiFastVPN
Administrator:
Email: admin@example.com
Password: CHANGE_ME_TO_STRONG_ADMIN_PASSWORD
Telegram:
Enable: false
BotID: 0
BotName: ""
BotToken: ""
GroupChatID: ""
EnableNotify: false
WebHookDomain: ""
Kutt:
Enable: false
ApiURL: ""
ApiKey: ""
TargetURL: ""
Domain: ""
OpenInstall:
Enable: false
AppKey: ""
ApiKey: ""
Loki:
Enable: true
URL: "http://localhost:3100"
AppSignature:
AppSecrets:
android-client: CHANGE_ME_ANDROID_SIGNATURE_SECRET
ios-client: CHANGE_ME_IOS_SIGNATURE_SECRET
web-client: CHANGE_ME_WEB_SIGNATURE_SECRET
ValidWindowSeconds: 300
SkipPrefixes:
- /v1/notify/
- /v1/iap/notifications
- /v1/telegram/webhook
- /v1/subscribe/config
Signature:
EnableSignature: false
device:
enable: true
security_secret: CHANGE_ME_DEVICE_SECURITY_SECRET
Register:
EnableTrial: true
EnableTrialEmailWhitelist: true
TrialEmailDomainWhitelist: "gmail.com,outlook.com,icloud.com,qq.com,163.com"
@@ -0,0 +1,33 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
client_max_body_size 20m;
access_log /var/log/nginx/ppanel-access.log;
error_log /var/log/nginx/ppanel-error.log warn;
location / {
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:8080;
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location = /nginx_status {
stub_status;
access_log off;
allow 127.0.0.1;
deny all;
}
}