Skip to content

auth

how people sign in to each app, on the lan and from outside, and what MFA each way in has. my accounts and their MFA are in entra ID, and entra is the MFA for any name outside that has none of its own.

three access paths

  • direct: the app's own address and port, on the lan only
  • traefik on the lan: https://<name>.mydomain.com, on 443 at the swarm's VIP
  • traefik outside: the same name from the internet. the router forwards its 443 to traefik's 1444, see traefik

the rules

  • outside, every name has MFA or is a public site. an app with MFA of its own keeps it, and every other name goes behind oauth2-proxy, so users sign in with entra first
  • on the lan, oauth2-proxy is also in front of the names that give control of something with no login, or only a password: the zigbee and z-wave UIs, dozzle's container logs, apprise's notification tokens, the unifi API browser's stored login, traefik's dashboard, seerr and the arr apps
  • an app with native oauth (entra), signing its users in with entra itself, needs no oauth2-proxy in front: proxmox, PBS, portainer and grafana
  • oauth2-proxy protects the name only. on the lan an app's own port still answers, with the app's own login, so that login still matters
  • jellyfin has no entra sign-in. its TV and phone apps can't pass one

two kinds of entra sign-in

entra is the provider for both here. oauth2-proxy and each of these apps also work with other OpenID Connect providers.

oauth2-proxy (entra) native oauth (entra)
who asks traefik, through oauth2-proxy, before the app sees the request the app, on its login page
after it the app's own login, if it has one nothing: the app maps the entra user to a user of its own
app registration one, shared by every name behind oauth2-proxy one per app
works on the name, through traefik any address the app's redirect URIs list

entra ID has each app registration and where it's set up.

every app

the table is written by the same script as traefik's routes, from the same registry, so it changes when a route does. it lists only the names traefik serves, and its columns are grouped by the three access paths.

  • each row is a name, <name>.mydomain.com, unless it shows another in brackets
  • the direct columns are the app's own login and MFA, which apply whichever way you reach it
  • sign-in and MFA on each traefik path are what you meet there: the app's own, with oauth2-proxy (entra), then in front where traefik asks oauth2-proxy first
  • entra's MFA is whatever my conditional access policy requires
  • not recorded means the registry doesn't say yet
namedirecttraefik on the lantraefik outside
addressits own loginMFAsign-inMFAsign-inMFA
adguard1192.168.1.5:80passwordnonepasswordnonenot served
adguard2192.168.1.6:3000passwordnonepasswordnonenot served
apex (mydomain.com)192.168.1.45:8180WordPress password login, at a custom address (wp-login.php answers 404); the network admin is herenot recordednone to read it; WordPress password login, at a custom address (wp-login.php answers 404); the network admin is herenot recordednone: every path redirects to https://www.mydomain.com
apprise192.168.1.45:8050nonenoneoauth2-proxy (entra)entranot served
auth (the sign-in)192.168.1.45:4180oauth2-proxy (entra): it is the sign-inentraoauth2-proxy (entra): it is the sign-inentraoauth2-proxy (entra): it is the sign-inentra
bazarr192.168.1.86:6767password (form)noneoauth2-proxy (entra), then password (form)entranot served
bentopdf192.168.1.45:8091nonenonenonenonenot served
blog192.168.1.45:8180WordPress password login (wp-login.php)not recordednone to read it; WordPress password login (wp-login.php)not recordednone to read it; WordPress password login (wp-login.php)not recorded
dozzle192.168.1.41:8888nonenoneoauth2-proxy (entra)entranot served
gatus192.168.1.45:8085nonenonenonenonenot served
glances-docker01192.168.1.41:61208nonenonenonenonenot served
glances-docker02192.168.1.42:61208nonenonenonenonenot served
glances-docker03192.168.1.43:61208nonenonenonenonenot served
glances-pi-zwave01192.168.1.96:61208nonenonenonenonenot served
glances-pve1192.168.1.81:61208nonenonenonenonenot served
glances-pve2192.168.1.82:61208nonenonenonenonenot served
glances-pve3192.168.1.83:61208nonenonenonenonenot served
glances-syn02192.168.1.31:61208nonenonenonenonenot served
glances-truenas1192.168.1.86:61208nonenonenonenonenot served
grafana192.168.1.86:30037native oauth (entra), grafana's Azure AD setting; password formentra; the password form has nonenative oauth (entra), grafana's Azure AD setting; password formentra; the password form has nonenot served
ha192.168.1.63:443 (homeassistant.mydomain.com)passwordauthenticator-app module: not yet confirmed for every usernot servedpasswordauthenticator-app module: not yet confirmed for every user
homepage192.168.1.45:3000nonenonenonenoneoauth2-proxy (entra)entra
infinitude192.168.1.45:4000nonenonenonenonenot served
jellyfin192.168.1.86:8096passwordnonepasswordnonenot served
npm192.168.1.45:181password (NPM's admin)nonepassword (NPM's admin)nonenot served
nvr192.168.1.86:8971passwordnonepasswordnonenot served
omni-tools192.168.1.45:8090nonenonenonenonenot served
open-webui192.168.1.86:31028password (sign-up off)nonepassword (sign-up off)nonenot served
pbspbs1.mydomain.com:8007native oauth (entra), realm 'EntraID'; password realms pam and pbsentra; the password realms: not recorded (per-user TOTP)native oauth (entra), realm 'EntraID'; password realms pam and pbsentra; the password realms: not recorded (per-user TOTP)not served
pbs-restore192.168.1.45:8008Proxmox's sign-in, per user: native oauth (entra) through the realm 'Azure AAD'; the pam, pve and AD password realms also appearentra, its only MFA: the portal can't do Proxmox's TOTP. The password realms: noneProxmox's sign-in, per user: native oauth (entra) through the realm 'Azure AAD'; the pam, pve and AD password realms also appearentra, its only MFA: the portal can't do Proxmox's TOTP. The password realms: nonenot served
portainer192.168.1.45:9000, :9443native oauth (entra); the initial admin's password (always on); API keysentra; the password and API keys have nonenative oauth (entra); the initial admin's password (always on); API keysentra; the password and API keys have nonenative oauth (entra); the initial admin's password (always on); API keys; oauth2-proxy (entra) first on /api/auth, X-API-Key requestsentra; the password and API keys have none; entra first on those
profilarr192.168.1.86:6868password (native oauth supported, not set up)noneoauth2-proxy (entra), then password (native oauth supported, not set up)entranot served
prometheus192.168.1.86:30104nonenonenonenonenot served
prowlarr192.168.1.86:9696password (forms, required for all)noneoauth2-proxy (entra), then password (forms, required for all)entranot served
proxmoxpve1-3.mydomain.com:8006native oauth (entra), realm 'Azure AAD'; password realms pam, pve and ADentra; root@pam: TOTP everywhere, and a WebAuthn passkey on proxmox.mydomain.com only; recovery keys held; other pam, pve and AD users: not recordednative oauth (entra), realm 'Azure AAD'; password realms pam, pve and ADentra; root@pam: TOTP everywhere, and a WebAuthn passkey on proxmox.mydomain.com only; recovery keys held; other pam, pve and AD users: not recordednot served
qbittorrent192.168.1.86:8080password (subnet whitelist off)noneoauth2-proxy (entra), then password (subnet whitelist off)entranot served
radarr192.168.1.86:7878password (forms, required for all)noneoauth2-proxy (entra), then password (forms, required for all)entranot served
sabnzbd192.168.1.86:8081passwordnoneoauth2-proxy (entra), then passwordentranot served
mydomain1 (mydomain1.com)192.168.1.45:8180WordPress password login, at a custom address (wp-login.php answers 404)not recordednot servednone to read it; WordPress password login, at a custom address (wp-login.php answers 404)not recorded
searxng192.168.1.86:30053nonenonenonenonenot served
seerr192.168.1.86:5055password (Jellyfin or local accounts)noneoauth2-proxy (entra), then password (Jellyfin or local accounts)entraoauth2-proxy (entra), then password (Jellyfin or local accounts)entra
sonarr192.168.1.86:8989password (forms, required for all)noneoauth2-proxy (entra), then password (forms, required for all)entranot served
syn01192.168.1.30:5101 (syn01.mydomain.com)passwordone-time codesnot servedpasswordone-time codes
syn02192.168.1.31:5101 (syn02.mydomain.com)passwordone-time codesnot servedpasswordone-time codes
traefikno port of its own; the API is also on :8080, for traefik-api onlynone: its read-only API has no loginnoneoauth2-proxy (entra)entranot served
unifi192.168.1.1:443 (efg.mydomain.com)UniFi OS loginMFA on the accountnot servedUniFi OS loginMFA on the account
unifiapibrowser192.168.1.45:8010none: its login is turned off (NOAPIBROWSERAUTH=1), and it holds a UniFi loginnoneoauth2-proxy (entra)entranot served
versitytruenas1.mydomain.com:30355S3 access key and secretnoneS3 access key and secretnonenot served
watch-your-lan192.168.1.31:8840nonenonenonenonenot served
www192.168.1.45:8180WordPress password login (wp-login.php)not recordednone to read it; WordPress password login (wp-login.php)not recordednone to read it; WordPress password login (wp-login.php)not recorded
zigbee2mqtt192.168.1.96:8080not recordednoneoauth2-proxy (entra), then the app's own login (not recorded)entranot served
zwave-js-ui192.168.1.96:80passwordnoneoauth2-proxy (entra), then passwordentranot served

secrets, ssh and active directory

the passwords and keys the apps use, and how they reach a container, are on secrets.

to be written

ssh and keys, and active directory.