From d490b648ac5acb65aa24c8e8314c1a6fa9e2c0c1 Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Sun, 10 Aug 2025 01:15:36 +0200 Subject: [PATCH] feat: Implement NixOS modules for madd server and client --- flake.nix | 8 ++++- modules/madd-client.nix | 72 +++++++++++++++++++++++++++++++++++++ modules/madd-server.nix | 79 +++++++++++++++++++++++++++++++++++++++++ nixos.nix | 78 ---------------------------------------- 4 files changed, 158 insertions(+), 79 deletions(-) create mode 100644 modules/madd-client.nix create mode 100644 modules/madd-server.nix delete mode 100644 nixos.nix diff --git a/flake.nix b/flake.nix index 479157c..67918d8 100644 --- a/flake.nix +++ b/flake.nix @@ -40,7 +40,13 @@ overlays.madd = final: prev: mkPackages final; overlays.default = overlays.madd; - nixosModules.madd = import ./nixos.nix { overlay = overlays.madd; }; + nixosModules.madd = { + imports = [ + ./modules/madd-client.nix + ./modules/madd-server.nix + ]; + config.nixpkgs.overlays = [ overlays.default ]; + }; nixosModules.default = nixosModules.madd; }; } diff --git a/modules/madd-client.nix b/modules/madd-client.nix new file mode 100644 index 0000000..915c15b --- /dev/null +++ b/modules/madd-client.nix @@ -0,0 +1,72 @@ +{ + lib, + pkgs, + config, + ... +}: + +with lib; +let + cfg = config.services.madd-client; +in +{ + options.services.madd-client = { + enable = mkEnableOption "MADD client"; + endpoint = mkOption { + type = types.str; + description = "Endpoint for MADD client to connect to."; + }; + interface = mkOption { + type = types.str; + description = "Network interface to use for MADD client."; + }; + priv-key-file = mkOption { + type = types.str; + default = "/etc/ssh/ssh_host_ed25519_key"; + description = "Path to the private SSH key file identifying this machine."; + }; + pub-key-file = mkOption { + type = types.str; + default = "${config.services.madd-client.priv-key-file}.pub"; + description = "Path to the public SSH key file identifying this machine."; + }; + hostname = mkOption { + type = types.str; + default = config.networking.hostName; + description = "Hostname to use for MADD client."; + }; + }; + + config = mkIf cfg.enable { + systemd.services.madd-client = { + description = "MADD Client Service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + requires = [ "network-online.target" ]; + script = '' + function run_update { + ipv4=$(${pkgs.iproute2}/bin/ip -4 addr show dev "${cfg.interface}" | grep -Po 'inet \K[\d.]+' || true) + if [ -n "$ipv4" ]; then + + export MADD_ENDPOINT="${cfg.endpoint}"; + export MADD_PRIV_KEY="${cfg.priv-key-file}"; + export MADD_PUB_KEY="${cfg.pub-key-file}"; + export MADD_HOSTNAME="${cfg.hostname}"; + export MADD_IP="$ipv4"; + + ${pkgs.madd-client}/bin/madd-client 2>/dev/null ; + fi + } + + run_update + + ${pkgs.iproute2}/bin/ip -4 monitor address label dev "${cfg.interface}" | while read -r event; do + if [[ $event == \[ADDR\]* ]]; then + echo "Detected address change" + run_update + fi + done + ''; + }; + }; +} diff --git a/modules/madd-server.nix b/modules/madd-server.nix new file mode 100644 index 0000000..a694597 --- /dev/null +++ b/modules/madd-server.nix @@ -0,0 +1,79 @@ +{ + lib, + pkgs, + config, + ... +}: + +with lib; +let + cfg = config.services.madd-server; +in +{ + options.services.madd-server = { + enable = mkEnableOption "MADD server"; + settings = { + bind = mkOption { + type = types.str; + default = "0.0.0.0:5301"; + description = "Address and port for MADD server to bind to."; + }; + zone = mkOption { + type = types.str; + example = "lan.example.com"; + description = "DNS zone under which the hosts are registered."; + }; + networks = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "10.0.0.0/8" ]; + description = "List of subnets to which hostnames can be registered."; + }; + registration_limit = mkOption { + type = types.int; + default = 1; + description = "Maximum number of hostnames a single host can register."; + }; + dns_server = mkOption { + type = types.str; + example = "localhost:53"; + description = "DNS server to use. Must support dynamic updates."; + }; + tsig_key_name = mkOption { + type = types.str; + default = "madd"; + description = "TSIG key name for DNS updates."; + }; + tsig_key_file = mkOption { + type = types.str; + default = "/etc/madd/tsig.key"; + description = "Path to the TSIG key file for DNS updates. Must be encoded in base64."; + }; + tsig_algorithm = mkOption { + type = types.str; + default = "hmac-sha256"; + description = "TSIG algorithm to use for DNS updates."; + }; + data_dir = mkOption { + type = types.str; + default = "/var/lib/madd"; + description = "Directory where MADD server stores its data."; + }; + }; + }; + + config = mkIf cfg.enable { + environment.etc."madd/madd.toml".source = (pkgs.formats.toml { }).generate "madd.toml" cfg.settings; + + systemd.services.madd-server = { + description = "MADD Server Service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + requires = [ "network-online.target" ]; + serviceConfig = { + ExecStart = "${pkgs.madd-server}/bin/madd-server"; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/nixos.nix b/nixos.nix deleted file mode 100644 index cb0e721..0000000 --- a/nixos.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ overlay }: - -{ - lib, - pkgs, - config, - ... -}: - -with lib; -{ - options.services.madd-client = { - enable = mkEnableOption "MADD client"; - endpoint = mkOption { - type = types.str; - description = "Endpoint for MADD client to connect to."; - }; - interface = mkOption { - type = types.str; - default = "eth0"; - description = "Network interface to use for MADD client."; - }; - priv-key-file = mkOption { - type = types.str; - default = "/etc/ssh/ssh_host_ed25519_key"; - description = "Path to the private SSH key file identifying this machine."; - }; - pub-key-file = mkOption { - type = types.str; - default = "${config.services.madd-client.priv_key_file}.pub"; - description = "Path to the public SSH key file identifying this machine."; - }; - hostname = mkOption { - type = types.str; - default = config.networking.hostName; - description = "Hostname to use for MADD client."; - }; - }; - - options.services.madd-server = { - enable = mkEnableOption "MADD server"; - }; - - config = { - nixpkgs.overlays = [ overlay ]; - } - // ( - let - cfg = config.services.madd-client; - in - optionalAttrs config.madd-client.enable { - systemd.services.madd-client = { - description = "MADD Client Service"; - wantedBy = [ "multi-user.target" ]; - before = [ "network-pre.target" ]; - requires = [ "network-pre.target" ]; - script = '' - ${pkgs.iproute2}/bin/ip -4 monitor address label dev "${cfg.interface}" | while read -r event; do - if [[ $event == \[ADDR\]* ]]; then - ipv4=$(${pkgs.iproute2}/bin/ip -4 addr show dev "${cfg.interface}" | grep -Po 'inet \K[\d.]+') - if [ -n "$ipv4" ]; then - - export MADD_ENDPOINT="${cfg.endpoint}" - export MADD_PRIV_KEY="${cfg.priv-key-file}" - export MADD_PUB_KEY="${cfg.pub-key-file}" - export MADD_HOSTNAME="${cfg.hostname}" - export MADD_IP="$ipv4" - - ${pkgs.madd-client}/bin/madd-client - fi - done - ''; - }; - } - ) - // (optionalAttrs config.madd-server.enable { - }); -}