I use a Hetzner VPS because an agent that depends on my laptop also depends on the lid being open, the network staying connected, and the right session still running. A small Linux server removes that fragility. It does not make the model smarter. It gives the surrounding system a permanent address, a clock, a filesystem, and a process that can restart after failure.
This guide explains the architecture we use without publishing private IP addresses, credentials, internal paths, customer data, or the exact attack surface of a live machine. The same method works with other reputable VPS providers; Hetzner is simply where our current persistent runtime lives.
§1What the VPS actually does
A model produces a response. An agent runtime surrounds that model with memory, tools, files, permissions, schedules, and delivery channels. The VPS hosts that surrounding layer twenty-four hours a day.
- 01Linux hostUsers, SSH, firewall, patches, disk, and network.
- 02RuntimeHermes, another agent framework, or your own service.
- 03ProfilesSeparate identity, model, memory, permissions, and files.
- 04ChannelsTelegram, terminal, API, or another private control surface.
- 05SchedulesMonitors, summaries, refreshes, and maintenance windows.
- 06EvidenceLogs, artifacts, health checks, and proof of delivery.
The VPS is allowed to stay awake. That does not mean every agent on it is allowed to do everything. Persistence and authority are separate settings.
§2Create the Hetzner server
In Hetzner Cloud Console, create a project and add a server. Hetzner’s current server-creation guide is the source of truth for the interface. The choices that matter are:
- Location: choose a region near the services and people that will use the agent. Location affects latency and data-handling decisions; it is not a cosmetic setting.
- Image: use a supported Linux long-term-support release. An end-of-life image is operational debt on day one.
- Size: start with enough memory for the runtime, containers, and expected concurrency. API-backed agents usually need persistence more than large local-model compute.
- Networking: a public IP is convenient for SSH, but expose only the traffic you actually need. Hetzner also supports private-network-only servers for architectures that do not need direct public access.
- SSH key: add your public key during creation. Do not begin with a reusable root password if key authentication is available.
- Firewall and backups: attach both at creation rather than promising to return later.
Hetzner documents configurable firewalls, private networks, automatic backups, snapshots, cloud-init, and rescaling. Those features are useful, but the first build should stay small enough that you can explain every open port and running process.
§3Secure the first login before installing the agent
Connect with the key you attached:
ssh root@YOUR_SERVER_IP
Update the base system, then create a non-root operator account:
apt update
apt upgrade
adduser agentops
usermod -aG sudo agentops
install -d -m 700 -o agentops -g agentops /home/agentops/.ssh
cp /root/.ssh/authorized_keys /home/agentops/.ssh/authorized_keys
chown agentops:agentops /home/agentops/.ssh/authorized_keys
chmod 600 /home/agentops/.ssh/authorized_keys
Open a second terminal and prove that ssh agentops@YOUR_SERVER_IP works before changing SSH policy. Keep the original session open until the new path is verified. Then review the SSH configuration, disable password authentication, validate with sshd -t, and reload SSH. Do not copy a hardening snippet blindly: cloud images can place settings in included files, and locking yourself out is still a successful configuration change.
At the Hetzner firewall, allow inbound SSH only from trusted source addresses where practical. Add ports 80 and 443 only if you intentionally host a web endpoint. A Telegram bot that makes outbound connections does not need a random public “agent port.” Keep outbound traffic open only as broadly as the model, package, messaging, time, and update services require.
A second SSH session works as the limited user; password login is disabled; the firewall matches the actual design; the original root session can now close.
§4Install the runtime, then prove one local turn
There are two sensible installation shapes:
One agent, one user
Install the agent runtime under the limited Linux account and use its supported service installer. This is easiest to understand.
Container plus volumes
Run the runtime in Docker, persist profiles and workspaces in explicit volumes, and keep the container replaceable.
Several supervised profiles
Give each agent a separate profile, token, model policy, working directory, and restart boundary.
For a Docker-based build, follow Docker’s official Ubuntu repository instructions rather than an old blog post. Verify both the engine and Compose before adding an agent:
docker version
docker compose version
sudo systemctl is-enabled docker
sudo systemctl is-active docker
Docker’s own documentation warns that published container ports can bypass rules created with ufw or firewalld. Keep the Hetzner network firewall as an external boundary, publish no port by default, and inspect Docker’s packet-filtering guidance before making a container public.
For Hermes, the complete public setup lives in Hermes, in your pocket. Install it using the current official instructions, choose a model provider, and complete one harmless terminal request before adding Telegram or schedules. If a basic local turn cannot authenticate and return, more infrastructure will only hide the original failure.
§5Add a model and Telegram only after the terminal path works
The model provider is the reasoning engine. Hermes is the agent runtime. Telegram is the control surface. Keeping those roles separate makes failures easier to diagnose and models easier to replace.
- Create a dedicated bot with Telegram’s official @BotFather.
- Store the bot token and model-provider key in the runtime’s private configuration—not in shell history, a repository, a screenshot, or a Telegram message.
- Run
hermes gateway setup, configure a strict user allowlist, and choose a deliberately limited working directory. - Start the gateway in the foreground and verify
/whoamiand/statusfrom the allowed Telegram account. - Only then install the supported gateway service and reboot once to prove it returns without an open SSH session.
The detailed commands and troubleshooting table are in the Telegram section of the Hermes guide. The important order is local model turn → foreground gateway → allowlisted Telegram turn → persistent service → reboot test.
§6Run more than one agent without turning one server into one giant permission
A second agent should not be “the first agent with another bot name.” It should have its own identity and boundary:
- Profile: separate configuration, memory, session history, and model choice.
- Messaging token: one bot token and allowlist per control surface.
- Filesystem: mount or expose only the project directories it needs.
- Service: a restartable process with an unambiguous status command.
- Budget: provider limits appropriate to that workload.
- Schedule: separate job identity, output destination, timeout, and overlap rule.
- Evidence: logs that show which profile acted, what it observed, and where the result went.
Containers help with packaging and filesystem boundaries, but they are not a complete security model. The host user, mounted sockets, secrets, network rules, and writable volumes still decide what the agent can reach.
§7What the agents are good at on a VPS
Watch quietly
Fetch known sources, preserve observations, and interrupt only when a threshold changes.
Run on time
Produce digests, maintenance checks, or refreshes without depending on a laptop session.
Receive remotely
Use Telegram as a private place to start, steer, approve, and receive bounded work.
Prepare artifacts
Generate reports, files, previews, or patches inside a scoped workspace.
Close on evidence
Test the user outcome, preserve logs, and distinguish success from attempted delivery.
The bad fit is unlimited autonomous administration. Do not give a chat-controlled agent unrestricted root access, every project, the Docker socket, all secrets, and permission to publish. The useful system automates observation and preparation broadly, then narrows authority as consequences rise.
§8How our Hetzner setup is arranged
Our live pattern is one migrated Hetzner Linux host with a containerized Hermes runtime. Persistent profiles survive container replacement. Each Telegram agent receives its own profile, token, model route, sessions, service identity, and working boundary. A supervisor keeps the gateways running and lets us restart one profile without taking down the others.
The VPS also carries scheduled operational work and monitored project runtimes. Jobs resolve their project from a stable root variable or a path relative to the repository; they do not assume the directory structure of my Mac exists on Linux. Source changes still belong in version control. The live VPS is the truth for running processes and current state, not automatically the canonical source tree.
| Surface | What it is good for | What it should not pretend to be |
|---|---|---|
| Phone | Direction, status, approvals, short inputs, and receiving finished artifacts. | The machine that owns source files or long-running processes. |
| Mac | Interactive building, visual QA, local repositories, browser state, and high-context work. | An always-on production host. |
| Hetzner VPS | Persistent agents, gateways, schedules, monitored services, and repeatable Linux execution. | A backup of every source or permission to act without limits. |
That division gives us two remote-control patterns. Codex in my pocket keeps execution on the Mac when the work depends on local source and browser state. Hermes on Hetzner keeps execution on the VPS when the work must remain available after the laptop sleeps.
§9Operate the server as infrastructure, not as a forgotten appliance
- Patch deliberately: update the OS and runtime on a schedule, read what will change, and retain a rollback path.
- Watch headroom: monitor memory, disk, inodes, load, and container growth. An agent can fill a disk with logs while still replying “healthy.”
- Prove delivery: a successful job process is not proof that Telegram, email, storage, or another downstream system received the result.
- Back up off the live disk: Hetzner automatic backups and snapshots help recover a server, but critical configuration and source need an independent, tested recovery path too.
- Rotate secrets: keep an inventory of credential names and owners, never print values during audits, and rehearse replacement before an incident.
- Test restarts: reboot the host, confirm the expected services return, and test as the same limited runtime identity that operates them.
- Record live truth: document which runtime, profile, service, and project path currently own each operational outcome.
Hetzner currently documents daily automatic server-disk backups with seven backup slots, plus user-triggered snapshots. Treat both as layers, not a complete recovery strategy. A backup becomes trustworthy when you have restored it into an isolated environment and verified the agent, configuration, data, and delivery path.
§10The complete launch checklist
SERVER
[ ] Supported Linux image
[ ] SSH key attached
[ ] Firewall attached
[ ] Backups enabled
[ ] Limited operator user verified
[ ] Password login disabled
RUNTIME
[ ] Docker or native runtime verified
[ ] One harmless local model turn passes
[ ] Secrets stored outside source control
[ ] Working directory deliberately scoped
[ ] Persistent profile path documented
REMOTE CONTROL
[ ] Dedicated Telegram bot
[ ] Strict user allowlist
[ ] /whoami and /status verified
[ ] Service survives logout and reboot
OPERATIONS
[ ] One profile per agent
[ ] Schedules have timeout and overlap rules
[ ] Logs identify observation, action, and delivery
[ ] Disk, memory, and service health monitored
[ ] Recovery tested from an independent copy
[ ] Consequential actions still require approval
The shortest honest version
- The VPS supplies persistence, not judgment.
- Hetzner supplies the virtual machine; you still own the operating system and its exposure.
- Prove one local agent turn before adding messaging, schedules, or more profiles.
- Separate agents by profile, token, files, service, budget, and evidence.
- Keep the Mac for interactive source-heavy work and the VPS for persistent runtime work.
- A running process is not the finish line; a verified user outcome is.