Ingress & Identity

Traefik serves as the single gateway for all HTTP/HTTPS traffic entering the HALO ecosystem. This document describes ingress routing, TLS policy, authentication strategies, and trusted proxy configuration that secure and manage access to Nexus services.


Traefik as Single Gateway

Architecture Overview

Traefik operates as the sole entry point for web traffic, providing:

Automatic Service Discovery: Monitors Docker for containers with Traefik labels, automatically registering routes

Path-Based Routing: Routes requests to backend services based on URL path prefixes and hostnames

TLS Termination: Handles HTTPS encryption, presenting HTTP to backend services for simplified service implementation

Load Balancing: Distributes traffic across multiple container instances when services scale horizontally

Middleware Pipeline: Request transformation, authentication, rate limiting, and header manipulation

Network Position

Internet/LAN → Router → Nexus Host → Traefik (frontnet) → Services (appnet)

Traefik is the only container connected to frontnet (public-facing network), ensuring all external traffic is funneled through a single, auditable entry point.


Service Discovery

Docker Labels

Services register with Traefik through Docker labels in compose files:

services:
  n8n:
    image: n8nio/n8n
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=PathPrefix(`/n8n`)"
      - "traefik.http.routers.n8n.entrypoints=websecure"
      - "traefik.http.routers.n8n.tls=true"
      - "traefik.http.services.n8n.loadbalancer.server.port=5678"
      - "traefik.http.middlewares.n8n-stripprefix.stripprefix.prefixes=/n8n"
      - "traefik.http.routers.n8n.middlewares=n8n-stripprefix"
    networks:
      - appnet

Key Labels:

  • traefik.enable: Opt-in to Traefik routing
  • rule: URL matching pattern (PathPrefix, Host, Headers, etc.)
  • entrypoints: Which port to listen on (web=80, websecure=443)
  • tls: Enable TLS for this route
  • loadbalancer.server.port: Backend service port
  • middlewares: Apply transformation pipeline

Dynamic Configuration

Traefik watches Docker socket for container events:

Container Start: Traefik detects new container with labels, registers routes

Container Stop: Routes automatically deregistered, traffic redirected or returns 404

Label Changes: Traefik reconfigures routes without restart

No Manual Config: No nginx.conf or Apache httpd.conf to maintain—services self-register


TLS Policy

Certificate Management

Let’s Encrypt (ACME):

Traefik can automatically obtain and renew TLS certificates from Let’s Encrypt:

# traefik.yml
certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web

Services reference the resolver in labels:

labels:
  - "traefik.http.routers.service.tls.certresolver=letsencrypt"

Self-Signed Certificates:

For local-only deployments, generate self-signed certificates:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout traefik-key.pem -out traefik-cert.pem \
  -subj "/CN=halo.local"

Mount certificates in Traefik container and configure:

tls:
  certificates:
    - certFile: /certs/traefik-cert.pem
      keyFile: /certs/traefik-key.pem

Wildcard Certificates:

Use DNS challenge for wildcard certs covering all subdomains:

certificatesResolvers:
  letsencrypt:
    acme:
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"

TLS Configuration

Minimum TLS Version:

# Force TLS 1.2 or higher
tls:
  options:
    default:
      minVersion: VersionTLS12

Cipher Suites:

tls:
  options:
    default:
      cipherSuites:
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305

HTTP to HTTPS Redirect:

http:
  routers:
    http-catchall:
      rule: "HostRegexp(`{host:.+}`)"
      entrypoints:
        - web
      middlewares:
        - redirect-to-https
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        permanent: true

Authentication & Access Control

Basic Authentication

Protect sensitive services with HTTP Basic Auth:

# Generate htpasswd file
htpasswd -nb admin secure_password > .htpasswd

# Reference in middleware
middlewares:
  auth:
    basicAuth:
      usersFile: /etc/traefik/.htpasswd

# Apply to router
labels:
  - "traefik.http.routers.n8n.middlewares=auth"

Forward Authentication

Delegate authentication to external service:

middlewares:
  auth-external:
    forwardAuth:
      address: "http://auth-service:8080/verify"
      trustForwardHeader: true
      authResponseHeaders:
        - "X-User-Id"
        - "X-User-Email"

Use cases:

  • OAuth2 provider (Authelia, Keycloak)
  • Custom authentication service
  • SSO integration

IP Whitelisting

Restrict access by source IP:

middlewares:
  local-only:
    ipWhiteList:
      sourceRange:
        - "192.168.1.0/24" # Local network
        - "10.0.0.0/8" # VPN subnet

Trusted Proxy Configuration

X-Forwarded Headers

Traefik adds standard forwarding headers:

X-Forwarded-For: <client-ip>
X-Forwarded-Host: <original-host>
X-Forwarded-Proto: https
X-Forwarded-Port: 443
X-Real-IP: <client-ip>

Backend services must trust these headers to log correct client IPs and generate proper redirects.

Backend Trust Configuration

Home Assistant:

# configuration.yaml
http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.18.0.0/16 # appnet subnet

n8n:

# Environment variable
N8N_PROXY_HOPS=1

Frigate:

# config.yml
proxy:
  trusted_proxies:
    - 172.18.0.0/16

Security Considerations

Only Trust Traefik: Backend services should only accept X-Forwarded headers from Traefik’s IP on appnet

Validate Headers: Ensure backends validate header format to prevent header injection attacks

Network Isolation: Frontend services should not directly expose ports to host network—only Traefik listens externally


Middleware Pipeline

Request Transformation

Strip Prefix:

Remove path prefix before forwarding to backend:

middlewares:
  strip-n8n:
    stripPrefix:
      prefixes:
        - "/n8n"

Request to https://halo.local/n8n/workflow becomes http://n8n:5678/workflow

Add Prefix:

Add path prefix when forwarding:

middlewares:
  add-api:
    addPrefix:
      prefix: "/api/v1"

Headers Modification:

middlewares:
  custom-headers:
    headers:
      customRequestHeaders:
        X-Custom-Header: "value"
      customResponseHeaders:
        X-Frame-Options: "DENY"
      sslRedirect: true
      stsSeconds: 31536000
      stsIncludeSubdomains: true

Rate Limiting

Prevent abuse and DoS attacks:

middlewares:
  rate-limit:
    rateLimit:
      average: 100 # requests per second
      burst: 200 # burst capacity
      period: 1s

Compression

Enable compression for responses:

middlewares:
  compress:
    compress: {}

Traefik automatically compresses responses with gzip when client supports it.


Service Routing Examples

Root Path (Omnia UI)

labels:
  - "traefik.http.routers.omnia.rule=Host(`halo.local`) && PathPrefix(`/`)"
  - "traefik.http.routers.omnia.priority=1" # Lower priority
  - "traefik.http.services.omnia.loadbalancer.server.port=80"

Subpath Routing (n8n)

labels:
  - "traefik.http.routers.n8n.rule=Host(`halo.local`) && PathPrefix(`/n8n`)"
  - "traefik.http.routers.n8n.priority=10" # Higher priority
  - "traefik.http.routers.n8n.middlewares=n8n-stripprefix,auth"

Subdomain Routing (Alternative)

labels:
  - "traefik.http.routers.grafana.rule=Host(`grafana.halo.local`)"
  - "traefik.http.services.grafana.loadbalancer.server.port=3000"

Requires DNS or /etc/hosts entry for subdomain.


Monitoring & Observability

Traefik Dashboard

Enable built-in dashboard:

# traefik.yml
api:
  dashboard: true
  insecure: false # Require authentication

# Secure with middleware
labels:
  - "traefik.http.routers.api.middlewares=auth"

Access at https://halo.local/dashboard/

Access Logs

accessLog:
  filePath: "/var/log/traefik/access.log"
  format: json
  fields:
    headers:
      defaultMode: keep
      names:
        User-Agent: keep
        Authorization: drop # Don't log sensitive headers

Metrics

Export Prometheus metrics:

metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true
    buckets:
      - 0.1
      - 0.3
      - 1.0
      - 3.0
      - 10.0

Grafana can scrape metrics and visualize:

  • Request rate per service
  • Response time percentiles
  • Error rates
  • TLS certificate expiration

External Access

Local Network Only (Default)

Traefik listens on host network interface, accessible from LAN:

entryPoints:
  websecure:
    address: ":443"

Access: https://halo.local or https://192.168.1.100

VPN Access

Run VPN server (WireGuard, OpenVPN) on Nexus or router, provide remote access to local network.

Public Internet (Advanced)

Port Forwarding:

  • Forward ports 80/443 from router to Nexus
  • Use Let’s Encrypt for valid TLS certificates
  • Configure Traefik authentication middleware for all services

Cloudflare Tunnel:

  • Avoid port forwarding using Cloudflare Argo Tunnel
  • Traffic proxied through Cloudflare with authentication
  • DDoS protection and caching included

Security Considerations:

  • Enable rate limiting
  • Use strong authentication (not just Basic Auth)
  • Monitor access logs for suspicious activity
  • Keep all services updated
  • Consider Web Application Firewall (WAF)

Troubleshooting

Service Not Accessible

  1. Check container has Traefik labels: docker inspect <container>
  2. Verify container on appnet: docker network inspect nexus_appnet
  3. Check Traefik logs: docker logs traefik
  4. Verify Traefik dashboard shows registered router
  5. Test backend directly: curl http://<service>:<port>

TLS Certificate Issues

  1. Check cert expiration: openssl s_client -connect halo.local:443 -servername halo.local
  2. Verify ACME configuration in Traefik logs
  3. Check acme.json has certificate data
  4. Test HTTP challenge: temporary allow port 80 inbound

Authentication Failures

  1. Verify htpasswd file is mounted correctly
  2. Check middleware is applied to router
  3. Test with curl: curl -u admin:password https://halo.local/n8n
  4. Review Traefik access logs for auth attempts

Best Practices

Label Consistency: Use consistent labeling patterns across all services for maintainability

Middleware Reuse: Define common middleware once, reference in multiple routers

Priority Management: Set router priorities to control matching order when rules overlap

Error Pages: Configure custom error pages for 404, 502, 503 responses

Security Headers: Always add security headers (HSTS, X-Frame-Options, CSP) via middleware

Certificate Automation: Use Let’s Encrypt wherever possible, automate renewal monitoring

Access Logging: Enable access logs for security auditing and troubleshooting



Back to top

Copyright © 2024-2025 HALO Project. All rights reserved.