2026-09-28 12:15:30 +02:00
|
|
|
# Tomter Vel's own platform: portal + its own Kanidm and NATS as podman
|
|
|
|
|
# containers. The content (pages, forms, desks) is not here: portal fetches
|
|
|
|
|
# it from tomtervel/questions on prosjekt.klingenbergbygg.no and hot-reloads
|
|
|
|
|
# it over NATS. This repo owns identity, the bus, and which portal version
|
|
|
|
|
# runs. TLS depends on where it runs: on a standalone host the bundled Caddy
|
|
|
|
|
# (`--profile edge`) terminates it; on kasse the host Caddy already owns
|
|
|
|
|
# 80/443 and reverse-proxies vel.klingenbergbygg.no -> portal (127.0.0.1:3050).
|
2026-09-22 19:06:31 +02:00
|
|
|
#
|
|
|
|
|
# bootstrap.sh first time on a fresh host: renders configs from
|
|
|
|
|
# .env, makes Kanidm's internal cert, starts it all,
|
|
|
|
|
# recovers the Kanidm admin, creates the portal client
|
|
|
|
|
# and desk groups.
|
2026-09-28 11:15:29 +02:00
|
|
|
# podman compose up -d --build every time after that.
|
2026-09-22 19:06:31 +02:00
|
|
|
|
|
|
|
|
name: tomtervel
|
|
|
|
|
|
|
|
|
|
services:
|
|
|
|
|
caddy:
|
2026-09-28 12:15:30 +02:00
|
|
|
# Bundled TLS for a standalone host only: `podman compose --profile edge up`.
|
|
|
|
|
# On kasse the host Caddy already owns 80/443 (it reverse-proxies
|
|
|
|
|
# vel.klingenbergbygg.no -> 127.0.0.1:3050, the portal port below), so this
|
|
|
|
|
# is profiled off there to avoid the port clash. Default `up` skips it.
|
|
|
|
|
profiles: ["edge"]
|
2026-09-22 19:06:31 +02:00
|
|
|
image: caddy:2
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
ports:
|
|
|
|
|
- "80:80"
|
|
|
|
|
- "443:443"
|
|
|
|
|
- "443:443/udp"
|
|
|
|
|
environment:
|
|
|
|
|
PORTAL_HOST: ${PORTAL_HOST}
|
|
|
|
|
ID_HOST: ${ID_HOST}
|
|
|
|
|
volumes:
|
|
|
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
|
|
|
- caddy_data:/data
|
|
|
|
|
- caddy_config:/config
|
|
|
|
|
depends_on:
|
|
|
|
|
- portal
|
|
|
|
|
- kanidm
|
|
|
|
|
|
|
|
|
|
nats:
|
|
|
|
|
image: nats:2.14.6-alpine
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
command: ["-c", "/etc/nats/nats.conf"]
|
|
|
|
|
volumes:
|
|
|
|
|
- ./nats/nats.conf:/etc/nats/nats.conf:ro
|
|
|
|
|
- nats_data:/data
|
2026-09-28 12:31:14 +02:00
|
|
|
# Published on the host so the reload job (`nats pub portal.content.reload ""`)
|
|
|
|
|
# can reach it; password-protected (see nats.conf). Host port 4223, not 4222:
|
|
|
|
|
# on kasse the shared platform NATS already owns 127.0.0.1:4222 and the vel
|
|
|
|
|
# runs its own NATS in isolation, so the reload workflow targets 4223 there.
|
|
|
|
|
# (Standalone, nothing else owns 4222, but 4223 is harmless.)
|
2026-09-22 19:06:31 +02:00
|
|
|
ports:
|
2026-09-28 12:31:14 +02:00
|
|
|
- "127.0.0.1:4223:4222"
|
2026-09-22 19:06:31 +02:00
|
|
|
healthcheck:
|
|
|
|
|
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8222/healthz"]
|
|
|
|
|
interval: 10s
|
|
|
|
|
timeout: 5s
|
|
|
|
|
retries: 3
|
|
|
|
|
|
|
|
|
|
kanidm:
|
|
|
|
|
image: kanidm/server:1.11.1
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
environment:
|
|
|
|
|
KANIDM_CONFIG_PATH: /data/server.toml
|
|
|
|
|
volumes:
|
|
|
|
|
- kanidm_data:/data
|
|
|
|
|
- ./kanidm/server.toml:/data/server.toml:ro
|
|
|
|
|
# Internal self-signed TLS: Caddy terminates the public
|
|
|
|
|
# certificate and proxies here without verification.
|
|
|
|
|
- ./certs/kanidm-chain.pem:/data/chain.pem:ro
|
|
|
|
|
- ./certs/kanidm-key.pem:/data/key.pem:ro
|
2026-09-28 12:31:14 +02:00
|
|
|
# Standalone (--profile edge): only the bundled Caddy talks to Kanidm.
|
|
|
|
|
# On kasse the host Caddy fronts it, so publish loopback-only for a conf.d
|
|
|
|
|
# entry: id.<vel> { reverse_proxy https://localhost:8443 {
|
|
|
|
|
# transport http { tls_insecure_skip_verify } } }
|
|
|
|
|
# (Kanidm's internal self-signed cert; 8443 is free on kasse — its shared
|
|
|
|
|
# Kanidm is on 8310.)
|
|
|
|
|
ports:
|
|
|
|
|
- "127.0.0.1:8443:8443"
|
2026-09-22 19:06:31 +02:00
|
|
|
|
|
|
|
|
portal:
|
|
|
|
|
build:
|
|
|
|
|
context: ./portal
|
|
|
|
|
args:
|
|
|
|
|
PORTAL_RELEASE: ${PORTAL_RELEASE}
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
env_file: portal.env
|
|
|
|
|
environment:
|
|
|
|
|
LEPTOS_SITE_ADDR: 0.0.0.0:3000
|
|
|
|
|
LEPTOS_SITE_ROOT: site
|
|
|
|
|
LEPTOS_HASH_FILES: "true"
|
2026-09-28 12:15:30 +02:00
|
|
|
ports:
|
|
|
|
|
# Host-published for kasse's host Caddy (vel.klingenbergbygg.no -> here).
|
|
|
|
|
# With --profile edge the bundled Caddy proxies portal:3000 internally
|
|
|
|
|
# instead, but publishing loopback-only is harmless there.
|
|
|
|
|
- "127.0.0.1:3050:3000"
|
2026-09-22 19:06:31 +02:00
|
|
|
depends_on:
|
|
|
|
|
nats:
|
|
|
|
|
condition: service_healthy
|
|
|
|
|
kanidm:
|
|
|
|
|
condition: service_started
|
|
|
|
|
|
2026-09-28 11:15:29 +02:00
|
|
|
# The Gitea Actions runner is a host service on kasse (pacman gitea-runner),
|
|
|
|
|
# registered against prosjekt.klingenbergbygg.no. It reaches this NATS via the
|
|
|
|
|
# published 127.0.0.1:4222 port above, so no in-compose runner — and no
|
|
|
|
|
# docker.sock/podman.sock mount — is needed here.
|
2026-09-22 19:06:31 +02:00
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
caddy_data:
|
|
|
|
|
caddy_config:
|
|
|
|
|
nats_data:
|
|
|
|
|
kanidm_data:
|
2026-09-28 11:15:29 +02:00
|
|
|
|
|
|
|
|
# Pin the project network subnet inside 172.16/12 so Kanidm's X-Forwarded-For
|
|
|
|
|
# trust (kanidm/server.toml.tpl) stays valid under Podman — its default pool
|
|
|
|
|
# hands out 10.89.x addresses that Caddy's forwarded client IP can't match.
|
|
|
|
|
networks:
|
|
|
|
|
default:
|
|
|
|
|
ipam:
|
|
|
|
|
config:
|
|
|
|
|
- subnet: 172.18.0.0/16
|