REMICO runs as a self-hosted platform on a single Hetzner VPS. All services are containerised with Docker Compose and exposed through Traefik with automatic TLS.
| Property |
Value |
| Provider |
Hetzner |
| IPv4 |
178.105.232.95 |
| IPv6 |
2a01:4f8:1c1a:63a4::1 |
| Base path |
/opt/platform/ |
| Domain |
remico.eu |
Public ports: 22 (SSH), 80 (HTTP → redirect), 443 (HTTPS). Everything else is internal to Docker networks.
- One compose stack per subdirectory under
/opt/platform/ (traefik, keycloak, postgres, wiki, gitea, …).
- Two external Docker networks must be created manually before any stack starts:
frontend (Traefik-routed HTTP) and backend (PostgreSQL and DB clients).
- Single identity provider: Keycloak 25 at
auth.remico.eu, realm remico.
- Flat access model: every authenticated realm user has full admin access on all services. Keycloak groups are not used.
- Two auth patterns:
- Cookie SSO via Traefik + oauth2-proxy (dashboard, monitoring, Traefik UI, Umami).
- Native OIDC inside the application (Wiki.js, Gitea) — avoids redirect loops.
flowchart TB
Internet([Internet])
Traefik[Traefik]
Web[web]
API[api]
Work[work]
Grafana[grafana]
Prometheus[prometheus]
TraefikUI[traefik UI]
Wiki[wiki]
Gitea[gitea]
Umami[umami]
KC[keycloak]
O2P[oauth2-proxy]
Bounce[auth-bounce]
PG[(postgres)]
NE[node-exporter]
PGE[postgres-exporter]
Internet --> Traefik
Traefik --> Web
Traefik --> API
Traefik --> Work
Traefik --> Grafana
Traefik --> Prometheus
Traefik --> TraefikUI
Traefik --> Wiki
Traefik --> Gitea
Traefik --> Umami
Traefik --> KC
Traefik --> O2P
Traefik --> Bounce
Work --> O2P
Grafana --> O2P
Prometheus --> O2P
TraefikUI --> O2P
Umami --> O2P
O2P --> KC
Wiki --> KC
Gitea --> KC
Wiki --> PG
Gitea --> PG
KC --> PG
Umami --> PG
| Group |
Nodes |
Auth |
| Public |
web, api |
None |
| Cookie SSO |
work, grafana, prometheus, traefik UI, umami |
oauth2-proxy (+ umami-sso bridge) |
| Native OIDC |
wiki, gitea |
Keycloak in-app |
| Identity |
keycloak, oauth2-proxy, auth-bounce |
IdP / helper |
| Internal |
postgres, exporters |
None |
flowchart LR
subgraph frontend ["frontend network"]
T[traefik]
KCf[keycloak]
O2Pf[oauth2-proxy]
Wf[wiki]
Gf[gitea]
Df[dashy]
Grf[grafana]
Uf[umami]
end
subgraph backend ["backend network"]
PG[(postgres)]
KCb[keycloak]
Wb[wiki]
Gb[gitea]
Ub[umami]
PE[postgres-exporter]
end
Wf --> PG
Gf --> PG
KCb --> PG
Ub --> PG
PE --> PG
- frontend — any container that Traefik routes to, plus oauth2-proxy and auth-bounce.
- backend — PostgreSQL and services that connect to it. Not reachable from the internet.
When building from scratch, start stacks in this order:
- Create Docker networks (
frontend, backend)
- postgres — shared database
- keycloak — identity provider (includes oauth2-proxy)
- traefik — edge proxy (needs target containers to have labels)
- auth-bounce — 401 redirect helper
- wiki, gitea, analytics — application stacks
- dashboard, monitoring, api, web — remaining services
See Operations Commands for the exact commands.
Authoritative DNS for remico.eu is hosted at Hetzner. Required records:
A * → 178.105.232.95
AAAA * → 2a01:4f8:1c1a:63a4::1
Individual subdomains (wiki, work, auth, gitea, grafana, etc.) can have explicit records or rely on the wildcard.