Skip to content

Deployment

The dev scripts in Getting started are the quickest way to hack on HiveKeeper. To run it as a deployed stack — the gateway plus an on-prem agent, optionally with Postgres and OIDC — use the committed Docker Compose files. (Everything here works the same with podman compose.)

This page is the DEVELOPMENT stack.

It is zero-config on purpose, and its defaults say so: a publicly-known encryption key, the database password app, a Keycloak in dev mode whose users’ passwords are their usernames. Do not run it on the internet.

For a deployment you intend to keep — TLS, generated secrets, per-user login, backups — follow Running in production, which uses a separate, self-contained stack that refuses those defaults rather than inheriting them.

Compose stack

The repo root ships a layered set of compose files:

FileAdds
docker-compose.ymlThe base: the gateway (in-memory, no DB) and one agent.
docker-compose.postgres.ymlPostgres + switches the gateway to the postgres profile (durable jobs, org/users/fleet, audit log, RLS).
docker-compose.keycloak.ymlA dev Keycloak (imports the hivekeeper realm) + the oidc profile for per-user login.
docker-compose.authentik.ymlA dev Authentik (OAuth2/OIDC provider) + the oidc,oidc-authentik profile for per-user login.

Bring it up

Terminal window
# Simplest: gateway (in-memory) + agent, built from source on a fresh clone.
docker compose up -d --build
# With persistence (Postgres):
docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d --build
# With persistence + OIDC/SSO (sign in at the console with owner/owner):
docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.keycloak.yml up -d --build
# OR with Authentik:
docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.authentik.yml up -d --build

The gateway listens on :8090. The agent dials out to it over WebSocket (no inbound ports) and resolves SSH credentials locally — the cloud never sees them. Configure via env (copy .env.example to .env); the key ones are HIVEKEEPER_DEFAULT_USER / HIVEKEEPER_DEFAULT_PASSWORD (the agent’s fallback SSH login), HIVEKEEPER_CREDENTIAL_VAULT + HIVEKEEPER_VAULT_KEY (a per-device vault HiveKeeper can manage from the UI, encrypted at rest), and, for the Postgres profile, HIVEKEEPER_CRYPTO_KEY (job-secret encryption — set a real key in production: openssl rand -base64 32).

Optional subsystem env (agent + gateway)

VariableOnEnables
HIVEKEEPER_PPSK_STOREagentPath to the on-prem PPSK key store — turns on admin-minted PPSK via RADIUS (with HIVEKEEPER_VAULT_KEY for at-rest encryption). Lab/untested; see PPSK runbook.
HIVEKEEPER_RADIUS_DIRagentDirectory the agent writes the FreeRADIUS authorize file to (the PPSK RADIUS runtime).
HIVEKEEPER_ALERT_POLL_INTERVAL_MSgateway (postgres)Background alert-poller interval (default 300000 = 5 min); …_INITIAL_DELAY_MS for the first run.
HIVEKEEPER_SMTP_HOST / …_PORT / …_USER / …_PASSWORD + HIVEKEEPER_ALERT_EMAIL_FROMgateway (postgres)SMTP for email alert channels. Unset ⇒ email channels are skipped (webhook channels need no config).

The poller and email/webhook delivery only run under the postgres profile; channels + thresholds are managed in the console under Alerts → Alert delivery (admin-gated).

The console (hive-web) is its own container: a static bundle behind nginx, which also proxies the console’s /gw calls to the gateway (in development that proxy is the Vite dev server’s job). It is not bundled into the gateway. For hacking on the UI, pnpm --dir hive-web dev is still the fastest loop.

Nothing about your deployment is baked into the bundle — it asks the gateway where to sign in (GET /api/mode) at runtime, so the published image works against whatever domain and identity provider you point it at.

Keycloak-in-Docker issuer gotcha: tokens are minted for the browser-facing URL (http://localhost:8081), so the gateway validates the iss claim against that while fetching JWKs over the container network. If you reach the console from another host or port, set HIVEKEEPER_OIDC_ISSUER to match where users log in.

Container images

Released images are published to the GitHub Container Registry:

  • ghcr.io/ggfto/hivekeeper-gateway
  • ghcr.io/ggfto/hivekeeper-agent
  • ghcr.io/ggfto/hivekeeper-server
  • ghcr.io/ggfto/hivekeeper-web — the console

Each is tagged with the release version (e.g. 0.2.0) and latest. To run the published images instead of building from source, set the tag and pull:

Terminal window
HIVEKEEPER_TAG=latest docker compose pull && docker compose up -d

Versioning & releases

Versioning is automated with semantic-release driven by Conventional Commits. On every push to main, the Release workflow inspects the commits since the last release and, if any warrant one (feat → minor, fix → patch, feat!/BREAKING CHANGE → major):

  1. bumps version in gradle.properties (the single source of truth for all JVM modules and the images),
  2. updates CHANGELOG.md, commits and tags it (vX.Y.Z),
  3. builds and pushes the gateway/agent/server images to GHCR (tagged with the version and latest),
  4. creates the GitHub Release.

No release-worthy commits since the last tag → the workflow does nothing.

One-time setup: so the first automated release does not jump to 1.0.0, create a baseline tag on the current commit: git tag v0.1.0 && git push origin v0.1.0. The release job needs the repository’s GITHUB_TOKEN to have contents: write and packages: write (already set in the workflow).