From 732ae81533c0c16281e1221c85d75a999232cfda Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sat, 15 Jan 2022 11:00:01 +0100 Subject: [PATCH] Add NNCP module --- flake.lock | 77 ++++++++++--------- flake.nix | 3 +- modules/nncp.nix | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 40 deletions(-) create mode 100644 modules/nncp.nix diff --git a/flake.lock b/flake.lock index e3e6ab21..f4beaa3d 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1641536797, - "narHash": "sha256-SlU2xiYPjN/a7NGosAI8LoHJPaFj+2gnwGLsdAh3wF4=", + "lastModified": 1642486955, + "narHash": "sha256-PiPn+ClAr/294i3hGHRygGCPtDrDnqbyl7JRcYRLmZc=", "owner": "nix-community", "repo": "fenix", - "rev": "80a97954c9d39423e9bd273d84bb55770335565e", + "rev": "a69f7ac3008066e991a83367bbe89c11ccf239ab", "type": "github" }, "original": { @@ -88,11 +88,11 @@ ] }, "locked": { - "lastModified": 1638219772, - "narHash": "sha256-R396OImY09dKCRgbY0s54/cQxoFNushVtHyCVw+y7FU=", + "lastModified": 1641890987, + "narHash": "sha256-CJOAOlk7mZlBVvUiv9q8SYkK0rjY0UmkWedMI0eajWE=", "owner": "mhuesch", "repo": "naersk", - "rev": "80649a7ebe7c0675699893b278ebed851d711a69", + "rev": "193e049d6e4c841faf800e302551d2e0a48eee88", "type": "github" }, "original": { @@ -103,11 +103,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1640686209, - "narHash": "sha256-6glXUlKRDhEhNuYx6r3fXU6KH2/Vq9mJZjB9oUpwrmc=", + "lastModified": 1641965797, + "narHash": "sha256-AfxfIzAZbt9aAzpVBn0Bwhd/M4Wix7G91kEjm9H6FPo=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "46df95ca81e7e4cf3458cdb4b7d1714b5fce9da5", + "rev": "87a35a0d58f546dc23f37b4f6af575d0e4be6a7a", "type": "github" }, "original": { @@ -118,11 +118,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1641528457, - "narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=", + "lastModified": 1642281915, + "narHash": "sha256-jcMsXmmO1knyf99o242A+2cy1A0eKa9afly0cwBknPA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ff377a78794d412a35245e05428c8f95fef3951f", + "rev": "d5dae6569ea9952f1ae4e727946d93a71c507821", "type": "github" }, "original": { @@ -134,11 +134,11 @@ }, "nixpkgs-master": { "locked": { - "lastModified": 1639061474, - "narHash": "sha256-iCrfAyfrQo7y1OFyp98lEcTFDGL6oJMduI1B8bwYZdg=", + "lastModified": 1641927215, + "narHash": "sha256-96otEPy5y/4aeM6Sjl//Qr8v3+CdjTBNtnS4eKyoY0U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "61727e0e57e73113aca16981ea00275b299fbf94", + "rev": "0fdbcb2355f0681908cc9fef0cc9138f938ae1a3", "type": "github" }, "original": { @@ -165,27 +165,26 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1641528457, - "narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=", + "lastModified": 1642533784, + "narHash": "sha256-RUgoUQe/p8hL2v8gjHQ3W9PNl+FioqOqrnQpI92PpM4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ff377a78794d412a35245e05428c8f95fef3951f", + "rev": "95dfbf360c09df1556a312297a7b3605252a2227", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1641550923, - "narHash": "sha256-vKd+7BWjZO6/p8kdP+szOfecJBw/zbWUWhNNoOx2PUU=", + "lastModified": 1642160200, + "narHash": "sha256-5mb1nvh2vWlnKvyJzGNKsL7AQRFk+H5E/Xh83fTzYG4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9bc01c54624b128a9533f912849cd7f2d2bab9f2", + "rev": "e5a50e8f2995ff359a170d52cc40adbcfdd92ba4", "type": "github" }, "original": { @@ -195,11 +194,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1641578038, - "narHash": "sha256-fE5tYnyxiAmgg4qJp7jcHxGcQIazhLY2AI89SInxOck=", + "lastModified": 1642522226, + "narHash": "sha256-m/j9U8KYuwwxjwgRCjmEj8ejftvdMLJ+NGXh/L2I4FU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "d89eab1e42717622cfdd5f43f3b99e8680bdb637", + "rev": "610d4ea2750e064bf34b33fa38cb671edd893d3d", "type": "github" }, "original": { @@ -243,11 +242,11 @@ }, "nixpkgs_6": { "locked": { - "lastModified": 1639061333, - "narHash": "sha256-rG04piqc/mCGM+6IU0o1JRlH+iqwOXbuuqA1Wtszexw=", + "lastModified": 1641924320, + "narHash": "sha256-DuOpJqoMmQ3Yk4C64QQHFaByhbSIi872He6z5BXY1YM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fe4ebb5a53789ecea5eddaf48589f69701c125c3", + "rev": "05f3de54d568dba52efaad966f0e09bfea796dcb", "type": "github" }, "original": { @@ -260,11 +259,11 @@ "openwrt": { "flake": false, "locked": { - "lastModified": 1638708860, - "narHash": "sha256-6az+TFKk6A94YEFvrNRBuCnDfTG2y9HT9xivx5wknhU=", + "lastModified": 1641673875, + "narHash": "sha256-Eb9tVxE9Pmob/xWZ6wRt95cTycPeyPkyyaaWaz6cWtA=", "ref": "openwrt-21.02", - "rev": "c67509efd7d0c43eb3f622f06c8a31aa28d22f6e", - "revCount": 50860, + "rev": "6ced8cad8edd2a04fc6bb914c333c8aac9a1c825", + "revCount": 50927, "type": "git", "url": "https://git.openwrt.org/openwrt/openwrt.git" }, @@ -296,11 +295,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1641511071, - "narHash": "sha256-xxT0f2r+9n3gxnvvIhwDeYpqr6xG6F5FzGXjO33rBdk=", + "lastModified": 1642463850, + "narHash": "sha256-kY5+G0F353wG4ob5cZLPAa+lnSmbC2Z7q9HcVqe8buk=", "owner": "rust-analyzer", "repo": "rust-analyzer", - "rev": "2fb6f5e46a5f53a78c2f750dd3c8e79dd418c4c9", + "rev": "477b654f4f4896dab766a398cf1f2955146088d5", "type": "github" }, "original": { @@ -473,11 +472,11 @@ "openwrt": "openwrt" }, "locked": { - "lastModified": 1640735504, - "narHash": "sha256-O/SGZSA61fmkHkXi6lTyMt0IovCqxxwBw4xgs9td3q0=", + "lastModified": 1642474243, + "narHash": "sha256-LZZUsdbpZvkjAL1+4G5aJKjnRCA+Kfa7hUoTtHEHIfs=", "ref": "master", - "rev": "187a20f67e1230c8ca5f1d6147a2d729ad54d502", - "revCount": 1299, + "rev": "2789589c25900bc87316dd9f1e7f66cf1ee5e3ab", + "revCount": 1330, "type": "git", "url": "https://gitea.c3d2.de/zentralwerk/network.git" }, diff --git a/flake.nix b/flake.nix index 7f10a164..64a27def 100644 --- a/flake.nix +++ b/flake.nix @@ -4,7 +4,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/release-21.11"; nixpkgs-mobilizon.url = "github:erictapen/nixpkgs/mobilizon"; - nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs-unstable.url = "github:nixos/nixpkgs"; secrets.url = "git+ssh://gitea@gitea.c3d2.de/c3d2-admins/secrets.git"; secrets.inputs.sops-nix.follows = "sops-nix"; nixos-hardware.url = "github:nixos/nixos-hardware"; @@ -509,6 +509,7 @@ c3d2.hosts = hostRegistry.hosts; c3d2.users = import ./users.nix; }; + nncp = ./modules/nncp.nix; plume = { imports = [ ./modules/plume.nix ]; nixpkgs.overlays = [ fenix.overlay naersk.overlay ]; diff --git a/modules/nncp.nix b/modules/nncp.nix new file mode 100644 index 00000000..f27d39a6 --- /dev/null +++ b/modules/nncp.nix @@ -0,0 +1,194 @@ +{ 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; +in { + options = { + programs.nncp = { + + enable = mkEnableOption "NNCP (Node to Node copy) utilities"; + + secrets = mkOption { + type = with types; listOf str; + example = [ "/run/keys/nncp.hjson" ]; + description = '' + A list of paths to NNCP configuration files that should not be + in the Nix store. These files are layered on top of the values at + . + ''; + }; + + settings = mkOption { + type = settingsFormat.type; + description = '' + NNCP configuration, see + . + At runtime these settings will be overlayed by the contents of + into the file + ${nncpCfgFile}. Node keypairs go in + secrets, do not specify them in + settings as they will be leaked into + /nix/store! + ''; + default = { }; + }; + + }; + + services.nncp = { + + caller = { + enable = mkEnableOption '' + croned NNCP TCP daemon caller. + The daemon will take configuration from + + ''; + 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 + + ''; + + socketActivation = { + enable = mkEnableOption '' + Whether to run nncp-daemon persistently or socket-activated. + ''; + listenStreams = mkOption { + type = with types; listOf str; + description = '' + TCP sockets to bind to. + See . + ''; + 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"; + }]; + + programs.nncp.settings = { + spool = mkDefault "/var/spool/nncp"; + log = mkDefault "/var/spool/nncp/log"; + }; + + environment = mkIf programCfg.enable { + systemPackages = [ pkgs.nncp ]; + etc."nncp.hjson".source = nncpCfgFile; + }; + + systemd.tmpfiles.rules = [ + "d ${programCfg.settings.spool} 0770 root uucp" + "f ${programCfg.settings.log} 0770 root uucp" + ]; + + system.activationScripts.nncp = '' + nncpCfgDir=$(mktemp --directory nncp.XXXXXXXXXX) + for f in ${jsonCfgFile} ${toString config.programs.nncp.secrets}; do + tmpdir=$(mktemp --directory nncp.XXXXXXXXXX) + ${pkgs.nncp}/bin/nncp-cfgdir -cfg $f -dump $tmpdir + ${pkgs.findutils}/bin/find $tmpdir -size 1c -delete + cp -a $tmpdir/* $nncpCfgDir/ + rm -rf $tmpdir + done + ${pkgs.nncp}/bin/nncp-cfgdir -load $nncpCfgDir > ${nncpCfgFile} + rm -rf $nncpCfgDir + chgrp uucp ${nncpCfgFile} + ''; + + 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 = '' + ${pkgs.nncp}/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 = '' + ${pkgs.nncp}/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 = '' + ${pkgs.nncp}/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; + }; + + }; + +}