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}) ++ [ + "" + ]) (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 ...";`. + '') + ]; +}