mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-11 03:13:16 +00:00
122 lines
5.2 KiB
Markdown
122 lines
5.2 KiB
Markdown
# goclaw
|
|
|
|
[GoClaw](https://docs.goclaw.sh) is a multi-tenant AI agent gateway in Go: LLM
|
|
providers, messaging channels (Telegram, Discord, Slack, Zalo, Feishu,
|
|
WhatsApp), agent teams, and a knowledge vault, behind one binary with a
|
|
built-in web dashboard.
|
|
|
|
Two containers: `goclaw`, and `postgres` — pgvector, which holds tenants,
|
|
sessions, encrypted provider keys and the semantic memory.
|
|
|
|
## Setup
|
|
|
|
1. Generate the two secrets:
|
|
|
|
```sh
|
|
openssl rand -hex 16 # GOCLAW_GATEWAY_TOKEN
|
|
openssl rand -hex 32 # GOCLAW_ENCRYPTION_KEY
|
|
```
|
|
|
|
2. Map the domain to port `18790` and deploy. Migrations run on start.
|
|
3. Open the domain and use the setup wizard to add an LLM provider key.
|
|
|
|
Health check: `GET /health`, which the `goclaw` container also polls as its
|
|
compose healthcheck so Coolify can report it healthy. The first check waits 60
|
|
seconds, to leave time for migrations on start.
|
|
|
|
## Authentication
|
|
|
|
`GOCLAW_GATEWAY_TOKEN` is the bearer token for the API and the dashboard, and
|
|
the only thing between the domain and a gateway whose agents run tools. It
|
|
fails fast if unset rather than defaulting to blank: upstream's own compose
|
|
allows an empty token for loopback-only development, which behind a public
|
|
domain would publish the gateway.
|
|
|
|
`GOCLAW_ENCRYPTION_KEY` encrypts the provider API keys at rest in PostgreSQL
|
|
(AES-256-GCM). It is required for the same reason, and it must not change once
|
|
keys are stored — every one of them becomes unreadable.
|
|
|
|
Both are the two values upstream's `prepare-env.sh` generates; the script
|
|
itself is not used here.
|
|
|
|
## Environment
|
|
|
|
| Variable | Default | Purpose |
|
|
| --- | --- | --- |
|
|
| `GOCLAW_GATEWAY_TOKEN` | — | Bearer token for the API and dashboard |
|
|
| `GOCLAW_ENCRYPTION_KEY` | — | AES-256-GCM key for stored provider keys |
|
|
| `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` | `goclaw` | Database credentials, read by both containers |
|
|
| `GOCLAW_AUTO_UPGRADE` | `true` | Apply schema migrations and data hooks on startup |
|
|
| `GOCLAW_MINIMAX_API_KEY` | optional | MiniMax LLM provider key |
|
|
| `GOCLAW_TTS_MINIMAX_API_KEY` / `GOCLAW_TTS_MINIMAX_GROUP_ID` | optional | MiniMax text-to-speech credentials |
|
|
| `GOCLAW_TRACE_VERBOSE` | optional | Set to `1` to log full LLM request and response bodies |
|
|
|
|
`GOCLAW_AUTO_UPGRADE` defaults to `true`, the value upstream recommends for
|
|
Docker. The image entrypoint already runs `goclaw upgrade` before `serve`, but
|
|
it only logs a warning when that fails. With the variable set, `serve` applies
|
|
any pending migrations itself rather than stopping on a schema check.
|
|
|
|
The MiniMax variables are the one case where a provider key comes from the
|
|
environment rather than the dashboard: GoClaw reads them directly for the
|
|
MiniMax provider and its text-to-speech.
|
|
|
|
`GOCLAW_HOST`, `GOCLAW_PORT`, `GOCLAW_CONFIG` and `GOCLAW_SKILLS_DIR` are set
|
|
in `compose.yml` rather than here — they are properties of this layout, not of
|
|
whoever deploys it. The two paths override image defaults that point outside
|
|
any volume (`/app/config.json`, `/app/skills`), which would drop the
|
|
configuration and every installed skill on redeploy.
|
|
|
|
Other provider API keys are not variables: they are entered in the dashboard
|
|
and stored encrypted in PostgreSQL.
|
|
|
|
## Storage
|
|
|
|
| Volume | Mount | Holds |
|
|
| --- | --- | --- |
|
|
| `goclaw-data` | `/app/data` | `config.json`, skills, Claude CLI credentials, runtime packages |
|
|
| `goclaw-workspace` | `/app/workspace` | Files the agents work on |
|
|
| `postgres-data` | `/var/lib/postgresql` | The database |
|
|
|
|
Upstream's PostgreSQL overlay adds a third `goclaw-skills` volume at
|
|
`/app/skills`; it is not here, because `GOCLAW_SKILLS_DIR` points at
|
|
`/app/data/skills` and the volume would mount empty over a path nothing reads.
|
|
Skills persist in `goclaw-data` instead.
|
|
|
|
`postgres-data` mounts `/var/lib/postgresql`, not `/var/lib/postgresql/data`.
|
|
PostgreSQL 18 images moved `PGDATA` down a level into a version directory, so
|
|
the parent is now the mount point.
|
|
|
|
The image's own user owns `/app` — `goclaw`, uid 1000, created with `/app` as
|
|
its home. `/app/.claude` is a symlink into `/app/data`, which is how CLI
|
|
credentials survive a recreate.
|
|
|
|
## Networking
|
|
|
|
Listens on `18790`.
|
|
|
|
`extra_hosts` maps `host.docker.internal` to the host gateway, so an agent can
|
|
reach a service running on the host itself.
|
|
|
|
## Image
|
|
|
|
`ghcr.io/nextlevelbuilder/goclaw:full`, the variant with every runtime and
|
|
skill dependency pre-installed — Python, Node, pandoc, poppler, the GitHub CLI.
|
|
The plain tag ships Python only and installs the rest on demand into
|
|
`/app/data/.runtime`, which means the first use of a skill waits on a package
|
|
install and a wiped data volume repeats it. Paying for the size once is the
|
|
better trade here.
|
|
|
|
The tag is moving, tracking the newest full build. The variant tags are only
|
|
published as `full` and `<major>.<minor>-full` — there is no `<major>-full` —
|
|
so `full` is the moving tag to follow.
|
|
|
|
## Hardening
|
|
|
|
`cap_drop: ALL` with `SETUID`/`SETGID`/`CHOWN` added back, `no-new-privileges`,
|
|
a `noexec` tmpfs on `/tmp`, and memory, CPU and pid limits — all as upstream
|
|
ships them. The three capabilities are what the entrypoint needs to install
|
|
persisted packages as root and then drop to the `goclaw` user via `su-exec`.
|
|
|
|
This is a service whose whole purpose is running model-chosen tools, so the
|
|
limits are worth keeping.
|