Reverse Proxy¶
Traefik serves as the central entry point for all HaLOS web traffic, providing port-based routing, TLS termination, and authentication enforcement.
Why a Reverse Proxy?¶
Without Traefik, each application would be accessed by IP address and port number (e.g., http://192.168.1.50:3000). With Traefik:
- Applications get dedicated HTTPS ports with path redirects for discoverability (e.g.,
halos.local/grafana/) - All traffic is encrypted with HTTPS
- Authentication is enforced centrally
- No port conflicts between applications — ports are assigned automatically
- Ports 80, 443, 9090, and 4430–4450 are exposed to the network
Routing¶
Traefik uses Docker labels to discover and route to applications automatically. When a container starts with the appropriate labels, Traefik creates a route for it — no configuration files to edit.
Port-Based Routing¶
Each application gets a dedicated HTTPS port from the range 4430–4450, with a path redirect on the base hostname for discoverability:
| URL | Application |
|---|---|
halos.local |
Homarr dashboard (root domain, port 443) |
halos.local/sso/ |
Authelia login portal (port 443) |
halos.local/<app>/ |
Redirects (302) to halos.local:<port>/ |
halos.local:9090 |
Cockpit web console |
Users navigate to apps via path URLs (e.g., halos.local/grafana/), which redirect to the app's dedicated port. The port numbers are managed automatically.
Port Registry¶
Ports are assigned from the range 4430–4450 and stored persistently in /etc/halos/port-registry. Each app gets a stable port that survives restarts and upgrades.
Path Redirects¶
Traefik serves 302 redirects from halos.local/<app-id>/ to halos.local:<port>/. This gives users a predictable, memorable URL without needing to know port numbers.
HALOS_EXTERNAL_PORT Environment Variable¶
Each container receives a HALOS_EXTERNAL_PORT environment variable with its assigned external port. Apps can use this for generating callback URLs, OIDC redirect URIs, and other self-referential configuration.
Docker Labels¶
Applications declare their routing via Docker labels in their docker-compose.yml. These labels are auto-generated by configure-container-routing from the app's metadata.yaml — they are not written manually:
services:
grafana:
image: grafana/grafana:latest
labels:
# Enable Traefik routing
- "traefik.enable=true"
# HTTPS router on dedicated port
- "traefik.http.routers.grafana-secure.rule=PathPrefix(`/`)"
- "traefik.http.routers.grafana-secure.entrypoints=app-4431"
- "traefik.http.routers.grafana-secure.tls=true"
- "traefik.http.routers.grafana-secure.middlewares=authelia@file"
# Backend service port
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
networks:
- halos-proxy-network
The HALOS_DOMAIN environment variable is set to the device hostname (e.g., halos.local), making the configuration portable across hostname changes.
TLS / HTTPS¶
Self-Signed Certificates¶
HaLOS generates a self-signed certificate on first boot:
- Covers
halos.localas a SAN - Valid for 365 days
- Works across all ports — accept the certificate once and it covers every app
A single certificate for halos.local is sufficient because all apps share the same hostname, just on different ports.
Let's Encrypt¶
Let's Encrypt is not supported for .local mDNS domains, as certificate authorities require publicly resolvable domain names. This may be added in the future for users with public domain names.
Network Architecture¶
Shared Docker Network¶
All proxied containers join a shared bridge network called halos-proxy-network:
halos-proxy-network (bridge)
├── traefik (owner)
├── authelia
├── homarr
├── grafana-container
├── influxdb-container
└── ... other container apps
Traefik can route to any container on this network by its service name and port.
Host Networking¶
Some applications require host networking for hardware access (e.g., Signal K needs USB/serial devices). These apps use network_mode: host and are reached by Traefik via host.docker.internal:
services:
signalk:
network_mode: host
labels:
- "traefik.http.services.signalk.loadbalancer.server.port=3000"
Host networking apps are accessible both via their path redirect URL and their direct port.
Port Exposure Policy¶
Container apps get dedicated external HTTPS ports via the port registry (range 4430–4450). All HTTP access goes through Traefik on these ports. Exceptions for additional port exposure are allowed for:
- Non-HTTP protocols: NMEA TCP streams, CAN bus data
- Host networking: Required for hardware access (USB, serial)
- External tool compatibility: When third-party tools require specific ports
Traefik Configuration¶
Entry Points¶
| Entry Point | Port | Purpose |
|---|---|---|
web |
80 | HTTP (redirects to HTTPS) |
websecure |
443 | HTTPS (dashboard, SSO, path redirects) |
app-4430–app-4450 |
4430–4450 | Per-app dedicated HTTPS ports |
Providers¶
- Docker provider: Watches for container labels, creates routes automatically
- File provider: Loads static middleware definitions (Authelia ForwardAuth, per-app customizations)
Authentication Middleware¶
The default Authelia ForwardAuth middleware is defined as a file provider configuration:
http:
middlewares:
authelia:
forwardAuth:
address: "http://authelia:9091/sso/api/authz/forward-auth"
trustForwardHeader: true
authResponseHeaders:
- Remote-User
- Remote-Groups
- Remote-Email
- Remote-Name
Applications reference this middleware in their Traefik labels to enable authentication. OIDC apps and no-auth apps omit the middleware reference.
Cockpit Integration¶
Cockpit runs on port 9090 with its own TLS certificate, independent of Traefik. A path redirect at halos.local/cockpit/ redirects to :9090 for discoverability.
Cockpit serves as a fallback if Traefik is down — it's always directly accessible at https://halos.local:9090/.