- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
7.1 KiB
在无 UI 的 Linux 服务器上部署 NomiFun WebUI
本目录是 headless(无图形界面) 部署产物。服务器上不要装 Tauri 桌面包(.deb/.AppImage 需要图形会话);要跑的是 nomifun-web —— 一个纯 axum 的 HTTP/WS 服务,后端 in-process + 同端口托管前端 SPA,零 GUI 依赖,可在没有显示器的服务器上运行。
访问与认证模型(重要)
nomifun-web默认要求登录。 第一次用浏览器打开时,登录框里你输入的用户名 + 密码就成为初始管理员账号(首启 setup,一次性)。之后该端点关闭(再调返回 409),只能用这套凭据登录。- 桌面版(Tauri)不受影响,仍是本机免认证。
- 默认建议先只监听
127.0.0.1,完成首启管理员设置或预置NOMIFUN_ADMIN_PASSWORD后,再显式改为0.0.0.0暴露给 LAN/VPN。 面向公网请务必在前面加 TLS(见下文 Caddy)。 - 可选:设置
NOMIFUN_ADMIN_PASSWORD在启动时预置管理员,跳过交互式首启(适合自动化部署 / 想关闭首启竞态窗口的场景)。
方式一:Docker(推荐)
仓库根目录已带 Dockerfile、docker-compose.yml、Caddyfile。
# 在仓库根目录
docker compose up -d --build
# 默认发布 8787;首次访问会创建管理员。公开暴露前建议预置管理员或先在可信网络完成 setup。
restart: unless-stopped 已让它开机自启 + 崩溃自拉——装好就等于"自动开启 webui"。数据(SQLite、日志、bun 运行时缓存、agent 状态)落在命名卷 nomifun-data:/data。
查看启动是否就绪:
docker compose logs -f nomifun # 看到 "nomifun-web: embedded backend + SPA on one port" 即 OK
加 TLS(公网必做)
docker-compose.yml 里有一段注释掉的 caddy 服务。启用步骤:
- 编辑
Caddyfile,把your.domain.com换成你的域名; - 在
nomifun的environment里加NOMIFUN_HTTPS: "true"(让会话 cookie 带Secure); - 把
nomifun的ports: ["8787:8787"]改成expose: ["8787"](只让 Caddy 对外); - 取消
caddy服务和caddy-*卷的注释; docker compose up -d。
Caddy 会自动签 HTTPS 证书,WebSocket(/ws)自动透传,无需额外配置。应用自带登录,所以 Caddy 不需要再配 basic_auth。
方式二:原生二进制 + systemd(不想用 Docker)
需要一台 Linux 构建机(Windows 交叉编译这堆 C 依赖很痛,不建议;也可直接从 Docker 镜像里 docker cp 出二进制)。
1) 构建产物
bun install
bun run build:ui # → ui/dist(SPA,~21MB)
cargo build --release -p nomifun-web # → target/release/nomifun-web
2) 部署布局
/opt/nomifun/nomifun-web # 二进制
/opt/nomifun/web/ # = ui/dist 的内容
/var/lib/nomifun/ # data 目录(systemd StateDirectory 自动创建)
sudo useradd --system --home /var/lib/nomifun --shell /usr/sbin/nologin nomifun
sudo mkdir -p /opt/nomifun/web
sudo cp target/release/nomifun-web /opt/nomifun/
sudo cp -r ui/dist/. /opt/nomifun/web/
⚠️ bun ≥ 1.3.13 必须在「系统」PATH 上。
nomifun是 nologin 账户,装到某人~/.bun/bin/里它读不到(systemd 服务也不会用你的~/.bun)。可靠做法二选一:
- 系统级安装:
curl -fsSL https://bun.sh/install | bash,然后sudo install ~/.bun/bin/bun /usr/local/bin/bun(或用包管理器 /npm i -g bun);- 编进二进制(免 PATH 依赖):构建时
NOMIFUN_EMBED_BUN=1 cargo build --release -p nomifun-web,bun 会嵌入并在 data 目录自解压(需构建环境能取到 bun)。校验:
sudo -u nomifun -s -- which bun必须返回路径,否则 agent 首次 spawn 才暴露失败、错误隐晦。
3) 安装并开机自启
sudo cp packaging/linux/nomifun-web.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now nomifun-web # 开机自启 + 立即启动 = 自动开 webui
sudo systemctl status nomifun-web
同样建议在前面摆一个 Caddy/nginx 做 TLS,并在 unit 里设 Environment=NOMIFUN_HTTPS=true。
⚠️ unit 里
Environment=NOMIFUN_DATA_DIR=/var/lib/nomifun必须与StateDirectory=nomifun保持一致。若你改 unit(比如注释掉User/Group改用 root)时不慎删掉那行,数据会悄悄落到服务用户的按用户目录($XDG_DATA_HOME/NomiFun/Nomi,通常是~nomifun/.local/share/NomiFun/Nomi),与 systemd 托管的/var/lib/nomifun脱钩。
启动参数 / 环境变量
| 参数 | 环境变量 | 默认 | 说明 |
|---|---|---|---|
--host |
NOMIFUN_WEB_HOST |
127.0.0.1 |
监听地址。0.0.0.0 会对 LAN/VPN/公网可达;请先完成管理员设置或预置密码,公网必须放在 TLS 之后 |
--port |
NOMIFUN_WEB_PORT |
8787 |
同时服务 API、/ws、SPA 的端口 |
--data-dir |
NOMIFUN_DATA_DIR |
按用户目录 | 数据目录(db / 日志 / bun 缓存 / agent 状态)。默认是服务用户的按用户目录(Linux 为 $XDG_DATA_HOME/NomiFun/Nomi);生产请显式指定绝对路径 |
--dist |
NOMIFUN_WEB_DIST |
../../ui/dist |
SPA 静态目录。部署时必须显式指定 |
| — | NOMIFUN_HTTPS |
false |
设 true 时会话/CSRF cookie 带 Secure(仅在 TLS 后用) |
--admin-user |
NOMIFUN_ADMIN_USERNAME |
admin |
预置管理员用户名(仅预置时用) |
--admin-password |
NOMIFUN_ADMIN_PASSWORD |
无 | 设了就在启动时预置管理员、跳过交互首启 |
--insecure-no-auth |
NOMIFUN_WEB_INSECURE_NO_AUTH |
false |
⚠️ 关闭认证(桌面式 no-auth)。只在仅 loopback / 受信私网可达时用 |
直接命令行示例:
nomifun-web --host 127.0.0.1 --port 8787 \
--data-dir /var/lib/nomifun --dist /opt/nomifun/web
Linux 运行时依赖
| 依赖 | 必需性 | 说明 |
|---|---|---|
| glibc + ca-certificates | 必需 | sqlite 静态链接、TLS 用 rustls,无需 openssl / libsqlite |
bun ≥ 1.3.13 |
必需 | agent 执行;1.1.38 有 stdin bug。Docker 镜像里已含 |
node / npm / npx |
推荐 | 用户启用的 MCP stdio server(npx -y …) |
git |
推荐 | skill 发现、部分内置工具 |
ripgrep(rg) |
推荐 | 代码搜索后端(缺则退化到 grep) |
| DISPLAY / X11 / WebView | ❌ 不需要 | nomifun-web 零 GUI 依赖,纯 headless |
安全须知
- 务必走 TLS(公网):cookie 与登录凭据明文传输会被嗅探。TLS 后记得
NOMIFUN_HTTPS=true。 - 首启竞态:从服务起来到你完成首启 setup 之间,理论上谁先访问谁就能占下管理员账号。要彻底关掉这个窗口,用
NOMIFUN_ADMIN_PASSWORD预置;或先监听127.0.0.1/ 内网 / 隧道完成首启,再改为0.0.0.0。 --insecure-no-auth谨慎:它把认证完全关掉(任何能连端口的人 = 特权用户,可执行 shell / 读写文件)。只在纯 loopback 或完全受信的私网用。- 后端有终端 / 文件 / agent 能力,等价于"远程运维 = 远程代码执行(对你自己)"——这正是产品本意,但也因此认证 + TLS 是底线。