早期的懒猫微服不知道是硬件设计上面是存在什么瑕疵或者是别的原因,短时间内我已经遇到两次硬盘故障。不知道现在的微服如何,我用的版本拆开换硬盘并不是很傻瓜,更要命的是,有两颗螺丝还滑丝了,怎么拧都拧不出来。 😂 我一开始也试过干脆只在本地用算力舱。可是离开微服之后,在外面就完全访问不到它了。这么好的算力只能在家里用,实在太浪费。所以我必须想个办法,在没有懒猫微服的情况下,也能从外网访问算力舱。
倒不是想跟懒猫分手。算力舱本身就是懒猫的产品,用着也挺顺手,lzc-ai-agent 我也一直留着,应用照样从懒猫的镜像仓库拉。我只是不想让算力舱跟那台拆不开的微服绑在一起。而且万一哪天新一代的懒猫微服设计得和群晖 NAS 一样好换硬盘了呢,我可能又会用回懒猫微服。
之前写过一篇《懒猫微服的非典型性玩法》,当时这种垦荒的感觉很有意思。官方的 AI 应用分发和远程访问都统一用微服来管理,本身是一个非常棒的一体化设计,但是微服一挂,算力舱瞬间成了一个瘸腿设备了。后来我不得不把它们做了个轻度解耦,实现出门在外通过 Cloudflare One 客户端来正常访问算力舱里面的 Ollama。这篇日志就记录一下整个过程。
言归正传。
算力舱为什么离不开微服
官方虽然说得很清楚:算力舱和微服是两台独立的设备。算力舱预装的是 Ubuntu,插上键盘、鼠标和显示器,本身就是一台可以 SSH 进去的机器。我平时都是通过 Wi-Fi SSH 登录,需要的时候也可以直接接键鼠和屏幕。
但他们其实并没有做到完全独立,把两者捆在一起的,大概是这几件事:
- 微服负责安装和分发 AI 应用,再由算力舱上的
lzc-ai-agent去拉镜像、拉起容器。 - 服务通过 Traefik 暴露,主机名通常是
*-ai这种形式。 - 外出访问靠的是微服自带的内网穿透,而不是算力舱自己对外提供入口。
所以微服一出问题,本地算力还在,但“远程访问”和“通过微服来管理应用”这两件事就会一起受影响。官方也说过,算力舱可以单独当 Ubuntu 用,只是应用和远程访问要自己折腾。 😂
我想要的结果
我给自己定了一个很简单的目标:
- 给算力舱一个固定的局域网 IP,不要每次都去猜地址。
- 需要用到的服务直接监听这个 IP。下面会以 Ollama 为例,其他服务也是同样的思路。
- 我自己写了一个基于 Node.js 的门户,跑在
8088端口,用来管理算力舱上的各种 AI 服务。 - 远程访问不再走微服的域名,而是用已经跑在群晖 NAS 上的
cloudflared,通过 Cloudflare Tunnel 把域名发到这些端口。刚好 NAS 已经有 cloudflared 了,所以算力舱上不用再装一份cloudflared。 lzc-ai-agent继续留着跑,这样算力舱还能从懒猫的镜像仓库拉镜像。
整体看起来就是这样:
Cloudflare One 客户端
│
│ 仅包含 ai.example.com、ollama.example.com
▼
Cloudflare Access(先检查 WARP 设备,否则走邮箱一次性验证码)
│
▼
Cloudflare Tunnel(cloudflared 跑在 NAS 上)
│
├── ai.example.com → 192.168.x.y:8088 门户
└── ollama.example.com → 192.168.x.y:11434 OllamaCode language: CSS (css)
下面出现的域名和 IP 都是占位符,请换成你自己的。
给算力舱一个固定的局域网地址
固定地址我没有在算力舱的系统里改,而是在路由器上做了 DHCP 地址预留(有的界面也叫 DHCP Reservation、地址绑定或 MAC 绑定)。算力舱本身继续用 DHCP,只是每次都会拿到同一个 192.168.x.y。
留下 lzc-ai-agent
算力舱毕竟还是懒猫的产品,lzc-ai-agent 我是故意留着、并且让它继续跑着的。没有它,从懒猫镜像仓库拉镜像就会失败。
这里说的解耦,解的是对微服的依赖:远程访问、路由和日常管理都不再走微服。并不是把懒猫的软件从算力舱上卸干净,所以不要去停掉或 disable 这个服务。需要的话可以用下面这条确认它还在跑:
systemctl status lzc-ai-agentCode language: Bash (bash)
以 Ollama 为例,先从局域网确认
算力舱的 Ollama 是跑在 Docker 容器里的。出厂时懒猫就已经把它配成监听所有网卡,并允许局域网里的设备跨域访问:
services:
ollama:
image: registry.lazycat.cloud/catdogai/jetson-ollama:0.20.0
environment:
- OLLAMA_ORIGINS=*
- OLLAMA_HOST=0.0.0.0
ports:
- 11434:11434Code language: YAML (yaml)
镜像来自懒猫自己的仓库,这也是前面要把 lzc-ai-agent 留着的原因:没有它,从这个仓库拉镜像就会失败。因为服务已经在 0.0.0.0 上监听,并且把 11434 发布出来了,NAS 上的 Tunnel 可以直接打到算力舱,不必再改监听地址。
OLLAMA_ORIGINS=* 表示接受来自任意来源的跨域请求。我这边远程访问已经放在 Cloudflare 后面,这样用可以接受;如果你更在意来源限制,可以把这个值收紧。
所以这一步只需要从局域网确认它能被访问到:
curl http://127.0.0.1:11434
curl http://192.168.x.y:11434Code language: Bash (bash)
正常的话都会返回 Ollama is running。下面我不会把每个服务都写一遍,只继续用 Ollama 当例子。
把门户也一起挂上
由于无法再使用微服应用来管理算力舱,我不得不自己用 Node.js 手搓一个门户,用来管理算力舱上跑着的各种 AI 服务。它也跑在算力舱的 Docker 里,网络用的是 network_mode: host,直接监听宿主机的 8088,以及 18081–18099。restart: always,Docker 守护进程会在开机时把它拉起来。

门户里还有一个 Ollama Studio 页面,可以直接查看和管理 Ollama 里的模型:

Compose 文件大致如下:
services:
aipod-portal:
container_name: aipod-portal
image: aipod-portal:latest
restart: always
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /sys:/host/sys:ro
- /proc:/host/proc:ro
- /ssd:/ssd
- /:/host/rootfs:roCode language: YAML (yaml)
这几个挂载各自有用:docker.sock 用来管理容器栈和读日志;/sys 和 /proc 只读挂进来,用来看 Orin 的 GPU 负载、INA3221 电源轨道、风扇转速和温度;/ssd 用来读写 Compose 配置、扫描本地模型文件;/ 只读挂成 /host/rootfs,用来看根分区(eMMC)占用。
挂上 docker.sock 相当于把宿主机 Docker 的根权限给了这个容器,所以这个门户一定不能直接暴露到公网。后面 Cloudflare 那一节就是在做这件事。
启动、看日志和重启:
docker compose -f /ssd/aipod-portal/docker-compose.pod.yml up -d
docker logs -f aipod-portal
docker restart aipod-portalCode language: Bash (bash)
本机和局域网可以先这样确认门户活着:
curl -I http://127.0.0.1:8088
curl -I http://192.168.x.y:8088Code language: Bash (bash)
用 Cloudflare Tunnel 发布域名
远程访问我没有在算力舱上再装一个 cloudflared,而是直接用已经跑在群晖 NAS 上的那条 Tunnel。NAS 和算力舱在同一局域网里,只要 NAS 能访问 192.168.x.y 的对应端口就行。
需要说明的是,我的 NAS 上早就装好了 cloudflared,Tunnel 也一直在跑,所以下面只是在现有的 Tunnel 上加路由。如果你还没有 Tunnel,步骤会和我的不太一样:要先新建一条 Tunnel,并在局域网里的某台机器上(NAS、算力舱或者其他常开的设备都行)装好 cloudflared 连上它,然后再按下面的步骤加路由。
具体在 Cloudflare 后台是这样操作的(当前文档写的是主控制台里的路径):
- 打开 Cloudflare 后台,进入 Networking → Tunnels,点开已经在 NAS 上跑着的那条 Tunnel。我这里不需要新建,也不用在算力舱上再装一遍
cloudflared。 - 打开 Routes 标签,点 Add route,再选 Published application。
- 第一条这样填:
- Subdomain:
ai - Domain:从下拉菜单里选
example.com(换成你自己的域名) - Service URL:
http://192.168.x.y:8088
- Subdomain:
- 点 Add route。
- 再用同样的步骤加第二条:Subdomain 填
ollama,Service URL 填http://192.168.x.y:11434。 - 加完后到 DNS 里看一眼。完整托管在 Cloudflare 上的域名,通常会自动加上对应的代理 CNAME,确认
ai.example.com和ollama.example.com已经是 Proxied 状态即可。已有的其他 Published application 不用动,它们会继续留在这张表里,互不影响。
如果你平时在 Zero Trust 后台里做事,也可以从 Zero Trust → Networks → Connectors 找到同一条 Tunnel。不过“给已有 Tunnel 添加 Published application”的逐步说明,当前文档写的是上面这条 Networking → Tunnels 路径。
如果你想对照一下配置的形状,后台里这两条大致相当于:
ingress:
- hostname: ai.example.com
service: http://192.168.x.y:8088
- hostname: ollama.example.com
service: http://192.168.x.y:11434
- service: http_status:404Code language: YAML (yaml)
最后那条 404 是兜底,避免没匹配到的请求被随便转到某个本地服务上。在后台添加 hostname 时一般会自动保留,不必特意去改。
Access 和 Cloudflare One 客户端
光把域名指过去还不够,这两个入口都要放到 Cloudflare Access 后面。我用的是和现有自托管应用同一套策略。每个应用两条策略,顺序很重要。
先为门户创建一个应用:
- 打开 Zero Trust → Access controls → Applications,点 Create new application。
- 类型选 Self-hosted and private,再选 Add public hostname。
- 在 Domain 下拉菜单里选你的域名,并填上子域名,得到
ai.example.com。名称可以随便起,例如ai。 - 会话时间(Session Duration)我设得比较长(730 小时)。
- 在 Access policies 里添加第一条策略,名称例如
WARP:- Action 选 Service Auth
- Include 条件选 Device posture 或 Warp,要求设备已通过 Cloudflare One 客户端的检查
- 再添加第二条策略,名称例如
Allow Me Only:- Action 选 Allow
- Include 条件选 Emails,填你自己的邮箱
- 点 Create。然后用同样的步骤再为
ollama.example.com建一个应用,两条策略保持一样,只是域名换成 Ollama 的。
策略的含义很简单:已经连上 Cloudflare One 客户端的设备可以直接过;否则会走邮箱一次性验证码。
然后是客户端分流,只让这两个域名走隧道:
- 打开 Zero Trust → Team & Resources → Devices → Device profiles → General profiles。
- 找到你自己在用的那张配置,点 Configure。
- 找到 Split Tunnels,模式选 Include IPs and Domains。
- 点 Manage,只加入需要走 Cloudflare 的主机名,例如:
ai.example.comollama.example.com
- 保存后(Save profile),重新连接一次 Cloudflare One 客户端,让新的 Include 列表生效。
这样客户端不会把设备上所有流量都送进隧道,只会转发这两个域名。
走 Ollama / OpenAI 兼容 API 的客户端,把地址改成 https://ollama.example.com 即可,不要再加端口。如果应用要求 OpenAI 兼容路径,把 /v1 留着。这类应用自己没法完成邮箱验证码登录,所以必须在 Cloudflare One 客户端开着的时候用。如果以后有某个应用必须在客户端关闭时访问,可以再单独给它配 Access 的 service token。
怎么确认它在工作
我是按从近到远的顺序检查的:
- 在算力舱本机:
curl http://127.0.0.1:11434和curl -I http://127.0.0.1:8088都正常。 - 在局域网另一台机器上,对
192.168.x.y的这两个端口重复一遍,确认同一网段的设备(包括跑 Tunnel 的 NAS)都能直接访问。 - 最好再在安装有
cloudflared的NAS 上对同样的地址 curl 一次,确认跑 Tunnel 的 NAS 能访问到算力舱。这一步常被跳过,后面公网域名不通时会很难排查。 - 关掉 Cloudflare One 客户端,在外部网络访问
https://ai.example.com,会被重定向到 Access 登录页。 - 打开客户端后再访问,门户可以直接打开,
https://ollama.example.com也可以正常调用。
第 5 步我在外部网络实测过:Cloudflare One 客户端开着的时候,门户和 Ollama 都已经可以端到端使用了。
一个容易遇到的问题
默认设备配置把所有流量都送进隧道。 给这些域名用 Include 模式,并且确保你的设备使用了这个配置。
好了,今天就先写到这了。微服那套开箱即用的体验确实省事,不过算力舱本身就是一台完整的 Ubuntu。固定好地址,让服务监听局域网地址,再用已经有的 Tunnel 把域名发出去,就算不再依赖微服,也能继续用自己的算力。lzc-ai-agent 我还是留着的,这样仍然可以从懒猫仓库拉镜像。现在这套已经在外面跑起来了。希望这篇日志对同样在琢磨怎么把算力舱从微服里独立出来的朋友有一点帮助。
























