diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index a4eaebdcbba018..d8386ff9ce9ca2 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -209,6 +209,8 @@ - Emacs lisp build helpers, such as `emacs.pkgs.melpaBuild`, now enables `__structuredAttrs` by default. Environment variables have to be passed via the `env` attribute. +- `services.cloudflare-dyndns.apiTokenFile` now must be just your Cloudflare api token. Previously it was supposed to be a file of the form `CLOUDFLARE_API_TOKEN=...`. + - `buildGoModule` now passes environment variables via the `env` attribute. `CGO_ENABLED` should now be specified with `env.CGO_ENABLED` when passing to buildGoModule. Direct specification of `CGO_ENABLED` is now redirected by a compatibility layer with a warning, but will become an error in future releases. Go-related environment variables previously shadowed by `buildGoModule` now results in errors when specified directly. Such variables include `GOOS` and `GOARCH`. diff --git a/nixos/modules/services/networking/cloudflare-dyndns.nix b/nixos/modules/services/networking/cloudflare-dyndns.nix index 4e2684b39d4372..5a4009d7325d09 100644 --- a/nixos/modules/services/networking/cloudflare-dyndns.nix +++ b/nixos/modules/services/networking/cloudflare-dyndns.nix @@ -15,12 +15,13 @@ in package = lib.mkPackageOption pkgs "cloudflare-dyndns" { }; apiTokenFile = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; + type = lib.types.pathWith { + absolute = true; + inStore = false; + }; + description = '' The path to a file containing the CloudFlare API token. - - The file must have the form `CLOUDFLARE_API_TOKEN=...` ''; }; @@ -91,19 +92,35 @@ in Type = "simple"; DynamicUser = true; StateDirectory = "cloudflare-dyndns"; - EnvironmentFile = cfg.apiTokenFile; Environment = [ "XDG_CACHE_HOME=%S/cloudflare-dyndns/.cache" ]; - ExecStart = - let - args = - [ "--cache-file /var/lib/cloudflare-dyndns/ip.cache" ] - ++ (if cfg.ipv4 then [ "-4" ] else [ "-no-4" ]) - ++ (if cfg.ipv6 then [ "-6" ] else [ "-no-6" ]) - ++ lib.optional cfg.deleteMissing "--delete-missing" - ++ lib.optional cfg.proxied "--proxied"; - in - "${lib.getExe cfg.package} ${toString args}"; + LoadCredential = [ + "apiToken:${cfg.apiTokenFile}" + ]; }; + + script = + let + args = + [ "--cache-file /var/lib/cloudflare-dyndns/ip.cache" ] + ++ (if cfg.ipv4 then [ "-4" ] else [ "-no-4" ]) + ++ (if cfg.ipv6 then [ "-6" ] else [ "-no-6" ]) + ++ lib.optional cfg.deleteMissing "--delete-missing" + ++ lib.optional cfg.proxied "--proxied"; + in + '' + export CLOUDFLARE_API_TOKEN=$(< "''${CREDENTIALS_DIRECTORY}/apiToken") + + # Added 2025-03-10: `cfg.apiTokenFile` used to be passed as an + # `EnvironmentFile` to the service, which required it to be of + # the form "CLOUDFLARE_API_TOKEN=" rather than just the secret. + # If we detect this legacy usage, error out. + if [[ $CLOUDFLARE_API_TOKEN == CLOUDFLARE_API_TOKEN* ]]; then + echo "Error: your api token starts with 'CLOUDFLARE_API_TOKEN='. Remove that, and instead specify just the token." >&2 + exit 1 + fi + + exec ${lib.getExe cfg.package} ${toString args} + ''; } // lib.optionalAttrs (cfg.frequency != null) { startAt = cfg.frequency;