domain: mydomain.com

vip: 192.168.1.45

oauth:
  host: auth.mydomain.com
  upstream: http://192.168.1.45:4180

other_endpoints:
  - name: Frigate API
    address: "192.168.1.86:5000"
    auth: "none: the whole API, config and camera control included"
    mfa: "none"
  - name: MQTT (mosquitto)
    address: "192.168.1.45:1883"
    auth: "none: allow_anonymous true, so anyone can publish, Zigbee2MQTT's command topics included"
    mfa: "none"
  - name: Docker API proxy (truenas1)
    address: "192.168.1.86:2375"
    auth: "none: read-only Docker API"
    mfa: "none"
  - name: Ollama
    address: "192.168.1.86:30068"
    auth: "none"
    mfa: "none"
  - name: FlareSolverr
    address: "192.168.1.86:8191"
    auth: "none"
    mfa: "none"
  - name: Portainer agent (swarm nodes)
    address: "192.168.1.41, .42, .43:9001"
    auth: "none: no AGENT_SECRET, so any Portainer that reaches it can adopt the node (owner accepted, 2026-09-22)"
    mfa: "none"
  - name: Portainer agent (truenas1, pi-zwave01)
    address: "192.168.1.86:9001, 192.168.1.96:9001"
    auth: "unknown: not defined in this repo, so whether AGENT_SECRET is set is unchecked"
    mfa: "none"
  - name: Dozzle agents
    address: "192.168.1.41, .42, .43, .31, .86, .96:7007"
    auth: "mutual TLS with the shared dozzle agent certificate"
    mfa: "none"
  - name: oauth2-proxy
    address: "192.168.1.45:4180"
    auth: "it is the Entra sign-in; nothing is behind it but a 202"
    mfa: "Entra"

services:

  traefik:
    upstream: api@internal
    internal: oauth
    native:
      auth: "none: its read-only API has no login"
      mfa: "none"
      direct: "no port of its own; the API is also on :8080, for traefik-api only"

  apprise:
    upstream: http://192.168.1.45:8050
    internal: oauth
    native:
      auth: "none"
      mfa: "none"

  bentopdf:
    upstream: http://192.168.1.45:8091
    internal: open
    native:
      auth: "none"
      mfa: "none"

  blog:
    upstream: http://192.168.1.45:8180
    internal: open
    external: public
    native:
      auth: "WordPress password login (wp-login.php)"
      mfa: "unknown: check for a 2FA plugin"

  apex:
    host: mydomain.com
    upstream: http://192.168.1.45:8180
    internal: open
    external: public
    external_redirect: https://www.mydomain.com
    native:
      auth: "WordPress password login, at a custom address (wp-login.php answers 404); the network admin is here"
      mfa: "unknown: check for a 2FA plugin"

  mydomain1:
    host: mydomain1.com
    upstream: http://192.168.1.45:8180
    external: public
    native:
      auth: "WordPress password login, at a custom address (wp-login.php answers 404)"
      mfa: "unknown: check for a 2FA plugin"

  dozzle:
    upstream: http://192.168.1.41:8888
    internal: oauth
    native:
      auth: "none"
      mfa: "none"

  gatus:
    upstream: http://192.168.1.45:8085
    internal: open
    native:
      auth: "none"
      mfa: "none"

  homepage:
    upstream: http://192.168.1.45:3000
    internal: open
    external: oauth
    native:
      auth: "none"
      mfa: "none"

  ha:
    upstream: https://192.168.1.63:443
    tls_name: homeassistant.mydomain.com
    external: own-mfa
    mfa: Home Assistant's authenticator-app (TOTP) module, which every user must have turned on
    native:
      auth: "password"
      mfa: "authenticator-app module: not yet confirmed for every user"
      direct: "192.168.1.63:443 (homeassistant.mydomain.com)"

  infinitude:
    upstream: http://192.168.1.45:4000
    internal: open
    native:
      auth: "none"
      mfa: "none"

  npm:
    upstream: http://192.168.1.45:181
    internal: open
    native:
      auth: "password (NPM's admin)"
      mfa: "none"

  omni-tools:
    upstream: http://192.168.1.45:8090
    internal: open
    native:
      auth: "none"
      mfa: "none"

  portainer:
    upstream: http://192.168.1.45:9000
    internal: open
    external: own-mfa
    mfa: Portainer's own OAuth sign-in to Entra, where Conditional Access requires MFA; its password login and API keys need the proxy's Entra sign-in outside
    external_oauth_paths:
      - /api/auth
    external_oauth_headers:
      - X-API-Key
    native:
      auth: "native oauth (Entra); the initial admin's password (always on); API keys"
      mfa: "Entra; the password and API keys have none"
      direct: "192.168.1.45:9000, :9443"

  unifiapibrowser:
    upstream: http://192.168.1.45:8010
    internal: oauth
    native:
      auth: "none: its login is turned off (NOAPIBROWSERAUTH=1), and it holds a UniFi login"
      mfa: "none"

  www:
    upstream: http://192.168.1.45:8180
    internal: open
    external: public
    native:
      auth: "WordPress password login (wp-login.php)"
      mfa: "unknown: check for a 2FA plugin"

  adguard1:
    upstream: http://192.168.1.5:80
    internal: open
    native:
      auth: "password"
      mfa: "none"

  adguard2:
    upstream: http://192.168.1.6:3000
    internal: open
    native:
      auth: "password"
      mfa: "none"

  bazarr:
    upstream: http://192.168.1.86:6767
    internal: oauth
    native:
      auth: "password (form)"
      mfa: "none"

  grafana:
    upstream: http://192.168.1.86:30037
    internal: open
    native:
      auth: "native oauth (Entra), grafana's Azure AD setting; password form"
      mfa: "Entra; the password form has none"

  jellyfin:
    upstream: http://192.168.1.86:8096
    internal: open
    native:
      auth: "password"
      mfa: "none"

  open-webui:
    upstream: http://192.168.1.86:31028
    internal: open
    native:
      auth: "password (sign-up off)"
      mfa: "none"

  profilarr:
    upstream: http://192.168.1.86:6868
    internal: oauth
    native:
      auth: "password (native oauth supported, not set up)"
      mfa: "none"

  prometheus:
    upstream: http://192.168.1.86:30104
    internal: open
    native:
      auth: "none"
      mfa: "none"

  prowlarr:
    upstream: http://192.168.1.86:9696
    internal: oauth
    native:
      auth: "password (forms, required for all)"
      mfa: "none"

  qbittorrent:
    upstream: http://192.168.1.86:8080
    internal: oauth
    native:
      auth: "password (subnet whitelist off)"
      mfa: "none"

  radarr:
    upstream: http://192.168.1.86:7878
    internal: oauth
    native:
      auth: "password (forms, required for all)"
      mfa: "none"

  sabnzbd:
    upstream: http://192.168.1.86:8081
    internal: oauth
    native:
      auth: "password"
      mfa: "none"

  searxng:
    upstream: http://192.168.1.86:30053
    internal: open
    native:
      auth: "none"
      mfa: "none"

  seerr:
    upstream: http://192.168.1.86:5055
    internal: oauth
    external: oauth
    native:
      auth: "password (Jellyfin or local accounts)"
      mfa: "none"

  sonarr:
    upstream: http://192.168.1.86:8989
    internal: oauth
    native:
      auth: "password (forms, required for all)"
      mfa: "none"

  versity:
    upstream: https://truenas1.mydomain.com:30355
    internal: open
    native:
      auth: "S3 access key and secret"
      mfa: "none"

  glances-docker01:
    upstream: http://192.168.1.41:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-docker02:
    upstream: http://192.168.1.42:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-docker03:
    upstream: http://192.168.1.43:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-pi-zwave01:
    upstream: http://192.168.1.96:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-pve1:
    upstream: http://192.168.1.81:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-pve2:
    upstream: http://192.168.1.82:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-pve3:
    upstream: http://192.168.1.83:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-syn02:
    upstream: http://192.168.1.31:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  glances-truenas1:
    upstream: http://192.168.1.86:61208
    internal: open
    native:
      auth: "none"
      mfa: "none"

  nvr:
    upstream: https://192.168.1.86:8971
    tls_name: frigate.mydomain.com
    internal: open
    native:
      auth: "password"
      mfa: "none"

  proxmox:
    upstream:
      - https://pve1.mydomain.com:8006
      - https://pve2.mydomain.com:8006
      - https://pve3.mydomain.com:8006
    internal: open
    native:
      auth: "native oauth (Entra), realm 'Azure AAD'; password realms pam, pve and AD"
      mfa: "Entra; root@pam: TOTP everywhere, and a WebAuthn passkey on proxmox.mydomain.com only (the nodes' :8006 fails Proxmox's origin check, which needs port 443; seen in pve1's log 2026-09-27); recovery keys held; other pam, pve and AD users: unknown"
      direct: "pve1-3.mydomain.com:8006"

  pbs:
    upstream: https://pbs1.mydomain.com:8007
    internal: open
    native:
      auth: "native oauth (Entra), realm 'EntraID'; password realms pam and pbs"
      mfa: "Entra; the password realms: unknown (per-user TOTP)"

  pbs-restore:
    upstream: https://192.168.1.45:8008
    upstream_tls: insecure
    internal: open
    cross_site_paths: [/, /login, /login/oidc/callback]
    native:
      auth: "Proxmox's sign-in, per user: native oauth (Entra) through the realm 'Azure AAD'; the pam, pve and AD password realms also appear"
      mfa: "Entra, its only MFA: the portal can't do Proxmox's TOTP. The password realms: none"

  syn01:
    upstream: https://syn01.mydomain.com:5101
    upstream_tls: insecure
    external: own-mfa
    mfa: DSM's 2-step verification (one-time codes), on for every account (owner, 2026-09-27)
    native:
      auth: "password"
      mfa: "one-time codes (owner)"
      direct: "192.168.1.30:5101 (syn01.mydomain.com)"

  syn02:
    upstream: https://syn02.mydomain.com:5101
    external: own-mfa
    mfa: DSM's 2-step verification (one-time codes), on for every account (owner, 2026-09-27)
    native:
      auth: "password"
      mfa: "one-time codes (owner)"
      direct: "192.168.1.31:5101 (syn02.mydomain.com)"

  unifi:
    upstream: https://192.168.1.1:443
    tls_name: unifi.mydomain.com
    external: own-mfa
    mfa: UniFi OS login, with MFA on the account (owner, 2026-09-27)
    native:
      auth: "UniFi OS login"
      mfa: "MFA on the account (owner)"
      direct: "192.168.1.1:443 (efg.mydomain.com)"

  watch-your-lan:
    upstream: http://192.168.1.31:8840
    internal: open
    native:
      auth: "none"
      mfa: "none"

  zigbee2mqtt:
    upstream: http://192.168.1.96:8080
    internal: oauth
    native:
      auth: "unknown: auth_token not checked (the Pi's SSH host key is not trusted here)"
      mfa: "none"

  zwave-js-ui:
    upstream: http://192.168.1.96:80
    internal: oauth
    native:
      auth: "password (owner)"
      mfa: "none"
