Perspective V Docs

Edge Stack Guide

The edge stack owns the public reverse proxy and the admin/monitoring entrypoints.

The active Swarm edge stack contains Traefik and Kener. Portainer is an independently scalable administration panel; the retained Compose layout below still keeps it beside the edge services for rollback compatibility.

Source Of Truth

  • Active Swarm: swarm/stacks/edge/{traefik,kener}.yml, assembled by swarm/scripts/edge/edge.{sh,bat} as edge

  • Active Portainer panel: swarm/stacks/panels/portainer.yml, assembled by swarm/scripts/panels/panels.{sh,bat} as panel

  • Compose files:

    • runtime/stacks/infrastructure/edge/docker-compose.traefik.yml
    • runtime/stacks/infrastructure/edge/docker-compose.portainer.yml
    • runtime/stacks/infrastructure/edge/docker-compose.kener.yml
  • VPS env files:

    • runtime/environments/vps/infrastructure/edge/traefik/.env
    • runtime/environments/vps/infrastructure/edge/portainer/.env
    • runtime/environments/vps/infrastructure/edge/kener/.env
  • Dev env templates:

    • runtime/environments/dev/infrastructure/edge/{traefik,portainer,kener}/*.dev.env
  • Launchers:

    • runtime/scripts/infrastructure/edge-traefik.{sh,bat}
    • runtime/scripts/infrastructure/edge-portainer.{sh,bat}
    • runtime/scripts/infrastructure/edge-kener.{sh,bat}

Dependencies

  • Docker external network: proxy
  • Docker external network: platform for Kener Redis connectivity
  • Host path: /var/lib/traefik/letsencrypt/acme.json
  • Host path: /var/lib/traefik/registry-auth/registry.htpasswd
  • Host path: /var/lib/traefik/dynamic — dynamic config directory, installed by operations/traefik/install-dynamic-config.sh
  • Host path: /var/log/traefik — access log destination, rotated by /etc/logrotate.d/traefik (7 days, copytruncate)

Required Variables

Traefik

  • LETSENCRYPT_EMAIL
  • NETBIRD_ALLOWED_CIDRS
  • ADMIN_BASIC_AUTH

TRAEFIK_DASHBOARD_HOST was removed on 2026-08-15 — see Dashboard below.

Portainer

  • PORTAINER_HOST

Kener

  • KENER_HOST
  • KENER_ORIGIN
  • KENER_SECRET_KEY
  • KENER_REDIS_URL
  • SMTP_HOST
  • SMTP_PORT
  • SMTP_USER
  • SMTP_PASSWORD
  • SMTP_FROM_EMAIL
  • SMTP_SECURE

Step-By-Step

docker network create proxy || true
docker network create platform || true

sudo mkdir -p /var/lib/traefik/letsencrypt
sudo touch /var/lib/traefik/letsencrypt/acme.json
sudo chmod 600 /var/lib/traefik/letsencrypt/acme.json

sudo mkdir -p /var/lib/traefik/registry-auth
sudo touch /var/lib/traefik/registry-auth/registry.htpasswd
sudo chmod 600 /var/lib/traefik/registry-auth/registry.htpasswd

Deploy Traefik and Portainer first:

./runtime/scripts/infrastructure/edge-traefik.sh up
./runtime/scripts/infrastructure/edge-portainer.sh up

Deploy Kener after the platform stack is up and Redis is reachable:

./runtime/scripts/infrastructure/edge-kener.sh up

Raw compose equivalents:

docker compose --env-file runtime/environments/vps/infrastructure/edge/traefik/.env -f runtime/stacks/infrastructure/edge/docker-compose.traefik.yml up -d
docker compose --env-file runtime/environments/vps/infrastructure/edge/portainer/.env -f runtime/stacks/infrastructure/edge/docker-compose.portainer.yml up -d
docker compose --env-file runtime/environments/vps/infrastructure/edge/kener/.env -f runtime/stacks/infrastructure/edge/docker-compose.kener.yml up -d

Validation

./runtime/scripts/infrastructure/edge-traefik.sh ps
./runtime/scripts/infrastructure/edge-portainer.sh ps
./runtime/scripts/infrastructure/edge-kener.sh ps

curl -Ik https://traefik-manager.perspective-v.com
curl -Ik https://portainer.perspective-v.com
curl -Ik https://kener.perspective-v.com
curl -Ik https://kener.perspective-v.com/healthcheck

Expected behavior:

  • traefik-manager.perspective-v.com is NetBird-only and uses Traefik Manager's own login.
  • portainer.perspective-v.com is NetBird-only and uses Portainer login.
  • kener.perspective-v.com is public and uses Kener login.

Dashboard

Traefik's built-in dashboard was disabled on 2026-08-15 (api.dashboard: false) and replaced by Traefik Manager at https://traefik-manager.perspective-v.com.

traefik.perspective-v.com now returns 404 and its DNS record should be retired.

The API stays on (api.insecure: true), bound to :8080 inside the container only — it has no ports: entry, so it is reachable from the proxy overlay and nowhere else. Traefik Manager reads live routers, services and health from it.

Traefik itself carries no traefik.enable label. Setting one without a loadbalancer port aborts the entire swarm provider and 404s every site — see the operations README before adding labels to this service.

Access logging

Enabled 2026-08-15, writing to /var/log/traefik/access.log (previously stdout only) so Traefik Manager can stream it.

All request and response headers are dropped (fields.headers.defaultMode: drop) — without that, Authorization and Cookie values are logged verbatim. Traefik cannot redact query strings, and this estate puts JWTs there (/notifications/hub?access_token=eyJ...), so log lines remain credential-bearing. Retention is therefore capped at 7 compressed days and the file is root-only. Do not lengthen retention without revisiting that.

On this page