低成本高性能海外服务架构实践:VMISS 入口机 + Contabo 后端

一、核心问题

目标是在预算有限的情况下,搭建一套适合个人服务、sub2apiFRPGitea博客面板等应用的海外服务器架构,并满足以下要求:

  • 国内访问尽量稳定
  • 后端服务器性能足够强
  • 成本控制在较低范围
  • 支持 50-100 人左右轻中等访问
  • 服务可逐步迁移,不影响旧服务器
  • NAS 作为数据中心和备份中心

最终采用的有效方案是:

国内用户
  ↓
VMISS 洛杉矶 CN2 入口机
  ↓ WireGuard 内网
Contabo 高性能后端服务器
  ↓
NAS 数据中心 / 备份中心

二、最终推荐架构

flowchart TB
    U["国内用户 / 客户端"] --> V["VMISS LA CN2 Core<br/>入口机 / 中转机"]

    V -->|"HTTPS 443 / Caddy 反代"| C["Contabo 后端服务器<br/>Docker / 1Panel / sub2api / 数据库"]

    V -->|"WireGuard 内网<br/>10.10.0.0/24"| C

    C --> APP["业务服务<br/>sub2api / Gitea / Blog / Chat / AIGC"]
    C --> DB["PostgreSQL / Redis / MySQL"]
    C --> NAS["NAS<br/>备份 / 附件 / 仓库 / 冷数据"]

    V --> FRP["frps<br/>内网穿透入口"]

三、服务器角色分配

组件 角色 说明
VMISS 国内入口 / 中转机 跑 Caddy、WireGuard、frps、代理端口
Contabo 主业务服务器 跑 1Panel、Docker、sub2api、数据库、Redis
NAS 数据中心 存备份、附件、Gitea 大文件、冷数据
第三方代理 AI API 出口 给 OpenAI、Gemini、Anthropic 等使用

四、链路质量验证

VMISS 与 Contabo 之间测试结果:

VMISS → Contabo:约 296 Mbps
Contabo → VMISS:约 188 Mbps
延迟:约 31ms
丢包:0%

这个结果说明:

  • VMISS 与 Contabo 互联质量足够好
  • Contabo 可以作为主后端服务器
  • VMISS 的 200Mbps 端口可能成为入口瓶颈
  • 该架构适合 50-100 人左右的轻中等规模服务

五、WireGuard 内网配置

1. IP 规划

VMISS WireGuard IP:10.10.0.1
Contabo WireGuard IP:10.10.0.2
WireGuard 端口:51820/udp

2. 两台服务器安装 WireGuard

apt update
apt install -y wireguard curl wget vim ufw

3. 开启 BBR 和 IP 转发

cat >> /etc/sysctl.conf <<'EOF'
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
net.ipv4.ip_forward=1
EOF

sysctl -p

检查:

sysctl net.ipv4.tcp_congestion_control
sysctl net.core.default_qdisc

理想结果:

net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

4. 生成密钥

两台服务器都执行:

mkdir -p /etc/wireguard
cd /etc/wireguard

wg genkey | tee private.key | wg pubkey > public.key
cat private.key
cat public.key

注意:私钥不要公开。如果已经泄露,建议重新生成。

5. VMISS 配置

文件:

nano /etc/wireguard/wg0.conf

内容:

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = VMISS_PRIVATE_KEY

[Peer]
PublicKey = CONTABO_PUBLIC_KEY
AllowedIPs = 10.10.0.2/32
Endpoint = CONTABO_PUBLIC_IP:51820
PersistentKeepalive = 25

启动:

systemctl enable wg-quick@wg0
systemctl restart wg-quick@wg0
wg

6. Contabo 配置

文件:

nano /etc/wireguard/wg0.conf

内容:

[Interface]
Address = 10.10.0.2/24
ListenPort = 51820
PrivateKey = CONTABO_PRIVATE_KEY

[Peer]
PublicKey = VMISS_PUBLIC_KEY
AllowedIPs = 10.10.0.1/32
Endpoint = VMISS_PUBLIC_IP:51820
PersistentKeepalive = 25

启动:

systemctl enable wg-quick@wg0
systemctl restart wg-quick@wg0
wg

7. 测试内网连通性

VMISS 上:

ping 10.10.0.2

Contabo 上:

ping 10.10.0.1

查看握手:

wg

看到 latest handshake 即表示正常。

六、防火墙配置

VMISS 防火墙

VMISS 作为入口机,需要开放:

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 51820/udp
ufw allow 7000/tcp
ufw --force enable
ufw status numbered

如果有代理端口,例如:

ufw allow 20530/tcp
ufw allow 20530/udp
ufw allow 18600/tcp
ufw allow 18600/udp

Contabo 防火墙

Contabo 作为后端,建议只允许 VMISS 内网访问全部服务端口:

ufw allow 22/tcp
ufw allow 51820/udp
ufw allow from 10.10.0.1
ufw --force enable
ufw status numbered

这样以后 VMISS 反代 Contabo 上的任意服务时,不需要单独逐个开放端口。

七、Caddy 反向代理配置

1. 安装 Caddy

在 VMISS 上执行:

apt update
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
  | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
  | tee /etc/apt/sources.list.d/caddy-stable.list

apt update
apt install -y caddy

检查:

caddy version
systemctl status caddy

2. 编辑 Caddyfile

nano /etc/caddy/Caddyfile

示例配置:

1panel.example.com {
    encode gzip zstd
    reverse_proxy 10.10.0.2:38622
}

frp.example.com {
    encode gzip zstd
    reverse_proxy 127.0.0.1:7500
}

sub2api-test.example.com {
    encode gzip zstd

    reverse_proxy 10.10.0.2:8080 {
        transport http {
            read_timeout 600s
            write_timeout 600s
        }
    }
}

检查并重载:

caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy

查看日志:

journalctl -u caddy --no-pager -n 80

八、1Panel 部署与访问

1Panel 安装在 Contabo 上,监听端口示例:

38622

推荐访问链路:

浏览器 → https://1panel.example.com → VMISS Caddy → WireGuard → Contabo:38622

安装后应立即修改:

  • 面板密码
  • 安全入口
  • 默认用户名

由于管理面板敏感,建议不要直接暴露 Contabo 公网端口。

九、FRPS 面板部署

1. 下载 FRP

在 VMISS 上执行:

cd /opt
wget https://github.com/fatedier/frp/releases/download/v0.68.1/frp_0.68.1_linux_amd64.tar.gz
tar -zxvf frp_0.68.1_linux_amd64.tar.gz
mv frp_0.68.1_linux_amd64 frp
cd /opt/frp

2. 配置 frps

nano /opt/frp/frps.toml

内容:

bindAddr = "0.0.0.0"
bindPort = 7000

auth.method = "token"
auth.token = "REPLACE_WITH_LONG_RANDOM_TOKEN"

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "REPLACE_WITH_DASHBOARD_PASSWORD"

log.to = "/opt/frp/frps.log"
log.level = "info"
log.maxDays = 7

transport.maxPoolCount = 5

3. 创建 systemd 服务

nano /etc/systemd/system/frps.service

内容:

[Unit]
Description=frps
After=network.target

[Service]
Type=simple
ExecStart=/opt/frp/frps -c /opt/frp/frps.toml
Restart=always
RestartSec=5s
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

启动:

systemctl daemon-reload
systemctl enable frps
systemctl start frps
systemctl status frps

开放端口:

ufw allow 7000/tcp
ufw reload

FRPS 面板通过 Caddy 反代:

frp.example.com {
    encode gzip zstd
    reverse_proxy 127.0.0.1:7500
}

十、FRPC 客户端配置示例

客户端配置:

serverAddr = "frp.example.com"
serverPort = 7000

auth.method = "token"
auth.token = "REPLACE_WITH_FRPS_TOKEN"

[[proxies]]
name = "feiniu_5666"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5666
remotePort = 5666

VMISS 防火墙放行远程端口:

ufw allow 5666/tcp
ufw reload

如果需要把 FRP 映射出来的 HTTP 服务再套 HTTPS,可以使用 Caddy:

feiniu.example.com {
    reverse_proxy 127.0.0.1:5666
}

十一、Sub2API 新实例部署

1. 创建目录

在 Contabo 上:

mkdir -p /opt/sub2api-test
cd /opt/sub2api-test
mkdir -p data postgres_data redis_data

2. 创建 .env

nano .env

内容示例:

BIND_HOST=10.10.0.2
SERVER_PORT=8080
SERVER_MODE=release
RUN_MODE=standard

POSTGRES_USER=sub2api
POSTGRES_PASSWORD=REPLACE_WITH_POSTGRES_PASSWORD
POSTGRES_DB=sub2api

REDIS_PASSWORD=REPLACE_WITH_REDIS_PASSWORD
REDIS_DB=0

ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=REPLACE_WITH_ADMIN_PASSWORD

JWT_SECRET=REPLACE_WITH_64_HEX_SECRET
JWT_EXPIRE_HOUR=24
TOTP_ENCRYPTION_KEY=REPLACE_WITH_64_HEX_SECRET

TZ=Asia/Shanghai

SECURITY_URL_ALLOWLIST_ENABLED=false
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=false
SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=false
SECURITY_URL_ALLOWLIST_UPSTREAM_HOSTS=

UPDATE_PROXY_URL=http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT

生成随机密钥:

openssl rand -hex 32

3. 创建 docker-compose.yml

nano docker-compose.yml

内容:

services:
  sub2api:
    image: weishaw/sub2api:0.1.124
    container_name: sub2api-test
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 100000
        hard: 100000
    ports:
      - "${BIND_HOST:-0.0.0.0}:${SERVER_PORT:-8080}:8080"
    volumes:
      - ./data:/app/data
    environment:
      - AUTO_SETUP=true
      - SERVER_HOST=0.0.0.0
      - SERVER_PORT=8080
      - SERVER_MODE=${SERVER_MODE:-release}
      - RUN_MODE=${RUN_MODE:-standard}
      - DATABASE_HOST=postgres
      - DATABASE_PORT=5432
      - DATABASE_USER=${POSTGRES_USER:-sub2api}
      - DATABASE_PASSWORD=${POSTGRES_PASSWORD}
      - DATABASE_DBNAME=${POSTGRES_DB:-sub2api}
      - DATABASE_SSLMODE=disable
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD}
      - REDIS_DB=${REDIS_DB:-0}
      - ADMIN_EMAIL=${ADMIN_EMAIL}
      - ADMIN_PASSWORD=${ADMIN_PASSWORD}
      - JWT_SECRET=${JWT_SECRET}
      - JWT_EXPIRE_HOUR=${JWT_EXPIRE_HOUR:-24}
      - TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}
      - TZ=${TZ:-Asia/Shanghai}
      - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - sub2api-network

  postgres:
    image: postgres:18-alpine
    container_name: sub2api-test-postgres
    restart: unless-stopped
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-sub2api}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB:-sub2api}
      - PGDATA=/var/lib/postgresql/data
      - TZ=${TZ:-Asia/Shanghai}
    networks:
      - sub2api-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sub2api} -d ${POSTGRES_DB:-sub2api}"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:8-alpine
    container_name: sub2api-test-redis
    restart: unless-stopped
    volumes:
      - ./redis_data:/data
    command: >
      sh -c '
        redis-server
        --save 60 1
        --appendonly yes
        --appendfsync everysec
        ${REDIS_PASSWORD:+--requirepass "$REDIS_PASSWORD"}'
    environment:
      - TZ=${TZ:-Asia/Shanghai}
      - REDISCLI_AUTH=${REDIS_PASSWORD:-}
    networks:
      - sub2api-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  sub2api-network:
    driver: bridge

启动:

cd /opt/sub2api-test
docker compose up -d
docker compose ps
docker compose logs -f sub2api

测试:

curl -I http://10.10.0.2:8080

十二、AI 代理出口测试

代理格式:

http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT

测试端口:

nc -vz PROXY_HOST PROXY_PORT

测试出口 IP:

curl -x "http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT" https://ip.sb

测试 OpenAI API 连通性:

curl -I -x "http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT" https://api.openai.com/v1/models

如果返回:

HTTP/2 401
www-authenticate: Bearer realm="OpenAI API"

说明网络正常,只是未提供 API Key。

测试耗时:

curl -o /dev/null -s -w "connect:%{time_connect}s tls:%{time_appconnect}s total:%{time_total}s speed:%{speed_download}B/s\n" \
-x "http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT" \
https://api.openai.com

示例优秀结果:

connect:0.073s tls:0.257s total:0.336s

十三、NAS 数据中心设计

NAS 不建议作为在线数据库主库。推荐用途:

数据类型 推荐位置
在线数据库 Contabo 本地
Gitea 仓库 NAS 或本地按需
Gitea LFS NAS
附件 NAS
Packages NAS
备份 NAS
长期日志 NAS

Gitea 推荐配置:

[repository]
ROOT = /data/git/repositories

[lfs]
PATH = /data/git/lfs

[attachment]
PATH = /data/gitea/attachments

[packages]
STORAGE_TYPE = local
PATH = /data/gitea/packages

[actions]
ARTIFACTS_PATH = /data/gitea/actions_artifacts

[dump]
PATH = /data/gitea/dump

Docker 挂载示例:

volumes:
  - ./gitea-data:/data
  - /mnt/nas/gitea/repositories:/data/git/repositories
  - /mnt/nas/gitea/lfs:/data/git/lfs
  - /mnt/nas/gitea/attachments:/data/gitea/attachments
  - /mnt/nas/gitea/packages:/data/gitea/packages
  - /mnt/nas/gitea/actions:/data/gitea/actions_artifacts
  - /mnt/nas/gitea/backups:/data/gitea/dump

十四、试错过程总结

1. 单台高配日本 CN2 机器

结论:性能和线路都好的日本 CN2 高配机价格较高,月付通常明显超过低预算范围。

2. Evoxt 马来西亚

测试显示部分方向不错,但单线程下行不够理想,不适合作为唯一主入口。

3. OVH

OVH VPS-3 性价比高,但支付流程遇到风控和支付卡住问题,最终放弃。

4. Contabo 新加坡

直接国内访问不佳,但作为后端时,关键要看与 VMISS 的互联。实测 VMISS 到 Contabo 带宽和延迟优秀,因此可用。

5. VMISS 入口机

VMISS 配置较低,但线路适合作为入口。最终定位为:

Caddy + WireGuard + frps + 少量代理端口

不承担数据库和重型业务。

十五、安全建议

  1. 所有泄露过的密码、token、WireGuard 私钥、代理密码都应更换
  2. 1Panel 不建议裸露公网
  3. Contabo 后端只允许 VMISS 内网访问业务端口
  4. frps 面板只监听本机,用 Caddy 反代
  5. 数据库不要暴露公网
  6. NAS 不要直接暴露数据库端口
  7. 定期备份 PostgreSQL、Redis、Gitea、1Panel 配置
  8. sub2api 代理池至少准备 2-3 条备用出口

十六、最终结论

这套架构的核心价值是:

VMISS 负责国内入口质量
Contabo 负责高性能低成本计算
NAS 负责容量和备份
代理出口负责 AI API 可达性

最终有效架构为:

国内用户
  ↓
VMISS LA CN2 Core
  ↓ WireGuard / Caddy / FRP
Contabo 高性能后端
  ↓
NAS 数据中心
  ↓
AI 代理出口 / OpenAI / Gemini / Anthropic

该方案相比购买单台高价 CN2 高性能服务器,更适合预算有限、服务较多、需要逐步迁移和扩展的个人服务器架构。

评论