先抛个问题:你手头有没有一台“吃灰”的树莓派或者旧笔记本?大概率有。买的时候想着搭个 NAS、跑点自动化脚本,结果配置好之后,它只在你家的局域网里待着。一旦人在外面,想连回家里那台设备,就得折腾公网 IP、端口转发、动态 DNS,要么就是隔三差五因为运营商大内网而直接放弃。我玩 homelab 这几年,试过一堆远程访问方案,最后把目光放在了 cloudflare-os 这个项目上。简单说,它就是一套把 Cloudflare 的边缘网络能力和 Linux 系统本身揉在一起的镜像。你把它烧到设备上,它会自己建立一条加密通道连到 Cloudflare 的全球网络,然后你就能用自己域名去访问家里或办公室的任何服务,而且完全不依赖公网 IP,也不需要在路由器上开任何入站端口。
这个项目对树莓派玩家、自建服务重度用户、以及所有想“把服务锁在 Cloudflare 后面”的人来说,几乎就是一套开箱即用的基础设施。我今天不打算照着官方文档念一遍,而是把这套系统从设计思路、技术组件到部署运维的完整过程拆开来聊,包括那些文档里不会明说的坑。
1. 项目概述与核心思路
1.1 这到底是个什么东西
cloudflare-os 不是一个“新的操作系统内核”,它是一个基于成熟 Linux 生态深度定制的系统镜像。你可以理解成:官方把一套完整的 Cloudflare 接入栈提前编译好、配置好、集成进了一个可启动的 Linux 发行版里。烧录之后,你获得的不是一个“需要从头配置的裸系统”,而是一个“开机就能连上 Cloudflare 网络的边缘网关”。
它跟普通发行版最大的区别在于用户态组件的预集成。常见的 Ubuntu Server 或 Debian 镜像装完只是个空壳,cloudflared、Zero Trust 接入逻辑、自更新机制这些都得自己装。而 cloudflare-os 把这一坨全部预置好,并且用 systemd 管起来,系统一启动就会自动拉取策略、建立通道。同时它的基础层也考虑了很多边缘设备场景,比如对写入寿命做了优化、无盘也能跑、支持 ARM 和 x86 两种架构,目的就是让用户不用管底层折腾,直接跑服务。
我自己的体会是,它本质上是在“把 Cloudflare 的整套边缘服务能力下沉到你自己的硬件”。原本 Cloudflare 提供的是云端的 CDN、DNS、防火墙,你只是它的一个普通用户;而用了这套系统之后,你自己的设备就成了 Cloudflare 网络的一部分。所有入站流量先经过 Cloudflare 的全球边缘节点做过滤和身份校验,再通过加密通道转发到你这台设备上。
1.2 为什么值得专门为它折腾一台设备
很多人会问:我在 Linux 上直接装个 cloudflared 不就行了?为什么非要刷一个完整的镜像?这个问题问到点子上了。答案是:是,纯手动安装确实可以,但 cloudflare-os 解决的是“可持续运维”的问题,而不只是“把隧道跑起来”的问题。
自己做的话,你要管理的东西很多:cloudflared 的版本更新、开机自启、崩溃重启、日志轮转、系统安全补丁。每一个环节都能跑,但每一个环节都在消耗你的时间。尤其隧道这类长连接服务,最忌讳的就是进程挂了没人管、版本更新之后配置格式不兼容。cloudflare-os 把这些都固化成系统的默认行为,至少对我的使用场景来说,“烧录即服务”这件事的价值比那点定制自由度大得多。
而且有个很现实的好处:它不需要你拥有公网 IP,也不需要高性能硬件。因为所有连接都是由设备主动向外发起的,走的出站连接。这个设计上的“反直觉”,恰恰是它最大的优势。很多人在内网部署服务时第一个想到的就是端口转发,但在运营商大内网、公司防火墙这些环境里根本行不通。而 cloudflare-os 换了个思路——本地服务不出网,远端用户也不直连你,两边都只跟 Cloudflare 的边缘节点通,那所有中间的 NAT、防火墙、公网 IP 都不再是阻碍了。
2. 关键组件与技术逻辑拆解
2.1 cloudflared:整个系统的枢纽
cloudflare-os 里最核心的组件就是cloudflared,这个守护进程负责建立和维护设备到 Cloudflare 边缘网络的加密隧道。很多人分不清“隧道”和“代理”的概念,我打个比方:代理像是你请了一个中间人帮你跑腿,它替你访问目标然后拿回来结果;而隧道更像是你和目标之间挖了一条私有的地下通道,你从这头钻进去,从那头钻出来,通道本身就保证了安全和可达性。
cloudflared 建立的就是那种“私有通道”的直觉——只不过它是逻辑上的,不是物理上的。它在你的设备上开启一个或多个本地端口监听,把收到的 HTTP/HTTPS 请求封装成协议帧,通过出站连接发送到 Cloudflare 边缘节点,再由边缘节点转发到访问者的浏览器。访问者根本不知道你到底是在家里、办公室还是某个云厂商的数据中心里跑的,用户看到的就是 Cloudflare 的域名。
这其中的关键是出站连接这个概念。普通自建服务要有公网才能被访问,但 cloudflare-os 上运行的 cloudflared 始终是在“呼出”,它在启动时主动找到最近的 Cloudflare 边缘节点并保持长连接。所以哪怕你的设备在一个极其严格的网络环境里,只要它能访问常规外网端口(比如 HTTPS 的 443),隧道就能建立,而且非常稳定。我把这套系统放到过好几个网络环境完全不同的地方,列个表给你感受下差别:
| 环境 | 传统端口转发方案 | cloudflare-os |
|---|---|---|
| 有公网 IP 的家庭宽带 | 可以做,但要配置路由器,麻烦 | 完全不需要配置,开箱即用 |
| 运营商大内网(无公网 IP) | 基本不可行,只有 P2P 等杂技方案 | 出站即可,完美避开限制 |
| 公司或机构网络(出站受限) | 想都别想,入站流量会被拦 | 只要 443 出站可用,大概率能通 |
| 手机热点 / 移动网络 | 极其不稳定,需要公网 IP | 设备主动发起连接,反而很稳 |
2.2 Zero Trust 接入与访问策略逻辑
cloudflare-os 跟单纯跑一条隧道最大的不同,是它在系统层面集成了 Zero Trust 这套东西。所谓的 Zero Trust,核心思想就是:默认不信任任何流量,无论你从哪个网络进来、带着什么样的来源 IP,都要先通过身份验证才能碰到后面的服务。
传统做法是把服务暴露出去,用“网络边界”保护——比如防火墙只允许公司 IP 访问;而 Zero Trust 是反过来的,即使流量已经通过加密隧道到达你的设备,在真正转发到本地服务之前,Cloudflare 还会做一层应用层校验。这层校验可以是登录邮箱的域名、一次性验证码、硬件密钥,也可以是管理员配置的各类访问策略。只有校验通过的会话才会被放行到cloudflared后面那个实际服务。
这个设计对 homelab 来说极其受用。你不需要为家里每一个服务单独做认证授权,不用在 Nginx 里配 basic auth,不用给每个应用接一个 SSO。在 Cloudflare 控制台里设置好一个策略,比如“只允许我这个邮箱登录”,所有走这条隧道的访问都会先经过这层过滤才能抵达服务端。我在本地跑了几个没有自带用户体系的服务,比如某些监控面板、某些内部分享工具,全都是靠这一层挡在前面的。
2.3 基于 Linux 的定制与裁剪思路
cloudflare-os 底层基于 Linux,但它不是把整个 Ubuntu 塞给你的那种风格。它更偏向“够用就好”的裁剪思路:内核仍然是标准内核,但用户态组件做了大量取舍。你不会有桌面环境、不会有图形界面、也不会有浏览器。系统里绝大部分空间留给了服务运行时、网络工具和 cloudflared 自己的依赖。
这样做的好处非常现实。第一是稳定,组件少意味着攻击面少、出问题的可能性低,系统可以长时间不重启地跑下去;第二是资源占用低,我实测在 1GB 内存的树莓派 4B 上运行,cloudflared 本身加上系统基础服务,空闲内存还能剩一半以上,跑两三个轻量容器完全没问题;第三是更新负担小,它不像通用发行版那样每隔几个月就要做一次大版本系统升级,它的更新粒度更贴近“少而勤”的节奏,保持核心补丁一直是最新的。
不过也正因为它裁剪得多,你不能拿它当一个全能型服务器系统用。它的定位就是边缘接入点。如果你要跑数据库集群、编译大项目、跑重型容器编排,那还是用正经的通用发行版吧。cloudflare-os 最适合的场景,是作为一个“前置网关”挡在其它服务器前面,承担隧道、认证、流量入口这些事情。
3. 部署实操和配置细节
3.1 硬件选型与镜像烧录
在动手之前先确认你手上的硬件。cloudflare-os 官方主要提供两个架构的镜像:amd64 和 arm64。前者基本通吃所有 x86 机器,包括旧笔记本、迷你主机、虚拟机;后者则覆盖了树莓派 4B、树莓派 5、RK3588 开发板这类 ARM 设备。如果你手上的是好几年前的树莓派 3B 或 3B+,也可以跑,但性能会比较紧,毕竟还要分资源给服务本身。
镜像的获取渠道是官方 GitHub Releases 页面,文件名一般会标清楚架构和版本号。下载之后,这一步和烧录树莓派系统是完全一样的:Windows 下我推荐用 balenaEtcher,直接选镜像、选 SD 卡或 U 盘,点上烧录就行;Linux 或 macOS 下我更习惯直接用dd,命令也顺手:
sudo dd if=cloudflare-os-arm64.img of=/dev/sdX bs=4M status=progress conv=fsync这里有个个人建议:不要用质量太差的 SD 卡。cloudflare-os 虽然考虑过写入寿命的问题,但毕竟它要跑常驻进程,有一堆日志要写。我用过一块杂牌卡,跑了不到两个星期就出现文件系统错误,换成正规品牌的工业级卡之后,半年多没出过问题。存储介质是在这种常驻设备上最值得花钱的部件。
3.2 系统初始化与连接
镜像烧录完,把设备接上电源和网线,系统会自动完成首次引导。cloudflare-os 没有交互式安装器,也没有配置向导,它的设计哲学是“让你的设备自己进网”。启动后会通过 DHCP 自动获取 IP,所以你在路由器后台就能看到新设备上线。至于 SSH 登录,默认的访问方式我建议直接参考官方引导流程里会给的那套初始化步骤,因为不同版本的初始做法可能略有差异——有的版本默认开启 SSH,有的版本需要先通过串口或接显示器做一次一次性配对。
我第一次启用这套系统时也在这卡了一会儿,后来把完整流程跑通了,给你捋一下共性逻辑:核心就是让设备拥有一个“身份”,也就是跟你的 Cloudflare 账户完成绑定。绑定需要提供一个一次性 token,这种 token 在 Cloudflare Zero Trust 控制台里创建隧道时就能拿到。一旦设备带上这个 token 启动,它就知道自己要接入哪个账户、归属哪个区域,然后所有后续配置都可以远程在控制台上完成,不再需要登录到设备上做任何事。
这一步之后,你再也不用关心它是否能被局域网访问到。设备会自行维持跟 Cloudflare 的加密通道,控制台状态页里能看到通道的链路状态和延迟数据。我当时拿着手机看了一眼控制台看到HEALTHY状态的那一刻,才意识到这东西是真的“开机即接入”,完全不需要我在物理现场做任何额外操作。
3.3 创建隧道与 ingress 规则详解
接下来是让隧道真正能“接客”。登录 Cloudflare Zero Trust 控制台,在 Tunnels 菜单里创建一条隧道。创建时可以选择模式,cloudflare-os 对应的是 “Cloudflared” 模式(其实就是把 token 交给设备)。创建成功后会得到一个隧道 ID 和一串 token,把这串 token 配置到你的设备上,方式不唯一,但最省事的路径是在设备上用一条命令写入配置然后重启 cloudflared 服务:
sudo cloudflared service install <TOKEN> systemctl restart cloudflared隧道建好之后,真正决定流量怎么走的是 ingress 规则。这块非常关键,它本质上是一个路由表,告诉 Cloudflare 边缘节点:某个主机名进来之后,应该转发到你设备上的哪个本地端口。在设备的 cloudflared 配置里,一段典型的 ingress 配置长这样:
tunnel: 8f1b2c…-xxxx-xxxx-xxxx-xxxxxxxx credentials-file: /etc/cloudflared/creds.json ingress: - hostname: grafana.example.com service: http://localhost:3000 - hostname: nas.example.com service: http://localhost:5000 - hostname: ssh.example.com service: ssh://localhost:22 - service: http_status:404规则是一层层从上往下匹配的,命中即停。最后一行的http_status:404是兜底规则,意思是什么都没匹配上的请求就返回 404,这个非常重要。如果你不写兜底规则,配置校验会直接报错,而且从安全角度讲也不该让未匹配的流量有路可走。我自己的习惯是永远把兜底规则放在最后,并且把新服务的规则放在前面,这个顺序在之后加服务时极其自然。
3.4 域名解析与访问验证
隧道配置好、ingress 规则也写好后,最后一步就是让全世界都能用自己的域名访问到你。这里有一个很多人没转过弯来的点:你不需要自己去配 DNS 解析记录——Cloudflare 自动给你生成一条指向隧道的内网 DNS 记录。
前提是你的域名在 Cloudflare 上面进行托管,也就是它的 NS 服务器指向 Cloudflare。在这个前提下,你为隧道添加一个公网主机名时,Cloudflare 会自动把它解析到隧道入口,这一整个过程都不涉及你的路由器、你的公网 IP。你在后台填一个子域名,比如cloud.example.com,系统自动建好关联,整个链路瞬间就能通。
验证方式上,我强烈建议分两步走。第一步是在本机试,直接访问那个域名,看能不能正确跳转到你的服务;第二步是关掉 Wi-Fi,用手机流量访问同一个域名,验证整个链路真的绕开了本地网络。我第一次按这个流程配置完,用 4G 网络打开自己家的服务界面时,延迟显示一百多毫秒,但功能完全正常,那一刻确实有“破除了网络次元壁”的爽感。
找人帮忙测试的时候还有个细节:如果你在配置中启用了 Zero Trust 访问策略,别人打开你的域名时可能看到的是 Cloudflare 登录页。要么你自己测试使用管理员邮箱过一遍验证流程,要么在策略里临时加一条放行规则,不然你很容易误判成“隧道挂了”。
4. 常见问题与排查技巧
4.1 隧道一直显示 DOWN,连不上
这是遇到最多的问题,几乎每个玩 tunnel 的人都经历过。先别急着怀疑镜像坏了,百分之八十的情况出在出站被限制。cloudflared 在建立连接时需要用 HTTPS 出站,如果你的网络环境有内容过滤或者只允许特定域名(比如公司网络的代理),阻断就会发生在网络层。排查方法简单直接:直接在设备上执行curl -I https://region1.v2.argotunnel.com,如果连这个域名都连不通,那说明网络层就卡住了。
第二个常见的坑是系统时间严重漂移。这个非常隐蔽——设备如果长期用廉价 RTC 且没有做时间同步,证书校验会失败,cloudflared 会对所有握手上报握手错误。跑一下date -R看看日期到底对不对,如果时间是乱的,手动先校准一次再观察 tunnel 是否恢复。尤其是那些长时间断电的设备,重新上电后时间可能停在了断电那一刻。
第三个可能的原因就是 token 已经失效了。Cloudflare 控制台的隧道如果被删除、重建,或者你更换了组织,原来的 token 就彻底作废。这时别心疼,删掉旧配置重新生成一条隧道即可,操作几分钟就搞定。下表是我整理的排查顺序,可以照着来:
| 状态 | 第一步检查 | 第二步检查 | 第三步检查 |
|---|---|---|---|
| 设备端显示 DOWN | 出站点是否可达 | 系统时间是否准确 | token 是否还有效 |
| 控制台显示 HEALTHY 但访问不了 | 域名是否在 Cloudflare 托管 | 是否遗漏域名和隧道的关联 | 是否触发 Zero Trust 拦截 |
| 能访问但提示 502/503 | ingress 规则顺序有没有问题 | 本地服务端口是否真的在监听 | 本地服务是否绑定到 127.0.0.1 |
4.2 ingress 规则不生效、路由错乱
很多时候你会遇到这样的情况:访问nas.example.com结果跳到了默认 404,或者访问某个域名却打开了另一个服务。这几乎都是 ingress 规则顺序惹的祸。因为规则是从上到下逐个匹配的,一旦你有一个宽泛的子域名规则写在了更精确的规则前面,流量就会提前命中然后停止匹配。
举一个常见案例:如果你写了hostname: *.example.com的规则放在第一条,那nas.example.com就会命中这个泛域名规则,根本不会走到下面的精确规则。解决方式没有太多技巧,就是把精确域名放前面、泛域名放后面、兜底放最后。另外改完配置记得重启 cloudflared 服务:sudo systemctl restart cloudflared。这步经常会被人忘掉,结果改了配置半天不见效。
4.3 容器和本地服务的端口绑定问题
这块我花过很多力气才琢磨明白。cloudflare-os 设备上如果直接跑服务,一般没问题;但如果你像我一样在它上面起 Docker 容器,就涉及端口绑定的细节。很多容器习惯于绑定到0.0.0.0:3000这样的全接口地址,但这在安全上其实不太好——因为只要隧道被穿透,任意外部流量理论上都能直接命中宿主机端口。
我建议的做法是:把本地服务绑定到127.0.0.1上,让它只对回环地址可见。这样 cloudflared 代理到localhost:3000时能正畅通,而外部网络永远无法直接触碰到端口本身。这也更符合“让 Cloudflare 作为唯一入口”的安全模型。用 Docker 时,-p 127.0.0.1:3000:3000加个地址前缀就行,等于给服务做了个微隔离。
4.4 镜像升级和系统回滚的注意事项
cloudflare-os 会提供自动更新机制,但我建议不要盲目开启自动升级到最新版。真实操作中,新版本可能会调整配置文件格式、改变环境变量名,甚至有极小的概率引入回归问题。我把自己的策略定为“手动检查、确认后升级”:先去 GitHub Release 页面看看更新日志,重点看有没有 breaking change,再决定要不要升级。升级之前用dd把当前存储卡做一个完整镜像备份,这样即使升级失败也能快速回滚,代价只是一张卡的空间和时间。
升级完成后至少要确认两类状态:cloudflared 的进程是否在跑,以及隧道是否显示 HEALTHY。如果有任何一个不满足,先不要继续往下测,立刻先检查日志journalctl -u cloudflared -f输出,看配置解析是否成功。
5. 这套系统还能往哪些方向折腾
5.1 家庭实验室场景的延伸玩法
一旦隧道通了,你会发现后面能做的远远超过“远程访问 NAS”这一步。我现在习惯的做法是:在 cloudflare-os 设备上跑一个轻量级容器集群,把各种服务都塞到“Cloudflare 背后”,比如自建监控面板、内网 Wiki、甚至临时起的测试站点。因为访问策略由 Zero Trust 统一控制,我根本不用操心每个服务自身的认证和暴露风险。
反向代理那一套在 cloudflare-os 面前也显得老气了。我之前用 Nginx 的时候,每个新服务都要申请证书、绑定域名、配置代理规则。现在呢?在控制台给新服务加一条 ingress 规则,域名自动就有 HTTPS,身份校验自动启用,链路就不需要考虑证书问题。从“给一个新服务建虚拟主机”到“加一行配置就能远程访问”,这个体验差距确实大。
5.2 我实测几个月后的一些个人心得
如果你问我要不要把自己的主力服务全部迁到 cloudflare-os 上,我的答案是:分情况。如果你追求的是最低成本的远程访问、想着重用一个旧设备、并且接受所有流量经过 Cloudflare 边缘节点,那它基本是当前最优解之一。但如果你对数据主权特别在意,希望所有流量都在自家网络内部闭环,那 Cloudflare 充当“中间人”的角色可能让你不太舒服。至于稳定性,我自己跑了几个月,除了一次因为硬件 SD 卡掉速导致日志写入异常之外,其它时间都是长期无重启持续运行的。它更像是一个“边缘基础设施部件”,而不是一个需要你频繁照顾的折腾玩具。
最后分享一个实用小技巧:在 Cloudflare 控制台里多创建一条只有你自己用的“管理专用”隧道规则,指向一个不会公开展示的高位端口,然后把管理入口独立出来。这样日常服务、管理入口两套路径彻底分开,既方便排障又减少了暴露面。把系统折腾得再顺手一点,才能真正把精力留给那台设备上跑着的事。