用自己的小主机和Cloudflare搭建自己的私人云服务 摘要本文以 PassXYZ、Finanalyzer 和 Vibe-Trading 三个真实开源项目为例完整演示如何利用 Cloudflare Tunnel Cloudflare Access在无公网 IP、不开放任何端口的前提下将跑在 Mac mini 或树莓派上的多个私有服务安全地部署为带零信任认证的私有云。文章涵盖 Nginx 路径路由配置、Cloudflare Tunnel 创建与路由规则、Cloudflare Access 零信任应用配置人类访问走邮箱/PIN、机器调用走 Service Token以及完整的测试验证步骤。通过这套方案你只需一台常开电脑 一个域名 免费 Cloudflare 账号即可拥有一个安全、免费、无需暴露源站 IP 的个人云服务。前言为什么会需要这套方案如果你也维护过自己的个人云服务——密码库、仪表盘、交易机器人、笔记系统——大概都卡在同样几个问题上家里宽带没有公网 IP或者运营商封了 80/443 端口在路由器上做端口转发等于把源站 IP 直接暴露给全世界担心被扫描、被攻击HTTPS 证书麻烦续期更麻烦多个应用各有各的端口对外一长串:8081、:8899既不优雅也不安全。我的开源项目 PassXYZ / Finanalyzer 和港大的开源项目 Vibe-Trading 正好就是这样一组服务一个 .NET 后端、两个前端、还有一个交易 Agent。最终我选了 Cloudflare 全家桶原因很简单免费、不用动路由器、源站 IP 完全隐藏、还能在边缘做身份认证。这篇文章把整套流程拆成 7 步你照抄即可。一、你需要准备的三样东西准备项说明一台常开的电脑Mac mini、树莓派Raspberry Pi 4/5ARM64、或者任意一台 7×24 开机的 Linux 小主机都可以一个域名在任意注册商处购买如yourdomain.com并把 DNS 解析托管到 Cloudflare一个 Cloudflare 账号免费版Free plan就够用零成本把域名的 Nameserver 改成 Cloudflare 提供的地址后这个域名下的所有解析就由 Cloudflare 接管了。后面我们既不在这里做 A 记录指向家庭 IP也不开放任何端口——这正是关键。二、我们要部署的 5 个服务下面是本文要上线的服务清单。所有请求都先经过 Cloudflare Tunnel 到达本机的Nginx端口 80再由 Nginx 根据路径把流量分发到各个后端服务。这种架构让 Cloudflare Tunnel 的配置变得极为简洁——只需一条指向 Nginx 的映射规则。外部路径Nginx 转发目标应用内部端口作用/api/*proxy_pass→ localhost:5182PassXYZ.Server5182统一后端 API密码库 金融数据/vault/*静态文件/usr/share/nginx/html/vaultpassxyz-web—兼容 KeePass 的网页密码管理器/app/*静态文件/usr/share/nginx/html/appfinanalyzer-app—基于 OpenBB Workspace 的金融分析工作台/根路径proxy_pass→ localhost:8899Vibe-Trading8899金融交易 / Agent 服务网站入口agent.yourdomain.comproxy_pass→ localhost:8899Vibe-Trading8899同一服务的 API 出口供其它应用调用PassXYZ.Server — 后端 API这是整个系统的核心后端基于 ASP.NET Core 10 构建监听 5182 端口。它承担三类职责密码库管理兼容 KeePass 的加密数据库读写、用户认证JWT 签发与校验、以及 Dashboard 和 Portfolio 的数据存储。数据层用 SQLite按用户隔离——每个用户的密码库文件和仪表盘数据库都独立存储在data/目录下用户名经过 Base58 编码后作为文件名避免特殊字符在不同操作系统上的兼容问题。认证体系是三层的Cloudflare Access 负责身份验证确认你是谁本地 JWT 负责会话管理保持登录状态主密码负责数据解密打开 KeePass 数据库。这意味着即使 JWT 被窃取没有主密码也无法解密密码库中的数据。passxyz-web — 密码管理前端React 18 SPA应用构建后的静态文件部署到 Nginx 的/vault路径下。它是 KeePass 密码库的 Web 前端支持条目的增删改查、自定义字段、Markdown 笔记、附件管理以及实时 TOTP 验证码生成。登录成功后JWT 会写入localStorage的passxyz-token键同域下的其他应用可以直接读取这个 token 来发送认证请求。finanalyzer-app — 金融分析仪表盘基于 OpenBB Workspace 架构的金融分析平台构建后的静态文件部署到 Nginx 的/app路径下。它采用核心应用 后端注册 Widget的架构核心只提供运行环境所有业务功能投资组合管理、交易记录都通过后端注册的 Widget 组件实现。由于和 passxyz-web 共用同一个域名它能自动读取localStorage中的passxyz-token无需用户二次登录。Vibe-Trading — AI 交易助手运行在 8899 端口的 AI 金融分析回测和交易服务。它通过根路径yourdomain提供 Web 界面同时通过agent.yourdomain子域名暴露 API 接口。这个子域名配置了独立的 client id 和 secret允许 OpenBB Workspace 等外部应用通过 OAuth 方式接入复用 Vibe-Trading 的 AI 分析能力。这种设计把面向用户的 Web 界面和面向程序的 API 接口分到了不同的域名上便于分别控制访问策略。三、安装 Nginx 和 Cloudflare Tunnel安装 NginxNginx 是本机的统一入口负责路径路由和静态文件托管。它把所有请求收口到一个端口再分发到各个后端服务。在 Mac 上安装brewinstallnginx# 配置文件位于 /opt/homebrew/etc/nginx/nginx.confApple Silicon或 /usr/local/etc/nginx/nginx.confIntel在树莓派 / Linux 上安装sudoaptinstallnginx# 配置文件位于 /etc/nginx/nginx.conf安装 cloudflaredCloudflared 是跑在你那台电脑上的代理它的唯一职责是主动向外连接 Cloudflare建立一条加密隧道。因为连接是由内向外发起的所以你不需要在防火墙上开任何入站端口。在 Mac 上安装brewinstallcloudflared在树莓派 / LinuxARM64上安装# 下载官方二进制wget-Ocloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64sudoinstall-m755cloudflared /usr/local/bin/cloudflared四、配置 Nginx用路径路由而不是用端口这是整套方案里最巧妙的一步。我们把不同的服务映射到同一个域名的不同的路径全部由 Nginx 统一分发。好处有两个对外只有一个域名、标准 443 端口浏览器和调用方都觉得很干净所有服务同源same-origin。前端调/api、调/app都是相对路径浏览器不会触发跨域CORS限制——你再也不用手忙脚乱地配Access-Control-Allow-Origin了。以下是一份完整的 Nginx 配置示例nginx.conf中的 server 块server { listen 80; server_name yourdomain.com; # API 请求 → 转发到 PassXYZ.Server 后端 location /api/ { proxy_pass http://127.0.0.1:5182/; 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; # 支持 WebSocket用于 SSE 和实时推送 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 300s; } # 网页密码管理器静态文件 SPA location /vault/ { alias /usr/share/nginx/html/vault/; try_files $uri $uri/ /vault/index.html; # 静态资源长期缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|woff|ttf|eot)$ { expires 1y; add_header Cache-Control public, immutable; } } # 金融分析工作台静态文件 SPA location /app/ { alias /usr/share/nginx/html/app/; try_files $uri $uri/ /app/index.html; # 静态资源长期缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|woff|ttf|eot)$ { expires 1y; add_header Cache-Control public, immutable; } } # 根路径 → Vibe-Trading 网站 location / { proxy_pass http://127.0.0.1:8899; 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_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }说明passxyz-web与finanalyzer-app的构建产物分别放到/usr/share/nginx/html/vault/和/usr/share/nginx/html/app/目录下Nginx 直接用alias指令做静态文件托管。每个 SPA 的try_files回退到各自路径下的index.html保证前端路由正常工作。proxy_pass末尾的/会自动剥离 location 前缀例如/api/users转发到后端变成/users无需额外 rewrite。关于agent.yourdomain.com的处理agent.yourdomain.com是给机器用的 API 出口——我们稍后会为它单独签发一组 Cloudflare AccessService TokenClient ID Client Secret让 OpenBB Workspace 这类外部应用能带着这两个值来调用而不走人类登录流程。一套服务两种入口互不干扰。测试 Nginx 配置并启动# 检查配置语法nginx-t# 重新加载配置无需停机nginx-sreload本地的curl http://localhost/vault/、curl http://localhost/app/能正常返回就说明 Nginx 路由没问题。五、创建 Cloudflare Tunnel 并配置路由在 Cloudflare Dashboard 创建 Tunnel现在我们通过 Cloudflare 控制台来创建和配置 Tunnel无需编辑任何本地的config.yml文件。登录 Cloudflare Zero Trust 控制台进入Networks → Tunnels → Create a tunnel给 Tunnel 起个名字如home-server选择Cloudflared类型点击Save tunnel添加公网路由规则创建 Tunnel 后在Public Hostname标签页中添加路由规则。由于 Nginx 已经做了路径分发Tunnel 只需要把域名流量转发到 Nginx 即可公网主机名Hostname路径PathServiceyourdomain.com留空所有路径http://localhost:80agent.yourdomain.com留空所有路径http://localhost:8899就这么简单——只有两条规则。所有的路径分发工作都交给了 NginxCloudflare Tunnel 只负责把外面的流量安全地送进来。为什么agent.yourdomain.com不经过 Nginx 而是直接指向 8899因为这个子域名专门给机器调用使用不需要 Nginx 的路径路由功能直连更简洁。如果你希望它也经过 Nginx可以改为http://localhost:80然后在 Nginx 中为agent.yourdomain.com配置独立的 server 块。在本机安装并启动 cloudflared回到 Cloudflare Dashboard 的 Tunnel 详情页会看到安装 cloudflared 的命令。在 Mac 上执行brewinstallcloudflaredsudocloudflaredserviceinstallyour-tokenyour-token是 Dashboard 上显示的一串 Base64 编码的认证令牌cloudflared 会用它自动完成 Tunnel 的关联和认证——不需要手动创建隧道、不需要编辑 config.yml、不需要处理证书文件。在 Linux 上安装并启动# 先安装 cloudflared 二进制sudocloudflaredserviceinstallyour-token安装完成后cloudflared 会作为系统服务自动运行。可以在 Tunnel 详情页的Health标签页看到连接状态变为HEALTHY说明隧道已经通了。六、创建 Cloudflare Access 应用给所有服务加一道门Tunnel 解决了能连进来但还没解决谁能进来。如果到此为止任何知道你域名的人都能摸到后端。所以我们要在 Cloudflare 边缘加一层零信任身份认证Cloudflare Access未通过认证的人流量根本到不了你的电脑。进入Cloudflare Zero Trust 控制台 → Access → Applications → Add an application → Self-hosted创建两个应用应用 A保护人类访问的主域名Application hostyourdomain.comPath留空保护该域名下所有路径或按需填写/vault、/app、/apiPolicies → Add a policyActionAllowRule个人使用最方便的是One-time PIN邮箱收一次性验证码也可以选 Emails / Email domain只允许你自己的邮箱通过保存后访问https://yourdomain.com/vault/会先跳到 Cloudflare 登录页验证通过才放行。应用 B保护机器调用的 agent 子域名Application hostagent.yourdomain.com这里不要用邮箱/ PIN 策略而是切到Service Tokens标签页点击Generate service token生成一对CF-Access-Client-IdCF-Access-Client-Secret再到 Policies 里加一条规则Allow → Service Token → 选择刚生成的 token。这样只有携带正确CF-Access-Client-Id/CF-Access-Client-Secret的请求才能访问agent.yourdomain.com。在 OpenBB Workspace 或 Finanalyzer 的连接配置里填入这两个值对应CF-Access-Client-Id/CF-Access-Client-Secret请求头即可完成对接。后端如何信任 Cloudflare 的身份以 PassXYZ.Server 为例它在CloudflareAccessMiddleware中读取 Cloudflare 注入的请求头Cf-Access-Identity-Email把邮箱写入上下文随后JwtAuthenticationMiddleware在校验该身份后签发应用自身的本地 JWT。也就是说认证分两层Cloudflare Access 回答你是谁本地 JWT 回答本次会话是否合法。开发环境下可通过appsettings.Development.json的Cloudflare:AccessEnabled:false临时关闭方便本地调试。七、测试你的服务隧道和 Access 都就位后逐项验证。1Nginx 本地路由先确认本机没问题# 密码管理前端curl-Ihttp://localhost/vault/# 金融分析工作台curl-Ihttp://localhost/app/# 后端 APIcurl-Ihttp://localhost/api/# Vibe-Tradingcurl-Ihttp://localhost/本机全部正常返回后再测试 Cloudflare Tunnel 链路。2隧道连通性命令行# 根域名应返回 Vibe-Tradingcurl-Ihttps://yourdomain.com# 后端 API未带 Access 凭证会被拦在 401curl-Ihttps://yourdomain.com/api3浏览器访问打开https://yourdomain.com/vault/应当先看到 Cloudflare 的一次性验证码 / 邮箱登录页登录成功后进入 PassXYZ 密码库登录界面。切换到https://yourdomain.com/app/应能打开 Finanalyzer 分析工作台——由于同源它调用/api时浏览器不会报 CORS 错误。4机器调用 agent 子域名curlhttps://agent.yourdomain.com/some-api\-HCF-Access-Client-Id: 你的 Client ID\-HCF-Access-Client-Secret: 你的 Client Secret返回正常 JSON 即说明 Service Token 鉴权链路打通。5一个极易踩的坑清缓存前端是静态文件部署后如果浏览器或 Cloudflare CDN 还缓存着旧的 404你会以为是配置错了。每次更新发布后务必到 Cloudflare 控制台 → Caching → 点一次 “Purge Everything”或按https://yourdomain.com/vault/*、/app/*前缀精确清理再nginx -s reload。八、小结与收获回顾一下我们用三样东西一台常开电脑 一个域名 一个免费 Cloudflare 账号达成了零公网 IP、零开放端口源站 IP 对互联网不可见家庭宽带也能安心托管Nginx 统一路由 Cloudflare Tunnel 极简配置Tunnel 只需两条规则所有路径分发交给 Nginx配置清晰、维护简单统一域名 路径路由对外只有一个yourdomain.com彻底告别 CORS 烦恼边缘零信任认证人类访问走邮箱/PIN机器访问走 Service Token两层防护让私有服务不再裸奔一份服务两种出口Vibe-Trading同时作为网站与 API 出口轻松对接 OpenBB Workspace 等外部生态免费Cloudflare Free 计划覆盖 Tunnel Access个人项目零成本。整体架构一览互联网请求 │ ▼ Cloudflare CDNHTTPS 443 │ ├── Cloudflare Access零信任认证 │ ▼ Cloudflare Tunnel加密隧道无需开放端口 │ ▼ Nginxlocalhost:80路径路由 │ ├── /api/* → PassXYZ.Serverlocalhost:5182 ├── /vault/* → passxyz-web静态文件 ├── /app/* → finanalyzer-app静态文件 └── /* → Vibe-Tradinglocalhost:8899 agent.yourdomain.com子域名直连 │ ▼ Vibe-Tradinglocalhost:8899Service Token 鉴权如果你也维护着一堆私有云服务不妨照这套流程把家里的 Mac mini 或树莓派升级成一个属于你自己的安全云。PassXYZ 与 Finanalyzer 的全部源码已在 GitHub 开源文中的 Nginx 路由配置、Cloudflare Dashboard 操作步骤、Access 中间件实现都能在仓库文档里找到对应参考。欢迎在评论区交流你的部署方案或告诉我你最想上云的服务是什么。