anchor.diff:  in
   {
     options = {
  -    services.spiped = mkOption {
  -      type = types.attrsOf (types.submodule (
  -        {
  -          options = {
  -            encrypt = mkOption {
  -              type    = types.bool;
  -              default = false;
  -              description = ''
  -                Take unencrypted connections from the
  -                <literal>source</literal> socket and send encrypted
  -                connections to the <literal>target</literal> socket.
  -              '';
  +    services.spiped = {
  +      enable = mkOption {
  +        type        = types.bool;
  +        default     = false;
  +        description = "Enable the spiped service module.";
  +      };
  +
  +      config = mkOption {
  +        type = types.attrsOf (types.submodule (
  +          {
  +            options = {
  +              encrypt = mkOption {
  +                type    = types.bool;
  +                default = false;
  +                description = ''
  +                  Take unencrypted connections from the
  +                  <literal>source</literal> socket and send encrypted
  +                  connections to the <literal>target</literal> socket.
  +                '';
  +              };
  +
  +              decrypt = mkOption {
  +                type    = types.bool;
  +                default = false;
  +                description = ''
  +                  Take encrypted connections from the
  +                  <literal>source</literal> socket and send unencrypted
  +                  connections to the <literal>target</literal> socket.
  +                '';
  +              };
  +
  +              source = mkOption {
  +                type    = types.str;
  +                description = ''
  +                  Address on which spiped should listen for incoming
  +                  connections.  Must be in one of the following formats:
  +                  <literal>/absolute/path/to/unix/socket</literal>,
  +                  <literal>host.name:port</literal>,
  +                  <literal>[ip.v4.ad.dr]:port</literal> or
  +                  <literal>[ipv6::addr]:port</literal> - note that
  +                  hostnames are resolved when spiped is launched and are
  +                  not re-resolved later; thus if DNS entries change
  +                  spiped will continue to connect to the expired
  +                  address.
  +                '';
  +              };
  +
  +              target = mkOption {
  +                type    = types.str;
  +                description = "Address to which spiped should connect.";
  +              };
  +
  +              keyfile = mkOption {
  +                type    = types.path;
  +                description = ''
  +                  Name of a file containing the spiped key. As the
  +                  daemon runs as the <literal>spiped</literal> user, the
  +                  key file must be somewhere owned by that user. By
  +                  default, we recommend putting the keys for any spipe
  +                  services in <literal>/var/lib/spiped</literal>.
  +                '';
  +              };
  +
  +              timeout = mkOption {
  +                type = types.int;
  +                default = 5;
  +                description = ''
  +                  Timeout, in seconds, after which an attempt to connect to
  +                  the target or a protocol handshake will be aborted (and the
  +                  connection dropped) if not completed
  +                '';
  +              };
  +
  +              maxConns = mkOption {
  +                type = types.int;
  +                default = 100;
  +                description = ''
  +                  Limit on the number of simultaneous connections allowed.
  +                '';
  +              };
  +
  +              waitForDNS = mkOption {
  +                type = types.bool;
  +                default = false;
  +                description = ''
  +                  Wait for DNS. Normally when <literal>spiped</literal> is
  +                  launched it resolves addresses and binds to its source
  +                  socket before the parent process returns; with this option
  +                  it will daemonize first and retry failed DNS lookups until
  +                  they succeed. This allows <literal>spiped</literal> to
  +                  launch even if DNS isn't set up yet, but at the expense of
  +                  losing the guarantee that once <literal>spiped</literal> has
  +                  finished launching it will be ready to create pipes.
  +                '';
  +              };
  +
  +              disableKeepalives = mkOption {
  +                type = types.bool;
  +                default = false;
  +                description = "Disable transport layer keep-alives.";
  +              };
  +
  +              weakHandshake = mkOption {
  +                type = types.bool;
  +                default = false;
  +                description = ''
  +                  Use fast/weak handshaking: This reduces the CPU time spent
  +                  in the initial connection setup, at the expense of losing
  +                  perfect forward secrecy.
  +                '';
  +              };
  +
  +              resolveRefresh = mkOption {
  +                type = types.int;
  +                default = 60;
  +                description = ''
  +                  Resolution refresh time for the target socket, in seconds.
  +                '';
  +              };
  +
  +              disableReresolution = mkOption {
  +                type = types.bool;
  +                default = false;
  +                description = "Disable target address re-resolution.";
  +              };
               };
  -
  -            decrypt = mkOption {
  -              type    = types.bool;
  -              default = false;
  -              description = ''
  -                Take encrypted connections from the
  -                <literal>source</literal> socket and send unencrypted
  -                connections to the <literal>target</literal> socket.
  -              '';
  -            };
  -
  -            source = mkOption {
  -              type    = types.str;
  -              description = ''
  -                Address on which spiped should listen for incoming
  -                connections.  Must be in one of the following formats:
  -                <literal>/absolute/path/to/unix/socket</literal>,
  -                <literal>host.name:port</literal>,
  -                <literal>[ip.v4.ad.dr]:port</literal> or
  -                <literal>[ipv6::addr]:port</literal> - note that
  -                hostnames are resolved when spiped is launched and are
  -                not re-resolved later; thus if DNS entries change
  -                spiped will continue to connect to the expired
  -                address.
  -              '';
  -            };
  -
  -            target = mkOption {
  -              type    = types.str;
  -              description = "Address to which spiped should connect.";
  -            };
  -
  -            keyfile = mkOption {
  -              type    = types.path;
  -              description = ''
  -                Name of a file containing the spiped key. As the
  -                daemon runs as the <literal>spiped</literal> user, the
  -                key file must be somewhere owned by that user. By
  -                default, we recommend putting the keys for any spipe
  -                services in <literal>/var/lib/spiped</literal>.
  -              '';
  -            };
  -
  -            timeout = mkOption {
  -              type = types.int;
  -              default = 5;
  -              description = ''
  -                Timeout, in seconds, after which an attempt to connect to
  -                the target or a protocol handshake will be aborted (and the
  -                connection dropped) if not completed
  -              '';
  -            };
  -
  -            maxConns = mkOption {
  -              type = types.int;
  -              default = 100;
  -              description = ''
  -                Limit on the number of simultaneous connections allowed.
  -              '';
  -            };
  -
  -            waitForDNS = mkOption {
  -              type = types.bool;
  -              default = false;
  -              description = ''
  -                Wait for DNS. Normally when <literal>spiped</literal> is
  -                launched it resolves addresses and binds to its source
  -                socket before the parent process returns; with this option
  -                it will daemonize first and retry failed DNS lookups until
  -                they succeed. This allows <literal>spiped</literal> to
  -                launch even if DNS isn't set up yet, but at the expense of
  -                losing the guarantee that once <literal>spiped</literal> has
  -                finished launching it will be ready to create pipes.
  -              '';
  -            };
  -
  -            disableKeepalives = mkOption {
  -              type = types.bool;
  -              default = false;
  -              description = "Disable transport layer keep-alives.";
  -            };
  -
  -            weakHandshake = mkOption {
  -              type = types.bool;
  -              default = false;
  -              description = ''
  -                Use fast/weak handshaking: This reduces the CPU time spent
  -                in the initial connection setup, at the expense of losing
  -                perfect forward secrecy.
  -              '';
  -            };
  -
  -            resolveRefresh = mkOption {
  -              type = types.int;
  -              default = 60;
  -              description = ''
  -                Resolution refresh time for the target socket, in seconds.
  -              '';
  -            };
  -
  -            disableReresolution = mkOption {
  -              type = types.bool;
  -              default = false;
  -              description = "Disable target address re-resolution.";
  -            };
  -          };
  -        }
  -      ));
  -
  -      default = {};
  -
  -      example = literalExample ''
  -        {
  -          pipe1 =
  -            { keyfile = "/var/lib/spiped/pipe1.key";
  -              encrypt = true;
  -              source  = "localhost:6000";
  -              target  = "endpoint.example.com:7000";
  -            };
  -          pipe2 =
  -            { keyfile = "/var/lib/spiped/pipe2.key";
  -              decrypt = true;
  -              source  = "0.0.0.0:7000";
  -              target  = "localhost:3000";
  -            };
  -        }
  -      '';
  -
  -      description = ''
  -        Configuration for a secure pipe daemon. The daemon can be
  -        started, stopped, or examined using
  -        <literal>systemctl</literal>, under the name
  -        <literal>spiped@foo</literal>.
  -      '';
  +          }
  +        ));
  +
  +        default = {};
  +
  +        example = literalExample ''
  +          {
  +            pipe1 =
  +              { keyfile = "/var/lib/spiped/pipe1.key";
  +                encrypt = true;
  +                source  = "localhost:6000";
  +                target  = "endpoint.example.com:7000";
  +              };
  +            pipe2 =
  +              { keyfile = "/var/lib/spiped/pipe2.key";
  +                decrypt = true;
  +                source  = "0.0.0.0:7000";
  +                target  = "localhost:3000";
  +              };
  +          }
  +        '';
  +
  +        description = ''
  +          Configuration for a secure pipe daemon. The daemon can be
  +          started, stopped, or examined using
  +          <literal>systemctl</literal>, under the name
  +          <literal>spiped@foo</literal>.
  +        '';
  +      };
       };
     };
   
  -  config = {
  +  config = mkIf cfg.enable {
       assertions = mapAttrsToList (name: c: {
         assertion = (c.encrypt -> !c.decrypt) || (c.decrypt -> c.encrypt);
         message   = "A pipe must either encrypt or decrypt";
  -    }) cfg;
  +    }) cfg.config;
   
       users.extraGroups.spiped.gid = config.ids.gids.spiped;
       users.extraUsers.spiped = {
  
positive.code:       script = "exec ${pkgs.spiped}/bin/spiped -F `cat /etc/spiped/$1.spec`";
      };
  
      system.activationScripts.spiped = optionalString (cfg != {})
        "mkdir -p /var/lib/spiped";
  
      # Setup spiped config files
  
negative.code:             (if cfg.disableReresolution then "-R"
                else "-r ${toString cfg.resolveRefresh}")
            ];
        }) cfg.config;
    };
  }
  