anchor.diff:  
     toOneZero = b: if b then "1" else "0";
   
  +  mkEndpointOpt = name: addr: port: {
  +    name = mkOption {
  +      type = types.str;
  +      default = name;
  +      description = "The endpoint name.";
  +    };
  +    address = mkOption {
  +      type = types.str;
  +      default = addr;
  +      description = "Bind address for ${name} endpoint. Default: " + addr;
  +    };
  +    port = mkOption {
  +      type = types.int;
  +      default = port;
  +      description = "Bind port for ${name} endoint. Default: " + toString port;
  +    };
  +  };
  +
  +  commonTunOpts = let
  +    i2cpOpts = {
  +      length = mkOption {
  +        type = types.int;
  +        description = "Guaranteed minimum hops.";
  +        default = 3;
  +      };
  +      quantity = mkOption {
  +        type = types.int;
  +        description = "Number of simultaneous tunnels.";
  +        default = 5;
  +      };
  +    };
  +  in name: {
  +    outbound = i2cpOpts;
  +    inbound = i2cpOpts;
  +    crypto.tagsToSend = mkOption {
  +      type = types.int;
  +      description = "Number of ElGamal/AES tags to send.";
  +      default = 40;
  +    };
  +   destination = mkOption {
  +      type = types.str;
  +      description = "Remote endpoint, I2P hostname or b32.i2p address.";
  +    };
  +    keys = mkOption {
  +      type = types.str;
  +      default = name + "-keys.dat";
  +      description = "Keyset used for tunnel identity.";
  +    };
  +  } // mkEndpointOpt name "127.0.0.1" 0;
  +
     i2pdConf = pkgs.writeText "i2pd.conf" ''
  -      v6 = ${toOneZero cfg.enableIPv6}
  -      unreachable = ${toOneZero cfg.unreachable}
  +      ipv6 = ${toOneZero cfg.enableIPv6}
  +      notransit = ${toOneZero cfg.notransit}
         floodfill = ${toOneZero cfg.floodfill}
         ${if isNull cfg.port then "" else "port = ${toString cfg.port}"}
  -      httpproxyport = ${toString cfg.proxy.httpPort}
  -      socksproxyport = ${toString cfg.proxy.socksPort}
  -      ircaddress = ${cfg.irc.host}
  -      ircport = ${toString cfg.irc.port}
  -      ircdest = ${cfg.irc.dest}
  -      irckeys = ${cfg.irc.keyFile}
  -      eepport = ${toString cfg.eep.port}
  -      ${if isNull cfg.sam.port then "" else "--samport=${toString cfg.sam.port}"}
  -      eephost = ${cfg.eep.host}
  -      eepkeys = ${cfg.eep.keyFile}
  +      ${flip concatMapStrings
  +        (collect (proto: proto ? port && proto ? address && proto ? name) cfg.proto)
  +        (proto: let portStr = toString proto.port; in ''
  +      [${proto.name}]
  +      address = ${proto.address}
  +      port = ${toString proto.port}
  +      '')
  +      }
     '';
   
     i2pdTunnelConf = pkgs.writeText "i2pd-tunnels.conf" ''
  
positive.code:         '';
        };
  
        http = {
          port = mkOption {
            type = types.int;
            default = 7070;
            description = ''
              HTTP listen port.
            '';
          };
        };
  
        proxy = {
          httpPort = mkOption {
            type = types.int;
            default = 4446;
            description = ''
              HTTP proxy listen port.
            '';
          };
          socksPort = mkOption {
            type = types.int;
            default = 4447;
            description = ''
              SOCKS proxy listen port.
            '';
          };
        };
  
        irc = {
          host = mkOption {
            type = types.str;
            default = "127.0.0.1";
            description = ''
              Address to forward incoming traffic to. 127.0.0.1 by default.
            '';
          };
          dest = mkOption {
            type = types.str;
            default = "irc.postman.i2p";
            description = ''
              Destination I2P tunnel endpoint address of IRC server. irc.postman.i2p by default.
            '';
          };
          port = mkOption {
            type = types.int;
            default = 6668;
            description = ''
              Local IRC tunnel endoint port to listen on. 6668 by default.
            '';
          };
          keyFile = mkOption {
            type = types.str;
            default = "privKeys.dat";
            description = ''
              File name containing destination keys. privKeys.dat by default.
            '';
          };
        };
  
        eep = {
          host = mkOption {
            type = types.str;
            default = "127.0.0.1";
            description = ''
              Address to forward incoming traffic to. 127.0.0.1 by default.
            '';
          };
          port = mkOption {
            type = types.int;
            default = 80;
            description = ''
              Port to forward incoming traffic to. 80 by default.
            '';
          };
          keyFile = mkOption {
            type = types.str;
            default = "privKeys.dat";
            description = ''
              File name containing destination keys. privKeys.dat by default.
            '';
          };
        };
  
        sam = {
          port = mkOption {
            type = with types; nullOr int;
            default = null;
            description = ''
              Local SAM tunnel endpoint. Usually 7656. SAM is disabled if not specified.
            '';
          };
        };
  
        outTunnels = mkOption {
          default = {};
  	      type = with types; loaOf optionSet;
  	      description = ''
  	      '';
  	      options = [ ({ name, config, ... }: {
  
  	        options = {
  	          name = mkOption {
  	            type = types.str;
  	            description = "The name of the tunnel.";
  	          };
  	          destination = mkOption {
  	            type = types.str;
  	            description = "Remote endpoint, I2P hostname or b32.i2p address.";
  	          };
  	          keys = mkOption {
  	            type = types.str;
  	            default = name + "-keys.dat";
  	            description = "Keyset used for tunnel identity.";
  	          };
  	          address = mkOption {
  	            type = types.str;
  	            default = "127.0.0.1";
  	            description = "Local bind address for tunnel.";
  	          };
  	          port = mkOption {
  	            type = types.int;
  	            default = 0;
  	            description = "Local tunnel listen port.";
  	          };
  	        };
  
  	        config = {
  	          name = mkDefault name;
  	        };
  
  	      }) ];
        };
  
        inTunnels = mkOption {
          default = {};
  	      type = with types; loaOf optionSet;
  	      description = ''
  	      '';
  	      options = [ ({ name, config, ... }: {
  
  	        options = {
  
  	          name = mkOption {
  	            type = types.str;
  	            description = "The name of the tunnel.";
  	          };
  	          keys = mkOption {
  	            type = types.path;
  	            default = name + "-keys.dat";
  	            description = "Keyset used for tunnel identity.";
  	          };
  	          address = mkOption {
  	            type = types.str;
  	            default = "127.0.0.1";
  	            description = "Local service IP address.";
  	          };
  	          port = mkOption {
  	            type = types.int;
  	            default = 0;
  	            description = "Local tunnel listen port.";
  	          };
  	          inPort = mkOption {
  	            type = types.int;
  	            default = 0;
  	            description = "I2P service port. Default to the tunnel's listen port.";
  	          };
  	          accessList = mkOption {
  	            type = with types; listOf str;
  	            default = [];
  	            description = "I2P nodes that are allowed to connect to this service.";
  	          };
  
  	        };
  
  	        config = {
  	          name = mkDefault name;
  	        };
  
  	      }) ];
        };
      };
    };
  
negative.code:   i2pdSh = pkgs.writeScriptBin "i2pd" ''
      #!/bin/sh
      ${if isNull cfg.extIp then extip else ""}
      ${pkgs.i2pd}/bin/i2pd --log=1 \
        --host=${if isNull cfg.extIp then "$EXTIP" else cfg.extIp} \
        --conf=${i2pdConf} \
        --tunconf=${i2pdTunnelConf}
    '';
  
  in
  