自托管 Iva:无需开放端口的 Telegram AI 助手
在小型 VPS 上部署 Iva Telegram AI 助手:无需开放入站端口或域名,使用 systemd 用户服务运行,并将可由 Obsidian 打开的 Markdown 记忆库自行备份。
构建内容
Iva 是一个自托管的 Telegram AI 助手。它是少数无需开放入站端口、也无需为其配置域名即可部署的助手之一。它也不需要证书,因为服务器上没有任何服务监听公网连接。该服务主动连接 Telegram,保持连接打开,并从响应中读取您的消息。其余机制都基于这一条出站连接。
Iva 采用 MIT 许可证,使用 Node 编写。它的记忆内容存储在一组纯 Markdown 文件中,Obsidian 可以直接打开这些文件。因此,即使不使用该应用,Iva 保存的关于您的笔记仍然可读。本指南固定使用于 6 August 2026 发布的 v0.3.13 版本。
大多数自托管软件都从 DNS(domain name system)记录和 使用 Certbot 签发的 Let's Encrypt 证书开始。Iva 完全跳过这一层,因此,一台仅允许 SSH 连接且位于防火墙后的轻量 VPS 就可以完成部署。
为何 Iva 不需要开放端口
iva-telegram-poll.service 是一个长轮询桥接程序。它调用 Telegram 的 getUpdates API 并等待响应,因此每个连接都由您的服务器发起。Telegram 不会反向连接,这意味着无需配置反向代理,也不会忘记续期证书。
代理本身确实会监听端口,但只监听 127.0.0.1 端口 8723。项目文档对此有明确说明:不要暴露 8723 端口;如果在代理前配置反向代理,必须保留 bearer token 要求。安装后请检查绑定地址。
sudo ss -tlnp | grep 8723地址必须显示为 127.0.0.1:8723。类似 0.0.0.0:8723 的通配地址表示代理的 HTTP 路由可从互联网访问。您应在向机器人发送任何私密内容前修复此问题。
因此,防火墙保持关闭状态。启用防火墙前先允许 SSH,因为 ufw enable 在没有 SSH 规则的情况下会关闭您当前使用的会话。
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status一行安装命令的实际操作
项目主页提供了一条命令,将 GitHub 上的脚本通过管道传给 bash。请先阅读脚本,因为它执行的操作远不止安装一个程序。
curl -fsSL https://raw.githubusercontent.com/smixs/iva/main/install.sh -o iva-install.sh
less iva-install.sh- 使用检测到的软件包管理器安装系统软件包:
git、gh、python3、ffmpeg、pandoc和poppler-utils。 - 当服务器的 RAM 少于 1.5 GB 且没有 swap 时,在
/swapfile创建 2 GB 的 swapfile,因为没有 swap 时构建过程会被终止。 - 安装 nvm,然后安装 Node 24。Iva 要求的最低版本就是该版本。
- 将
uv(Python 软件包管理器)安装到~/.local/bin。 - 将代码仓库克隆到
~/iva,然后运行npm ci。 - 安装两个全局 npm 软件包:
agent-browser(随后会下载 Chromium)和@googleworkspace/cli。 - 运行设置向导,构建项目,并创建 vault。
- 将
iva命令写入~/.local/bin,并安装 systemd 用户单元。
一条命令会安装这么多软件。这也说明了 README 要求使用普通用户而不是 root 执行安装的原因:后续 agent 的 shell 工具会继承安装程序所使用的权限。脚本只在安装软件包和创建 swapfile 时调用 sudo,并通过一个辅助函数处理这些操作;如果当前用户已经是 root,该函数会直接运行命令。
安装前创建专用用户
为 Iva 创建独立账户。该代理通过 Node 的 child_process 在主机上执行 shell 命令,不使用容器或沙箱,因此它运行所用的账户就是安全边界。
sudo adduser --disabled-password --gecos "" iva
sudo usermod -aG sudo iva
sudo install -d -m 700 -o iva -g iva /home/iva/.ssh
sudo cp ~/.ssh/authorized_keys /home/iva/.ssh/authorized_keys
sudo chown iva:iva /home/iva/.ssh/authorized_keys
sudo chmod 600 /home/iva/.ssh/authorized_keys
sudo loginctl enable-linger ivaenable-linger 很重要,因为 Iva 以 systemd user 单元运行。未启用 linger 时,用户的最后一个会话结束后,systemd 会立即停止该用户的服务,因此关闭 SSH 后,助手也会退出。您在 systemd 下自行编写的任何 服务和计时器 也遵循相同规则。
只有在安装程序添加软件包期间,账户才需要 sudo。安装完成后将其移除。
sudo deluser iva sudo直接通过 SSH 以该用户登录。使用 sudo -iu iva 进入的 shell 未设置 DBUS_SESSION_BUS_ADDRESS 或 XDG_RUNTIME_DIR,因此每个 systemctl --user 命令都会因 Failed to connect to bus 而失败。设置这一安全边界,与让服务以最低权限用户运行遵循相同原则。
安装固定版本,而不是通过管道传给 bash
安装脚本有一个实用特性。在执行任何克隆操作前,它会检查脚本所在目录中是否已经存在包含 "eve" 的 package.json。如果存在,脚本会构建该代码检出目录,并跳过克隆操作。因此,您可以自行选择版本。
git clone --branch v0.3.13 https://github.com/smixs/iva.git ~/iva
cd ~/iva
git log -1 --oneline
bash install.sh现在您知道正在运行的是哪份代码。如果脚本在某个时间点克隆 main,您就无法确定当时使用的是哪个状态。Iva 在 2026 年 8 月 4 日至 6 日期间发布了 5 个版本,因此今天上午的 main 和今天下午的 main 不是同一个程序。
检出 tag 后,git 会处于 detached HEAD 状态。程序仍可正常运行,但您需要了解其限制:iva update 会将代码检出目录前移到更新分支,因此固定版本只是一个已知起点,并不表示永久冻结。iva version 会输出软件包版本和 git 提交,因此您随时可以确认当前使用的版本。
如果要主动切换到较新的版本,请列出 tags,将 IVA_TAG 设置为您选择的 tag,然后再次从代码检出目录中运行安装脚本。
cd ~/iva
git fetch --tags
git tag --list 'v*' | sort -V | tail -5
IVA_TAG=v0.3.13
git checkout "$IVA_TAG"
bash install.sh --skip-setup
iva restart--skip-setup 可防止向已经正常运行的 .env 再次运行向导。
向导分为 5 个步骤,并会要求以下密钥
- 模型提供商和模型。
MODEL_PROVIDER接受opencode、ollama、openrouter或codex。向导会实时验证密钥,并列出您的套餐可用的模型。 - 语音和搜索。Deepgram 密钥用于转录语音消息。Web 搜索密钥(Tavily、Exa、Parallel 或 Brave)是可选的。
- 从 @BotFather 获取 Telegram bot token,并通过
getMe端点进行检查。 - 访问控制。您向 bot 发送一条消息,向导会从
getUpdates中读取您的数字用户 ID。 - 系统设置。包括 IANA 时区、vault 目录和本地端口,默认端口为 8723。
“一个命令”这种说法掩盖了其中的两个依赖项。Iva 不附带模型,因此在回答任何内容前,需要付费模型套餐或 API key。Iva 也不会自行转录音频,因此语音消息需要单独的服务。Deepgram 的 nova-3 模型配合 DEEPGRAM_LANGUAGE=multi 可检测语言。新的 Deepgram 账户会获得 starter credits,足以支持数月的个人使用。仅使用模型 key 即可处理文本。只有语音功能依赖 Deepgram。
检查向导写入的内容。
grep -E '^(MODEL_PROVIDER|TELEGRAM_ALLOWED_USER_IDS|ASSISTANT_VAULT_DIR|IVA_PORT)=' ~/iva/.env
ls -l ~/iva/.envls 应输出 -rw-------,权限模式应为 0600,因为该文件包含您刚才粘贴的所有密钥。TELEGRAM_ALLOWED_USER_IDS 必须包含您的数字 ID。允许列表采用默认拒绝策略,因此空值意味着 Iva 不会回答任何人。
模型只会在进程启动时读取一次。编辑 MODEL_PROVIDER 或修改 .env 中的模型名称,在运行 iva restart 之前都不会生效。在 openrouter 中,模型名称是类似 anthropic/claude-sonnet-4.5 的供应商 slug,而不是不带供应商信息的名称。在 codex 中,完全不需要 API key:iva login 会登录现有的 ChatGPT 订阅。
Iva 每月运行成本是多少
The data behind this chart
[
{
"plan": "Small VPS, always on",
"usd_per_month": 5
},
{
"plan": "OpenCode Go model plan",
"usd_per_month": 5
},
{
"plan": "Ollama Cloud model plan",
"usd_per_month": 20
},
{
"plan": "Deepgram voice, starter credits",
"usd_per_month": 0
},
{
"plan": "Tavily web search, free tier",
"usd_per_month": 0
},
{
"plan": "Cheapest complete setup",
"usd_per_month": 10
}
]以下是截至 2026 年 8 月公布的标价,不是实际测量结果。小型 VPS 的费用为 5 美元,OpenCode Go 计划的费用为 5 美元,这是最便宜的完整方案,每月约为 10 美元。Ollama Cloud 是另一种固定费率方案,费用为 20 美元;其前沿模型的费用会在计划费用之外按用量计费。Deepgram starter credits 用完前,语音服务的费用为 0。
这里没有列出 OpenRouter,因为它按实际用量计费,账单金额取决于您的用量。这是需要重点关注的选项:如果助手在每轮对话中都使用 131072 token 的上下文窗口,费用可能很快超过固定费率方案。请将上下文窗口变量设置为模型的实际大小,因为设置过大的值只会浪费 token。
两个服务和两个计时器
iva.service运行代理本身。iva-telegram-poll.service运行与 Telegram 通信的长轮询桥接服务。iva-memory-doctor.timer在 05:00 触发,并对 vault 执行每晚维护。iva-update-check.timer在 10:00 触发,并检查是否存在更新版本。iva-telegram-userbot.service仅在设置了可选的 Telethon 代理时存在。
iva status
systemctl --user status iva.service iva-telegram-poll.service
systemctl --user list-timers
iva logs polliva status 报告两个服务和两个监控计时器的状态。systemctl --user list-timers 输出每个计时器的下一次运行时间。通过该时间可以确认 memory doctor 今晚确实会运行。两个服务都应处于 active (running) 状态。如果其中一个服务循环重启,journalctl --user -u iva.service -n 100 会给出原因。
调试时,拆分服务很重要。桥接服务可能仍在运行并持续轮询,但代理已经停止。此时 Telegram 会接受您的消息,却始终没有服务响应。iva logs poll 跟踪桥接服务,iva logs 跟踪代理,因此两个日志可以帮助您确定哪一部分发生故障。
Obsidian 库的位置及备份方法
ASSISTANT_VAULT_DIR 默认位于安装目录中的 vault,因此记忆数据存储在 ~/iva/vault。它是独立的 Git 仓库,与代码分开,因此更新 Iva 不会影响您的笔记。
vault/CORE.md保存长期有效的事实和固定偏好,最多 1200 个字符,并会随每个系统提示一起发送。vault/daily/YYYY-MM-DD.md保存当天的记录,并且只允许追加内容。vault/cards/保存联系人、项目、决策、想法和笔记的结构化卡片。vault/summaries/daily/、weekly/、monthly/和yearly/保存汇总数据。vault/attachments/按日期保存文件,vault/.graph/保存链接图。vault/schema.json定义卡片类型和衰减规则。
汇总任务在进程内部按计划运行。每天 04:00 执行的任务会将前一天的记录转换为卡片和摘要,并重写 CORE.md;随后每周、每月和每年的任务会依次压缩这些内容。05:00 时,记忆维护程序会执行一个不涉及模型的确定性任务:检查并强制执行架构、重建链接图、重新生成索引,然后提交并推送更改。
推送就是备份,也是最容易被忽略的步骤。如果库没有 Git 远程仓库,维护程序会通过 gh 尝试创建私有 GitHub 仓库;这需要已完成身份验证的 GitHub CLI。
gh auth login
systemctl --user start iva-memory-doctor.service
cd ~/iva/vault && git log --oneline -3提交日期为今天,表示任务已运行且库已提交。日志中的 gh not available 警告表示相反的情况:库虽然得到维护,但从未离开服务器,因此 VPS 故障会连同您的记忆一起丢失。
同时保留一份由您控制的副本。
tar czf ~/iva-vault-backup.tgz -C ~/iva vault使用 scp 将该文件复制到服务器外,然后从服务器中删除它。要在 Obsidian 中读取记忆,请让 Obsidian 使用库仓库的克隆副本。Wikilink、反向链接以及图谱视图都无需额外配置即可使用。手动编辑卡片和 CORE.md 是安全的。请勿修改 MOC.md 和 .graph/,因为每晚的任务会重新生成这两个文件。
将 vault 视为人生日志
该目录记录了您在一台租用的机器上说过什么、见过谁以及做过哪些决定,并按日期整理。由此可以得出两点。
自托管改变的是存储位置,而不是处理位置。每轮请求都会发送给您的模型提供商,每条语音笔记都会发送给 Deepgram。vault 属于您。但为这些请求提供服务的公司仍能看到请求内容。自行运行记忆层也是如此,例如在自己的 VPS 上运行 Mem0 记忆服务器:存储在本地,但模型调用仍会离开您的服务器。如果某个主题敏感到不适合交给第三方处理,请不要将其放入聊天中。
该账户可以访问整个 vault。Iva 的工具通过 Node 的 fs 和 child_process 在主机上原生运行,不使用 Docker 或沙箱,因此一轮请求被劫持后,可以获得服务用户拥有的全部权限。这就是安装完成后该账户不保留任何 sudo 的原因,也是允许列表值得重点关注的原因:它决定哪些人的消息可以在您的服务器上变成命令。如果您希望随身使用助手,但不开放任何端口,这与从手机访问自行托管的 Hermes 代理采用的是同一模式:由聊天客户端承担原本需要公网端点完成的工作。
出现的问题及对应提示
构建被终止,退出码为 137。 内核的 out of memory killer 终止了构建。安装程序仅在 RAM 小于 1.5 GB 且不存在 swap 时添加 swap,因此请手动添加 swap,然后再次运行安装程序。
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
free -hFailed to connect to bus。 每个 systemctl --user 命令都会在 shell 没有用户会话总线时显示此提示,而 sudo -iu iva 正是用于提供该总线的命令。以该用户打开普通 SSH 会话,或在运行命令前导出 XDG_RUNTIME_DIR=/run/user/$(id -u iva)。
机器人不响应。 TELEGRAM_ALLOWED_USER_IDS 为空,并且允许列表采用默认拒绝策略。向机器人发送一条消息:它只会回复您的数字 ID,不会回复其他内容。将该 ID 写入 .env,然后运行 iva restart。
机器人在 iva config 后立即停止响应。 向导可能会移动 IVA_PORT,但不更新 ASSISTANT_HOST,因此桥接服务会连接到没有任何服务响应的端口。比较这两行内容,然后重启。
grep -E '^(IVA_PORT|ASSISTANT_HOST)=' ~/iva/.env
iva restart语音消息没有回复。 Telegram Bot API 拒绝下载超过 20 MB 的文件,因此桥接服务无法接收较长的音频,也就无法将其发送给 Deepgram。发送前请拆分文件。
ffmpeg -i long.ogg -f segment -segment_time 600 -c copy part-%02d.ogg一轮对话卡住且始终没有回复。 卡住的工作流状态会在重启后保留,并重新加入队列,因此仅重启无法清除该状态。iva reset 会隔离该状态并重启两个服务。在聊天中发送 /new 可开始新的对话。
Chromium 在 Ubuntu 24.04 上启动失败。 Ubuntu 24.04 通过 AppArmor 阻止非特权用户命名空间,因此 Chromium 自带的沙箱无法启动,agent-browser 会失败。安装程序通过将 "--no-sandbox" 写入 ~/.agent-browser/config.json 来绕过此限制。请注意该配置的存在。它会降低浏览器的隔离级别,因此账户更应只拥有 Iva 所需的权限。
FAQ
自托管 Iva 是否需要域名或开放端口?
不需要。Iva 通过长轮询与 Telegram 通信:iva-telegram-poll.service 调用 getUpdates 并等待响应,因此所有连接都由您的服务器主动发起。外部无需访问该服务器,因此不需要 DNS 记录或证书。代理自身的 HTTP 端口 8723 绑定到 127.0.0.1,项目文档明确要求不要将其暴露到公网。防火墙只允许 SSH、拒绝其他所有连接,就是正确配置。
每月运行 Iva 需要多少费用?
按 2026 年 8 月公布的目录价格计算,一台小型 VPS 每月 5 美元,加上价格最低的固定费率模型方案 5 美元,合计每月约 10 美元。Ollama Cloud 每月费用为 20 美元,前沿模型还需另外计费。Deepgram 的入门额度起初可以覆盖语音处理,网页搜索方案也提供免费额度。OpenRouter 按使用量计费,因此没有固定的月度费用。
Iva 将数据存放在哪里?如何备份?
默认存放在 ~/iva/vault 中,由 ASSISTANT_VAULT_DIR 设置。这是一个独立的私有 git 仓库,内容为纯 Markdown 文件:CORE.md、daily/YYYY-MM-DD.md、cards/ 和 summaries/。05:00 运行的 memory doctor 会提交并推送这些内容,但只有在仓库配置了远程仓库时才有作用。因此,请运行 gh auth login,或在安装过程中添加您自己的远程仓库。还应使用 tar czf ~/iva-vault-backup.tgz -C ~/iva vault 保存离线副本,并将该文件移出服务器。
自托管 Iva 时,我的数据是否私密?
存储由您控制,但处理过程并非如此。vault 在推送前会保留在您的磁盘上,.env 的权限为 0600,所有者是服务用户。模型调用和语音转录使用云 API,因此相关消息会经过您的模型提供商和 Deepgram。Iva 使用 MIT 许可证授权,您可以准确查看它发送的内容并进行修改。Telegram allowlist 采用默认拒绝策略,因此空的 TELEGRAM_ALLOWED_USER_IDS 会阻止所有人,包括您自己。
Iva 支持哪些模型提供商?
MODEL_PROVIDER 接受 opencode(OpenCode Go)、ollama(Ollama Cloud)、openrouter 和 codex。OpenRouter 使用类似 anthropic/claude-sonnet-4.5 的供应商标识符,并提供最广泛的模型选择。codex 通过 iva login 登录现有的 ChatGPT 订阅,无需 API key。设置提供商,将匹配的上下文窗口设置为模型的实际大小,然后运行 iva restart,因为模型配置只会在进程启动时读取一次。