Skip to content

Kimai

Time tracking.

Runtime Container (Docker Swarm), 2 containers: app, db
Tier Apps (Important)
Node swarm-core
Image kimai/kimai2:2.62.0; mariadb:11.4
URL https://kimai.lab.riversfamily.uk
Auth Native SAML
Source ansible/stacks/apps/kimai/

Bumped to 2.62.0 (issue #105/PR #106): the apache- image prefix was retired after 2.57.0; the bare 2.62.0 tag is now the Apache variant and still serves on port 8001, so this was a straight tag bump.

Configuration

SAML config is rendered into a mounted Symfony local.yaml (/opt/kimai/config/packages/local.yaml), not env vars. It embeds the shared SAML signing certificate directly ({{ authentik_saml_signing_cert | indent(10) }}) — the certificate is public, so this is not a secret.

TRUSTED_HOSTS/TRUSTED_PROXIES are pre-set for the Traefik-fronted deployment.

Volumes

Volume Path Backing Contents
data /opt/kimai/var/data Local Application data
database /var/lib/mysql Local MariaDB data — never NFS
(rendered) /opt/kimai/config/packages/local.yaml Read-only SAML config

Networking

app joins both the shared traefik network (for its Traefik route) and this stack's private internal network. db joins internal only — it is unreachable from every other stack.

Secrets

Vault variable Delivered as Purpose
vault_kimai_db_password Swarm secret on db (MARIADB_PASSWORD_FILE); app reads the same value inline in DATABASE_URL MariaDB password
vault_kimai_app_secret Plain env var (APP_SECRET) Symfony app secret
vault_kimai_admin_password Plain env var (ADMINPASS) Initial admin password

db also sets MARIADB_RANDOM_ROOT_PASSWORD: "yes" — a random root password needs no secret at all.

Gotchas

  • Kimai has no native OIDC support, so it is the only Apps-tier service using SAML instead of OIDC or forward-auth.
  • Shares the SAML signing certificate with Snipe-IT and Fleet (both experimental tier) — rotating that certificate means redeploying all three.