From cd0331f5391fdd676bb07a3daa8b6492188fe8dd Mon Sep 17 00:00:00 2001 From: tk Date: Fri, 18 Apr 2025 10:45:38 -0400 Subject: [PATCH] CNSPRCY: adds service module and basic test to cnsprcy project --- projects/CNSPRCY/default.nix | 30 +++++-- .../cnsprcy/examples/basic.nix} | 1 + .../CNSPRCY/{ => programs/cnsprcy}/module.nix | 2 +- .../cnsprcy/tests/basic.nix} | 3 +- .../services/cnsprcy/examples/basic.nix | 5 ++ projects/CNSPRCY/services/cnsprcy/module.nix | 86 +++++++++++++++++++ .../CNSPRCY/services/cnsprcy/tests/basic.nix | 46 ++++++++++ 7 files changed, 165 insertions(+), 8 deletions(-) rename projects/CNSPRCY/{example.nix => programs/cnsprcy/examples/basic.nix} (97%) rename projects/CNSPRCY/{ => programs/cnsprcy}/module.nix (100%) rename projects/CNSPRCY/{test.nix => programs/cnsprcy/tests/basic.nix} (88%) create mode 100644 projects/CNSPRCY/services/cnsprcy/examples/basic.nix create mode 100644 projects/CNSPRCY/services/cnsprcy/module.nix create mode 100644 projects/CNSPRCY/services/cnsprcy/tests/basic.nix diff --git a/projects/CNSPRCY/default.nix b/projects/CNSPRCY/default.nix index f79bf9294..e195d3f9b 100644 --- a/projects/CNSPRCY/default.nix +++ b/projects/CNSPRCY/default.nix @@ -3,20 +3,38 @@ pkgs, sources, }@args: + { metadata = { + summary = "E2EE connections between trusted devices for establishing private group chats."; subgrants = [ "CNSPRCY" ]; + links = { + source = { + text = "CNSPRCY source code"; + url = "https://git.sr.ht/~xaos/cnsprcy"; + }; + }; }; - # https://git.sr.ht/~xaos/cnsprcy/tree/master/item/src/config.rs nixos.modules.programs.cnsprcy = { - module = ./module.nix; - examples.cnsprcy = { - module = ./example.nix; - description = ""; - tests.basic = import ./test.nix args; + name = "cnsprcy"; + module = ./programs/cnsprcy/module.nix; + examples.basic = { + module = ./programs/cnsprcy/examples/basic.nix; + description = "Checks for cnspr executable"; + tests.basic = import ./programs/cnsprcy/tests/basic.nix args; + }; + }; + + nixos.modules.services.cnsprcy = { + name = "cnsprcy"; + module = ./services/cnsprcy/module.nix; + examples.basic = { + module = ./services/cnsprcy/examples/basic.nix; + description = "Checks that cnsprcy systemd service is running"; + tests.basic = import ./services/cnsprcy/tests/basic.nix args; }; }; } diff --git a/projects/CNSPRCY/example.nix b/projects/CNSPRCY/programs/cnsprcy/examples/basic.nix similarity index 97% rename from projects/CNSPRCY/example.nix rename to projects/CNSPRCY/programs/cnsprcy/examples/basic.nix index 2aa6176c4..67b43498b 100644 --- a/projects/CNSPRCY/example.nix +++ b/projects/CNSPRCY/programs/cnsprcy/examples/basic.nix @@ -1,4 +1,5 @@ { ... }: + { programs.cnsprcy.enable = true; } diff --git a/projects/CNSPRCY/module.nix b/projects/CNSPRCY/programs/cnsprcy/module.nix similarity index 100% rename from projects/CNSPRCY/module.nix rename to projects/CNSPRCY/programs/cnsprcy/module.nix index b0fe6ec3a..27ec34801 100644 --- a/projects/CNSPRCY/module.nix +++ b/projects/CNSPRCY/programs/cnsprcy/module.nix @@ -1,7 +1,7 @@ { + config, lib, pkgs, - config, ... }: let diff --git a/projects/CNSPRCY/test.nix b/projects/CNSPRCY/programs/cnsprcy/tests/basic.nix similarity index 88% rename from projects/CNSPRCY/test.nix rename to projects/CNSPRCY/programs/cnsprcy/tests/basic.nix index d8a421d25..8621ac3fa 100644 --- a/projects/CNSPRCY/test.nix +++ b/projects/CNSPRCY/programs/cnsprcy/tests/basic.nix @@ -2,6 +2,7 @@ sources, ... }: + { name = "cnsprcy"; @@ -12,7 +13,7 @@ imports = [ sources.modules.ngipkgs sources.modules.programs.cnsprcy - sources.examples.CNSPRCY.cnsprcy + sources.examples.CNSPRCY.basic ]; }; }; diff --git a/projects/CNSPRCY/services/cnsprcy/examples/basic.nix b/projects/CNSPRCY/services/cnsprcy/examples/basic.nix new file mode 100644 index 000000000..a8c711c85 --- /dev/null +++ b/projects/CNSPRCY/services/cnsprcy/examples/basic.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + services.cnsprcy.enable = true; +} diff --git a/projects/CNSPRCY/services/cnsprcy/module.nix b/projects/CNSPRCY/services/cnsprcy/module.nix new file mode 100644 index 000000000..25f937d39 --- /dev/null +++ b/projects/CNSPRCY/services/cnsprcy/module.nix @@ -0,0 +1,86 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.cnsprcy; +in +{ + options.services.cnsprcy = { + enable = lib.mkEnableOption "cnsprcy"; + package = lib.mkPackageOption pkgs "cnsprcy" { }; + + hostname = lib.mkOption { + type = lib.types.str; + description = "Hostname of CNSPRCY server"; + default = config.networking.hostName; + }; + + stateDir = lib.mkOption { + type = lib.types.str; + description = "State directory for CNSPRCY server"; + default = "/var/lib/cnsprcy"; + }; + + user = lib.mkOption { + type = lib.types.str; + description = "Username of the system user that should own files and services related to CNSPRCY."; + default = "cnsprcy"; + }; + group = lib.mkOption { + type = lib.types.str; + description = "Group that contains the system user that executes CNSPRCY."; + default = "cnsprcy"; + }; + }; + + config = lib.mkIf cfg.enable { + + environment.systemPackages = [ cfg.package ]; + + users.users."${cfg.user}" = { + isSystemUser = true; + group = cfg.group; + + # CNSPRCY looks for the user home to initialize its data directory + # at $stateDir/.local/share/cnsprcy, but systemd.tmpfiles needs to create + # the dir otherwise permissions won't be set correctly. + home = cfg.stateDir; + useDefaultShell = true; + }; + users.groups."${cfg.group}" = { }; + + systemd.tmpfiles.rules = [ + "d ${cfg.stateDir}/.local/share/cnsprcy 0700 ${cfg.user} ${cfg.group} -" + "d ${cfg.stateDir}/.local/share/cnsprcy/handlers 0700 ${cfg.user} ${cfg.group} -" + ]; + + systemd.services.cnsprcy = { + description = "CNSPRCY service"; + wantedBy = [ "multi-user.target" ]; + after = [ + "nss-user-lookup.target" + "systemd-tmpfiles-setup.service" + ]; + + # Runs interactive config initialization to set machine name, generate + # conspirator keys and initial CNSPRCY db. TODO use the config init flags + # instead, but will need to investigate how to feed args to `cnspr serve`. + # + # That said we'll ultimately want to generate the config using options rather + # than dynamically like this. + # See https://github.com/ngi-nix/ngipkgs/pull/870#discussion_r2077898766 + preStart = "printf 'n\n${cfg.hostname}\ny\n' | ${lib.getExe cfg.package} config init"; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} serve"; + Restart = "on-failure"; + User = cfg.user; + Group = cfg.group; + }; + }; + + }; +} diff --git a/projects/CNSPRCY/services/cnsprcy/tests/basic.nix b/projects/CNSPRCY/services/cnsprcy/tests/basic.nix new file mode 100644 index 000000000..40e4ec908 --- /dev/null +++ b/projects/CNSPRCY/services/cnsprcy/tests/basic.nix @@ -0,0 +1,46 @@ +{ + sources, + ... +}: +{ + name = "cnsprcy-server"; + + nodes = { + machine1 = + { ... }: + { + imports = [ + sources.modules.ngipkgs + sources.modules.services.cnsprcy + sources.examples.CNSPRCY.basic + ]; + networking.firewall.enable = false; + }; + machine2 = + { ... }: + { + imports = [ + sources.modules.ngipkgs + sources.modules.services.cnsprcy + sources.examples.CNSPRCY.basic + ]; + networking.firewall.enable = false; + }; + }; + + testScript = + { nodes, ... }: + '' + start_all() + + machine1.wait_for_unit("cnsprcy.service") + machine2.wait_for_unit("cnsprcy.service") + + machine1.succeed("su cnsprcy -c 'cnspr interface add 192.168.1.1:3030'") + machine2.succeed("su cnsprcy -c 'cnspr interface add 192.168.1.2:3030'") + + pubkey = machine1.succeed("su cnsprcy -c 'cnspr manage advertise'").split()[-1] + invitation = machine2.succeed("su cnsprcy -c 'cnspr manage invite {}'".format(pubkey)).split()[-1] + machine1.succeed("su cnsprcy -c 'cnspr manage accept {}'".format(invitation)) + ''; +}