ACME Null weird error

My module:

{ ... }:

{
  security.acme = {
    acceptTerms = true;
    certs."x.duckdns.org" = {
      dnsProvider = "duckdns";
      webroot = null;
      environmentFile = "/home/x/.flakes/.secrets";
    };
  };
  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    virtualHosts."x.duckdns.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8081";
      };
    };
  };
}

error:

error:
       … while checking flake output 'nixosConfigurations'

         at /nix/store/qdz7hh2x0imqhscnjv0xszs6lf1pkvqp-source/flake.nix:12:7:

           11|     {
           12|       nixosConfigurations =
             |       ^
           13|         let

       … while checking the NixOS configuration 'nixosConfigurations.x'

         at /nix/store/qdz7hh2x0imqhscnjv0xszs6lf1pkvqp-source/flake.nix:20:11:

           19|
           20|           x = nixpkgs.lib.nixosSystem rec {
             |           ^
           21|             system = "aarch64-linux";

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:918:24:

          917|     let f = attrPath:
          918|       zipAttrsWith (n: values:
             |                        ^
          919|         let here = attrPath ++ [n]; in

       … while calling 'g'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:701:19:

          700|           g =
          701|             name: value:
             |                   ^
          702|             if isAttrs value && cond value

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:704:20:

          703|               then recurse (path ++ [name]) value
          704|               else f (path ++ [name]) value;
             |                    ^
          705|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `system.build.toplevel':

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/activation/top-level.nix':

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/activation/top-level.nix:71:12:

           70|   # Replace runtime dependencies
           71|   system = foldr ({ oldDependency, newDependency }: drv:
             |            ^
           72|       pkgs.replaceDependency { inherit oldDependency newDependency drv; }

       … while calling 'foldr'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:53:20:

           52|   */
           53|   foldr = op: nul: list:
             |                    ^
           54|     let

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:60:8:

           59|         else op (elemAt list n) (fold' (n + 1));
           60|     in fold' 0;
             |        ^
           61|

       … while calling 'fold''

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:56:15:

           55|       len = length list;
           56|       fold' = n:
             |               ^
           57|         if n == len

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/activation/top-level.nix:68:10:

           67|     then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
           68|     else showWarnings config.warnings baseSystem;
             |          ^
           69|

       … while calling 'showWarnings'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/trivial.nix:414:28:

          413|
          414|   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
             |                            ^
          415|

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/trivial.nix:414:33:

          413|
          414|   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
             |                                 ^
          415|

       … while calling 'foldr'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:53:20:

           52|   */
           53|   foldr = op: nul: list:
             |                    ^
           54|     let

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:60:8:

           59|         else op (elemAt list n) (fold' (n + 1));
           60|     in fold' 0;
             |        ^
           61|

       … while calling 'fold''

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:56:15:

           55|       len = length list;
           56|       fold' = n:
             |               ^
           57|         if n == len

       … while calling 'g'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:701:19:

          700|           g =
          701|             name: value:
             |                   ^
          702|             if isAttrs value && cond value

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:704:20:

          703|               then recurse (path ++ [name]) value
          704|               else f (path ++ [name]) value;
             |                    ^
          705|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `warnings':

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/boot/systemd.nix':

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:615:10:

          614|     attrs:
          615|     map (name: f name attrs.${name}) (attrNames attrs);
             |          ^
          616|

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:615:16:

          614|     attrs:
          615|     map (name: f name attrs.${name}) (attrNames attrs);
             |                ^
          616|

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/boot/systemd.nix:425:16:

          424|       mapAttrsToList
          425|         (name: service:
             |                ^
          426|           let

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/boot/systemd.nix:432:16:

          431|             concatLists [
          432|               (optional (type == "oneshot" && (restart == "always" || restart == "on-success"))
             |                ^
          433|                 "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'"

       … while calling 'optional'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:359:20:

          358|   */
          359|   optional = cond: elem: if cond then [elem] else [];
             |                    ^
          360|

       … while calling 'g'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:701:19:

          700|           g =
          701|             name: value:
             |                   ^
          702|             if isAttrs value && cond value

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:704:20:

          703|               then recurse (path ++ [name]) value
          704|               else f (path ++ [name]) value;
             |                    ^
          705|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `systemd.services."acme-x.duckdns.org".serviceConfig':

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/boot/systemd.nix':

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … while calling 'g'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:701:19:

          700|           g =
          701|             name: value:
             |                   ^
          702|             if isAttrs value && cond value

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:704:20:

          703|               then recurse (path ++ [name]) value
          704|               else f (path ++ [name]) value;
             |                    ^
          705|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `systemd.services."acme-x.duckdns.org".script':

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/security/acme':

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/security/acme/default.nix:396:16:

          395|       # Working directory will be /tmp
          396|       script = (if (lockfileName == null) then lib.id else wrapInFlock "${lockdir}${lockfileName}") ''
             |                ^
          397|         ${optionalString data.enableDebugLogs "set -x"}

       … while calling 'wrapInFlock'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/security/acme/default.nix:37:31:

           36|   roundRobinApplyAttrs = funcsAttrs: argsList: lib.listToAttrs (map (x: {inherit (x.snd) name; value = x.snd.value x.fst;}) (roundRobinAssign argsList (attrsToList funcsAttrs)));
           37|   wrapInFlock = lockfilePath: script:
             |                               ^
           38|     # explainer: https://stackoverflow.com/a/60896531

       error: cannot coerce null to a string

And with deleted line with webroot = null;

{ ... }:

{
  security.acme = {
    acceptTerms = true;
    certs."x.duckdns.org" = {
      dnsProvider = "duckdns";
      environmentFile = "/home/x/.flakes/.secrets";
    };
  };
  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    virtualHosts."x.duckdns.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8081";
      };
    };
  };
}

error:

error:
       … while checking flake output 'nixosConfigurations'

         at /nix/store/xnxj2sd7w9yqpjg5bb43d970mqmz3sjl-source/flake.nix:12:7:

           11|     {
           12|       nixosConfigurations =
             |       ^
           13|         let

       … while checking the NixOS configuration 'nixosConfigurations.x'

         at /nix/store/xnxj2sd7w9yqpjg5bb43d970mqmz3sjl-source/flake.nix:20:11:

           19|
           20|           x = nixpkgs.lib.nixosSystem rec {
             |           ^
           21|             system = "aarch64-linux";

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:918:24:

          917|     let f = attrPath:
          918|       zipAttrsWith (n: values:
             |                        ^
          919|         let here = attrPath ++ [n]; in

       … while calling 'g'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:701:19:

          700|           g =
          701|             name: value:
             |                   ^
          702|             if isAttrs value && cond value

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/attrsets.nix:704:20:

          703|               then recurse (path ++ [name]) value
          704|               else f (path ++ [name]) value;
             |                    ^
          705|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `system.build.toplevel':

       … while calling anonymous lambda

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/activation/top-level.nix':

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/nixos/modules/system/activation/top-level.nix:71:12:

           70|   # Replace runtime dependencies
           71|   system = foldr ({ oldDependency, newDependency }: drv:
             |            ^
           72|       pkgs.replaceDependency { inherit oldDependency newDependency drv; }

       … while calling 'foldr'

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:53:20:

           52|   */
           53|   foldr = op: nul: list:
             |                    ^
           54|     let

       … from call site

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:60:8:

           59|         else op (elemAt list n) (fold' (n + 1));
           60|     in fold' 0;
             |        ^
           61|

       … while calling 'fold''

         at /nix/store/14hmp9p41qbskdqz5c63708lpgk8imk4-source/lib/lists.nix:56:15:

           55|       len = length list;
           56|       fold' = n:
             |               ^
           57|         if n == len

       error:
       Failed assertions:
       - Exactly one of the options
       `security.acme.certs.x.duckdns.org.dnsProvider`,
       `security.acme.certs.x.duckdns.org.webroot`,
       `security.acme.certs.x.duckdns.org.listenHTTP` and
       `security.acme.certs.x.duckdns.org.s3Bucket`
       is required.
       Current values: {
         dnsProvider = "duckdns";
         listenHTTP = null;
         s3Bucket = null;
         webroot = "/var/lib/acme/acme-challenge";
       }.

So i am not 100% if thats correct.

When using enableACME = true, nginx is set up to gather the certificate. As you are using a dns provider, it seems not correct to use the HTTP variant for acme here.

Using enableACME = true does set up the webroot, when enabled. Overriding that with null does make the assertion in service.acme go away, thus breaking internal logic in the nginx module if i see it correctly.

I assume that you might want to use useACMEHost and set up security.acme accordingly (if i understand the useACMEHost doc and code usage correctly).

Possibly the following snippet does what you want (it evals, but i can not test it, as i dont have a duckdns account)

  security.acme = {
    acceptTerms = true;
    certs."x.duckdns.org" = {
      dnsProvider = "duckdns";
      environmentFile = "/home/x/.flakes/.secrets";
      group = "nginx";
    };
  };
  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    virtualHosts."x.duckdns.org" = {
      useACMEHost = "x.duckdns.org";
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8081";
      };
    };
  };
1 Like