Hermes: a 24/7 AI agent on your own VPS, no middleman
How I put Hermes, a 24/7 AI agent, on my own hardened VPS, reachable over Telegram. No middleman, no markup, plus the footguns I hit.
Most "AI agents" you can use today live on someone else's server. You rent a seat, you talk to it through their app, and it runs inside their guardrails on hardware you'll never see. That's fine for a lot of things. It bugged me anyway. I wanted an agent that was actually mine: running on a box I control, reachable from my phone, with no company sitting in the middle taking a cut.
So I built hermesbox.
Hermes is Nous Research's personal AI agent. It's good. But standing it up safely on a server is the kind of job that's easy to get dangerously wrong. You're putting an always-on thing that runs shell commands on a public box, and you have to harden it without locking yourself out. hermesbox is one script that turns a fresh Ubuntu server into a hardened home for Hermes, reachable over Telegram, in about ten minutes. A 24/7 agent that lives on your own VPS. No middleman, no markup.
That last bit matters to me. I don't mark up a cent of it. Hetzner gets their eight-ish bucks a month for the box, Tailscale's free tier handles private SSH, your LLM provider gets your key. I'm not in the money path. What you're buying, if you can even call it buying when the whole thing is free and documented, is convenience and a safe default.
The firewall call I'm proud of
Here's the design decision I like most. The box has zero open inbound ports. None. SSH is reachable only over Tailscale, and Telegram works over an outbound long-poll, so the always-on bot never needs to listen for anything. Nothing to port-scan, nothing to brute-force, no inbound surface at all.
The obvious risk with "lock the firewall down hard" is locking yourself out of your own server. So there's a deadman timer: arm the lockdown, and if Tailscale isn't actually working, the firewall auto-reverts in ten minutes and you're back in. Belt and suspenders. I'd rather the script assume I fat-fingered something than strand me.
The agent also runs as an unprivileged user, not root, and risky commands get bounced back to me in Telegram for a yes/no before they run. It's my box, but it's not a blank check.
The wall: a venv I owned wrong
Field notes are only honest if I include the part where I was wrong.
The first version installed Hermes as root. Seemed reasonable. Then the bot would come up, try to talk to Telegram or a provider, and quietly fail to install its own runtime dependencies, because Hermes lazy-installs that stuff at runtime and a root-owned virtualenv was the wrong shape for it. I burned real time staring at journalctl before it clicked: the ownership was the bug, not the deps.
v0.2 reworks the whole install to be owned by a dedicated hermes user, the way a normal local install would be. Re-baked on fresh hardware, the Telegram and Anthropic SDKs both self-installed cleanly and the gateway came up polling. Six separate empirical bugs got caught and fixed this way: wrong Hetzner SKU names, a curl | bash exit code, an interactive prompt that hung the headless path, a model default that quietly routed to the wrong provider. None of those show up in a design doc. You only find them by actually running the thing on real hardware until it works.
What surprised me
How fragile the messaging layer is. Hermes v0.15.1 only allows one poller per Telegram bot token. Leave an orphaned poller around and you get getUpdates 409 conflicts that look like the bot is just dead. hermesbox runs exactly one clean gateway and documents the webhook alternative, but I would not have predicted that the hardest part of "self-host an AI agent" would be Telegram bookkeeping, not the AI and not the firewall. The boring plumbing is always where the bodies are.
If you want an agent that's actually yours, try Hermes on your own box. Read the script before you run it. I mean that, less hermes.sh is in the instructions for a reason.
And if you spin one up, come tell me on X. Especially if it locked you out and the deadman saved you. I want to hear it.
Now copy Josh.