diff --git a/nixos-module/default.nix b/nixos-module/default.nix index 02824ce..ffd1187 100644 --- a/nixos-module/default.nix +++ b/nixos-module/default.nix @@ -121,6 +121,20 @@ let lib.concatStringsSep "\n" (lib.mapAttrsToList mkEnvLine envVars) + "\n" ); + # Cron jobs curl the app's own loopback address rather than its + # externally-reachable appUrl, on the port nginx/caddy actually listen on + # (80, or 443 when proxy.ssl -- never cfg.port, which per its own option + # doc doesn't change that). Otherwise cron would depend on the host being + # able to route back to its own public domain (hairpin NAT, not + # guaranteed) and, whenever cfg.port is set to an externally-forwarded + # port nginx/caddy don't themselves listen on (e.g. the QEMU test VM's + # hostfwd), would curl a port nothing is listening on at all. curl's + # --resolve pins the connection to 127.0.0.1 while keeping the + # Host header/SNI as cfg.domain, so vhost routing and cert validation + # still work normally. + cronPort = if cfg.proxy.ssl then 443 else 80; + cronUrl = path: "${scheme}://${cfg.domain}:${toString cronPort}${path}"; + # curl'd cron endpoints -> (name, path, calendar spec) cronjobs = { "tasks-overdue" = { path = "/cronjob/tasks/overdue"; when = "*-*-* 06,18:00:00"; }; @@ -424,12 +438,13 @@ in { } // (lib.mapAttrs' (name: job: lib.nameValuePair "hortusfox-cron-${name}" { description = "HortusFox cronjob: ${name}"; - after = [ "nginx.service" ]; + after = [ "${cfg.proxy.server}.service" ]; serviceConfig = { Type = "oneshot"; User = cfg.user; ExecStart = "${pkgs.curl}/bin/curl -fsS --max-time 300 " - + "${appUrl}${job.path}"; + + "--resolve ${cfg.domain}:${toString cronPort}:127.0.0.1 " + + "${cronUrl job.path}"; }; }) cronjobs);