先说一个我自己的场景。家里一台小主机跑了 Docker,上面挂着 NAS 文件服务、下载工具、媒体库,最近又陆续加了 Ollama、Dify、ComfyUI 这些本地 AI 服务。东西一多问题就来了:每个服务一个端口,浏览器书签攒了几十个,IP 和端口经常记混,隔几天就得翻历史记录。后来我用 Heimdall 做了一个服务导航仪表盘,把所有自部署服务的入口收拢到一个网页里,再通过域名和反向代理实现外部访问,手机在外头也能直接打开。
这篇博文就围绕 Heimdall 的本地部署和外部访问,把我的完整操作过程、配置细节和踩过的坑都写出来。适合三类人看:一是家里有 NAS 或 Linux 小主机、正被一堆服务地址搞到头大的玩家;二是折腾 Dify、Ollama 这类本地 AI 部署、需要一个统一入口的人;三是已经装了 Heimdall 但不知道怎么安全地从外网访问的新手。
1. 为什么是 Heimdall:定位、选型和部署思路
1.1 服务一多,入口就成了刚需
先说说这个需求的来源。本地部署这件事,本质上是一个个服务各自为政:Ollama 默认跑在 11434,Dify 跑在 80 或 3000,ComfyUI 跑在 8188,各服务还有自己的管理后台。你可以在浏览器里存书签,可书签只能记一串 URL,没法展示服务状态,也没法分类、检索,更别说让家人一起用了。
服务导航仪表盘解决的就是这个问题:把内网所有 Web 服务变成一个个带图标的卡片,放在同一个页面里,点一下就跳过去。它更像一个“自建服务专用起始页”,比浏览器默认标签页直观得多,也比手工记 IP 端口这件事可靠得多。
在众多同类项目里,Heimdall 属于老牌且稳定的那个。它基于 Laravel 框架开发,界面清爽、配置不复杂,支持 Docker 部署,而且社区镜像维护很活跃。它不会给你堆一堆用不上的复杂功能,但该有的导航、搜索、多用户、增强应用、天气插件都有,对 homelab 场景来说非常够用。
1.2 导航面板怎么选:Heimdall 的优劣势
同类工具其实不少,每个都有一定用户群。我在选型时对比过 Dashy、Homarr、Flame,还有 Sun-Panel,简单梳理一下各自的差异。
| 项目 | 部署难度 | 界面特点 | 主要优势 | 主要短板 |
|---|---|---|---|---|
| Heimdall | 很低 | 简洁卡片式,默认风格大气 | 稳定、升级省心、增强应用实用 | 默认主题偏少,配置项不算多 |
| Dashy | 中等 | 高度可定制 | 配置能力极强,支持 YAML 管理 | 配置复杂,组件多时容易蒙圈 |
| Homarr | 中等 | 偏媒体服务器风格 | 集成 Radarr/Sonarr 等媒体栈状态 | 和纯导航场景比有些重 |
| Flame | 很低 | 极简 | 轻量、适合作为个人起始页 | 功能少,不适合多人多服务场景 |
| Sun-Panel | 中等 | 美观现代 | 国内作者维护,汉化好 | 项目相对较新,生态不如 Heimdall 厚 |
我最后选 Heimdall,核心原因有三点。第一,linuxserver 镜像对新手极其友好,环境变量、卷映射、权限处理都是现成的,照着抄就能跑起来。第二,它的增强应用模式可以“原生嵌入”很多服务,这个后面细说,这是很多同类工具做不到那么顺的。第三,它用 SQLite 存配置,备份就是一个目录的事,对折腾党来说太重要了。
如果你喜欢极致自定义,Dashy 也可以考虑;如果你主要玩媒体服务,Homarr 可能更合适。但论“省心、通用、有人维护”,Heimdall 表现最均衡。
1.3 部署形态:Docker 是最省心的方式
Heimdall 本质上是一个 PHP 应用,传统方式需要 Nginx、PHP-FPM 等一堆依赖。手动安装不是不行,但升级、迁移、排障都很折腾。Docker 把这些问题全部封装起来,你只需要关心镜像、端口和目录挂载。
用 Docker 部署还有一个好处:和宿主机环境隔离,不会污染系统。比如你宿主机已经装了 Nginx 占着 80 端口,Heimdall 容器内部还是可以自由用 80;只要把宿主机的 8088 映射到容器的 80 就行。将来想升级,直接换个镜像 tag,config 目录里的数据还在。
如果你的环境是群晖、极空间或者绿联这类 NAS,Docker 套件本身就内置了,等于零门槛。如果是一台 Ubuntu 或者 Debian 服务器,装好 Docker Engine 和 Compose 插件后,下面这套配置基本可以照搬。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与核心部署步骤
2.1 硬件、系统与网络要求
先说硬件。Heimdall 的镜像体积不大,运行时内存占用通常在 200MB 以下,CPU 需求也很低。理论上树莓派这种 ARM 小盒子也能跑,更不用说当代 NAS 或淘汰下来的迷你主机。
系统层面,只要是能跑 Docker 的 Linux 发行版都行;群晖 DSM、极空间 ZOS、绿联 UGOS 的 Docker 套件也同理。Windows 上用 Docker Desktop 也能跑,但端口映射、文件挂载的路径格式和 Linux 有差异,没有特殊原因我还是建议放在 Linux 或 NAS 上。
网络要求分两层:内网访问只需要设备在同一局域网,宿主机 IP 和容器端口通就行;外部访问则是另一个话题,后面单独讲。部署前建议先确认宿主机 IP,比如 192.168.1.100,后续所有配置都会围绕这个地址展开。
2.2 用 Docker Compose 完成部署
我推荐使用 Docker Compose 而不是直接 docker run,因为 Compose 文件本身就是配置文档,下次迁移或重建容器时直接复用一份 YAML 就够了。
先创建目录并编写 compose 文件:
bash复制mkdir -p /opt/heimdall/config
cd /opt/heimdall
nano docker-compose.yml
yaml复制services:
heimdall:
image: lscr.io/linuxserver/heimdall:latest
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Shanghai
volumes:
- /opt/heimdall/config:/config
ports:
- "8088:80"
- "8089:443"
restart: unless-stopped
几个关键点逐个解释。
PUID 和 PGID 是用来控制容器内文件属主的,避免生成的配置文件变成 root 所有、宿主机上反而不好管理。一般填你登录用户的 uid 和 gid,id 命令可以查看。
TZ=Asia/Shanghai 设置时区,主要影响仪表盘上的时间显示。
端口映射部分,我把容器的 80 映射到宿主机的 8088,443 映射到 8089。之所以不直接用 80/443,是因为这两个端口通常被其他服务占用,而且未来接反向代理时,反代服务本身需要占用 80/443。
写好之后启动:
bash复制docker compose up -d
等几十秒拉镜像和启动,访问 http://192.168.1.100:8088 就能看到安装向导。检查容器状态可以用 docker ps 和 docker logs heimdall。
2.3 首次初始化:管理员与基础设置
第一次打开页面会进入设置向导,需要创建管理员账号和密码。Heimdall 默认界面以英文为主,但配置项不多,对照翻译基本能看懂。建议这一步就设一个强密码,因为后续一旦暴露到公网,弱密码会非常危险。
登录之后可以先做三件小事。第一,在设置里把背景改成一个你喜欢的图片或纯色,让仪表盘更合眼缘。第二,确认时区正确,避免时间和实际不符。第三,把默认的几个示例应用删掉或改掉,替换成你自己的服务。
Heimdall 的配置会自动保存到 /config 下的 SQLite 数据库文件里,不需要手动存储,这点很省心。
2.4 提前配置好反向代理
这一步看起来和本地部署无关,但强烈建议在开始用之前就配好。反向代理的作用,是把“域名 + 80/443 端口”的请求,转发到内网里的 Heimdall 端口,同时自动处理 HTTPS 证书。这样外部访问只需要记住一个域名,而不用记 http://IP:8088 这种地址。
我用的是 Caddy,配置简单到令人发指。宿主机装好 Caddy 后,在 Caddyfile 里写:
caddyfile复制heimdall.example.com {
reverse_proxy 127.0.0.1:8088
}
然后 caddy reload,Caddy 会自动申请 Let's Encrypt 证书并开启 HTTPS。只要域名解析到了这台机器,访问 https://heimdall.example.com 就能打开仪表盘。
如果你更喜欢图形界面,可以用 Nginx Proxy Manager。它提供网页操作,添加 Proxy Host,填域名、内网 IP 和端口,再一键申请证书,效果一样。反向代理做在前面,后面不管是接 frp 还是 Cloudflare Tunnel,都不用再改 Heimdall 本身。
3. 仪表盘功能配置与玩法实操
3.1 添加应用:名称、地址与图标细节
导航仪表盘的核心操作就是添加应用。登录后点击右上角的“Add App”,需要填写应用名称、URL 地址,以及选择图标。
图标有三种常见方式。第一种是 Heimdall 内置的图标库,里面有不少流行服务,选一个就完事。第二种是直接填一个图片 URL,用服务的 favicon 或者网上找的图标地址。第三种是上传本地图片,在内网环境最稳,因为不依赖外部图床。
我的建议是:能上传本地就上传本地。很多图标放在外网图床,内网访问时加载很慢,甚至直接裂开。本地图标的做法也简单,把图片下载下来放到 config/www/icons 目录下,然后在添加应用时选择上传即可。
添加完应用后,卡片会显示在主页上。拖动卡片可以排序,让最常用的服务放在最前面。这一步做得好,日常使用体验会舒服很多。
3.2 增强应用:把页面嵌到仪表盘里
Heimdall 的“增强应用”是个被低估的功能。普通应用只是跳转链接,增强应用则可以在仪表盘内直接嵌入目标页面,相当于把整个 Web 服务塞进了一个 iframe。比如把 Grafana 监控面板嵌进去,打开仪表盘就能看到数据,不用再点一次跳转。
创建增强应用时,除了名称和 URL,还需要设置展示方式。Heimdall 支持 iframe 嵌入、自定义 CSS 注入等选项。对大多数人来说,选择 iframe 嵌入就够了。
但这里有一个很常见的坑:很多 Web 应用会在响应头里设置 X-Frame-Options: SAMEORIGIN 或 CSP 规则,禁止被其他网站 iframe 嵌套。结果是 Heimdall 里显示空白或报错,但直接用浏览器打开却正常。
要解决这个问题,需要在那台目标服务的反向代理层去掉或改写相关响应头。Caddy 下可以用 header -X-Frame-Options 删除该头,Nginx 下用 proxy_hide_header X-Frame-Options;。改了之后重启反代,一般就能嵌进去了。
另外,像 Grafana 这类工具自身也有开关,在配置文件里设置 allow_embedding = true 即可。整体来说,增强应用适合“想看状态一眼”的场景,不适合所有服务都嵌入,否则仪表盘会变得很高很长。
3.3 分组排序、搜索与多用户
服务数量一多,就需要整理。Heimdall 的卡片可以按类别整理,虽然没有特别复杂的文件夹体系,但可以通过标签或自定义分类来划分。比如“AI 服务”“媒体服务”“监控服务”各放一组,视觉上清晰很多。
顶部搜索栏是另一个很实用的功能。服务多了之后,凭记忆找卡片不如直接输入名字。Heimdall 的搜索会实时过滤卡片,回车就能打开第一个匹配项,效率比鼠标点卡高得多。
Heimdall 还支持多用户。管理员可以创建普通用户,每个用户可以有自己的应用列表和个性化设置。对家庭场景来说,你可以给家人开一个账号,把常用服务放在他们的页面上,不用让他们面对一大堆技术后台。
如果只是自己一个人用,单账号完全够。但多用户能力在需要多人访问时是很加分的,这是它区别于一些极简导航页的关键点。
3.4 备份与迁移
本地部署最怕数据丢失,Heimdall 的备份几乎零成本。所有配置、用户、图标、布局都存放在 /config 目录里,备份时只要把整个目录拷走即可。
需要注意的一点是:Heimdall 的数据库是 SQLite,不要在容器运行期间直接 cp 数据库文件,避免读到不一致的数据。稳妥的做法是先执行 docker stop heimdall,再拷贝 /config 目录,拷贝完再启动容器。整个过程几秒钟,服务中断时间很短。
迁移到新机器也很简单:新机器装好 Docker,把备份的 config 目录放到对应位置,启动容器,所有配置就回来了。这也是我极力推荐 Docker 部署的原因之一,配置与运行环境彻底解耦。
4. 实现外部访问:三种方案与安全加固
4.1 先判断自己有没有公网 IP
外部访问的第一步不是配置工具,而是搞清楚自己的网络环境。不同环境决定了完全不同的方案。
最简单的方法是登录路由器查看 WAN 口 IP。如果这个 IP 以 100.64.x.x 开头,基本可以确定运营商没有分配公网 IPv4,你处在运营商级 NAT 后面。如果 IP 是 10.x 或 192.168.x 开头,同样也是内网 IP。
还有一个办法是直接访问一个显示本机公网 IP 的网站,对比路由器 WAN 口 IP 是否一致。一致说明有公网 IP,不一致就说明被 NAT 了。
如果你的宽带能申请到公网 IPv4,那恭喜你,方案最省事。如果申请不到,也不用灰心,后面有两套不需要公网 IPv4 的方案。IPv6 用户也可以考虑,但终端网络环境差异大,稳定性需要自己测试。
4.2 有公网 IP:端口转发 + DDNS + 反代
这套方案的核心思路是:让外部请求先到路由器,再由路由器转发到跑 Heimdall 的机器,最后由反向代理把请求送到容器。
具体步骤分三步。第一,去域名服务商注册一个域名,然后在路由器里设置 DDNS,把域名动态绑定到你家的公网 IP。很多路由器自带花生壳、DuckDNS 等 DDNS 客户端,也可以用 ddns-go 这类工具在 NAS 上跑。第二,在路由器上设置端口映射,把 443 端口转发到内网 Heimdall 主机的 443 端口(也就是反代的端口)。第三,在反向代理层配置好域名和证书,就是 2.4 节里 Caddy 那套。
配置完成后,外部访问 https://heimdall.example.com 就能打开你的仪表盘。整个过程看起来简单,实际上有两个隐藏问题需要提前处理。
第一,国内很多宽带运营商封禁了 80 和 443 端口,导致你虽然做了映射,但从外网访问还是不通。这种情况下,可以把路由器的外部端口改为 8443 或其他高位端口,访问时带上端口号:https://heimdall.example.com:8443。
第二,动态 IP 会变化。如果 DDNS 没配置好,域名解析会滞后,表现为“昨天还能访问,今天突然打不开”。排查时先看域名解析到了哪个 IP,和当前路由器 WAN 口 IP 是否一致。
4.3 无公网 IP:frp 内网穿透方案
如果你的运营商不给公网 IPv4,最常用的方案是 frp 内网穿透。原理很简单:找一台有公网 IP 的云服务器做中转,家里机器主动和服务器建立长连接,外部用户访问云服务器的某个端口时,流量经过这个连接转发到家里的 Heimdall。
frp 是开源项目,分为服务端 frps 和客户端 frpc。云服务器上部署 frps,家里 NAS 或小主机上部署 frpc。
frps 端配置比较简洁,核心是设置一个 token 用于认证:
toml复制bindPort = 7000
auth.token = "换成你自己的复杂Token"
家里机器上的 frpc 配置:
toml复制serverAddr = "你的云服务器公网IP"
serverPort = 7000
auth.token = "换成你自己的复杂Token"
[[proxies]]
name = "heimdall"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8088
remotePort = 8088
这里把家里的 8088 端口映射到云服务器的 8088 端口。外部用户访问 http://云服务器IP:8088 就能打开 Heimdall。本地 Heimdall 本身已经配好反向代理和域名,所以在 frpc 里也可以只映射 80/443 端口,让反代域名直接生效。
云服务器端别忘了在安全组里放行 7000 和 8088 端口,这是新手最容易漏掉的一步。服务商的安全组放行后,还要在服务器系统防火墙里确认。
frp 方案需要一台云服务器,成本相对高一些,但优势是稳定、可控,除了导航页,其他服务也能一起穿透出去。
4.4 免公网 IP:Cloudflare Tunnel 方案
如果你不想花钱买云服务器,Cloudflare Tunnel 是一条免费路线。它由 Cloudflare 提供隧道服务,你只需要有一个托管在 Cloudflare 的域名、一台能跑 cloudflared 的设备,不需要公网 IP,也不需要路由器端口映射。
实现逻辑也不复杂。家里设备安装 cloudflared 后,主动和 Cloudflare 的 Edge 建立连接,然后你在 Cloudflare 后台配置一条 Public Hostname,把 heimdall.example.com 指向内网服务器的 http://127.0.0.1:8088。外部用户访问你的域名时,流量经 Cloudflare 网络进入隧道,最终转发到家里的 Heimdall。
cloudflared 的安装和配置在 Linux、NAS 上都有现成方案。命令行的核心步骤大致是:
bash复制cloudflared tunnel create heimdall
cloudflared tunnel route dns heimdall heimdall.example.com
cloudflared tunnel run heimdall
整个过程配置完成后,HTTPS 证书由 Cloudflare 自动管理,你甚至不需要自己申请证书。由于入站流量只穿过 Tunnel,它不需要在路由器上开任何端口,安全性很不错,因为公网根本扫不到你的 8088 端口。
有一点需要自行评估:Cloudflare 服务的连通性在不同的网络环境差异比较大,部分地区访问速度可能不稳定,这属于网络服务本身的情况,我建议先把服务搭好,然后用手机流量测一下实际访问效果再决定是否长期使用。
4.5 外部访问的安全加固
把任何 Web 服务暴露到公网,都等于给互联网上所有人开了一道门,所以安全不能省。我之前见过不少直接把服务裸奔在公网上的案例,最后被扫到漏洞或暴力破解,教训很深刻。
首先,Heimdall 自己一定要用强密码,并且不要用默认管理员名。如果你担心暴力破解,可以在反向代理层加访问控制。Nginx Proxy Manager 支持简单的 IP 访问规则,Caddy 下可以用 @blocked 配合 abort 拦截可疑请求。
更稳妥的做法是在反向代理之前再加一层身份认证服务,比如 Authelia 或 Authentik。这层认证通过后,才把请求转发到 Heimdall。这样即使 Heimdall 的登录页暴露在公网,也先被外层认证挡住了一大半攻击。
其次,不要轻易把 docker 容器的高位端口直接映射到公网。如果走 frp 或端口转发,尽量用非默认端口,并且不要在你的主域名和常用端口上暴露管理后台。
最后,记得关注镜像更新。Heimdall 本身安全维护尚可,但老版本可能存在漏洞,定期更新镜像是个好习惯。升级前先备份 config 目录,不用我多提醒了吧。
5. 踩坑记录与常见问题排查速查
5.1 容器起来了,页面却访问不了
这是新手遇到最多的问题:docker ps 看着容器是 Up 状态,但浏览器打不开。
第一步,先在宿主机上测试 curl http://127.0.0.1:8088。如果宿主机能返回 HTML,说明服务本身正常,问题出在端口映射或防火墙。如果宿主机也打不开,大概率是容器异常,去看 docker logs heimdall 的输出。
第二步,检查端口映射是否冲突。如果你启动多个容器都映射了 8088 端口,Docker 会直接报错。可以通过 docker ps 查看端口占用情况。
第三步,检查系统防火墙。Ubuntu 的 ufw、CentOS 的 firewalld 默认可能没放行 8088 端口,执行放行命令后再访问。
第四步,如果你用的是云服务器或 NAS,还要看安全组里有没有放行端口。这一步很多人忘记,明明其他都正常,外网就是不通。
5.2 外网一直访问不通
外部访问失败的原因通常比内网更复杂。可以先做个端口连通性测试:用手机流量执行 telnet 你的域名 端口,如果能连上说明路由已经通了,剩下是反代或域名配置的问题;如果连接超时,问题往往出在端口映射、运营商封端口或没有公网 IP 这三件事上。
一个很常见的场景是:路由器映射做了、DDNS 也配了,但从外部还是不通。这时候打开云服务商的端口检测工具扫一下你的公网 IP 或域名端口,如果显示端口关闭,基本就是运营商封锁或路由映射没生效。换高位端口映射往往能绕开封锁。
还有一个容易被忽略的点:如果外部访问走的是 https://域名:8443 这种形式,一定要确认反向代理监听了对应端口。Caddy 默认监听 443,要额外监听 8443 时需要在 Caddyfile 里写成 :8443 并在前面加域名匹配规则,不然请求到了服务器也会被拒。
5.3 图标不显示或加载慢
Heimdall 图标不显示,绝大多数时候不是 Heimdall 的问题,而是图标资源本身不可达。很多外部图标服务在国内网络环境下访问不稳定,或者某些网站设置了防盗链,导致图片返回 403。
解决的终极方案就是本地化:把图标文件下载下来,放到 config/www/icons 目录,添加应用时选择上传本地图片。这样无论从内网还是外网访问,图标都走自己服务器的资源,加载速度反而更快。
如果你是批量添加应用,图标一个一个下载太麻烦,可以写一个简单的脚本:先收集每个服务的 favicon URL,然后 curl 到本地目录,最后统一上传。这个操作不用太复杂,手动处理几十个图标也完全可以接受。
5.4 反向代理常见错误:502 / 504
反代配置好之后,访问域名提示 502 Bad Gateway,大部分原因是反向代理连不上 Heimdall 容器。先检查反代配置里的目标端口是不是 8088,再确认容器是否在监听 127.0.0.1 或对应网卡。
如果你把容器跑在 Docker 默认的 bridge 网络里,容器内 Heimdall 监听的是 0.0.0.0:80,宿主机的 8088 端口做了映射,反向代理指向 127.0.0.1:8088 是没问题的。但如果你的反代本身也跑在 Docker 容器里,指向 127.0.0.1 就可能连不上,因为每个容器有独立的网络命名空间。这种情况下要用宿主机在 Docker 网络中的 IP,或用 host 网络模式跑反代。
504 通常意味着上游服务超时。如果 Heimdall 页面加载很慢,或者你嵌入了很多外部资源,可以在反代配置里调大超时时间。Caddy 默认超时对 Heimdall 来说是够用的,但如果你强行嵌入了某些很慢的外部页面,就要单独增加超时设置。
5.5 升级覆盖后配置丢失
升级容器本身不会丢数据,前提是你的卷映射正确。有些用户图省事,直接 docker rm 删除容器再重新 docker run,但忘了挂载 /config 目录,于是数据全部丢在新容器里,只能重新配置。
解决方案就是从一开始就用 Compose 管理。升级时先把 docker-compose.yml 里的镜像 tag 改掉,或直接用 docker compose pull 拉新镜像,然后 docker compose up -d,容器重建但卷挂载不会丢。
还有一点:升级前一定备份 config 目录。虽然 LinuxServer 镜像升级出问题的概率不高,但备份一下永远不吃亏。具体操作很简单,把整个 /opt/heimdall/config 目录打包到 NAS 存储或其他地方即可。
5.6 几个“早知道就好了”的实操心得
写到这里,再说几个我在实际操作中积累下来的体会,不一定写在官方文档里,但确实能减少不少折腾时间。
第一,尽早把 Heimdall 的访问入口固定为域名+反代,而不是一直用 IP:端口。后面无论接入 frp 还是 Tunnel,都只需要改反代层,不需要动 Heimdall 本身。这个前置工作很值得做。
第二,把 config 目录放到 NAS 的共享文件夹里,同时开启快照或定期同步。这样即使硬件坏了,配置也能很快恢复。我之前吃过一次固态硬盘故障的亏,重装完所有服务之后最怀念的就是一个完整的 heimdall 配置备份。
第三,如果只是自己在手机和电脑上用,其实可以用 Tailscale 这类组网工具来访问,连域名都不需要。它把设备组成一个虚拟局域网,浏览器直接访问内网地址就可以,安全性和体验都比直接暴露公网好。外部访问的方案不是只有“映射到公网”一条路,组合使用往往更舒服。我把 Heimdall 当作所有本地服务的总入口,包括 Ollama、Dify 和 ComfyUI 这些 AI 服务的地址全部挂上去,再配合反代做外部访问,到目前为止用得很稳定。如果你也在折腾本地部署,这个组合值得一试。
