Operator notes
A short reference for operators running a Hivemind instance. This page will grow as we hit more real-world ops scenarios — if you trip over something not covered here, email support@seglamater.com so we can add it.
Updating
Hivemind self-updates against the channel set in
/etc/hivemind/.env (HIVEMIND_UPDATE_CHANNEL=canary is the default
during alpha). When a new release lands, the server polls
updates.seglamater.app/hivemind/channels/<channel>/latest.json,
verifies the signed manifest, pulls the pinned image digest, and
performs a rolling restart.
To force a check immediately:
To pin to a different channel:
Then docker compose up -d to apply.
During alpha, only canary is populated
beta and stable channels exist but currently have no releases.
Pin to canary until that changes.
Backups
Hivemind stores all durable state in PostgreSQL. Back up:
- The Postgres data volume (
hivemind-db-databy default). /etc/hivemind/.env— contains DB password and signing keys.
A typical nightly backup:
docker compose exec -T hivemind-db \
pg_dump -U hivemind hivemind | gzip > /var/backup/hivemind-$(date +%F).sql.gz
Restore is symmetric — see the email/ticket from support@seglamater.com if you need the full DR runbook.
Logs and health
docker compose ps
docker compose logs --tail=200 hivemind-server
docker compose logs --tail=200 hivemind-db
The server exposes a health endpoint at /health (returns JSON).
Reverse-proxy health checks should hit this.
Where things live
| Path | Contents |
|---|---|
/etc/hivemind/.env |
Runtime config + secrets. Back this up. |
/var/lib/hivemind/ |
Compose stack working dir + volumes. |
/var/log/hivemind/ |
Docker log overflow if size limits hit. |
Reaching out
- Bug reports / ops help: support@seglamater.com
- Roadmap / sales: sales@seglamater.com
- Status page: TBD — until we publish one, watch the
canarychannel pointer for release timing:https://updates.seglamater.app/hivemind/channels/canary/latest.json.
Reverse proxy + TLS
Hivemind binds to 127.0.0.1:8585 by default, so a reverse proxy on
the same host is required for any external access. Below is a minimal
Caddy snippet that handles TLS termination and forwards to Hivemind.
Drop this into /etc/caddy/Caddyfile (or wherever your Caddy config
lives) and replace hivemind.example.com with your real domain.
hivemind.example.com {
encode zstd gzip
# Hivemind's own UI + API.
reverse_proxy 127.0.0.1:8585 {
# Pass through real client IP so the audit log and any
# rate-limiting logic see the actual user, not 127.0.0.1.
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Caddy auto-provisions a Let's Encrypt cert as long as the DNS A/AAAA
records point at the host. For nginx, the equivalent is a standard
proxy_pass http://127.0.0.1:8585 block plus your TLS config.
Authentik / forward-auth SSO
Hivemind has built-in support for forward-auth (Authentik, Pomerium,
etc.) — the SSO middleware lives in the server binary and is enabled
via environment variables in your .env. The flow is: a reverse
proxy in front of Hivemind authenticates the user against your IdP,
forwards a few trusted headers, and Hivemind auto-provisions / updates
the user's account based on group membership.
When you'd use this
- Your team already runs Authentik (or another OIDC IdP) and you want Hivemind logins gated by it.
- You want group-based RBAC: members of
hivemind-adminget admin, members ofhivemind-userget the normal role, everyone else gets the default role.
Enabling forward-auth
Add the following to your .env (next to DB_PASSWORD,
ADMIN_API_KEY, etc.):
# Toggle. Local password login is disabled when this is true.
HIVEMIND_FORWARD_AUTH=true
# Trusted upstream CIDRs — load-bearing security boundary. Hivemind
# only trusts forward-auth headers from peer IPs in this list. Set
# this to whatever Caddy / your reverse proxy presents as its source
# IP (typically the docker bridge subnet on the same host).
HIVEMIND_FORWARD_AUTH_TRUSTED_NETS=172.17.0.0/16,127.0.0.1/32
# Header names — defaults match Authentik's ProxyProvider outpost.
HIVEMIND_FORWARD_AUTH_USER_HEADER=X-Authentik-Username
HIVEMIND_FORWARD_AUTH_EMAIL_HEADER=X-Authentik-Email
HIVEMIND_FORWARD_AUTH_GROUPS_HEADER=X-Authentik-Groups
HIVEMIND_FORWARD_AUTH_GROUPS_DELIM=|
# Group → role mapping. Authentik group named on the left maps to
# the Hivemind role on the right.
HIVEMIND_GROUP_ADMIN=hivemind-admin
HIVEMIND_GROUP_USER=hivemind-user
Then docker compose up -d to apply.
Caddy snippet for forward-auth
This is the same Caddyfile as above, plus a forward_auth block that talks to your Authentik outpost.
hivemind.example.com {
encode zstd gzip
# Authentik forward-auth — replace the URL with your outpost.
forward_auth authentik-outpost:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Email X-Authentik-Groups X-Authentik-Uid
trusted_proxies 127.0.0.1
}
reverse_proxy 127.0.0.1:8585 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Limitations during alpha
- Group changes in Authentik don't propagate until the user logs in again (we read groups from headers on every request, but the database role is only updated at login time).
- One Hivemind instance maps to one Authentik tenant. Multi-IdP deployments need separate Hivemind instances.
- The web UI's login page doesn't currently redirect to Authentik automatically — users hit Hivemind, get bounced via Caddy's forward-auth, log in at Authentik, get redirected back. This works but is uglier than a "Sign in with Authentik" button. v0.2.x.
If your IdP isn't Authentik, the same forward-auth contract works with anything that produces standard headers (Pomerium, oauth2-proxy, Vouch, etc.) — adjust the header names accordingly.