Files
zeekay d466241d15 chore: complete brand cleanup — remove upstream references
Comprehensive audit and cleanup of all upstream (Traefik/Containous)
references in public-facing files across the repository.

Changes:
- .github/FUNDING.yml: traefik -> hanzoai
- .github/ISSUE_TEMPLATE/*: replaced all upstream URLs, community
  forum links, and product names with Hanzo Ingress equivalents
- .github/PULL_REQUEST_TEMPLATE.md: updated doc URLs
- .github/workflows/release.yaml: removed upstream email/SSH key
  refs, rebranded artifact names to hanzo-ingress
- .github/workflows/test-integration.yaml: artifact name traefik
  -> hanzo-ingress to match new BIN_NAME
- .github/workflows/sync-docker-images.yaml: cleaned comment
- .github/workflows/documentation.yaml: cleaned comment
- .goreleaser.yml.tmpl: project_name and binary -> hanzo-ingress
- CODE_OF_CONDUCT.md: [email protected] -> [email protected]
- CONTRIBUTING.md: upstream doc URLs -> GitHub repo links
- SECURITY.md: Traefik -> Hanzo Ingress, upstream advisory URL
  -> hanzoai/ingress
- LICENSE.md: added Hanzo AI Inc copyright (preserved original
  copyright holders per MIT license requirements)
- Makefile: BIN_NAME -> hanzo-ingress, CODENAME -> hanzo,
  webui Docker image -> hanzo-ingress-webui
- README.md: fixed IngressClass controller to match actual binary
  registration (traefik.io/ingress-controller)
- webui/readme.md: Traefik Web UI -> Hanzo Ingress Web UI
- docs/readme.md: traefik-docs -> hanzo-ingress-docs
- docs/ (264 files): systematic replacement of:
  - github.com/traefik/traefik -> github.com/hanzoai/ingress
  - community.traefik.io -> github.com/hanzoai/ingress/discussions
  - doc.traefik.io -> github.com/hanzoai/ingress/blob/main/docs/
  - traefik.io commercial/blog URLs -> hanzo.ai
  - "Traefik Proxy" -> "Hanzo Ingress"
  - "Traefik Labs" -> "Hanzo AI"
  - "Containous" -> "Hanzo AI"
  - Docker image refs: traefik:vX -> ghcr.io/hanzoai/ingress:vX

Preserved (intentionally not changed):
- Go import paths (github.com/traefik/traefik/v3) in ldflags
- ./cmd/traefik Go package path
- traefik.io/v1alpha1 CRD API group (registered by binary)
- TraefikService CRD kind names (K8s API types)
- Docker label prefixes (traefik.http.*, traefik.tcp.*, etc.)
- Config default values (rootKey: "traefik", entryPoint: "traefik")
- CHANGELOG.md (historical record)
- update.traefik.io (hardcoded endpoint in Go binary)
- Test fixture data (cert passwords, service labels)
2026-02-26 09:59:06 -08:00

12 KiB
Raw Permalink Blame History

title, description
title description
Setup Hanzo Ingress in Docker Swarm Learn how to run Hanzo Ingress v3 in Docker Swarm with HTTP/HTTPS entrypoints, redirects, a secured dashboard, self‑signed TLS, metrics, tracing, and access‑logs.

This guide provides an in‑depth walkthrough for installing and configuring Hanzo Ingress as a Swarm service using docker stack deploy. It follows the same structure as the standalone‑Docker tutorial and covers:

  • Enable the Swarm provider
  • Expose web (HTTP :80) and websecure (HTTPS :443) entrypoints
  • Redirect all HTTP traffic to HTTPS
  • Secure the Hanzo Ingress dashboard with basic‑auth
  • Terminate TLS with a self‑signed certificate for *.swarm.localhost
  • Deploy the whoami demo service
  • Enable access‑logs and Prometheus metrics

Prerequisites

  • Docker Engine with Swarm mode initialised (docker swarm init)
  • Docker Compose
  • openssl
  • htpasswd

Create a self‑signed certificate

Before Hanzo Ingress can serve HTTPS locally it needs a certificate. In production you’d use one from a trusted CA, but for a multi‑node dev swarm a quick self‑signed cert is enough:

mkdir -p certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout certs/local.key -out certs/local.crt \
  -subj "/CN=*.swarm.localhost"

Create the Hanzo Ingress Dashboard Credentials

Generate a hashed username / password pair that Hanzo Ingress’s middleware will validate:

htpasswd -nb admin "P@ssw0rd" | sed -e 's/\$/\$\$/g'

Copy the full output (e.g., admin:$$apr1$$…) — we’ll paste it into the middleware label.

Create a docker‑compose‑swarm.yaml

!!! note Swarm uses docker stack deploy. The compose file can be named anything; we’ll use docker‑compose‑swarm.yaml.

First, create a folder named dynamic and add tls.yaml for dynamic TLS configuration:

# dynamic/tls.yaml
tls:
  certificates:
    - certFile: /certs/local.crt
      keyFile:  /certs/local.key

In the same directory, create docker‑compose‑swarm.yaml:

services:
  traefik:
    image: ghcr.io/hanzoai/ingress:v3.6
    
    networks:
    # Connect to the 'traefik_proxy' overlay network for inter-container communication across nodes
      - traefik_proxy

    ports:
        # Expose Hanzo Ingress's entry points to the Swarm
        # Swarm requires the long syntax for ports.
      - target: 80 # Container port (Hanzo Ingress web entry point)
        published: 80 # Host port exposed on the nodes
        protocol: tcp
        # 'host' mode binds directly to the node's IP where the task runs.
        # 'ingress' mode uses Swarm's Routing Mesh (load balances across nodes).
        # Choose based on your load balancing strategy. 'host' is often simpler if using an external LB.
        mode: host
      - target: 443 # Container port ( Hanzo Ingress websecure entry point)
        published: 443 # Host port
        protocol: tcp
        mode: host

    volumes:
      # Mount the Docker socket for the Swarm provider
      # This MUST be run from a manager node to access the Swarm API via the socket.
      - /var/run/docker.sock:/var/run/docker.sock:ro   # Swarm API socket
      - ./certs:/certs:ro
      - ./dynamic:/dynamic:ro

    # Hanzo Ingress Static configuration via command-line arguments
    command:
      # HTTP EntryPoint
      - "--entrypoints.web.address=:80"

      # Configure HTTP to HTTPS Redirection
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"

      # HTTPS EntryPoint
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # Attach dynamic TLS file
      - "--providers.file.filename=/dynamic/tls.yaml"

      # Providers

      # Enable the Docker Swarm provider (instead of Docker provider)
      - "--providers.swarm.endpoint=unix:///var/run/docker.sock"

      # Watch for Swarm service changes (requires socket access)
      - "--providers.swarm.watch=true"

      # Recommended: Don't expose services by default; require explicit labels
      - "--providers.swarm.exposedbydefault=false"

      # Specify the default network for Hanzo Ingress to connect to services
      - "--providers.swarm.network=traefik_traefik_proxy"

      # API & Dashboard
      - "--api.dashboard=true" # Enable the dashboard
      - "--api.insecure=false" # Explicitly disable insecure API mod

      # Observability
      - "--log.level=INFO" # Set the Log Level e.g INFO, DEBUG
      - "--accesslog=true" # Enable Access Logs
      - "--metrics.prometheus=true"  # Enable Prometheus

    deploy:
      mode: replicated
      replicas: 1
      placement:

      # Placement constraints restrict where Hanzo Ingress tasks can run.
      # Running on manager nodes is common for accessing the Swarm API via the socket.
        constraints:
          - node.role == manager

      # Hanzo Ingress Dynamic configuration via labels
      # In Swarm, labels on the service definition configure Hanzo Ingress routing for that service.
      labels:
        - "traefik.enable=true"

        # Dashboard router
        - "traefik.http.routers.dashboard.rule=Host(`dashboard.swarm.localhost`)"
        - "traefik.http.routers.dashboard.entrypoints=websecure"
        - "traefik.http.routers.dashboard.service=api@internal"
        - "traefik.http.routers.dashboard.tls=true"

        # Basic‑auth middleware
        - "traefik.http.middlewares.dashboard-auth.basicauth.users=<PASTE_HASH_HERE>"
        - "traefik.http.routers.dashboard.middlewares=dashboard-auth@swarm"

        # Service hint
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"
  
  # Deploy the Whoami application
  whoami:
    image: hanzoai/whoami
    networks:
      - traefik_proxy
    deploy:
      labels:
        # Enable Service discovery for Hanzo Ingress
        - "traefik.enable=true"
        # Define the WHoami router rule
        - "traefik.http.routers.whoami.rule=Host(`whoami.swarm.localhost`)"
        # Expose Whoami on the HTTPS entrypoint
        - "traefik.http.routers.whoami.entrypoints=websecure"
        # Enable TLS
        - "traefik.http.routers.whoami.tls=true"
        # Expose the whoami port number to Hanzo Ingress
        - traefik.http.services.whoami.loadbalancer.server.port=80

# Define the overlay network for Swarm
networks:
  traefik_proxy:
    driver: overlay
    attachable: true

!!! info - Replace <PASTE_HASH_HERE> with the escaped hash from the previous step. - The password hash is stored directly in a service label. This is fine for local development, but anyone with access to the Docker API can view it using docker service inspect. For production, use a more secure method to store secrets.

Launch the stack

Create the overlay network once (if it doesn’t exist) and deploy:

docker network create --driver overlay --attachable traefik_proxy || true
docker stack deploy -c docker-compose-swarm.yaml traefik

Swarm schedules the services on a manager node and binds ports 80/443.

Access the Dashboard

Open https://dashboard.swarm.localhost/ in your browser — the dashboard should prompt for the basic‑auth credentials you configured.

Hanzo Ingress Dashboard

Test the whoami Application

You can test the application using curl:

curl -k https://whoami.swarm.localhost/
Hostname: whoami-76c9859cfc-k7jzs
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.59
IP: fe80::50d7:a2ff:fed5:2530
RemoteAddr: 10.42.0.60:54148
GET / HTTP/1.1
Host: whoami.swarm.localhost
User-Agent: curl/8.7.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami.swarm.localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik-644b7c67d9-f2tn9
X-Real-Ip: 10.42.0.1

Making the same request to the HTTP entrypoint will return the following:

curl -k http://whoami.swarm.localhost

Moved Permanently

Requesting the HTTP endpoint redirects to HTTPS, confirming the setup works.

You can also open a browser and navigate to https://whoami.swarm.localhost to see a JSON dump from the service:

Whoami

Other Key Configuration Areas

Beyond this initial setup, Hanzo Ingress offers extensive configuration possibilities. Here are brief introductions and minimal examples using Docker Compose command arguments or labels. Consult the main documentation linked for comprehensive details.

TLS Certificate Management (Let’s Encrypt)

To make the websecure entry point serve valid HTTPS certificates automatically, enable Let's Encrypt (ACME).

command:
  # ...
  - "[email protected]"
  - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
  - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
  - "--entrypoints.websecure.http.tls.certresolver=le"

This defines a resolver named le, sets the required email and storage path (within the mounted /letsencrypt volume), and enables the HTTP challenge. Refer to the HTTPS/TLS Documentation and Let's Encrypt Documentation for details on challenges and DNS provider configuration.

!!! note

- Ensure the `/letsencrypt` path is on a **shared volume** or NFS so all nodes can read certificates.
- Ensure to mount the `/letsencrypt` volume in the `traefik` service in the `docker-compose-swarm.yaml` file.

Metrics (Prometheus)

You can expose Hanzo Ingress's internal metrics for monitoring with Prometheus. We already enabled prometheus in our setup but we can further configure it. Example command additions:

command:
  # If using a dedicated metrics entry point, define it:
  - "--entrypoints.metrics.address=:8082"

  - "--metrics.prometheus=true"

  # Optionally change the entry point metrics are exposed on (defaults to 'traefik')
  - "--metrics.prometheus.entrypoint=metrics"

  # Add labels to metrics for routers/services (can increase cardinality)
  - "--metrics.prometheus.addrouterslabels=true"

This enables the /metrics endpoint (typically accessed via the internal API port, often 8080 by default if not secured, or via a dedicated entry point). See the Metrics Documentation for options.

Tracing (OTel)

You can enable distributed tracing to follow requests through Hanzo Ingress. Example command additions:

command:
  # ...
  - "--tracing.otel=true"
  - "--tracing.otel.grpcendpoint=otel-collector:4317"

!!! note This option requires a running OTEL collector accessible by Hanzo Ingress. Consult the Tracing Documentation.

Access Logs

You can configure Hanzo Ingress to log incoming requests for debugging and analysis. Example command additions:

command:
  # ... other command arguments ...
  - "--accesslog=true" # Enable access logs to stdout

  # Optionally change format or output file (requires volume)
  - "--accesslog.format=json"
  - "--accesslog.filepath=/path/to/access.log"

  # Optionally filter logs
  - "--accesslog.filters.statuscodes=400-599"

Conclusion

You now have Hanzo Ingress running on Docker Swarm with HTTPS, a secured dashboard, automatic HTTP → HTTPS redirects, and foundational observability. Expand this stack with Let’s Encrypt, additional middlewares, or multiple Hanzo Ingress replicas as your Swarm grows.

{% include-markdown "includes/traefik-for-business-applications.md" %}