at master 5.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.paretosecurity; 9in 10{ 11 12 options.services.paretosecurity = { 13 enable = lib.mkEnableOption "[ParetoSecurity](https://paretosecurity.com) [agent](https://github.com/ParetoSecurity/agent) and its root helper"; 14 package = lib.mkPackageOption pkgs "paretosecurity" { }; 15 trayIcon = lib.mkOption { 16 type = lib.types.bool; 17 default = true; 18 description = "Set to false to disable the tray icon and run as a CLI tool only."; 19 }; 20 users = lib.mkOption { 21 type = lib.types.attrsOf ( 22 lib.types.submodule { 23 options = { 24 inviteId = lib.mkOption { 25 type = lib.types.str; 26 description = '' 27 A unique ID that links the agent to Pareto Cloud. 28 Get it from the Join Team page on `https://cloud.paretosecurity.com/team/join/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. 29 In Step 2, under Linux tab, enter your email then copy it from the generated command. 30 ''; 31 example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; 32 }; 33 }; 34 } 35 ); 36 default = { }; 37 description = "Per-user Pareto Security configuration."; 38 }; 39 }; 40 41 config = lib.mkIf cfg.enable { 42 environment.systemPackages = [ cfg.package ]; 43 systemd.packages = [ cfg.package ]; 44 45 # In traditional Linux distributions, systemd would read the [Install] section from 46 # unit files and automatically create the appropriate symlinks to enable services. 47 # However, in NixOS, due to its immutable nature and the way the Nix store works, 48 # the [Install] sections are not processed during system activation. Instead, we 49 # must explicitly tell NixOS which units to enable by specifying their target 50 # dependencies here. This creates the necessary symlinks in the proper locations. 51 systemd.sockets.paretosecurity.wantedBy = [ "sockets.target" ]; 52 53 # In NixOS, systemd services are configured with minimal PATH. However, 54 # paretosecurity helper looks for installed software to do its job, so 55 # it needs the full system PATH. For example, it runs `iptables` to see if 56 # firewall is configured. And it looks for various password managers to see 57 # if one is installed. 58 # The `paretosecurity-user` timer service that is configured lower has 59 # the same need. 60 systemd.services = { 61 paretosecurity.serviceConfig.Environment = [ 62 "PATH=${config.system.path}/bin:${config.system.path}/sbin" 63 ]; 64 } 65 // ( 66 67 # Each user can set their inviteID, which creates a systemd service 68 # that runs `paretosecurity link ...` to link their device to Pareto Cloud. 69 lib.mapAttrs' ( 70 username: userConfig: 71 lib.nameValuePair "paretosecurity-link-${username}" { 72 description = "Link Pareto Desktop to Pareto Cloud for user ${username}"; 73 after = [ "network-online.target" ]; 74 wants = [ "network-online.target" ]; 75 76 serviceConfig = { 77 Type = "oneshot"; 78 RemainAfterExit = true; 79 User = username; 80 StateDirectory = "paretosecurity/${username}"; 81 82 ExecStart = pkgs.writeShellScript "paretosecurity-link-${username}" '' 83 set -euo pipefail 84 85 INVITE_ID="${userConfig.inviteId}" 86 STATE_FILE="/var/lib/paretosecurity/${username}/linked-$INVITE_ID" 87 CONFIG_FILE="$HOME/.config/pareto.toml" 88 89 # Check if already linked with this specific invite 90 if [ -f "$STATE_FILE" ]; then 91 echo "Device already linked with invite $INVITE_ID for user ${username}" 92 exit 0 93 fi 94 95 # Ensure config directory exists 96 mkdir -p "$(dirname "$CONFIG_FILE")" 97 98 # Perform linking 99 echo "Linking device to Pareto Cloud for user ${username}..." 100 ${cfg.package}/bin/paretosecurity link \ 101 "paretosecurity://linkDevice/?invite_id=$INVITE_ID" 102 103 # Verify linking succeeded 104 if [ -f "$CONFIG_FILE" ] && grep -q "TeamID" "$CONFIG_FILE"; then 105 echo "Successfully linked to Pareto Cloud for user ${username}" 106 touch "$STATE_FILE" 107 else 108 echo "Failed to link to Pareto Cloud for user ${username}" 109 exit 1 110 fi 111 ''; 112 }; 113 114 wantedBy = [ "multi-user.target" ]; 115 } 116 ) cfg.users 117 ); 118 119 # Enable the tray icon and timer services if the trayIcon option is enabled 120 systemd.user = lib.mkIf cfg.trayIcon { 121 services = { 122 paretosecurity-trayicon.wantedBy = [ "graphical-session.target" ]; 123 paretosecurity-user = { 124 wantedBy = [ "graphical-session.target" ]; 125 serviceConfig.Environment = [ 126 "PATH=${config.system.path}/bin:${config.system.path}/sbin" 127 ]; 128 }; 129 }; 130 timers.paretosecurity-user.wantedBy = [ "timers.target" ]; 131 }; 132 }; 133}