How I run AI agents on a Hetzner VPS

I keep my always-on AI agents on one Hetzner Linux server. This is the version of the setup I can publish, from an empty server to isolated agents, Telegram control, scheduled jobs, monitoring and recovery.

A small vented server case standing on a green marble plinth in a study
Illustration: a small vented server case standing on a green marble plinth in a study.

I use a Hetzner VPS because an agent on my laptop needs the lid open, the network connected and the right session still running. A small Linux server removes all three dependencies. The model stays the same; the server adds a permanent address, a clock, a filesystem and a process that can restart after a failure.

This guide describes the architecture I use. It leaves out private IP addresses, credentials, internal paths, customer data and anything that would map the open ports and services of a live machine. The same method works with other reputable VPS providers; Hetzner is where my always-on runtime currently lives.

What the VPS does

A model produces a response. An agent runtime wraps that model in memory, tools, files, permissions, schedules and delivery channels. The VPS hosts that layer twenty-four hours a day.

One machine holds six layers with separate jobs:

  1. Linux hostUsers, SSH, firewall, patches, disk and network.
  2. RuntimeHermes, another agent framework or your own service.
  3. ProfilesSeparate identity, model, memory, permissions and files.
  4. ChannelsTelegram, a terminal, an API or another private control channel.
  5. SchedulesMonitors, summaries, refreshes and maintenance windows.
  6. RecordsLogs, output files, health checks and proof of delivery.

Create the Hetzner server

In Hetzner Console, create a project and add a server. Hetzner’s current server-creation guide shows the interface as it is today. These are the choices that matter:

  1. Location: choose a region near the services and people that will use the agent. Location affects latency and where your data is handled, so choose it on purpose.
  2. Image: use a supported Linux long-term-support release. An end-of-life image starts you with maintenance debt on day one.
  3. Size: start with enough memory for the runtime, containers and expected concurrency. Agents that call a hosted model API usually need a server that stays up and keeps its state more than they need large local-model compute.
  4. Networking: a public IP is convenient for SSH, but expose only the traffic you need. Hetzner also supports servers with no public IP on a private network, for designs that do not need direct public access.
  5. SSH key: add your public key during creation. If key authentication is available, do not start with a reusable root password.
  6. Firewall and backups: attach both at creation instead of promising to return to them later.

Hetzner documents configurable firewalls, private networks, automatic backups, snapshots, cloud-init and rescaling. Keep the first build small enough that you can explain every open port and running process. Hetzner supplies the virtual machine; the operating system and what it exposes are yours to run.

Secure the first login before installing the agent

Connect with the key you attached, using ssh root@YOUR_SERVER_IP. Update the base system, then create a non-root operator account:

Base update and 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 check that ssh agentops@YOUR_SERVER_IP works before changing SSH policy. Keep the original session open until the new login works. Then review the SSH configuration, disable password authentication, validate with sshd -t and reload SSH. Read any hardening snippet before you paste it. Cloud images can put settings in included files, and a change that locks you out still reports success.

At the Hetzner firewall, allow inbound SSH only from trusted source addresses where practical. Open ports 80 and 443 only if you mean to host a web endpoint. A Telegram bot makes outbound connections, so it needs no random public “agent port”. Allow outbound traffic only as broadly as the model, package, messaging, time and update services require.

Install the runtime, then prove one local turn

There are two sensible installation shapes, plus a third for scaling up:

Simple · one agent, one user
Install the agent runtime under the limited Linux account with its supported service installer. This shape is the easiest to understand.
Isolated · container plus volumes
Run the runtime in Docker, store profiles and workspaces in declared volumes, and keep the container replaceable.
Scaled · several supervised profiles
Give each agent its own profile, token, model policy, working directory and restart boundary.

For a Docker-based build, follow Docker’s official Ubuntu repository instructions instead of an old blog post. Check both the engine and Compose before adding an agent:

Docker Engine and Compose checks
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 the outer boundary, publish no port by default, and read Docker’s packet-filtering guidance before making a container public.

For Hermes, the full public setup is in the Hermes Agent on Telegram setup guide. Install it from 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.

Add a model and Telegram only after the terminal path works

The model provider does the reasoning, Hermes is the agent runtime and Telegram is the control channel. With those roles kept apart, failures are easier to trace and models are easier to replace.

  1. Create a dedicated bot with Telegram’s official @BotFather.
  2. Store the bot token and model-provider key in the runtime’s private configuration. Keep them out of shell history, repositories, screenshots and Telegram messages.
  3. Run hermes gateway setup, configure a strict user allowlist, and choose a limited working directory.
  4. Start the gateway in the foreground and verify /whoami and /status from the allowed Telegram account.
  5. Only then install the supported gateway service, and reboot once to check that it comes back without an open SSH session.

The detailed commands and troubleshooting table are in the Telegram section of the Hermes guide. The order I follow is a local model turn, the foreground gateway, an allowlisted Telegram turn, the persistent service and the reboot test.

Run more than one agent with separate permissions

A second agent needs more than a new bot name. Give it its own identity and limits:

  • Profile: separate configuration, memory, session history and model choice.
  • Messaging token: one bot token and allowlist per control channel.
  • Filesystem: mount or expose only the project directories it needs.
  • Service: a restartable process with an unambiguous status command.
  • Budget: provider limits sized to that workload.
  • Schedule: separate job identity, output destination, timeout and overlap rule.
  • Logs: records that show which profile acted, what it observed and where the result went.

Containers help with packaging and filesystem separation, but they do not make the agent secure on their own. What the agent can reach is still decided by the host user, mounted sockets, secrets, network rules and writable volumes.

What agents are good at on a VPS

Monitor · watch sources
Fetch known sources, keep each observation, and interrupt only when a threshold changes.
Schedule · run on time
Produce digests, maintenance checks or refreshes without depending on a laptop session.
Route · receive remotely
Use Telegram as a private place to start, steer, approve and receive scoped work.
Build · prepare outputs
Generate reports, files, previews or patches inside a scoped workspace.
Verify · close on a checked result
Test the user outcome, keep the logs, and tell a confirmed delivery apart from an attempted one.

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. I let agents observe and prepare work broadly, then narrow their authority as the consequences rise.

How my Hetzner setup is arranged

My live setup is one migrated Hetzner Linux host running Hermes in a container. Persistent profiles survive container replacement. Each Telegram agent has its own profile, token, model route, sessions, service identity and working boundary. A supervisor keeps the gateways running and lets me restart one profile without taking down the others.

The VPS also runs scheduled operational jobs and monitored project runtimes. Each job finds its project from a stable root variable or a path relative to the repository, and never assumes my Mac’s directory layout exists on Linux. Source changes still go through version control, which holds the canonical source tree. For which processes are running and what state they are in, the live VPS is the authority.

How the work is divided between the phone, the Mac and the Hetzner VPS.
MachineWhat it is good forWhat it should not be used as
PhoneDirection, status, approvals, short inputs and receiving finished files.The machine that owns source files or long-running processes.
MacInteractive building, visual QA, local repositories, browser state and high-context work.An always-on production host.
Hetzner VPSPersistent agents, gateways, schedules, monitored services and repeatable Linux execution.A backup of every source, or a place to act without limits.

That split gives me two remote-control patterns. Codex on my phone 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 stay available after the laptop sleeps.

Operate, back up and recover the server

  • Patch on a schedule: update the OS and runtime, read what will change first, and keep 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 job process that exits cleanly does not show 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 also need an independent, tested recovery path.
  • 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 runs them.
  • Record live state: write down 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 snapshots you trigger yourself. Treat both as layers; neither is a full recovery plan on its own. A backup earns trust once you have restored it into an isolated environment and checked the agent, configuration, data and delivery path.

Launch checklist

Launch checklist, plain text
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

Sources

Suhail Mohebi · published 28 July 2026 · the cover is a generated illustration

Want this inside your team’s workflow? The Verified AI Operations Sprint tests one workflow in ten business days. See the sprint →

What the VPS does
  1. What the VPS does
  2. Create the Hetzner server
  3. Secure the first login before installing the agent
  4. Install the runtime, then prove one local turn
  5. Add a model and Telegram only after the terminal path works
  6. Run more than one agent with separate permissions
  7. What agents are good at on a VPS
  8. How my Hetzner setup is arranged
  9. Operate, back up and recover the server
  10. Launch checklist