diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md index 4c656e8037b7..c4ed81e0b5b6 100644 --- a/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixos/doc/manual/release-notes/rl-2311.section.md @@ -53,6 +53,8 @@ - [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server with minimal setup and support costs. Available as [services.honk](#opt-services.honk.enable). +- [NNCP](http://www.nncpgo.org/). Added nncp-daemon and nncp-caller services. Configuration is set with [programs.nncp.settings](#opt-programs.nncp.settings) and the daemons are enabled at [services.nncp](#opt-services.nncp.caller.enable). + ## Backward Incompatibilities {#sec-release-23.11-incompatibilities} - The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index e0d940c8f3ef..ec6424682ccc 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -981,6 +981,7 @@ ./services/networking/nix-serve.nix ./services/networking/nix-store-gcs-proxy.nix ./services/networking/nixops-dns.nix + ./services/networking/nncp.nix ./services/networking/nntp-proxy.nix ./services/networking/nomad.nix ./services/networking/nsd.nix diff --git a/nixos/modules/services/networking/nncp.nix b/nixos/modules/services/networking/nncp.nix new file mode 100644 index 000000000000..3cfe41995e76 --- /dev/null +++ b/nixos/modules/services/networking/nncp.nix @@ -0,0 +1,131 @@ +{ config, lib, pkgs, ... }: +with lib; + +let + nncpCfgFile = "/run/nncp.hjson"; + programCfg = config.programs.nncp; + callerCfg = config.services.nncp.caller; + daemonCfg = config.services.nncp.daemon; + settingsFormat = pkgs.formats.json { }; + jsonCfgFile = settingsFormat.generate "nncp.json" programCfg.settings; + pkg = programCfg.package; +in { + options = { + + services.nncp = { + caller = { + enable = mkEnableOption '' + cron'ed NNCP TCP daemon caller. + The daemon will take configuration from + [](#opt-programs.nncp.settings) + ''; + extraArgs = mkOption { + type = with types; listOf str; + description = "Extra command-line arguments to pass to caller."; + default = [ ]; + example = [ "-autotoss" ]; + }; + }; + + daemon = { + enable = mkEnableOption '' + NNCP TCP synronization daemon. + The daemon will take configuration from + [](#opt-programs.nncp.settings) + ''; + socketActivation = { + enable = mkEnableOption '' + Whether to run nncp-daemon persistently or socket-activated. + ''; + listenStreams = mkOption { + type = with types; listOf str; + description = lib.mdDoc '' + TCP sockets to bind to. + See [](#opt-systemd.sockets._name_.listenStreams). + ''; + default = [ "5400" ]; + }; + }; + extraArgs = mkOption { + type = with types; listOf str; + description = "Extra command-line arguments to pass to daemon."; + default = [ ]; + example = [ "-autotoss" ]; + }; + }; + + }; + }; + + config = mkIf (programCfg.enable or callerCfg.enable or daemonCfg.enable) { + + assertions = [{ + assertion = with builtins; + let + callerCongfigured = + let neigh = config.programs.nncp.settings.neigh or { }; + in lib.lists.any (x: hasAttr "calls" x && x.calls != [ ]) + (attrValues neigh); + in !callerCfg.enable || callerCongfigured; + message = "NNCP caller enabled but call configuration is missing"; + }]; + + systemd.services."nncp-caller" = { + inherit (callerCfg) enable; + description = "Croned NNCP TCP daemon caller."; + documentation = [ "http://www.nncpgo.org/nncp_002dcaller.html" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = '' + ${pkg}/bin/nncp-caller -noprogress -cfg "${nncpCfgFile}" ${ + lib.strings.escapeShellArgs callerCfg.extraArgs + }''; + Group = "uucp"; + UMask = "0002"; + }; + }; + + systemd.services."nncp-daemon" = mkIf daemonCfg.enable { + enable = !daemonCfg.socketActivation.enable; + description = "NNCP TCP syncronization daemon."; + documentation = [ "http://www.nncpgo.org/nncp_002ddaemon.html" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = '' + ${pkg}/bin/nncp-daemon -noprogress -cfg "${nncpCfgFile}" ${ + lib.strings.escapeShellArgs daemonCfg.extraArgs + }''; + Restart = "on-failure"; + Group = "uucp"; + UMask = "0002"; + }; + }; + + systemd.services."nncp-daemon@" = mkIf daemonCfg.socketActivation.enable { + description = "NNCP TCP syncronization daemon."; + documentation = [ "http://www.nncpgo.org/nncp_002ddaemon.html" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = '' + ${pkg}/bin/nncp-daemon -noprogress -ucspi -cfg "${nncpCfgFile}" ${ + lib.strings.escapeShellArgs daemonCfg.extraArgs + }''; + Group = "uucp"; + UMask = "0002"; + StandardInput = "socket"; + StandardOutput = "inherit"; + StandardError = "journal"; + }; + }; + + systemd.sockets.nncp-daemon = mkIf daemonCfg.socketActivation.enable { + inherit (daemonCfg.socketActivation) listenStreams; + description = "socket for NNCP TCP syncronization."; + conflicts = [ "nncp-daemon.service" ]; + wantedBy = [ "sockets.target" ]; + socketConfig.Accept = true; + }; + }; +}