Skip to content

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.local as 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-4430app-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/.