anchor.diff:        pki.manual = manualPkiOptions;
         pki.auto = autoPkiOptions;
   
  -      extraConfig = mkOption {
  -        type = types.lines;
  -        default = "";
  -        example = "client.cert = /tmp/debugging.cert";
  -        description = ''
  -          Extra lines to append to the taskdrc configuration file.
  -        '';
  +      config = mkOption {
  +        type = types.attrs;
  +        example.client.cert = "/tmp/debugging.cert";
  +        description = ''
  +          Configuration options to pass to Taskserver.
  +
  +          The options here are the same as described in <citerefentry>
  +            <refentrytitle>taskdrc</refentrytitle>
  +            <manvolnum>5</manvolnum>
  +          </citerefentry>, but with one difference:
  +
  +          The <literal>server</literal> option is
  +          <literal>server.listen</literal> here, because the
  +          <literal>server</literal> option would collide with other options
  +          like <literal>server.cert</literal> and we would run in a type error
  +          (attribute set versus string).
  +
  +          Nix types like integers or booleans are automatically converted to
  +          the right values Taskserver would expect.
  +        '';
  +        apply = let
  +          mkKey = path: if path == ["server" "listen"] then "server"
  +                        else concatStringsSep "." path;
  +          recurse = path: attrs: let
  +            mapper = name: val: let
  +              newPath = path ++ [ name ];
  +              scalar = if val == true then "true"
  +                       else if val == false then "false"
  +                       else toString val;
  +            in if isAttrs val then recurse newPath val
  +               else [ "${mkKey newPath}=${scalar}" ];
  +          in concatLists (mapAttrsToList mapper attrs);
  +        in recurse [];
         };
       };
     };
  +
  +  imports = [
  +    (mkRemovedOptionModule ["services" "taskserver" "extraConfig"] ''
  +      This option was removed in favor of `services.taskserver.config` with
  +      different semantics (it's now a list of attributes instead of lines).
  +
  +      Please look up the documentation of `services.taskserver.config' to get
  +      more information about the new way to pass additional configuration
  +      options.
  +    '')
  +  ];
   
     config = mkMerge [
       (mkIf cfg.enable {
  
positive.code:         gid = config.ids.gids.taskd;
        };
  
        systemd.services.taskserver-init = {
          wantedBy = [ "taskserver.service" ];
          before = [ "taskserver.service" ];
  
negative.code:         in "${helperTool} process-json '${jsonFile}'";
  
          serviceConfig = {
            ExecStart = let
              mkCfgFlag = flag: escapeShellArg "--${flag}";
              cfgFlags = concatMapStringsSep " " mkCfgFlag cfg.config;
            in "@${taskd} taskd server ${cfgFlags}";
            ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID";
            Restart = "on-failure";
            PermissionsStartOnly = true;
  