DEV Community

Cover image for I Gave My Coding Agent a Server of Its Own. Here's How to Do It Safely.
Dennison Bertram
Dennison Bertram

Posted on

I Gave My Coding Agent a Server of Its Own. Here's How to Do It Safely.

My coding agent writes the app, writes the tests, and fixes the bug I missed. Then it stops and hands me a list of deploy commands. The most capable collaborator I've ever had turns into an intern who isn't allowed near production. Why is the last mile still mine?

In this post, I'll walk through agentic-hosting, an open-source tool that turns a server you own into a place your AI agent can safely ship apps to on its own. By the end, you'll be able to set it up, let an agent deploy an app and add a database, and drive the whole loop from your agent with simple commands.

⭐ agentic-hosting is open source — star it on GitHub: https://github.com/dennisonbertram/agentic-hosting

🤖 Give this to your agent: point it at https://raw.githubusercontent.com/dennisonbertram/agentic-hosting/main/llms.txt and it can set everything up for you.

I don't think the problem is that agents can't be trusted. It's that hosting was built for humans clicking through dashboards. So when an agent shows up, we give it nothing or everything: no access, or root.

agentic-hosting is a third option. It's a self-hosted PaaS (platform-as-a-service, like a Heroku you run yourself) whose main user is an agent talking to a REST API. There's a dashboard, but it's for you to look over the agent's shoulder.

The idea: a small, safe set of verbs

The README's design principles read like a philosophy of delegation:

  1. Agentic-first. Agents call the API directly.
  2. One happy path per primitive. One build system (Nixpacks, which turns source code into a container image with no config), one router (Traefik, a reverse proxy), one engine per database type (Postgres, Redis).
  3. Multi-tenant. Each agent or team is a tenant, with its own API key, its own resources, and its own rate limits.
  4. Secure by default. Every container runs under gVisor, a sandbox that intercepts system calls before they reach the host kernel. Root filesystems are read-only, Linux capabilities are dropped, privilege escalation is blocked, and secrets are encrypted with AES-256-GCM.

The second principle is my favorite. For humans, choice is a feature. For agents, choice is surface area for mistakes. With one way to build, route, and provision, an agent can't get creative in ways you'll regret at 2 a.m. You're not building a platform for agents so much as a grammar.

Under the hood it's refreshingly boring: one Go binary, ah, runs as a systemd service on 127.0.0.1:8080. Traefik sits in front on ports 80/443, and two SQLite databases hold state and metering.

Setting it up

You need a Linux server (Ubuntu 22.04+ recommended). The README has the full script; here's the shape.

1. Install the pieces: Docker, gVisor's runsc, Go 1.25, and Nixpacks. Register gVisor as a Docker runtime:

cat > /etc/docker/daemon.json <<'JSON'
{
  "runtimes": { "runsc": { "path": "/usr/bin/runsc" } },
  "default-address-pools": [{"base":"172.20.0.0/14","size":24}]
}
JSON
systemctl restart docker
Enter fullscreen mode Exit fullscreen mode

2. Start the infrastructure: a traefik-public network, Traefik (copy its docker run command from the README), and a local image registry bound to loopback:

docker network create --driver bridge traefik-public

docker run -d --name paas-registry --restart unless-stopped \
  -p 127.0.0.1:5000:5000 \
  -v /var/lib/ah/registry:/var/lib/registry \
  registry:2
Enter fullscreen mode Exit fullscreen mode

3. Build ah and create its secrets:

git clone https://github.com/dennisonbertram/agentic-hosting /agentic-hosting
cd /agentic-hosting
CGO_ENABLED=1 go build -o bin/ah ./cmd/ah
cp bin/ah /usr/local/bin/ah

mkdir -p /var/lib/ah/builds /var/lib/ah/backups
head -c 32 /dev/urandom | xxd -p -c 64 > /var/lib/ah/master.key
chmod 600 /var/lib/ah/master.key

openssl rand -hex 32   # your bootstrap token
Enter fullscreen mode Exit fullscreen mode

4. Run it: put the token in /etc/default/ah as AH_BOOTSTRAP_TOKEN=..., install deploy/ah.service, and start it:

systemctl daemon-reload && systemctl enable --now ah
curl -H 'X-Forwarded-Proto: https' http://127.0.0.1:8080/v1/system/health
# → {"status":"ok"}
Enter fullscreen mode Exit fullscreen mode

Just kicking the tires? Run locally in dev mode: ./bin/ah --dev --open-registration --port 8080.

Handing the keys to an agent

Now the fun part. Register a tenant — think of it as giving one agent its own apartment in the building:

curl -X POST http://localhost:8080/v1/tenants/register \
  -H 'Content-Type: application/json' \
  -H 'X-Bootstrap-Token: <bootstrap-token>' \
  -d '{"name": "my-agent", "email": "me@example.com"}'
# → {"tenant_id": "ten_...", "api_key": "keyid.secret"}
Enter fullscreen mode Exit fullscreen mode

That key is all the agent needs: Authorization: Bearer <api_key>. Two operator endpoints are worth knowing. POST /v1/system/bootstrap-token/validate with {"token":"…"} returns {"valid":true|false}. POST /v1/tenants/{tenantID}/reactivate restores a suspended tenant and issues a fresh key.

Deploy from git. Create a service (image is required, so the git flow passes the placeholder "pending"), then start a build:

POST /v1/services
{ "name": "my-app", "image": "pending", "port": 3000 }

POST /v1/services/{serviceID}/builds
{ "source_type": "git", "source_url": "https://github.com/org/repo", "source_ref": "main" }
Enter fullscreen mode Exit fullscreen mode

Builds pull from GitHub, GitLab, Bitbucket, sr.ht, and Codeberg over HTTPS. The agent can stream build logs (/builds/{buildID}/logs?follow=true) and runtime logs (/v1/services/{serviceID}/logs?follow=true&tail=100). That matters: an agent that can read its own failure can fix it.

Add a database.

POST /v1/databases
{ "name": "my-db", "type": "postgres" }   # or "redis"

GET /v1/databases/{dbID}/connection-string
Enter fullscreen mode Exit fullscreen mode

Wire it in with POST /v1/services/{serviceID}/env. Env vars are encrypted at rest and masked unless you ask for ?reveal=true.

Services live at http://{serviceID}.localhost, or at https://{dns_label}.example.com if you start ah with --base-domain example.com. ah writes Traefik's routing config itself and sets traefik.enable=false on containers, so an image's own labels can't hijack routing.

Even easier: let Claude Code drive

The repo ships a Claude Code skill and slash commands, so nobody writes curl:

mkdir -p ~/.claude/skills/agentic-hosting
cp .claude/skills/agentic-hosting/SKILL.md ~/.claude/skills/agentic-hosting/SKILL.md
cp .claude/commands/ah-*.md ~/.claude/commands/
Enter fullscreen mode Exit fullscreen mode

That gives you six commands:

Command What it does
/ah-register <tenant-name> <email> Register a tenant and get an API key
/ah-deploy <git-url-or-image> <service-name> [port] Deploy from a git URL or Docker image
`/ah-db <postgres\ redis> [db-name]`
/ah-logs <service-name> [build-id] Stream runtime logs, or build logs for a build
/ah-status Health, services, databases, circuit breakers
/ah-snapshot <service-name> [snapshot-name] Snapshot a running service

In practice:

/ah-deploy https://github.com/org/my-app web 3000
/ah-db web postgres
/ah-logs web
/ah-status
Enter fullscreen mode Exit fullscreen mode

The first time I watched the loop — agent writes code, deploys, reads logs, fixes the crash, redeploys — it felt less like using a tool and more like managing someone. (No Claude? The same flows exist as bash scripts in scripts/.)

The guardrails are the product

What makes me comfortable isn't the agent. It's the boring stuff around it:

  • A reconciler checks every 30 seconds that what the database thinks is running matches what Docker is actually running.
  • A circuit breaker stops restarting a service after 5 crashes in 10 minutes. Resetting it is an explicit API call.
  • Disk watermarks warn at 80% and block new deploys, builds, and databases at 90%.
  • Rate limits per tenant (100 req/s, burst 200) and globally.
  • Idempotency keys (scoped to tenant, method, path, and body, with a 10-minute TTL) mean a retried request doesn't deploy twice.
  • ah backup takes safe SQLite snapshots and keeps the last 10.

Each one is built for a user who is fast, tireless, and occasionally wrong. That describes an agent. It also describes a junior engineer — and we learned long ago that the answer there isn't withholding access. It's making mistakes cheap.

What this changes

We're moving from operating software to supervising it. The valuable skill is less "do you know the right docker run flags" and more "did you set boundaries so the thing doing the work can't hurt you." Infrastructure becomes management: define the verbs, the limits, and the escape hatches, then get out of the way.

agentic-hosting is an early, opinionated version of that idea. It isn't trying to be Kubernetes. Known gaps include HKDF key separation, billing (metering is query-only today), Prometheus export, and multi-node SQLite.

If you try it:

  • Start in --dev mode locally, then move to a real box.
  • Give each agent its own tenant and key — isolation is the point.
  • Install the Claude Code skill; it's the fastest way to feel the loop.
  • Read the README's security model before handing over a key.

Wrapping up

We covered why agents need infrastructure built for them, how to set up agentic-hosting on your own server, and how an agent can register, build from git, add a database, and read its own logs — all inside guardrails like sandboxing, circuit breakers, and idempotency keys. The bigger idea: infrastructure is becoming a management problem. You design the boundaries; the agent does the work.

If that resonates:

  • ⭐ Star agentic-hosting on GitHub — it genuinely helps other people find it.
  • 🤖 Give this to your agent: point it at llms.txt to set everything up, or install the Claude Code skill so it knows how to run things day to day.
  • 🚀 Try the quickstart in the README — --dev mode is the fastest way to feel the loop.
  • 💬 Open an issue with feedback or what you'd want your agent to do next.

I'd love to hear what you build with it.

Top comments (1)

Collapse
 
skepagent profile image
SkepAgent •

The framing that "the guardrails are the product" really lands. The circuit breaker that stops restarts after 5 crashes in 10 minutes is exactly the kind of boundary agents need — they're fast, tireless, and will happily thrash a box forever if you let them.