ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI Agent托管到家庭主机:systemd服务化与反向代理远程接入实践

AI Agent托管到家庭主机:systemd服务化与反向代理远程接入实践 站在2026年回看AI Agent早就不稀奇了。稀奇的是怎么让它别总赖在开发机上白天你盯着终端的时候它跑得欢一合上笔记本、一出门它就跟着连滚带爬地断线。我手头有一个基于Rust写的Agent负责盯数据源、跑定时任务、做代码评审折腾完模型配置和Prompt之后最让我头疼的反而是这些最不“AI”的事——进程守护、日志管理、远程访问、安全防护。这篇文章就是我把这个Agent托管到家里电脑上并且实现远程CLI管理和安全接入的完整实测记录适合那些手里正好有闲置小主机、旧笔记本或NUC想让Agent 7x24小时稳定常驻的开发者。我会按实际改造顺序讲先讲为什么我坚持放家里而不是上云再讲怎么把它变成系统级服务然后讲端口映射和反向代理的安全姿势最后是踩过的坑和一套可以直接抄走的配置。1. 为什么要把AI Agent托管在家里电脑而不是直接租一台云服务器很多人一听“托管”就想上云我一开始也是。但在2026年云主机的费用、数据边界和本地算力闲置这三个问题叠在一起让我仔细算了这笔账。1.1 隐私和数据边界是最先被我说服的理由我的Agent不是只调API回答问题它手里握着很多不能随便外传的东西内部代码仓库的读取权限、自己写的笔记、抓取下来的业务数据、历史对话记录。如果把它放到第三方云主机上这些数据就得先离开我的控制范围虽然云平台本身不会主动看但多一跳就多一层风险。放在家里电脑上数据只在我自己的磁盘里转调用外部大模型API时也只需要提交当前任务所需的片段而不是把整个上下文目录都交出去。对一些习惯把Agent当成“私人秘书”的人来说这条比成本还重要。1.2 算力与成本云GPU太贵家里的显卡却在吃灰云服务器的CPU实例其实不贵4核8G一个月几十块也能接受。但AI Agent很多场景要靠GPU推理比如本地跑小模型做二次过滤、图像处理、Whisper语音转写这时候云GPU的价格就上去了按小时计费长期常驻一个月几百到上千很正常。反观家里这台闲置电脑CPU常年10%都跑不到显卡更是吃灰已久让它每天多干点活唯一成本就是几十瓦的功耗。我实测这台托管主机整机待机时功耗约45W,满载约120W,按照0.55元/度电算一天满载跑8小时一个月电费也就十几块。这笔账怎么算都是本地划算。1.3 这个方案到底适合谁不适合谁说到底决定权在场景。如果你的Agent要服务公网用户有SLA要求需要多节点容灾那别想了直接上云。如果你只是自己用、小队内部用、定时跑任务、需要它能操作家里的其他设备那本地托管是性价比极高的路线。它最大的短板是家里断电断网和没有公网IP这两点我在后面会给出对应的应对方案但它确实不适合那种“必须全年无休在线”的严肃生产场景。一句话自用有余商用不足定位清楚就好办。2. 托管的第一步把“终端里跑的Agent”变成“系统级常驻服务”我最早跑Agent的方式很原始开一个终端窗口执行agent serve然后祈祷自己不要关窗口、不要断SSH、不要让电脑休眠。这直接导致Agent的可用性大概只有30%——不是它跑得不好而是我根本没把它当成一个“服务”来对待。2.1 为什么不能依赖“开个终端挂着”的野路子这个问题要从进程生命周期讲起。你在终端里启动的Agent进程是挂在当前终端会话下面的。终端窗口一关或者SSH会话断开系统就会向这个进程发送SIGHUP信号默认行为就是终止进程。就算你用了nohup绕过挂断信号进程还是没人看护崩溃了没人拉起日志越写越大没人轮转开机不会自启升级时还得手动去终端里找那个锈迹斑斑的进程。更严重的是很多人图省事直接用root跑Agent一旦Agent被外部输入诱导做了危险操作权限边界就直接被击穿了。所以托管的起点一定是把它注册成操作系统层面的常驻服务。2.2 用systemd把Agent注册成常驻服务在Linux小主机上我选systemd这几乎是现代Linux的事实标准配置一次就能获得开机自启、崩溃重启、内存限制、日志收集这些能力。先为Agent创建一个独立用户不要让服务进程以root身份运行sudo useradd --system --home /opt/agent --shell /usr/sbin/nologin agent sudo mkdir -p /opt/agent/data /opt/agent/logs sudo chown -R agent:agent /opt/agent然后写服务单元文件/etc/systemd/system/agent.service[Unit] DescriptionHome AI Agent Service Afternetwork-online.target Wantsnetwork-online.target [Service] Useragent Groupagent WorkingDirectory/opt/agent EnvironmentFile/etc/agent.env ExecStart/opt/agent/agent serve --host 127.0.0.1 --port 8765 Restartalways RestartSec5 TimeoutStopSec30 KillModemixed MemoryMax2G MemoryHigh1.5G CPUQuota50% LimitNOFILE65535 NoNewPrivilegestrue ProtectSystemstrict ProtectHometrue ReadWritePaths/opt/agent/data /opt/agent/logs PrivateTmptrue [Install] WantedBymulti-user.target这个配置有几个关键点值得展开说说。Restartalways加RestartSec5保证进程无论正常退出还是崩溃都能在5秒后自动拉起来这是“7x24小时可用”的第一道保险。KillModemixed的意思是停止服务时先向主进程发SIGTERM给它时间做优雅退出等超时再用SIGKILL清掉剩余进程。为什么要专门提这个因为很多Agent会拉起Python脚本、浏览器进程、子任务worker如果只是杀掉主进程子进程会变成孤儿继续跑下一节我会专门讲这个坑。MemoryMax2G是硬限制超过2G系统直接OOM杀掉进程防止Agent内部的内存泄漏把整台小主机拖死。ProtectSystemstrict和ProtectHometrue是systemd提供的沙箱能力让Agent只能写指定目录就算被攻破也改不了系统文件。2.3 日志不要自己管文件交给journald日志处理我走过弯路。最初Agent自己写日志文件结果要写logrotate配置、处理文件锁、还要担心磁盘被写满。后来干脆让所有日志输出到标准输出由systemd的journald统一收集。好处是日志会自动按时间和大小轮转查看时一条journalctl -u agent搞定还能按时间范围过滤journalctl -u agent -f # 实时跟踪 journalctl -u agent --since 1 hour ago # 最近一小时 journalctl -u agent -p err # 只看错误唯一要主动设置的是journald的体积上限不然后果就是日志悄悄吃掉大量磁盘空间这个坑我放在最后一节详细说。先在这里改一下/etc/systemd/journald.confSystemMaxUse500M SystemMaxFileSize64M改完重启journald即可。这套组合拳下来Agent已经从一个“跑在终端里的程序”变成了“系统托管的服务”接下来才轮到远程访问的问题。3. 远程接入方案自建反向代理做安全入口端口映射只做通道Agent变成常驻服务之后我要解决的下一个问题是出门在外怎么安全地访问它。这个环节坑最多我见过太多人直接把Agent的Web端口映射到公网然后等着被人扫到漏洞轻则token被刷爆重则整台机器被种马。3.1 为什么不能直接把Agent的Web端口裸奔到公网Agent通常自带一个Web管理面板或API服务里面一般包含对话记录、历史任务、上传文件入口甚至有些人会配置成可以执行命令的工具。只要这个端口暴露到公网就等于把自家大门钥匙挂在门框上。公网扫描器是不会休息的一个端口从映射生效到被扫描器发现通常只需要几分钟到几十分钟。扫描器会用常见的路径试探/api、/admin、/v1/chat、/v1/completions如果你的Agent没有做认证或者认证逻辑有疏漏极其容易被打穿。所以我的第一步是让Agent只监听回环地址127.0.0.1也就是前面服务配置里--host 127.0.0.1的意义它本机可以用外部一律不进。ss -tlnp | grep 18765看到监听地址是127.0.0.1:8765而不是0.0.0.0:8765时这一步才算做对了。3.2 Caddy反向代理加自动HTTPS最省心的进门方案既然Agent不允许直接对外就必须有一个“门卫”替它接收外部流量再做一层转发这个门卫就是反向代理。我选了Caddy而不是Nginx最大原因是Caddy会自动申请和续期HTTPS证书不需要我手动维护证书文件。2026年的现状是没有HTTPS的管理接口本身就等于裸奔登录凭据在网络上明文传输所以自动HTTPS不是省事的问题是底线问题。Caddy配置非常简单一个Caddyfile就搞定agent.example.com { reverse_proxy 127.0.0.1:8765 basicauth { admin $2y$05$abcdefghijklmnopqrstuvwx } }这里第一行是你的域名第二行把外部请求转发给内网的Agent服务第三行加了一层HTTP Basic Auth。不过说实话Basic Auth只适合个人自用它的密码是明文放在Caddyfile里的如果有多人使用我还是建议再套一层OAuth2 Proxy让登录走GitHub或企业微信等身份提供商这能在不写死密码的前提下做统一的访问控制。basicauth密码可以用caddy hash-password命令生成注意别把原密码写进配置。3.3 端口映射操作细节高位端口、防火墙白名单、来源IP限制Caddy只需要监听443端口但家庭宽带运营商通常会在公网侧封禁80和443端口。硬顶着这些端口不仅容易被封而且会让你的主机暴露在所有扫描器的默认扫描范围里。我的做法是公网侧用8443之类的非标准高位端口然后在路由器里做“端口映射”把公网8443转发到内网主机的443。具体操作以我家的路由器为例登录管理后台后找到“端口映射”或“端口转发”页面添加一条规则公网端口内网IP内网端口协议状态8443192.168.1.10443TCP启用保存后用手机流量访问https://agent.example.com:8443试一下能打开Web面板就说明映射成功。这里要特别提醒如果路由器支持“源IP过滤”或“访问控制”一定要把你常用的办公网段或手机运营商出口网段加进去其余来源直接丢弃。注意运营商给手机分配的IP是可变的所以不能依赖白名单作为唯一防线它只是减少暴露面的第一层真正的安全还是要靠认证和限流。3.4 没有公网IPv4时怎么兜底这个前提在2026年仍然存在很多家庭宽带拿不到公网IPv4只有大内网地址。我的处理优先级是这样的按推荐程度排最推荐给运营商客服打电话申请开通动态公网IPv4。很多地区家庭宽带是可以免费开的申请之后再用DDNS绑定域名就能获得一个用于自用的公网入口。次选检查是否有公网IPv6地址。现在不少地区的家庭宽带默认下发IPv6只要路由器支持你可以用IPv6 DDNS的方式在公网访问内网主机的IPv6地址记得在路由器IPv6防火墙里只放行指定端口到指定主机。兜底如果两种公网IP都拿不到老实说我不建议去折腾那些第三方穿透工具维护成本和安全风险都不可控。我的建议是把Agent用途限制在家庭局域网内远程场景只做应急处理或者干脆给Agent配一台有公网IP的轻量云服务器作为跳板入口通过标准加密通道回连但这已经超出本文“家里托管”的范畴了。3.5 顺带解决Agent出站访问的统一出口问题“网络代理”这个词在标题里出现了我这里必须说明我实际是怎么用的。我的Agent需要调用外部大模型API但家里上网出口的IP是动态变动的导致一些服务端的频率限制策略时不时把我拦下来。我在小主机上部署了一个正向代理服务作为“统一出口”让Agent的所有出站请求都走这个出口IP同时也方便统一审计Agent到底在请求哪些外部接口。配置方式只是给Agent的环境变量加上出口代理地址export HTTP_PROXYhttp://127.0.0.1:7899 export HTTPS_PROXYhttp://127.0.0.1:7899这样做的目的是出口统一、IP稳定、请求可审计属于合规的出站访问管理手段。需要澄清的是这跟“让不能访问的网络变得可访问”完全是两码事它解决的是API调用审计和出口稳定的问题不是让你去碰不该碰的网络边界。4. 远程CLI在手机和另一台电脑上操作家里的Agent端口映射和反向代理解决的是“Web面板能打开”但我的日常操作更依赖命令行。远程CLI的好处是脚本化、省流量、可审计而且很多操作比如查看状态、拉日志、提交新任务在命令行里一条命令就能完成比打开网页点来点去快得多。4.1 SSH访问的家庭局域网路径先说SSH。我的公网入口只开放HTTPS不直接暴露SSH端口这是我给自己定的规矩。但家庭局域网内SSH可以全开因为在同一局域网里本来就默认是可信环境。我在另一台电脑上这样连家里的Agent主机ssh agent192.168.1.10为了让这个操作更简短我用了SSH配置文件。在~/.ssh/config里加一段Host home HostName 192.168.1.10 Port 22 User agent IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 30这样每次登录只需要输入ssh home。如果一定要在外网使用SSH我的建议是先确保公网入口只对特定IP开放SSH端口改成高位端口关闭密码登录只保留密钥再挂一道fail2ban。这些我在第5节会一起讲。4.2 Agent本身CLI的远程使用我的Agent带了一个CLI入口它和serve命令分开专门用于提交任务和查询状态。在远程SSH会话里我实际是这样的使用模式ssh home agent status ssh home agent submit 帮我整理一下今天的项目进展输出成markdown ssh home agent logs --tail 20 ssh home agent latest这几条命令覆盖了我90%的需求看Agent是不是活着有没有在处理任务最近结果是什么日志里有没有报错。这里有个经验之谈Agent的CLI设计成“无状态、单命令”最好。不要搞成交互式会话因为交互式会卡在远程终端里还必须留一个终端窗口挂着而单命令执行完就退出可以被cron调度、可以被CI/CD调用、可以被封装成脚本。4.3 把常用运维操作封装成脚本远程命令虽然好但每次都打一长串还是累。我把常用操作封装到~/.local/bin/ha脚本里内容大致是这样#!/usr/bin/env bash set -euo pipefail case ${1:-} in status) ssh home agent status ;; logs) ssh home journalctl -u agent --since ${2:-10 minutes ago} -n ${3:-100} --no-pager ;; restart) ssh home sudo systemctl restart agent ;; submit) shift ssh home agent submit \$*\ ;; snapshot) ssh home sudo tar czf /root/agent-$(date %Y%m%d).tar.gz /opt/agent/data ;; *) echo Usage: ha {status|logs|restart|submit|snapshot} ;; esac写完之后chmod x ~/.local/bin/ha日常操作就变成了ha status、ha logs、ha restart。手机端我直接用SSH客户端App连家里局域网信号稳定时也能临时查状态、提交任务完全不需要依赖任何第三方中转服务。4.4 CLI合规性检查小建议如果用这套方案的人不止你一个我建议在CLI层面顺手做两件事一是让每个submit操作都带上提交者身份比如环境变量AGENT_REQUESTER这样Agent能区分任务是谁发起的二是把CLI命令的操作日志也吐到journald方便日后审计谁在什么时候让Agent做了什么。这看起来是小细节真出了事追溯问题时能省很多力气。5. 安全加固把“能用”提升到“扛住公网扫描”的等级端口映射开起来、CLI能用之后安全等级只能算“能用”离“敢放心长期挂在公网”还有距离。这一节我把踩过的安全和运维细节一次性说透。5.1 公网扫描是常态先学会看日志我第一次把8443端口映射到公网那天第二天早上看防火墙日志发现来自海外的扫描IP已经刷了三千多条记录。大部分扫描请求长这样GET /、POST /api、GET /admin、POST /v1/chat/completions。这说明你的IP只要暴露在公网扫描是24小时不间断的心态上一定要接受这件事然后用工具去挡。我实际启用了两层防护。第一层是fail2ban它监控SSH和Web服务的日志探测到同一IP多次失败登录就自动在防火墙层面封禁该IP一段时间。配置路径是/etc/fail2ban/jail.local我把SSH的maxretry设成5次bantime设成6小时效果立竿见影。第二层是Caddy的rate_limit指令给Web面板加一个单位时间内的请求次数上限防止有人对登录接口做暴力枚举agent.example.com { rate_limit { zone dynamic { key {remote_host} events 20 window 1m } } reverse_proxy 127.0.0.1:8765 basicauth { admin $2y$05$... } }这段配置表示同一来源IP在1分钟内超过20次请求就暂时拒绝。对正常的个人使用来说这个阈值完全够用。5.2 弄清楚“AI Agent Token”到底存的是什么东西标题热搜词里有“ai agent token是什么意思”这里必须讲清楚。在2026年做Agent应用token这个词至少指三种东西混淆它们就会出安全事故第一种是外部大模型API的密钥形式通常是sk-xxx代表你调用模型服务的身份和计费凭证谁拿到它就能用你的钱去调模型。第二种是Agent自身会话的鉴权token用于验证当前请求是不是来自合法客户端防止接口被越权调用。第三种是Agent服务内部的加密密钥用来加密存储的对话历史、凭证等敏感数据。这三种token的共性是一旦泄漏后果轻则被盗用计费重则数据泄露。我把它们全部统一管理不放代码里、不放配置文件里只放在/etc/agent.env同时让这个文件只能被agent用户读取sudo chown root:agent /etc/agent.env sudo chmod 640 /etc/agent.env环境文件内容长这样OPENAI_API_KEYsk-xxxxx AGENT_AUTH_TOKENxxxxx AGENT_STORAGE_KEYxxxxx然后在systemd服务里通过EnvironmentFile/etc/agent.env加载。这样即使源代码仓库被公开密钥也不会被带出去。别忘了做定期轮换我给自己定了90天换一次API Key的规矩手机上设了个循环提醒。5.3 访问控制三板斧认证、限流、隔离我把这里的经验总结成“三板斧”缺一不可。认证是判断你是谁限流是防止别人暴力试你隔离是压住攻击后的爆炸半径。认证层上面写了Basic Auth和OAuth2 Proxy这里再补一句如果Agent提供了自己的登录页面优先关掉它而不要依赖它。因为Agent自带的登录逻辑往往是模型工程师顺手写的测试覆盖不足不如让反向代理统一接管认证。隔离层要做两件事。第一件是网络隔离主路由器如果支持VLAN或有线网段隔离就把Agent主机单独放到一个隔离网段避免Agent被攻破后横向渗透到家里其他设备。第二件是进程隔离前面systemd配置里的Useragent、NoNewPrivilegestrue、ProtectSystemstrict都在做这件事让Agent进程即使被利用也没有权限读写系统文件。5.4 日志中的敏感信息也要处理最后说一个大家容易忽略的点Agent的日志里会完整打印Prompt内容、API响应、甚至包含被截断的API Key片段。如果你直接把整个journalctl导出发给朋友排查问题等于把内部的完整调用上下文交了底。我的处理办法是三个给Agent日志级别设置生产阈值平时只记录INFO以上不输出DEBUG级别的完整Prompt体。在日志输出链路加一层脱敏过滤器把类似sk-开头的长字符串统一替换成sk-***。定时清理过期日志按需求保留30天超过的直接清除不做无限期保留。安全这件事永远是层层设防而不是单点解决。反向代理、fail2ban、密钥轮换、日志脱敏每层都能挡掉一部分攻击合在一起才是“敢长期裸奔在公网”的底气。6. 踩坑记录与最终稳定运行配置这一节我把托管过程中真正让我熬夜的四个问题原样复盘每个都附上排查思路和修复方法。这些问题在文档里几乎查不到但实际运行时个个都能让Agent从“在线”变成“装死”。6.1 坑systemd重启后Agent装死旧子进程还活着现象是这样的我改完配置执行systemctl restart agentStatus显示active (running)但Agent的Web面板怎么都打不开。journalctl -u agent里只有一条启动日志然后什么都没了。排查的时候我用ps -ef | grep agent发现旧的主进程被杀掉了但一个名为agent-worker的子进程还挂在系统里CPU占用为0也不响应信号。根因出在KillModemixed的语义上它只向主进程发SIGTERM子进程并不会收到。Agent的主进程收到SIGTERM后正常退出但负责任务调度的worker进程已经和主进程脱钩变成了孤儿进程占着HTTP端口新启动的Agent因为端口被占而失败。修复方案有两处第一把KillMode改成control-group这样systemd停止单元时会向服务所属cgroup内的所有进程发送SIGTERM第二给Agent程序加上SIGTERM处理逻辑收到信号后优雅退出所有worker线程而不是直接让进程结束。两个都做完restart就永远干净利落。6.2 坑HTTPS证书续期失败因为DDNS更新晚于续期请求Caddy虽然自动续期证书但前提是域名解析必须指向当前的家宽IP。家庭宽带IP是动态的我用一个DDNS脚本每5分钟检查一次公网IP是否有变化变了就调用DNS服务商API更新解析记录。问题出在某一次家宽IP变动后DNS解析还指向旧IPCaddy尝试续期证书时校验域名所有权失败续期一直失败直到证书过期。排查过程很典型手机浏览器访问https://agent.example.com:8443直接证书错误SSH到主机上看journalctl -u caddy确认Caddy在报“TLS handshake error”和“challenge failed”。然后用dig agent.example.com看解析发现记录还是旧的。修复很简单确认DDNS脚本已经把解析更新到新IP再执行systemctl reload caddy。但教训很深刻我之后在DDNS脚本里加了一行“更新成功后再等待15秒”确保DNS缓存和Caddy的查询都能拿到新记录避免更新还没生效就触发续期流程。6.3 坑日志把磁盘写满Agent和整个系统一起躺平这个坑最隐蔽。因为我把Agent日志交给journald后就一直没管过它结果Agent的DEBUG级别日志异常狂刷/var/lib/journal把一个20G的系统盘写满了。磁盘满了之后Agent写不了任何文件连数据库锁都拿不到进程反复崩溃SSH登录也报错因为写不了/var/run相关的会话文件。排查时用journalctl --disk-usage查看日志占用显示已经接近10G当时就明白问题在哪儿了。立即执行journalctl --vacuum-size200M清理到200M以下再修改/etc/systemd/journald.conf加上SystemMaxUse500M最后重启journald。从那以后我还在监控面板里加了一条磁盘使用率告警超过80%就通知彻底根治。6.4 坑Token被不小心提交进Git仓库这个事故很经典我在开发Agent时把/etc/agent.env的测试版放到项目目录下又在调试时手滑执行了git add -A结果带着OPENAI_API_KEY的agent.env被推进了私有仓库。虽然仓库是私有的但当时的规则是“任何密钥都不应该出现在Git历史里”而且私有仓库也有被泄露的可能。处理分三步走的第一步是登录模型服务商后台把泄漏的API Key直接轮换让旧Key立即失效第二步是用git filter-repo把文件从Git历史里彻底抹掉第三步是给仓库加.gitignore模板强制忽略*.env和.env同时在团队Wiki里写了一条铁律所有密钥文件只进系统环境文件永远不进仓库。“立即轮换”是第一优先级的不要想着“仓库是私有的应该没人看到”在这个行当里没有“应该”。6.5 最终稳定配置清单和实测效果踩完这些坑之后我整理了一份最终清单照着这个配置又稳定跑了45天无故障全部记录如下项目配置说明进程托管systemd KillModecontrol-group崩溃自愈重启不残留孤儿进程资源限制MemoryMax2G CPUQuota50%防内存泄漏防CPU失控日志journald SystemMaxUse500M自动轮转磁盘占用可控远程入口Caddy HTTPS Basic Auth rate_limit不暴露裸端口默认加密端口映射公网8443 转发 内网443仅放行指定来源IP减少暴露面配合认证兜底SSH仅局域网全开公网不直接暴露日常CLI操作走局域网密钥统一放 /etc/agent.envchmod 640远离代码仓库90天轮换防暴力破解fail2ban同一IP多次失败自动封禁6小时备份每天定时tar打包到另一块磁盘数据丢了能快速恢复最终的主机配置是一台N100小主机16G内存一块500G SSD系统是Debian 12。Agent常驻内存约800M空闲时整机功耗23W满载运行功耗约85W。在45天连续运行期间进程零崩溃、日志无异常增长、证书续期成功三次、整个系统没有被公网扫描器打穿。我可以放心地出门、合上笔记本Agent依然在墙角的弱电箱旁边安静地跑任务。最后再分享一个小技巧给Agent的数据目录单独做一份每日打包压缩后加密推到家里的另一台NAS上。如果你用的是btrfs或ZFS文件系统直接做快照更省事。托管AI Agent这件事最难的从来不是模型选型或Prompt调优而是这些进程管理、网络接入、安全加固的体力活。把链路搭好、把坑填平之后Agent才能从“你人在它就动”的阶段真正进化成“你不在它也稳稳当当地干活”。
返回列表