diff --git a/CLAUDE.md b/CLAUDE.md index 58225fb..c5a4b00 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,6 +112,10 @@ expect Nix to report the correct hash on a failed build (or use `nix-prefetch`/` earlier version of this module additionally set a second, static set of `Access-Control-*` headers at the proxy level, which browsers reject as conflicting duplicates (server-to-server/curl checks don't notice, since only browsers enforce CORS header validation). + - Caddy matches vhosts on the exact `Host` header, unlike nginx (where a single vhost acts as the default + regardless of `Host`). When `hostname == "localhost"`, the caddy vhost adds `serverAliases` for + `127.0.0.1:80`/`[::1]:80` too — otherwise visiting the VM via the IP literal instead of `localhost` matches no + vhost and Caddy silently returns an empty `200 OK` (a blank page with no error anywhere). - Chromium is required at runtime for PDF generation (`PDF_GENERATOR=snappdf`, `SNAPPDF_CHROMIUM_PATH`) and is added to the PHP-FPM and data-setup services' `path`. diff --git a/nixos-module/invoiceninja.nix b/nixos-module/invoiceninja.nix index 697b68b..5a0d6c7 100644 --- a/nixos-module/invoiceninja.nix +++ b/nixos-module/invoiceninja.nix @@ -557,6 +557,14 @@ in cfg.proxy.caddyConfig { hostName = lib.mkForce proto_hostname; + # Caddy matches vhosts on the exact Host header, unlike nginx's single-vhost-is-default + # behavior. For local dev, accept requests to 127.0.0.1/[::1] too - otherwise visiting + # via the IP literal instead of "localhost" hits no vhost and gets an empty 200 response + # (a silent white screen, no error anywhere). + serverAliases = lib.mkIf (cfg.hostname == "localhost") [ + "127.0.0.1:80" + "[::1]:80" + ]; extraConfig = '' encode zstd gzip root ${invoiceninja}/public