17 containers are currently running. Each stack lives under /opt/platform/<name>/.
| Container | Image | Public URL | Networks | Auth | Notes |
|---|---|---|---|---|---|
| traefik | traefik:v2.11 | https://traefik.remico.eu | frontend | oauth2-proxy | Edge proxy, TLS, middleware definitions |
| keycloak | keycloak:25.0 | https://auth.remico.eu | frontend, backend | IdP (public login UI) | Realm remico, DB in postgres |
| oauth2-proxy | oauth2-proxy:v7.6.0 | https://auth.remico.eu/oauth2/* | frontend | OIDC client remico-web |
forwardAuth target; upstream static://202 |
| auth-bounce | custom build | https://auth.remico.eu/bounce | frontend | none | Redirects 401 → /oauth2/start?rd= |
| postgres | postgres:16 | — (internal :5432) | backend | — | Shared DB: keycloak, wiki, gitea, umami |
| wiki | ghcr.io/requarks/wiki:2 | https://wiki.remico.eu | frontend, backend | Native OIDC | No Traefik oauth middleware |
| gitea | gitea:1.26-rootless | https://gitea.remico.eu | frontend, backend | Native OIDC | Rootless, 384M mem limit, no Traefik oauth |
| dashy | dashy:latest | https://work.remico.eu | frontend | oauth2-proxy | Dashboard / link hub |
| logged-out | nginx:alpine | https://work.remico.eu/logged-out | frontend | none | Static post-logout page |
| grafana | grafana | https://grafana.remico.eu | default, frontend | oauth2-proxy + auth proxy | Login form disabled; auto Admin role |
| prometheus | prom/prometheus | https://prometheus.remico.eu | default, frontend | oauth2-proxy | Metrics storage |
| node-exporter | node-exporter | — (:9100 internal) | default | none | Host metrics for Prometheus |
| postgres-exporter | postgres-exporter | — (:9187 internal) | default, backend | none | PostgreSQL metrics |
| web | nginx:alpine | https://remico.eu, https://www.remico.eu | frontend | none | Static site; Umami tracker script |
| api | nginx:alpine | https://api.remico.eu | frontend | none | /health is public |
| umami | umami:postgresql-latest | https://analytics.remico.eu | frontend, backend | oauth2-proxy + SSO bridge | Self-hosted web analytics; DB in postgres |
| umami-sso | custom build | — (internal) | frontend | — | Keycloak → Umami session bootstrap on /login |
oauth-auth and oauth-errors are defined as labels on the traefik container itself — other services reference them by name./opt/platform/traefik/acme.json (Let's Encrypt HTTP challenge)./oauth2/start, /oauth2/callback, /oauth2/auth, /oauth2/sign_out on auth.remico.eu..remico.eu — shared across all oauth2-protected subdomains.static://202 (auth-only mode).oauth-errors middleware on 401/403.https://auth.remico.eu/oauth2/start?rd=<original URL>./opt/platform/postgres/data/.backend network.analytics.remico.eu.umami on the shared postgres container (no separate DB container).oauth-auth → Keycloak; umami-sso intercepts /login and injects Umami JWT (no second login).script.js and POST /api/send routed without SSO (loaded from remico.eu).DISABLE_LOGIN=1)./opt/platform/web/html/js/analytics.js (WEBSITE_ID)./opt/platform/analytics/setup-analytics.sh/opt/platform/analytics/sso-bridge/).X-Auth-Request-Email for an Umami API token and sets umami.auth in browser localStorage./opt/platform/analytics/.env only (not shown in UI).securityTrustProxy: true).gitea/gitea:1.26-rootless).X-Auth-Request-Email and X-Auth-Request-User from oauth2-proxy.GF_AUTH_DISABLE_LOGIN_FORM=true — users never see Grafana's own login.A compose file exists at /opt/platform/security/fail2ban/ for host-level SSH protection. It is not currently running in the standard stack.
| Container | Port | Purpose |
|---|---|---|
| postgres | 5432 | PostgreSQL |
| keycloak | 8080 | HTTP (via Traefik externally) |
| oauth2-proxy | 4180 | forwardAuth endpoint |
| wiki / gitea / grafana / umami | 3000 | Application HTTP |
| prometheus | 9090 | Metrics UI |
| node-exporter | 9100 | Host metrics |
| postgres-exporter | 9187 | DB metrics |
| dashy | 8080 | Dashboard |
| traefik | 80, 443 | Public HTTP/S |