本文记录了我在 VPS 上,从零开始构建一套集流量网关、AI 大脑、自动化流水线、可视化监控、个人品牌博客及企业级备份于一体的全栈系统的完整过程。
本教程注重架构规范、安全性与长期可维护性,直接提供经过验证的生产环境配置。
推荐硬件配置
虽然本架构高度模块化,但考虑到 AI 服务(Dify)与数据库的负载,建议配置如下:
- CPU: 4 vCPU 及以上
- 内存: 建议 16GB 起步(若仅运行 n8n 和博客,4GB 即可;运行 Dify 建议 16GB+)
- 硬盘: 50GB SSD 及以上
- 系统: Ubuntu 22.04 / Debian 11+
第一章:顶层架构设计规范
在部署任何服务之前,必须制定严格的系统规范,这是长期稳定运行的基石。
1.1 文件目录规范
拒绝将数据散落在 /home 或 /root。所有 Docker 容器的配置 (docker-compose.yml) 与持久化数据 (volumes),统一存放于:/opt/docker_data/<服务名>
1.2 端口管理规范 (50000-60000)
为了安全隐蔽及避免冲突,宿主机对外暴露的管理端口严格限制在 50000 以上的高位端口段。
| 服务 | 端口 | 说明 |
|---|---|---|
| Nginx Proxy Manager | 58001 | 全站流量入口 (Ingress) |
| n8n (Pro) | 58002 | 自动化工作流引擎 |
| Dify | 58003 | LLM 应用开发平台 (AI 大脑) |
| Portainer | 58004 | 容器可视化管理 |
| Beszel | 58006 | 轻量级服务器监控 |
| Ghost | 58008 | 个人品牌博客 / CMS |
1.3 网络安全规范
- 统一网络: 创建一个名为
npm_network的 Docker 网络,所有 Web 服务加入该网络,禁止直接暴露 HTTP 端口。 - SSL 强制: 全站启用 Cloudflare Origin CA (15年源服务器证书),配合 Cloudflare SSL "Full (Strict)" 模式。
# 创建统一网络
docker network create npm_network
第二章:流量守门员 - Nginx Proxy Manager
作为唯一的 Web 流量入口,负责 SSL 卸载、反向代理与访问控制。
2.1 部署配置
创建目录:/opt/docker_data/npm
文件:docker-compose.yml
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
container_name: nginx_proxy_manager
# 加入 Watchtower 白名单,允许自动更新
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
# HTTP/HTTPS 入口 (保持标准端口)
- '80:80'
- '443:443'
# 管理面板映射到高位端口
- '58001:81'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- npm_network
networks:
npm_network:
external: true
2.2 启动与配置
docker compose up -d
- 访问:
http://IP:58001 - 安全建议: 登录后,立即在 NPM 中为管理面板自身配置反向代理(如
admin.your-domain.com),指向172.17.0.1:58001,并开启 SSL,通过域名访问管理后台。
第三章:可视化运维 - Portainer
当容器数量增多,命令行管理将变得困难。Portainer 提供图形化管理界面。
3.1 部署配置
创建目录:/opt/docker_data/portainer
文件:docker-compose.yml
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
# 加入 Watchtower 白名单
labels:
- "com.centurylinklabs.watchtower.enable=true"
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock # 核心:接管 Docker 守护进程
- ./data:/data
ports:
# HTTPS 访问入口
- 58004:9443
networks:
- npm_network
networks:
npm_network:
external: true
第四章:自动化中枢 - n8n
n8n 是强大的工作流自动化工具。生产环境建议放弃默认的 SQLite,使用 PostgreSQL 以支持高并发。
4.1 部署配置
创建目录:/opt/docker_data/n8n
文件:docker-compose.yml
version: '3.8'
services:
db:
image: postgres:16-alpine
restart: always
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=更改为你的强密码
- POSTGRES_DB=n8n
volumes:
- ./db_data:/var/lib/postgresql/data
networks:
- npm_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U n8n -d n8n"]
interval: 5s
timeout: 5s
retries: 5
n8n:
image: n8nio/n8n:latest
restart: always
container_name: n8n
# 加入 Watchtower 白名单
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
- "58002:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=db
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=更改为你的强密码
- N8N_HOST=n8n.your-domain.com
- WEBHOOK_URL=https://n8n.your-domain.com/
- GENERIC_TIMEZONE=Asia/Shanghai
volumes:
- ./n8n_data:/home/node/.n8n
networks:
- npm_network
depends_on:
db:
condition: service_healthy
networks:
npm_network:
external: true
第五章:AI 大脑 - Dify (私有化部署)
Dify 是一套复杂的微服务架构(包含 9+ 容器)。建议使用官方仓库代码进行部署,但需修改端口以符合规范。
5.1 部署步骤
- 修改配置:编辑
docker-compose.yaml:- 找到
nginx服务部分。 - 修改端口映射:将
80:80改为58003:80。 - (可选) 将所有服务加入
npm_network,或者仅让 Dify 的 nginx 暴露端口并在 NPM 中通过 IP+端口转发。
- 找到
启动:
docker compose up -d
克隆代码:
mkdir -p /opt/docker_data/dify
cd /opt/docker_data/dify
git clone https://github.com/langgenius/dify.git .
cd docker
cp .env.example .env
注意: Dify 严禁使用自动更新工具更新,升级请使用 git pull 后重启容器。
第六章:监控系统 - Beszel
相比复杂的 Netdata,Beszel 更轻量且界面美观,适合单机或小规模集群监控。
6.1 部署配置 (Hub + Agent)
创建目录:/opt/docker_data/beszel
文件:docker-compose.yml
注意: 必须先启动 Hub 获取 Public Key,再填入 Agent 配置中。
version: '3.8'
services:
# 1. 控制台 (Hub)
beszel-hub:
image: 'henrygd/beszel:latest'
container_name: beszel-hub
restart: unless-stopped
# 加入 Watchtower 白名单
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
- '58006:8090'
volumes:
- ./beszel_data:/beszel_data
networks:
- npm_network
# 2. 采集器 (Agent)
beszel-agent:
image: 'henrygd/beszel-agent:latest'
container_name: beszel-agent
restart: unless-stopped
# 关键:Agent 必须使用 host 模式才能准确读取宿主机资源
network_mode: host
# 加入 Watchtower 白名单
labels:
- "com.centurylinklabs.watchtower.enable=true"
environment:
# 使用字典格式以避免 SSH Key 格式错误
PORT: 45876
# ⚠️ 启动 Hub 后,去后台创建 System 获取 Key,并填入下方
KEY: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI......"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /:/extra/filesystem:ro
networks:
npm_network:
external: true
第七章:内容管理系统 - Ghost
部署轻量级博客平台。为了便于迁移,数据库推荐使用 SQLite3。
7.1 环境配置 (.env)
创建目录:/opt/docker_data/ghost
文件:.env
# 前端访问域名
url=https://blog.your-domain.com
NODE_ENV=production
# 数据库 (SQLite3)
database__client=sqlite3
database__connection__filename=/var/lib/ghost/content/data/ghost.db
# 宿主机映射端口
HOST_PORT=58008
# 邮件配置 (SMTP)
mail__transport=SMTP
mail__options__host=smtp.example.com
mail__options__port=465
mail__options__secure=true
mail__options__auth__user=user@example.com
mail__options__auth__pass=password
mail__from=user@example.com
7.2 部署文件
文件:docker-compose.yml
version: '3.8'
services:
ghost:
image: ghost:latest
container_name: ghost
restart: unless-stopped
# 加入 Watchtower 白名单
labels:
- "com.centurylinklabs.watchtower.enable=true"
env_file:
- .env
ports:
- "${HOST_PORT}:2368"
volumes:
- ./content:/var/lib/ghost/content
networks:
- npm_network
networks:
npm_network:
external: true
第八章:系统优化与维护
8.1 系统性能调优
# 1. 增加 4GB Swap (防止 OOM)
fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 2. 开启 TCP BBR (网络加速)
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
# 3. 限制 Docker 日志大小 (防止爆盘)
# 编辑 /etc/docker/daemon.json 添加:
# { "log-driver": "json-file", "log-opts": { "max-size": "20m", "max-file": "3" } }
8.2 镜像自动更新 (Watchtower)
采用 “白名单模式”,默认不更新任何容器,只更新带有 label-enable=true 标签的容器(如上文中的 NPM, n8n, Ghost, Beszel)。
部署 Watchtower:
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--schedule "0 0 4 * * *" \
--cleanup \
--label-enable
--label-enable: 关键参数,开启白名单模式,保护 Dify 等复杂应用不被自动升级损坏。
第九章:企业级容灾备份
采用 Rclone + Cloudflare R2 进行异地冷备。为了保证数据库的一致性,采用“闪断备份法”。
9.1 备份脚本
文件:/opt/rclone_backup.sh
#!/bin/bash
SOURCE_DIR="/opt/docker_data"
BACKUP_DIR="/opt/backup_staging"
REMOTE_PATH="remote:backup/vps_data" # 这里的 remote 需提前配置好
DATE=$(date +%Y%m%d_%H%M%S)
ARCHIVE_NAME="vps_data_$DATE.tar.gz"
LOG_FILE="/var/log/rclone_backup.log"
echo "[$(date)] 开始备份..." >> $LOG_FILE
# 1. 停止 Docker (同时停止 Socket 防止被意外唤醒)
systemctl stop docker.socket
systemctl stop docker.service
# 2. 打包数据
tar -zcf "$BACKUP_DIR/$ARCHIVE_NAME" -C /opt docker_data
# 3. 立即恢复服务 (业务中断约 1-2 分钟)
systemctl start docker.service
# 4. 上传并清理旧备份 (保留最近 25 天)
rclone copy "$BACKUP_DIR/$ARCHIVE_NAME" "$REMOTE_PATH"
rclone delete "$REMOTE_PATH" --min-age 25d
# 5. 清理本地
find "$BACKUP_DIR" -name "vps_data_*.tar.gz" -type f -mtime +1 -delete
echo "[$(date)] 备份完成。" >> $LOG_FILE
9.2 定时任务
设置每周日凌晨执行:
crontab -e
# 添加:
0 4 * * 0 /bin/bash /opt/rclone_backup.sh
结语
至此,一套基于 Gateway (NPM) + Brain (Dify) + Automation (n8n) + Monitor (Beszel) 的现代化数字基地构建完成。这套架构兼顾了高性能与易维护性,配合完善的备份策略。