家庭 Ubuntu 服务器公网访问完整部署文档

本文档记录了从零搭建“云服务器 frps + 家庭 Ubuntu frpc + 域名访问 Web 服务”的全过程,包含所有关键配置、命令和安全加固步骤。


一、整体架构

用户浏览器
    │
    ▼
域名 (x.x.com) ──► 云服务器公网 IP (x.x.x.x)
    │
    ▼
宝塔 Nginx (443/80) ──► 反向代理至 127.0.0.1:8080
    │
    ▼
云服务器 frps (Docker, 监听 7000 / vhostHTTPPort 8080)
    │
    ▼
frp 隧道 (加密)
    │
    ├──► 机器A frpc (remotePort 7001) ──► SSH 22
    │
    └──► 机器B frpc (remotePort 7002) ──► SSH 22
                                      └──► Web 服务 3011
  • 云服务器:腾讯云 / 阿里云等,2核4G,已安装宝塔面板,Docker 运行 frps。
  • 机器A:家庭 Ubuntu 24.04,内网 IP 192.168.122.20,用于 SSH。
  • 机器B:家庭 Ubuntu 24.04,内网 IP 192.168.122.245,用于 SSH + Web 服务。
  • 域名:解析到云服务器公网 IP。
  • Web 服务:FastAPI + gunicorn,监听 127.0.0.1:3011,通过 frp 暴露。

二、云服务器端部署 frps(Docker + 宝塔)

2.1 创建配置文件

在宝塔文件管理器中创建目录 /www/dk_project/dk_app/frps/frps_6pfP/data/,并新建 frps.toml:

bindPort = 7000
auth.method = "token"
auth.token = "你的强密码Token至少32位"

vhostHTTPPort = 8080          # 用于 HTTP 类型代理,绑定域名
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "你的管理后台密码"

2.2 宝塔 Docker 创建容器

  • 镜像:snowdreamtech/frps:latest
  • 容器名称:frps
  • 网络模式:host
  • 重启策略:always
  • 挂载目录:
    • 宿主机 /www/dk_project/dk_app/frps/frps_6pfP/data/frps.toml → 容器 /etc/frp/frps.toml
    • (可选)宿主机 .../data/ssl → 容器 /etc/frp/ssl

启动后检查日志:docker logs frps,应显示 frps started successfully。

2.3 防火墙放行

  • 云厂商安全组:放行 TCP 7000、7001、7002、7500、8080、80、443(按需)。

  • 系统 firewalld:

    sudo firewall-cmd --permanent --add-port=7000/tcp
    sudo firewall-cmd --permanent --add-port=7001/tcp
    sudo firewall-cmd --permanent --add-port=7002/tcp
    sudo firewall-cmd --permanent --add-port=7500/tcp
    sudo firewall-cmd --permanent --add-port=8080/tcp
    sudo firewall-cmd --reload
  • 宝塔面板安全:同样放行上述端口。


三、家庭 Ubuntu 安装 frpc 客户端

3.1 安装 frpc(两台机器均执行)

# 添加 GPG 密钥和软件源
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://go-frp.awfufu.com/public.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/go-frp.gpg
echo "deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/go-frp.gpg] https://go-frp.awfufu.com stable main" | sudo tee /etc/apt/sources.list.d/go-frp.list

# 安装
sudo apt update
sudo apt install frpc -y

3.2 配置 frpc.toml

机器A (/etc/frpc/frpc.toml):

serverAddr = "x.x.x.x" #云服务器公网IP
serverPort = 7000
auth.method = "token"
auth.token = "与 frps.toml 完全一致的 Token"

[[proxies]]
name = "ssh-machine-a"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 7001

机器B (/etc/frpc/frpc.toml):

serverAddr = "x.x.x.x" #云服务器公网IP
serverPort = 7000
auth.method = "token"
auth.token = "与 frps.toml 完全一致的 Token"

# SSH 代理
[[proxies]]
name = "ssh-machine-b"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 7002

# Web 代理(绑定域名)
[[proxies]]
name = "web-shuake"
type = "http"
localIP = "127.0.0.1"
localPort = 3011
customDomains = ["x.x.com"]

启动并开机自启:

sudo systemctl enable --now frpc
sudo systemctl status frpc

四、SSH 密钥登录与安全加固

4.1 在 Windows 本地生成密钥

ssh-keygen -t ed25519
# 默认保存至 C:\Users\Administrator\.ssh\id_ed25519

4.2 上传公钥到两台 Ubuntu

type ~/.ssh/id_ed25519.pub | ssh -p 7001 siri@x.x.x.x "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

type ~/.ssh/id_ed25519.pub | ssh -p 7002 siri@x.x.x.x "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

4.3 禁用密码登录

在两台 Ubuntu 上编辑 /etc/ssh/sshd_config:

PasswordAuthentication no
PubkeyAuthentication yes

重启 SSH:sudo systemctl restart ssh

4.4 安装 fail2ban

sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban

4.5 修改 frp Token(安全建议)

  • 修改云服务器 frps.toml 中的 auth.token 为新强密码。
  • 修改两台 Ubuntu frpc.toml 中的 auth.token 为相同值。
  • 重启 frps 容器和两台 frpc 服务。

五、机器B部署 FastAPI Web 项目

5.1 上传代码

  • 通过 WinSCP 或 scp 将 F:\web 下的源码上传至 /home/siri/webhook/。

  • 目录结构:

    /home/siri/webhook/
    ├── server.py
    ├── requirements.txt
    ├── config.json
    ├── .env
    ├── web/
    ├── core/
    └── static/

5.2 安装依赖

cd /home/siri/webhook
python3 -m venv venv
venv/bin/pip install --upgrade pip
venv/bin/pip install -r requirements.txt gunicorn

5.3 配置环境变量 .env

tee /home/siri/webhook/.env >/dev/null <<'EOF'
FOUNDER_USERNAME=xxxxxxxx
FOUNDER_PASSWORD=你的强密码
EOF
chmod 600 /home/siri/webhook/.env

5.4 创建 systemd 服务

/etc/systemd/system/shuake-web.service:

[Unit]
Description=shuake web console (FastAPI :3011)
After=network.target

[Service]
Type=exec
User=siri
Group=siri
WorkingDirectory=/home/siri/webhook
Environment=PYTHONUNBUFFERED=1
ExecStart=/home/siri/webhook/venv/bin/gunicorn \
    --chdir /home/siri/webhook \
    --workers 1 \
    --threads 2 \
    --worker-class uvicorn.workers.UvicornWorker \
    --bind 0.0.0.0:3011 \
    --access-logfile - \
    --error-logfile - \
    server:app
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

启动服务:

sudo systemctl daemon-reload
sudo systemctl enable --now shuake-web
sudo systemctl status shuake-web

验证本地访问:

curl -sS http://127.0.0.1:3011/login | head -5

六、Nginx 反向代理(宝塔面板)

6.1 创建站点并申请 SSL

  • 在宝塔面板创建站点 x.x.com,申请 Let's Encrypt 证书并开启强制 HTTPS。

6.2 配置反向代理

在站点设置 → 反向代理,添加:

  • 目标 URL:http://127.0.0.1:8080
  • 发送域名:$host

6.3 修改 Nginx 配置文件(关键:SSE 支持)

将 location ^~ / { ... } 块修改为:

location ^~ / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Real-Port $remote_port;
    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_set_header REMOTE-HOST $remote_addr;

    proxy_buffering off;          # 关闭缓冲,SSE 必需
    proxy_cache off;              # 关闭缓存
    proxy_connect_timeout 60s;
    proxy_send_timeout 3600s;
    proxy_read_timeout 3600s;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

保存后重载 Nginx:nginx -t && nginx -s reload


七、验证与日常使用

7.1 公网 SSH 访问

ssh -p 7001 用户名@x.x.x.x    # 机器A
ssh -p 7002 用户名@x.x.x.x    # 机器B

7.2 公网 Web 访问

浏览器打开:https://x.x.com,使用 .env 中设置的 founder 账号登录。

7.3 frp 管理后台

http://x.x.x.x:7500,查看代理在线状态。


八、常见问题与注意事项

问题 原因 / 解决
frps 返回 404 The server is powered by frp frpc 未配置 type = "http" 或 customDomains 不匹配;检查 frpc 配置并重启
SSE 实时日志卡住不刷新 Nginx 未设置 proxy_buffering off; 和 proxy_cache off;
proxy_read_timeout 指令重复 宝塔默认已生成,删除重复行,只保留一行 3600s
location directive is not allowed here 大括号不匹配或 location 嵌套错误,检查 {} 配对
frpc 连接失败 auth.token 不一致;检查云服务器安全组和防火墙
Web 服务启动失败 查看 journalctl -u shuake-web -n 50,常见为路径、依赖、权限问题
数据库备份 使用 sqlite3 .backup,禁止直接复制 WAL 模式数据库文件

九、最终状态

  • ✅ 云服务器 frps 稳定运行(Docker + host 网络)
  • ✅ 两台 Ubuntu frpc 开机自启,SSH 端口 7001/7002 免密登录
  • ✅ SSH 密码登录已禁用,fail2ban 已启用
  • ✅ 机器B Web 服务通过 systemd 守护,监听 3011
  • ✅ 域名 x.x.com 通过 Nginx 反代 + HTTPS 访问
  • ✅ frp 管理后台可监控所有代理状态

整个链条已完全打通,可长期稳定运行。