One docker-compose.yml. No cloning. No forking. Just deploy.
The image builds itself by pulling the source from GitHub at build time.
- Prerequisites
- Quick Start
- Environment Variables
- Data Persistence
- Pinning a Version
- Updating
- Architecture
- Troubleshooting
- License
| Requirement | Details |
|---|---|
| Coolify | A running Coolify instance (v4+) |
| LLM API Key | OpenRouter, OpenAI-compatible, or a built-in provider |
| Bot Token | At least one messaging platform (Telegram, Discord, Slack, etc.) |
1. Coolify → Projects → Pick a project → + New → Docker Compose
2. Select "Empty Compose File" (or point to this repo)
3. Paste the contents of docker-compose.yml
4. Go to Environment Variables tab and set your keys
5. Click Deploy
That's it. First build takes a few minutes (clones repo, installs deps). Subsequent rebuilds use Docker layer cache.
You need one of the following:
Option A — OpenRouter (easiest — access to many models)
| Variable | Value |
|---|---|
OPENROUTER_API_KEY |
Your key from openrouter.ai/keys |
LLM_MODEL |
e.g. anthropic/claude-opus-4.6, openai/gpt-4o, google/gemini-3-flash-preview |
Option B — Custom OpenAI-compatible provider
Works with vLLM, Ollama, LiteLLM proxy, Together, Groq, local llama.cpp, or any OpenAI-compatible API.
| Variable | Value |
|---|---|
OPENAI_BASE_URL |
Your provider's base URL (e.g. https://api.together.xyz/v1) |
OPENAI_API_KEY |
API key for that provider |
LLM_MODEL |
Model name your provider expects (e.g. meta-llama/Llama-3-70b-chat-hf) |
Option C — Built-in providers
| Provider | Key Variable | Base URL Variable |
|---|---|---|
| z.ai / ZhipuAI | GLM_API_KEY |
GLM_BASE_URL (optional) |
| Kimi / Moonshot | KIMI_API_KEY |
KIMI_BASE_URL (optional) |
| MiniMax | MINIMAX_API_KEY |
MINIMAX_BASE_URL (optional) |
Configure at least one:
Telegram
| Variable | Description |
|---|---|
TELEGRAM_BOT_TOKEN |
From @BotFather |
TELEGRAM_ALLOWED_USERS |
Comma-separated Telegram user IDs |
TELEGRAM_HOME_CHANNEL |
(Optional) Channel ID for the bot's "home" |
Discord
| Variable | Description |
|---|---|
DISCORD_BOT_TOKEN |
From the Discord Developer Portal |
DISCORD_ALLOWED_USERS |
Comma-separated Discord user IDs |
DISCORD_HOME_CHANNEL |
(Optional) Channel ID for the bot's "home" |
Slack
| Variable | Description |
|---|---|
SLACK_BOT_TOKEN |
xoxb-... from Slack App settings |
SLACK_APP_TOKEN |
xapp-... for Socket Mode |
SLACK_ALLOWED_USERS |
Comma-separated Slack user IDs |
| Variable | Description |
|---|---|
WHATSAPP_ENABLED |
true to enable |
WHATSAPP_ALLOWED_USERS |
Comma-separated phone numbers (e.g. 15551234567) |
Note: Requires a one-time QR code pairing. After deploying, exec into the container and run
hermes whatsappto pair your device.
Signal
| Variable | Description |
|---|---|
SIGNAL_HTTP_URL |
URL of your signal-cli-rest-api instance |
SIGNAL_ACCOUNT |
Your Signal phone number |
SIGNAL_ALLOWED_USERS |
Comma-separated phone numbers |
Home Assistant
| Variable | Description |
|---|---|
HASS_URL |
e.g. http://homeassistant.local:8123 |
HASS_TOKEN |
Long-lived access token from HA |
All optional — enable the capabilities you need:
| Variable | Service | Get a key |
|---|---|---|
FIRECRAWL_API_KEY |
Web search & extraction | firecrawl.dev |
FAL_KEY |
Image generation (FLUX) | fal.ai |
HONCHO_API_KEY |
Cross-session user modeling | honcho.dev |
VOICE_TOOLS_OPENAI_KEY |
Whisper transcription & TTS | platform.openai.com |
BROWSERBASE_API_KEY |
Cloud browser automation | browserbase.com |
BROWSERBASE_PROJECT_ID |
Browserbase project | (from your Browserbase dashboard) |
| Variable | Default | Description |
|---|---|---|
HERMES_REF |
main |
Git branch/tag to build from (build argument) |
TERMINAL_ENV |
local |
Terminal backend (local, docker, ssh) |
TERMINAL_TIMEOUT |
60 |
Command timeout in seconds |
HERMES_MAX_ITERATIONS |
90 |
Max tool-calling iterations per conversation |
GATEWAY_ALLOW_ALL_USERS |
false |
Allow all users without allowlist |
HERMES_HUMAN_DELAY_MODE |
off |
Response pacing (off, natural, custom) |
CONTEXT_COMPRESSION_ENABLED |
true |
Auto-compress long conversations |
The hermes-data volume is mounted at /root/.hermes inside the container and persists across redeployments:
| Data | Description |
|---|---|
| Memory | The agent's learned knowledge across sessions |
| Skills | Autonomously created and improved skills |
| Config | config.yaml and auth.json |
| Logs | Session trajectories |
By default the image builds from the main branch. To pin to a specific release:
- In Coolify, set the build argument
HERMES_REFto a tag or commit hash (e.g.v1.0.0) - Redeploy
- In Coolify, click Rebuild on the service
- The Docker build will
git clonethe latestmain(or your pinnedHERMES_REF)
Tip: Disable Docker build cache in Coolify if the rebuild serves a cached old image.
┌──────────────────────────────────────────────────┐
│ Coolify Server │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ hermes-gateway container │ │
│ │ │ │
│ │ python -m gateway.run │ │
│ │ ├── Telegram adapter ──► Telegram API │ │
│ │ ├── Discord adapter ──► Discord API │ │
│ │ ├── Slack adapter ──► Slack API │ │
│ │ ├── WhatsApp adapter ──► WhatsApp │ │
│ │ ├── Signal adapter ──► Signal API │ │
│ │ └── Home Assistant ──► HA API │ │
│ │ │ │
│ │ /root/.hermes ◄──► hermes-data volume │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
The gateway connects outbound to messaging APIs — no inbound ports, domains, or SSL certificates needed.
Build fails with uv: not found
This was a known issue with ENV PATH inside dockerfile_inline. The compose file uses absolute paths (/root/.local/bin/uv) to avoid this. Make sure you're using the latest docker-compose.yml from this repo.
Bot requires interactive authentication (Telegram, WhatsApp, etc.)
Some platforms require a one-time interactive approval. After deploying, open a terminal to the container via the Coolify web UI:
- Click Terminal in the left sidebar of your Coolify dashboard
- Select the hermes-gateway container from the resource list
- Follow the prompts to complete authentication
If the terminal option is not available, go to Servers → select your server → Configuration → Advanced and enable terminal access. Ports
6001and6002must be open on your Coolify server.
Container starts but bot doesn't respond
Check the logs in Coolify. Common causes:
- Missing or invalid bot token
- Your user ID is not in the
*_ALLOWED_USERSlist - No messaging platform configured at all
Want to use Docker-in-Docker for the terminal backend
Set TERMINAL_ENV=docker and mount the Docker socket:
volumes:
- hermes-data:/root/.hermes
- /var/run/docker.sock:/var/run/docker.sockWant to exec into the container
In Coolify, click Terminal in the left sidebar and select the hermes-gateway container. This gives you a full interactive shell in your browser — no SSH or docker exec needed. From there you can run:
hermes statusThe upstream Hermes Agent project is MIT licensed. This deployment configuration is provided as-is.
Built with ❤️ for the self-hosting community