The target is a VM inside the company network, reachable only from there. Two consequences decide whether this works at all, and both are easy to discover too late — after the firewall rules are already written. The server needs outbound access even though nothing comes in. Auth.js exchanges the authorisation code for a token server-side and fetches the issuer's configuration, so login.microsoftonline.com must be reachable from the VM; the database likewise. That the person signs in through their own browser is not enough, which is the assumption worth naming before someone builds a closed network around it. HTTPS is not optional either: Entra accepts http only for localhost. The practical route without public reachability is a public DNS name pointing at a private address and a certificate obtained through the DNS challenge — allowed, common, and it yields a normally trusted certificate while the server stays unreachable from outside. deploy/Caddyfile does that, and the alternative (self-signed, trusted on every workstation) is written down with its cost. docker-compose now publishes port 3000 on 127.0.0.1 only. It was on every interface, so the same service also stood there unencrypted, and one gap in the firewall was enough. The proxy is the only way in. AUTH_URL is documented for the same reason a comment sits in the Caddyfile: behind a proxy the container does not see the name the browser used, and the callback would point somewhere nobody can reach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
46 lines
1.6 KiB
Caddyfile
46 lines
1.6 KiB
Caddyfile
# Reverse Proxy für den Betrieb im Firmennetz.
|
|
#
|
|
# Der Name ist öffentlich (hr.elycon.solutions), die Adresse dahinter privat
|
|
# (10.x). Das ist erlaubt und der übliche Weg: der DNS-Eintrag ist von aussen
|
|
# auflösbar, der Server nicht erreichbar.
|
|
#
|
|
# Warum das der Aufwand wert ist: Entra ID akzeptiert `http` nur für
|
|
# localhost. Ohne HTTPS gibt es keine Anmeldung — und ein selbst signiertes
|
|
# Zertifikat müsste auf jedem Arbeitsplatz als vertrauenswürdig hinterlegt
|
|
# werden. Mit der DNS-Challenge kommt ein regulär vertrauenswürdiges
|
|
# Zertifikat zustande, ohne dass der Server je aus dem Internet erreichbar
|
|
# sein muss.
|
|
#
|
|
# Voraussetzung: ein Caddy-Build mit dem DNS-Modul des eigenen Anbieters,
|
|
# etwa
|
|
# xcaddy build --with github.com/caddy-dns/cloudflare
|
|
# Andere Anbieter siehe https://github.com/caddy-dns
|
|
#
|
|
# Der API-Schlüssel gehört in eine Umgebungsvariable des Dienstes, nicht in
|
|
# diese Datei.
|
|
|
|
hr.elycon.solutions {
|
|
tls {
|
|
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
|
|
}
|
|
|
|
# Die Anwendung lauscht nur auf der Loopback-Adresse (siehe
|
|
# docker-compose.yml), erreichbar ist sie also ausschliesslich über
|
|
# diesen Proxy.
|
|
reverse_proxy 127.0.0.1:3000
|
|
|
|
# Ohne diese Weitergabe baut Auth.js seine Rückruf-Adresse aus dem
|
|
# Container-Hostnamen statt aus dem echten Namen — die Anmeldung landet
|
|
# dann auf einer Adresse, die niemand kennt. `trustHost` in
|
|
# lib/auth/config.ts wertet genau diese Header aus.
|
|
header_up X-Forwarded-Proto {scheme}
|
|
header_up X-Forwarded-Host {host}
|
|
|
|
encode gzip zstd
|
|
|
|
log {
|
|
output file /var/log/caddy/hr.log
|
|
format json
|
|
}
|
|
}
|