clickclack/docs/deployment.md
2026-05-08 09:11:41 +01:00

142 lines
4.2 KiB
Markdown

---
read_when:
- shipping a release, building Docker, or planning a new install
- changing how data is laid out on disk
---
# Deployment
ClickClack ships as one Go binary that embeds the Svelte SPA and the SQL
migrations. The deployment story is "drop a binary on a box, point it at a
data directory, run it behind a reverse proxy."
Public surfaces:
- `clickclack.chat` — product website.
- `app.clickclack.chat` — chat app. The same app is also available at `/app`
for local development and simple single-host deployments.
- `docs.clickclack.chat` — documentation site built by `pnpm docs:site`.
## Single binary
```sh
pnpm install
pnpm build # builds the SPA into apps/api/internal/webassets/dist
go build -o clickclack ./apps/api/cmd/clickclack
./clickclack serve --addr :8080 --data /var/lib/clickclack
```
The Go build step requires the SPA `dist/` to be present because `webassets`
uses `go:embed`. The `pnpm build` script copies `apps/web/dist` into
`apps/api/internal/webassets/dist`; CI must run it before `go build`.
## Releases
GoReleaser is configured in `.goreleaser.yml`. It builds `clickclack` for
Linux, macOS, Windows, and FreeBSD on `amd64` and `arm64`, with Windows
archives emitted as `.zip` and the others as `.tar.gz`. Linux `.deb` and
`.rpm` packages are generated through nfpm.
```sh
pnpm install
goreleaser release --snapshot --clean
```
The GoReleaser config runs `pnpm build` before compiling so the embedded SPA
is refreshed. Publishing is handled by `.github/workflows/release.yml` on
`v*` tags or manual dispatch with an existing tag.
## Docker
The provided `Dockerfile` is multi-stage:
```sh
docker build -t clickclack .
docker run --rm -p 8080:8080 -v clickclack-data:/app/data clickclack
```
Stages:
1. `node:25-alpine` — installs pnpm dependencies and runs `pnpm build`.
2. `golang:1.26-alpine` — builds the Go binary, importing the SPA dist.
3. `alpine:3.23` — runtime image, runs as the `clickclack` user, exposes
`8080`, mounts `/app/data` as a volume.
Override the entrypoint command to run admin tasks:
```sh
docker run --rm -v clickclack-data:/app/data clickclack \
admin bootstrap --name "Peter" --email steipete@gmail.com
```
## Data layout
```
<data>/
clickclack.db # SQLite database (WAL files alongside)
uploads/ # local files for /api/uploads
logs/ # reserved; nothing writes here today
```
Back this directory up. SQLite WAL means a snapshot of the directory is
consistent enough, but prefer the online backup:
```sh
clickclack backup --data /var/lib/clickclack --out /var/backups/clickclack-$(date +%F).db
```
## Reverse proxy
Required for TLS, `Origin` enforcement, and request size limits. The
WebSocket endpoint accepts upgrades with `InsecureSkipVerify=true` today, so
the proxy is the right place to enforce origin policy.
A minimal nginx block:
```nginx
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
}
```
## GitHub OAuth
If you want GitHub login, set:
```sh
CLICKCLACK_PUBLIC_URL=https://chat.example.com
CLICKCLACK_GITHUB_CLIENT_ID=...
CLICKCLACK_GITHUB_CLIENT_SECRET=...
CLICKCLACK_GITHUB_ALLOWED_ORG=openclaw
CLICKCLACK_DEV_BOOTSTRAP=false
```
Configure the GitHub OAuth app callback to
`<public-url>/api/auth/github/callback`. When `CLICKCLACK_GITHUB_ALLOWED_ORG`
is set, ClickClack asks GitHub for `read:org` and only accepts active members
of that org. See [features/auth.md](features/auth.md).
## Migrations
`clickclack serve` applies migrations on boot. For zero-downtime deploys, run
`clickclack migrate` ahead of the new binary so the old binary doesn't see
unexpected tables. Migrations live in
`apps/api/internal/store/sqlite/migrations/` and are append-only.
## Backups and restore
```sh
# hot backup
clickclack backup --out /var/backups/clickclack-$(date +%F).db
# JSON dump (good for sanity, not for restore)
clickclack export --out /var/backups/clickclack-$(date +%F).json
```
Restore is a file swap: stop `clickclack`, replace `<data>/clickclack.db`,
delete any stale `*.db-wal`/`*.db-shm`, start it back up.