Two commands and you have the whole thing: multi-tenant auth, billing, 14 tools, memory, vibe coding, and a dedicated agent per paying user. One SQLite file, three Bun processes, no external services required to boot.
Read live from the upstream release feed every time this page is opened, so it never drifts out of date. ChatHermes talks to Hermes Agent over an OpenAI-compatible endpoint, so a runtime upgrade does not require a ChatHermes upgrade.
The fastest way to see it running. Interactive setup wizard, dependency install, build, and a smoke test — then all three services.
git clone https://github.com/kwkuh/chathermes.git cd chathermes ./bin/install.sh # wizard + deps + build + smoke test ./bin/start.sh # boots orchestrator, web, and the shared agent proxy
Open http://localhost:7000 and sign in with any email.
Same install, then systemd units so it survives reboots. Put nginx and Certbot in front for HTTPS. A $5 box is enough to start.
git clone https://github.com/kwkuh/chathermes.git /opt/chathermes cd /opt/chathermes && ./bin/install.sh cp deploy/systemd/*.service /etc/systemd/system/ systemctl enable --now chathermes-orch chathermes-web chathermes-hermes-proxy
Full production notes — HTTPS, Stripe webhooks, verified email domain — are in INSTALL.md. INSTALL.md
One image runs all three processes and keeps every byte of state in one volume. This is the path that works on any platform that can run a container.
git clone https://github.com/kwkuh/chathermes.git && cd chathermes cp orchestrator/.env.example .env # set SESSION_SECRET + one LLM key docker compose up -d
On macOS, port 7000 is taken by AirPlay Receiver — run WEB_PORT=7600 docker compose up -d, or turn AirPlay off in System Settings.
Provision a server from inside the admin panel with your own Hetzner token. Cloud-init installs and boots everything. This is also what provisions a dedicated agent per Pro user.
# from a running instance: # Admin → Hetzner → pick server type + region → Deploy
Needs HETZNER_API_TOKEN in the orchestrator env. Gated by default: an admin approves every spawn.
Hetzner is wired into the admin panel because that is what the hosted product uses. Nothing about ChatHermes is tied to it. Paste the block below as user data when you create a server and it installs itself on first boot — same script the one-click deploy runs.
#cloud-config
package_update: true
packages: [docker.io, docker-compose-plugin, git]
write_files:
- path: /opt/chathermes/.env
permissions: '0600'
content: |
SESSION_SECRET=REPLACE_WITH_openssl_rand_hex_32
PUBLIC_BASE_URL=https://your-domain.com
NOUS_API_KEY=REPLACE_OR_USE_ANOTHER_PROVIDER
DATA_ROOT=/data
runcmd:
- systemctl enable --now docker
- git clone https://github.com/kwkuh/chathermes.git /opt/chathermes/repo
- cp -r /opt/chathermes/repo/. /opt/chathermes/
- cd /opt/chathermes && docker compose up -d --buildAnything that boots Ubuntu with cloud-init works. If your provider has no user-data field, SSH in and run the four runcmd lines.
Point any of these at the repo. They read the Dockerfile, build it, and run it. Two things to set everywhere: SESSION_SECRET, and a persistent volume on /data — without the volume your database disappears on the next deploy.
Open the address in a browser. A fresh install sends you straight to a setup form — admin account, site name, and one model. No config files to edit by hand.
The form asks for a token first. It is printed on first boot and written to $DATA_ROOT/setup.token. That is deliberate: without it, anyone who found a fresh box before you did could claim it as admin.
docker logs chathermes | grep -A2 "SETUP REQUIRED" # or, without Docker: cat data/setup.token
Finishing setup signs you in, deletes the token, and closes the form for good.
./bin/health.sh
./bin/stop.sh
./bin/setup.sh
./bin/verify-bundle.sh
The first account you create becomes the admin. Add your model providers under Admin → LLM, then set one as default — that is what new users get before they pick anything.