for homelabs and small fleets
A hotel, not a pile of containers.
Self-hosted control panel for AI agents: check them in, watch them work, and let the panel hold the routes, the certificates and the keys.
What install.sh actually does
On a fresh Ubuntu or Debian VPS, as root:
git clone https://github.com/magnusfroste/agenthotel.git
cd agenthotel && ./install.sh
The script installs Docker, Git and lsof, creates a 2 GB swapfile if the host has none, builds the images with the checked-out commit baked in, and starts everything. There is no separate docker compose up afterwards and there are no parameters to get wrong.
Requirements: ports 80 and 443 free, and DNS that already points at the box — an A record for the panel and one per agent, or a single wildcard, which is simpler since every agent gets its own subdomain. Caddy asks Let's Encrypt for a certificate the first time a domain is requested, and that fails if the name does not resolve here yet.
Pick a box, not a plan
Panel only
1 vCPU/ 1 GB
The panel itself is light. This runs the front desk with no guests.
- Caddy, frontend and backend in three containers
- SQLite state
- No agents deployed
Small fleet
2 vCPU/ 4 GB
Panel plus one or two agents — the usual first hotel.
- Each Hermes or OpenClaw agent ~0.5–1 GB RAM
- Room to redeploy while one runs
- Swapfile created if missing
Comfortable
4 vCPU/ 8 GB
A comfortable fit for a handful of agents.
- Several guests at once
- Room for a compose stack beside them
- SkillHub fits alongside two agents
Many agents
8 vCPU/ 16 GB+
Many agents, or a heavier observability stack.
- Prometheus, Grafana and Loki run as Docker App deployments
- SkillHub budgets separately
What the panel enforces for you
Things that usually bite you at 2 a.m.
The panel cannot be frozen out
Agents run at low cpu-shares and a high OOM-kill priority; the panel runs at 2048 shares with oom_score_adj -500. Shares only matter under saturation, so agents still use all idle capacity.
Routes that heal
Caddy holds routes in memory and a compose stack's containers come back on their own networks when recreated. Both are re-checked every minute — a present route over a lost network is a 502 that no route check would catch.
Every deploy keeps its log
Build output, pulls, container start and the error if it failed, followed live on the Deployments tab and readable over MCP, with secrets masked.
Serialized deploys
One build or deploy at a time, so two concurrent deploys cannot saturate the host.
Daily Docker cleanup
Unused resources are pruned on a schedule with history and space reclaimed. Agent volumes are never touched; orphaned ones are reviewed and removed explicitly.
Alerts you already have
Webhook (Slack or Discord) or Telegram when an agent goes down or recovers, or when host disk or memory crosses a threshold.
Your models, your endpoint
Paste the address of a vLLM, llama.cpp, Ollama or LM Studio server and the panel lists what it serves with each model's context window. It flags models too small for Hermes — the runtime declines anything under 64k context at deploy rather than failing later — and shows the exact provider/model an agent should write.
Local-server context windows are read correctly, including vLLM's max_model_len. Point the whole fleet at your own hardware with one setting: the panel probes each provider's models, declines any too small to run, and says so rather than falling back to a hosted API without telling you.
Homelab questions
Can I run it behind NAT?
Yes. Cloudflare Tunnel needs no open ports, no DNS record pointing here and no local certificate, and one origin serves every hostname because Caddy still routes on the Host header. NetBird is the other option: the hotel joins a WireGuard mesh and publishes hostnames through its reverse proxy with no open ports.
What does the panel itself listen on?
80 and 443 through Caddy, which handles automatic Let's Encrypt and dynamic per-agent routes via its admin API.
Where does state live?
SQLite in the backend, plus one volume per agent for sessions, memory and workspace files. Volumes outlive the container; that is the difference between a redeploy and a reset.
Will an agent eat the box?
Each one is capped at its own RAM and CPU (1 core and 1024 MB by default), and the panel warns before you overbook the host. Host-wide defaults are set with DEFAULT_AGENT_CPU and DEFAULT_AGENT_MEM_MB.
Is the MCP endpoint on by default?
No. It is off until you enable it under System → MCP Server. The token is the panel's own and is root-equivalent on that host, so rotate it from the same page.
One command on a spare box.
Ubuntu or Debian, ports 80 and 443, DNS pointed here. Everything else the installer does.