diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml
index c4847b60e274e..ac5a2201c8694 100644
--- a/nixos/doc/manual/release-notes/rl-1903.xml
+++ b/nixos/doc/manual/release-notes/rl-1903.xml
@@ -122,6 +122,14 @@
the Python 2 or 3 version of the package.
+
+
+ Options
+ services.znc.confOptions.networks.name.userName and
+ services.znc.confOptions.networks.name.modulePackages
+ were removed. They were never used for anything and can therefore safely be removed.
+
+
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index f55c32fa511d1..290db674c68e9 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -634,7 +634,7 @@
./services/networking/zerobin.nix
./services/networking/zeronet.nix
./services/networking/zerotierone.nix
- ./services/networking/znc.nix
+ ./services/networking/znc/default.nix
./services/printing/cupsd.nix
./services/scheduling/atd.nix
./services/scheduling/chronos.nix
diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix
deleted file mode 100644
index f817db2ad000b..0000000000000
--- a/nixos/modules/services/networking/znc.nix
+++ /dev/null
@@ -1,431 +0,0 @@
-{ config, lib, pkgs, ...}:
-
-with lib;
-
-let
- cfg = config.services.znc;
-
- defaultUser = "znc"; # Default user to own process.
-
- # Default user and pass:
- # un=znc
- # pw=nixospass
-
- defaultUserName = "znc";
- defaultPassBlock = "
-
- Method = sha256
- Hash = e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93
- Salt = l5Xryew4g*!oa(ECfX2o
-
- ";
-
- modules = pkgs.buildEnv {
- name = "znc-modules";
- paths = cfg.modulePackages;
- };
-
- # Keep znc.conf in nix store, then symlink or copy into `dataDir`, depending on `mutable`.
- mkZncConf = confOpts: ''
- Version = 1.6.3
- ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.modules}
-
-
- Port = ${toString confOpts.port}
- IPv4 = true
- IPv6 = true
- SSL = ${boolToString confOpts.useSSL}
- ${lib.optionalString (confOpts.uriPrefix != null) "URIPrefix = ${confOpts.uriPrefix}"}
-
-
-
- ${confOpts.passBlock}
- Admin = true
- Nick = ${confOpts.nick}
- AltNick = ${confOpts.nick}_
- Ident = ${confOpts.nick}
- RealName = ${confOpts.nick}
- ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.userModules}
-
- ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (name: net: ''
-
- ${concatMapStrings (m: "LoadModule = ${m}\n") net.modules}
- Server = ${net.server} ${lib.optionalString net.useSSL "+"}${toString net.port} ${net.password}
- ${concatMapStrings (c: "\n\n") net.channels}
- ${lib.optionalString net.hasBitlbeeControlChannel ''
-
-
- ''}
- ${net.extraConf}
-
- '') confOpts.networks) }
-
- ${confOpts.extraZncConf}
- '';
-
- zncConfFile = pkgs.writeTextFile {
- name = "znc.conf";
- text = if cfg.zncConf != ""
- then cfg.zncConf
- else mkZncConf cfg.confOptions;
- };
-
- networkOpts = { ... }: {
- options = {
- server = mkOption {
- type = types.str;
- example = "chat.freenode.net";
- description = ''
- IRC server address.
- '';
- };
-
- port = mkOption {
- type = types.int;
- default = 6697;
- example = 6697;
- description = ''
- IRC server port.
- '';
- };
-
- userName = mkOption {
- default = "";
- example = "johntron";
- type = types.string;
- description = ''
- A nick identity specific to the IRC server.
- '';
- };
-
- password = mkOption {
- type = types.str;
- default = "";
- description = ''
- IRC server password, such as for a Slack gateway.
- '';
- };
-
- useSSL = mkOption {
- type = types.bool;
- default = true;
- description = ''
- Whether to use SSL to connect to the IRC server.
- '';
- };
-
- modulePackages = mkOption {
- type = types.listOf types.package;
- default = [];
- example = [ "pkgs.zncModules.push" "pkgs.zncModules.fish" ];
- description = ''
- External ZNC modules to build.
- '';
- };
-
- modules = mkOption {
- type = types.listOf types.str;
- default = [ "simple_away" ];
- example = literalExample "[ simple_away sasl ]";
- description = ''
- ZNC modules to load.
- '';
- };
-
- channels = mkOption {
- type = types.listOf types.str;
- default = [];
- example = [ "nixos" ];
- description = ''
- IRC channels to join.
- '';
- };
-
- hasBitlbeeControlChannel = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether to add the special Bitlbee operations channel.
- '';
- };
-
- extraConf = mkOption {
- default = "";
- type = types.lines;
- example = ''
- Encoding = ^UTF-8
- FloodBurst = 4
- FloodRate = 1.00
- IRCConnectEnabled = true
- Ident = johntron
- JoinDelay = 0
- Nick = johntron
- '';
- description = ''
- Extra config for the network.
- '';
- };
- };
- };
-
-in
-
-{
-
- ###### Interface
-
- options = {
- services.znc = {
- enable = mkOption {
- default = false;
- type = types.bool;
- description = ''
- Enable a ZNC service for a user.
- '';
- };
-
- user = mkOption {
- default = "znc";
- example = "john";
- type = types.string;
- description = ''
- The name of an existing user account to use to own the ZNC server process.
- If not specified, a default user will be created to own the process.
- '';
- };
-
- group = mkOption {
- default = "";
- example = "users";
- type = types.string;
- description = ''
- Group to own the ZNCserver process.
- '';
- };
-
- dataDir = mkOption {
- default = "/var/lib/znc/";
- example = "/home/john/.znc/";
- type = types.path;
- description = ''
- The data directory. Used for configuration files and modules.
- '';
- };
-
- openFirewall = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether to open ports in the firewall for ZNC.
- '';
- };
-
- zncConf = mkOption {
- default = "";
- example = "See: http://wiki.znc.in/Configuration";
- type = types.lines;
- description = ''
- Config file as generated with `znc --makeconf` to use for the whole ZNC configuration.
- If specified, `confOptions` will be ignored, and this value, as-is, will be used.
- If left empty, a conf file with default values will be used.
- '';
- };
-
- confOptions = {
- modules = mkOption {
- type = types.listOf types.str;
- default = [ "webadmin" "adminlog" ];
- example = [ "partyline" "webadmin" "adminlog" "log" ];
- description = ''
- A list of modules to include in the `znc.conf` file.
- '';
- };
-
- userModules = mkOption {
- type = types.listOf types.str;
- default = [ "chansaver" "controlpanel" ];
- example = [ "chansaver" "controlpanel" "fish" "push" ];
- description = ''
- A list of user modules to include in the `znc.conf` file.
- '';
- };
-
- userName = mkOption {
- default = defaultUserName;
- example = "johntron";
- type = types.string;
- description = ''
- The user name used to log in to the ZNC web admin interface.
- '';
- };
-
- networks = mkOption {
- default = { };
- type = with types; attrsOf (submodule networkOpts);
- description = ''
- IRC networks to connect the user to.
- '';
- example = {
- "freenode" = {
- server = "chat.freenode.net";
- port = 6697;
- useSSL = true;
- modules = [ "simple_away" ];
- };
- };
- };
-
- nick = mkOption {
- default = "znc-user";
- example = "john";
- type = types.string;
- description = ''
- The IRC nick.
- '';
- };
-
- passBlock = mkOption {
- example = defaultPassBlock;
- type = types.string;
- description = ''
- Generate with `nix-shell -p znc --command "znc --makepass"`.
- This is the password used to log in to the ZNC web admin interface.
- '';
- };
-
- port = mkOption {
- default = 5000;
- example = 5000;
- type = types.int;
- description = ''
- Specifies the port on which to listen.
- '';
- };
-
- useSSL = mkOption {
- default = true;
- type = types.bool;
- description = ''
- Indicates whether the ZNC server should use SSL when listening on the specified port. A self-signed certificate will be generated.
- '';
- };
-
- uriPrefix = mkOption {
- type = types.nullOr types.str;
- default = null;
- example = "/znc/";
- description = ''
- An optional URI prefix for the ZNC web interface. Can be
- used to make ZNC available behind a reverse proxy.
- '';
- };
-
- extraZncConf = mkOption {
- default = "";
- type = types.lines;
- description = ''
- Extra config to `znc.conf` file.
- '';
- };
- };
-
- modulePackages = mkOption {
- type = types.listOf types.package;
- default = [ ];
- example = literalExample "[ pkgs.zncModules.fish pkgs.zncModules.push ]";
- description = ''
- A list of global znc module packages to add to znc.
- '';
- };
-
- mutable = mkOption {
- default = true;
- type = types.bool;
- description = ''
- Indicates whether to allow the contents of the `dataDir` directory to be changed
- by the user at run-time.
- If true, modifications to the ZNC configuration after its initial creation are not
- overwritten by a NixOS system rebuild.
- If false, the ZNC configuration is rebuilt by every system rebuild.
- If the user wants to manage the ZNC service using the web admin interface, this value
- should be set to true.
- '';
- };
-
- extraFlags = mkOption {
- default = [ ];
- example = [ "--debug" ];
- type = types.listOf types.str;
- description = ''
- Extra flags to use when executing znc command.
- '';
- };
- };
- };
-
-
- ###### Implementation
-
- config = mkIf cfg.enable {
-
- networking.firewall = mkIf cfg.openFirewall {
- allowedTCPPorts = [ cfg.confOptions.port ];
- };
-
- systemd.services.znc = {
- description = "ZNC Server";
- wantedBy = [ "multi-user.target" ];
- after = [ "network.service" ];
- serviceConfig = {
- User = cfg.user;
- Group = cfg.group;
- Restart = "always";
- ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
- ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
- };
- preStart = ''
- ${pkgs.coreutils}/bin/mkdir -p ${cfg.dataDir}/configs
-
- # If mutable, regenerate conf file every time.
- ${optionalString (!cfg.mutable) ''
- ${pkgs.coreutils}/bin/echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated."
- ${pkgs.coreutils}/bin/rm -f ${cfg.dataDir}/configs/znc.conf
- ''}
-
- # Ensure essential files exist.
- if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then
- ${pkgs.coreutils}/bin/echo "No znc.conf file found in ${cfg.dataDir}. Creating one now."
- ${pkgs.coreutils}/bin/cp --no-clobber ${zncConfFile} ${cfg.dataDir}/configs/znc.conf
- ${pkgs.coreutils}/bin/chmod u+rw ${cfg.dataDir}/configs/znc.conf
- ${pkgs.coreutils}/bin/chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf
- fi
-
- if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then
- ${pkgs.coreutils}/bin/echo "No znc.pem file found in ${cfg.dataDir}. Creating one now."
- ${pkgs.znc}/bin/znc --makepem --datadir ${cfg.dataDir}
- fi
-
- # Symlink modules
- rm ${cfg.dataDir}/modules || true
- ln -fs ${modules}/lib/znc ${cfg.dataDir}/modules
- '';
- script = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${toString cfg.extraFlags}";
- };
-
- users.users = optional (cfg.user == defaultUser)
- { name = defaultUser;
- description = "ZNC server daemon owner";
- group = defaultUser;
- uid = config.ids.uids.znc;
- home = cfg.dataDir;
- createHome = true;
- };
-
- users.groups = optional (cfg.user == defaultUser)
- { name = defaultUser;
- gid = config.ids.gids.znc;
- members = [ defaultUser ];
- };
-
- };
-}
diff --git a/nixos/modules/services/networking/znc/default.nix b/nixos/modules/services/networking/znc/default.nix
new file mode 100644
index 0000000000000..bce5b15a19ec7
--- /dev/null
+++ b/nixos/modules/services/networking/znc/default.nix
@@ -0,0 +1,306 @@
+{ config, lib, pkgs, ...}:
+
+with lib;
+
+let
+
+ cfg = config.services.znc;
+
+ defaultUser = "znc";
+
+ modules = pkgs.buildEnv {
+ name = "znc-modules";
+ paths = cfg.modulePackages;
+ };
+
+ listenerPorts = concatMap (l: optional (l ? Port) l.Port)
+ (attrValues (cfg.config.Listener or {}));
+
+ # Converts the config option to a string
+ semanticString = let
+
+ sortedAttrs = set: sort (l: r:
+ if l == "extraConfig" then false # Always put extraConfig last
+ else if isAttrs set.${l} == isAttrs set.${r} then l < r
+ else isAttrs set.${r} # Attrsets should be last, makes for a nice config
+ # This last case occurs when any side (but not both) is an attrset
+ # The order of these is correct when the attrset is on the right
+ # which we're just returning
+ ) (attrNames set);
+
+ # Specifies an attrset that encodes the value according to its type
+ encode = name: value: {
+ null = [];
+ bool = [ "${name} = ${boolToString value}" ];
+ int = [ "${name} = ${toString value}" ];
+
+ # extraConfig should be inserted verbatim
+ string = [ (if name == "extraConfig" then value else "${name} = ${value}") ];
+
+ # Values like `Foo = [ "bar" "baz" ];` should be transformed into
+ # Foo=bar
+ # Foo=baz
+ list = concatMap (encode name) value;
+
+ # Values like `Foo = { bar = { Baz = "baz"; Qux = "qux"; Florps = null; }; };` should be transmed into
+ #
+ # Baz=baz
+ # Qux=qux
+ #
+ set = concatMap (subname: [
+ "<${name} ${subname}>"
+ ] ++ map (line: "\t${line}") (toLines value.${subname}) ++ [
+ "${name}>"
+ ]) (filter (v: v != null) (attrNames value));
+
+ }.${builtins.typeOf value};
+
+ # One level "above" encode, acts upon a set and uses encode on each name,value pair
+ toLines = set: concatMap (name: encode name set.${name}) (sortedAttrs set);
+
+ in
+ concatStringsSep "\n" (toLines cfg.config);
+
+ semanticTypes = with types; rec {
+ zncAtom = nullOr (either (either int bool) str);
+ zncAttr = attrsOf (nullOr zncConf);
+ zncAll = either (either zncAtom (listOf zncAtom)) zncAttr;
+ zncConf = attrsOf (zncAll // {
+ # Since this is a recursive type and the description by default contains
+ # the description of its subtypes, infinite recursion would occur without
+ # explicitly breaking this cycle
+ description = "znc values (null, atoms (str, int, bool), list of atoms, or attrsets of znc values)";
+ });
+ };
+
+in
+
+{
+
+ imports = [ ./options.nix ];
+
+ options = {
+ services.znc = {
+ enable = mkEnableOption "ZNC";
+
+ user = mkOption {
+ default = "znc";
+ example = "john";
+ type = types.str;
+ description = ''
+ The name of an existing user account to use to own the ZNC server
+ process. If not specified, a default user will be created.
+ '';
+ };
+
+ group = mkOption {
+ default = defaultUser;
+ example = "users";
+ type = types.str;
+ description = ''
+ Group to own the ZNC process.
+ '';
+ };
+
+ dataDir = mkOption {
+ default = "/var/lib/znc/";
+ example = "/home/john/.znc/";
+ type = types.path;
+ description = ''
+ The state directory for ZNC. The config and the modules will be linked
+ to from this directory as well.
+ '';
+ };
+
+ openFirewall = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to open ports in the firewall for ZNC. Does work with
+ ports for listeners specified in
+ .
+ '';
+ };
+
+ config = mkOption {
+ type = semanticTypes.zncConf;
+ default = {};
+ example = literalExample ''
+ {
+ LoadModule = [ "webadmin" "adminlog" ];
+ User.paul = {
+ Admin = true;
+ Nick = "paul";
+ AltNick = "paul1";
+ LoadModule = [ "chansaver" "controlpanel" ];
+ Network.freenode = {
+ Server = "chat.freenode.net +6697";
+ LoadModule = [ "simple_away" ];
+ Chan = {
+ "#nixos" = { Detached = false; };
+ "##linux" = { Disabled = true; };
+ };
+ };
+ Pass.password = {
+ Method = "sha256";
+ Hash = "e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93";
+ Salt = "l5Xryew4g*!oa(ECfX2o";
+ };
+ };
+ }
+ '';
+ description = ''
+ Configuration for ZNC, see
+ https://wiki.znc.in/Configuration for details. The
+ Nix value declared here will be translated directly to the xml-like
+ format ZNC expects. This is much more flexible than the legacy options
+ under , but also can't do
+ any type checking.
+
+
+ You can use nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.services.znc.config
+ to view the current value. By default it contains a listener for port
+ 5000 with SSL enabled.
+
+
+ Nix attributes called extraConfig will be inserted
+ verbatim into the resulting config file.
+
+
+ If is turned on, the
+ option values in will be
+ gracefully be applied to this option.
+
+
+ If you intend to update the configuration through this option, be sure
+ to enable , otherwise none of the
+ changes here will be applied after the initial deploy.
+ '';
+ };
+
+ configFile = mkOption {
+ type = types.path;
+ example = "~/.znc/configs/znc.conf";
+ description = ''
+ Configuration file for ZNC. It is recommended to use the
+ option instead.
+
+
+ Setting this option will override any auto-generated config file
+ through the or
+ options.
+ '';
+ };
+
+ modulePackages = mkOption {
+ type = types.listOf types.package;
+ default = [ ];
+ example = literalExample "[ pkgs.zncModules.fish pkgs.zncModules.push ]";
+ description = ''
+ A list of global znc module packages to add to znc.
+ '';
+ };
+
+ mutable = mkOption {
+ default = true; # TODO: Default to true when config is set, make sure to not delete the old config if present
+ type = types.bool;
+ description = ''
+ Indicates whether to allow the contents of the
+ dataDir directory to be changed by the user at
+ run-time.
+
+
+ If enabled, modifications to the ZNC configuration after its initial
+ creation are not overwritten by a NixOS rebuild. If disabled, the
+ ZNC configuration is rebuilt on every NixOS rebuild.
+
+
+ If the user wants to manage the ZNC service using the web admin
+ interface, this option should be enabled.
+ '';
+ };
+
+ extraFlags = mkOption {
+ default = [ ];
+ example = [ "--debug" ];
+ type = types.listOf types.str;
+ description = ''
+ Extra arguments to use for executing znc.
+ '';
+ };
+ };
+ };
+
+
+ ###### Implementation
+
+ config = mkIf cfg.enable {
+
+ services.znc = {
+ configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString);
+ config = {
+ Version = (builtins.parseDrvName pkgs.znc.name).version;
+ Listener.l.Port = mkDefault 5000;
+ Listener.l.SSL = mkDefault true;
+ };
+ };
+
+ networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall listenerPorts;
+
+ systemd.services.znc = {
+ description = "ZNC Server";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ Restart = "always";
+ ExecStart = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${escapeShellArgs cfg.extraFlags}";
+ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
+ };
+ preStart = ''
+ mkdir -p ${cfg.dataDir}/configs
+
+ # If mutable, regenerate conf file every time.
+ ${optionalString (!cfg.mutable) ''
+ echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated."
+ rm -f ${cfg.dataDir}/configs/znc.conf
+ ''}
+
+ # Ensure essential files exist.
+ if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then
+ echo "No znc.conf file found in ${cfg.dataDir}. Creating one now."
+ cp --no-clobber ${cfg.configFile} ${cfg.dataDir}/configs/znc.conf
+ chmod u+rw ${cfg.dataDir}/configs/znc.conf
+ chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf
+ fi
+
+ if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then
+ echo "No znc.pem file found in ${cfg.dataDir}. Creating one now."
+ ${pkgs.znc}/bin/znc --makepem --datadir ${cfg.dataDir}
+ fi
+
+ # Symlink modules
+ rm ${cfg.dataDir}/modules || true
+ ln -fs ${modules}/lib/znc ${cfg.dataDir}/modules
+ '';
+ };
+
+ users.users = optional (cfg.user == defaultUser)
+ { name = defaultUser;
+ description = "ZNC server daemon owner";
+ group = defaultUser;
+ uid = config.ids.uids.znc;
+ home = cfg.dataDir;
+ createHome = true;
+ };
+
+ users.groups = optional (cfg.user == defaultUser)
+ { name = defaultUser;
+ gid = config.ids.gids.znc;
+ members = [ defaultUser ];
+ };
+
+ };
+}
diff --git a/nixos/modules/services/networking/znc/options.nix b/nixos/modules/services/networking/znc/options.nix
new file mode 100644
index 0000000000000..505ebb3bf0ade
--- /dev/null
+++ b/nixos/modules/services/networking/znc/options.nix
@@ -0,0 +1,268 @@
+{ lib, config, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.znc;
+
+ networkOpts = {
+ options = {
+
+ server = mkOption {
+ type = types.str;
+ example = "chat.freenode.net";
+ description = ''
+ IRC server address.
+ '';
+ };
+
+ port = mkOption {
+ type = types.ints.u16;
+ default = 6697;
+ description = ''
+ IRC server port.
+ '';
+ };
+
+ password = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ IRC server password, such as for a Slack gateway.
+ '';
+ };
+
+ useSSL = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to use SSL to connect to the IRC server.
+ '';
+ };
+
+ modules = mkOption {
+ type = types.listOf types.str;
+ default = [ "simple_away" ];
+ example = literalExample "[ simple_away sasl ]";
+ description = ''
+ ZNC network modules to load.
+ '';
+ };
+
+ channels = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "nixos" ];
+ description = ''
+ IRC channels to join.
+ '';
+ };
+
+ hasBitlbeeControlChannel = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to add the special Bitlbee operations channel.
+ '';
+ };
+
+ extraConf = mkOption {
+ default = "";
+ type = types.lines;
+ example = ''
+ Encoding = ^UTF-8
+ FloodBurst = 4
+ FloodRate = 1.00
+ IRCConnectEnabled = true
+ Ident = johntron
+ JoinDelay = 0
+ Nick = johntron
+ '';
+ description = ''
+ Extra config for the network. Consider using
+ instead.
+ '';
+ };
+ };
+ };
+
+in
+
+{
+
+ options = {
+ services.znc = {
+
+ useLegacyConfig = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Whether to propagate the legacy options under
+ to the znc config. If this
+ is turned on, the znc config will contain a user with the default name
+ "znc", global modules "webadmin" and "adminlog" will be enabled by
+ default, and more, all controlled through the
+ options.
+ You can use nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.services.znc.config
+ to view the current value of the config.
+
+
+ In any case, if you need more flexibility,
+ can be used to override/add to
+ all of the legacy options.
+ '';
+ };
+
+ confOptions = {
+ modules = mkOption {
+ type = types.listOf types.str;
+ default = [ "webadmin" "adminlog" ];
+ example = [ "partyline" "webadmin" "adminlog" "log" ];
+ description = ''
+ A list of modules to include in the `znc.conf` file.
+ '';
+ };
+
+ userModules = mkOption {
+ type = types.listOf types.str;
+ default = [ "chansaver" "controlpanel" ];
+ example = [ "chansaver" "controlpanel" "fish" "push" ];
+ description = ''
+ A list of user modules to include in the `znc.conf` file.
+ '';
+ };
+
+ userName = mkOption {
+ default = "znc";
+ example = "johntron";
+ type = types.str;
+ description = ''
+ The user name used to log in to the ZNC web admin interface.
+ '';
+ };
+
+ networks = mkOption {
+ default = { };
+ type = with types; attrsOf (submodule networkOpts);
+ description = ''
+ IRC networks to connect the user to.
+ '';
+ example = literalExample ''
+ {
+ "freenode" = {
+ server = "chat.freenode.net";
+ port = 6697;
+ useSSL = true;
+ modules = [ "simple_away" ];
+ };
+ };
+ '';
+ };
+
+ nick = mkOption {
+ default = "znc-user";
+ example = "john";
+ type = types.str;
+ description = ''
+ The IRC nick.
+ '';
+ };
+
+ passBlock = mkOption {
+ example = literalExample ''
+ <Pass password>
+ Method = sha256
+ Hash = e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93
+ Salt = l5Xryew4g*!oa(ECfX2o
+ </Pass>
+ '';
+ type = types.str;
+ description = ''
+ Generate with `nix-shell -p znc --command "znc --makepass"`.
+ This is the password used to log in to the ZNC web admin interface.
+ You can also set this through
+
+ and co.
+ '';
+ };
+
+ port = mkOption {
+ default = 5000;
+ type = types.int;
+ description = ''
+ Specifies the port on which to listen.
+ '';
+ };
+
+ useSSL = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Indicates whether the ZNC server should use SSL when listening on
+ the specified port. A self-signed certificate will be generated.
+ '';
+ };
+
+ uriPrefix = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "/znc/";
+ description = ''
+ An optional URI prefix for the ZNC web interface. Can be
+ used to make ZNC available behind a reverse proxy.
+ '';
+ };
+
+ extraZncConf = mkOption {
+ default = "";
+ type = types.lines;
+ description = ''
+ Extra config to `znc.conf` file.
+ '';
+ };
+ };
+
+ };
+ };
+
+ config = mkIf cfg.useLegacyConfig {
+
+ services.znc.config = let
+ c = cfg.confOptions;
+ # defaults here should override defaults set in the non-legacy part
+ mkDefault = mkOverride 900;
+ in {
+ LoadModule = mkDefault c.modules;
+ Listener.l = {
+ Port = mkDefault c.port;
+ IPv4 = mkDefault true;
+ IPv6 = mkDefault true;
+ SSL = mkDefault c.useSSL;
+ };
+ User.${c.userName} = {
+ Admin = mkDefault true;
+ Nick = mkDefault c.nick;
+ AltNick = mkDefault "${c.nick}_";
+ Ident = mkDefault c.nick;
+ RealName = mkDefault c.nick;
+ LoadModule = mkDefault c.userModules;
+ Network = mapAttrs (name: net: {
+ LoadModule = mkDefault net.modules;
+ Server = mkDefault "${net.server} ${optionalString net.useSSL "+"}${toString net.port} ${net.password}";
+ Chan = optionalAttrs net.hasBitlbeeControlChannel { "&bitlbee" = mkDefault {}; } //
+ listToAttrs (map (n: nameValuePair "#${n}" (mkDefault {})) net.channels);
+ extraConfig = if net.extraConf == "" then mkDefault null else net.extraConf;
+ }) c.networks;
+ extraConfig = [ c.passBlock ] ++ optional (c.extraZncConf != "") c.extraZncConf;
+ };
+ };
+ };
+
+ imports = [
+ (mkRemovedOptionModule ["services" "znc" "zncConf"] ''
+ Instead of `services.znc.zncConf = "... foo ...";`, use
+ `services.znc.configFile = pkgs.writeText "znc.conf" "... foo ...";`.
+ '')
+ ];
+}