···14141515 config = lib.mkIf config.services.paretosecurity.enable {
1616 environment.systemPackages = [ config.services.paretosecurity.package ];
1717+ systemd.packages = [ config.services.paretosecurity.package ];
17181818- systemd.sockets."paretosecurity" = {
1919- wantedBy = [ "sockets.target" ];
2020- socketConfig = {
2121- ListenStream = "/var/run/paretosecurity.sock";
2222- SocketMode = "0666";
1919+ # In traditional Linux distributions, systemd would read the [Install] section from
2020+ # unit files and automatically create the appropriate symlinks to enable services.
2121+ # However, in NixOS, due to its immutable nature and the way the Nix store works,
2222+ # the [Install] sections are not processed during system activation. Instead, we
2323+ # must explicitly tell NixOS which units to enable by specifying their target
2424+ # dependencies here. This creates the necessary symlinks in the proper locations.
2525+ systemd.sockets.paretosecurity.wantedBy = [ "sockets.target" ];
2626+2727+ # Enable the tray icon and timer services if the trayIcon option is enabled
2828+ systemd.user = lib.mkIf config.services.paretosecurity.trayIcon {
2929+ services.paretosecurity-trayicon = {
3030+ wantedBy = [ "graphical-session.target" ];
2331 };
2424- };
2525-2626- systemd.services."paretosecurity" = {
2727- serviceConfig = {
2828- ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity helper";
2929- User = "root";
3030- Group = "root";
3131- StandardInput = "socket";
3232- Type = "oneshot";
3333- RemainAfterExit = "no";
3434- StartLimitInterval = "1s";
3535- StartLimitBurst = 100;
3636- ProtectSystem = "full";
3737- ProtectHome = true;
3838- StandardOutput = "journal";
3939- StandardError = "journal";
3232+ services.paretosecurity-user = {
3333+ wantedBy = [ "graphical-session.target" ];
4034 };
4141- };
4242-4343- systemd.user.services."paretosecurity-trayicon" = lib.mkIf config.services.paretosecurity.trayIcon {
4444- wantedBy = [ "graphical-session.target" ];
4545- serviceConfig = {
4646- ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity trayicon";
3535+ timers.paretosecurity-user = {
3636+ wantedBy = [ "timers.target" ];
4737 };
4838 };
4949-5039 };
5140}
+68-3
nixos/tests/paretosecurity.nix
···44 meta.maintainers = [ lib.maintainers.zupo ];
5566 nodes.terminal =
77- { config, pkgs, ... }:
77+ {
88+ config,
99+ pkgs,
1010+ lib,
1111+ ...
1212+ }:
1313+ let
1414+ # Create a patched version of the package that points to the local dashboard
1515+ # for easier testing
1616+ patchedPareto = pkgs.paretosecurity.overrideAttrs (oldAttrs: {
1717+ postPatch = ''
1818+ substituteInPlace team/report.go \
1919+ --replace-warn 'const reportURL = "https://dash.paretosecurity.com"' \
2020+ 'const reportURL = "http://dashboard"'
2121+ '';
2222+ });
2323+ in
824 {
925 imports = [ ./common/user-account.nix ];
10261111- services.paretosecurity.enable = true;
2727+ services.paretosecurity = {
2828+ enable = true;
2929+ package = patchedPareto;
3030+ };
3131+3232+ };
3333+3434+ nodes.dashboard =
3535+ { config, pkgs, ... }:
3636+ {
3737+ networking.firewall.allowedTCPPorts = [ 80 ];
3838+3939+ services.nginx = {
4040+ enable = true;
4141+ virtualHosts."dashboard" = {
4242+ locations."/api/v1/team/".extraConfig = ''
4343+ add_header Content-Type application/json;
4444+ return 200 '{"message": "Linked device."}';
4545+ '';
4646+ };
4747+ };
1248 };
13491450 nodes.xfce =
···3874 enableOCR = true;
39754076 testScript = ''
7777+ # Test setup
7878+ terminal.succeed("su - alice -c 'mkdir -p /home/alice/.config'")
7979+ for m in [terminal, dashboard]:
8080+ m.systemctl("start network-online.target")
8181+ m.wait_for_unit("network-online.target")
8282+8383+ # Test 1: Test the systemd socket is installed & enabled
8484+ terminal.succeed('systemctl is-enabled paretosecurity.socket')
8585+8686+ # Test 2: Test running checks
4187 terminal.succeed(
4242- "su -- alice -c 'paretosecurity check"
8888+ "su - alice -c 'paretosecurity check"
4389 # Disable some checks that need intricate test setup so that this test
4490 # remains simple and fast. Tests for all checks and edge cases available
4591 # at https://github.com/ParetoSecurity/agent/tree/main/test/integration
···4894 + " --skip 21830a4e-84f1-48fe-9c5b-beab436b2cdb" # Disk encryption
4995 + " --skip 44e4754a-0b42-4964-9cc2-b88b2023cb1e" # Pareto Security is up to date
5096 + " --skip f962c423-fdf5-428a-a57a-827abc9b253e" # Password manager installed
9797+ + " --skip 2e46c89a-5461-4865-a92e-3b799c12034a" # Firewall is enabled
5198 + "'"
5299 )
53100101101+ # Test 3: Test linking
102102+ terminal.succeed("su - alice -c 'paretosecurity link"
103103+ + " paretosecurity://enrollTeam/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
104104+ + "eyJ0b2tlbiI6ImR1bW15LXRva2VuIiwidGVhbUlEIjoiZHVtbXktdGVhbS1pZCIsImlhdCI6"
105105+ + "MTcwMDAwMDAwMCwiZXhwIjoxOTAwMDAwMDAwfQ.WgnL6_S0EBJHwF1wEVUG8GtIcoVvK5IjWbZpUeZr4Qw'")
106106+107107+ config = terminal.succeed("cat /home/alice/.config/pareto.toml")
108108+ assert 'AuthToken = "dummy-token"' in config
109109+ assert 'TeamID = "dummy-team-id"' in config
110110+111111+ # Test 4: Test the tray icon
54112 xfce.wait_for_x()
113113+ for unit in [
114114+ 'paretosecurity-trayicon',
115115+ 'paretosecurity-user',
116116+ 'paretosecurity-user.timer'
117117+ ]:
118118+ status, out = xfce.systemctl("is-enabled " + unit, "alice")
119119+ assert status == 0, f"Unit {unit} is not enabled (status: {status}): {out}"
55120 xfce.succeed("xdotool mousemove 850 10")
56121 xfce.wait_for_text("Pareto Security")
57122 xfce.succeed("xdotool click 1")
+23-9
pkgs/by-name/pa/paretosecurity/package.nix
···991010buildGoModule rec {
1111 pname = "paretosecurity";
1212- version = "0.0.91";
1212+ version = "0.0.96";
13131414 src = fetchFromGitHub {
1515 owner = "ParetoSecurity";
1616 repo = "agent";
1717 rev = version;
1818- hash = "sha256-/kGwV96Jp7U08jh/wPQMcoV48zQe9ixY7gpNdtFyOkk=";
1818+ hash = "sha256-SyeIGSDvrnOvyOJ0zC8CulpaMa+iZeRaMTJUSydz2tw=";
1919 };
20202121- vendorHash = "sha256-kGrYoN0dGcSuQW47Y4LUFdHQYAoY74NOM1LLPdhmLhc=";
2121+ vendorHash = "sha256-O/OF3Y6HiiikMxf657k9eIM7UfkicIImAUxVVf/TgR8=";
2222 proxyVendor = true;
23232424- subPackages = [
2525- "cmd/paretosecurity"
2626- ];
2727-2824 ldflags = [
2925 "-s"
3026 "-X=github.com/ParetoSecurity/agent/shared.Version=${version}"
···3228 "-X=github.com/ParetoSecurity/agent/shared.Date=1970-01-01T00:00:00Z"
3329 ];
34303131+ postInstall = ''
3232+ # Install global systemd files
3333+ install -Dm400 ${src}/apt/paretosecurity.socket $out/lib/systemd/system/paretosecurity.socket
3434+ install -Dm400 ${src}/apt/paretosecurity.service $out/lib/systemd/system/paretosecurity.service
3535+ substituteInPlace $out/lib/systemd/system/paretosecurity.service \
3636+ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity"
3737+3838+ # Install user systemd files
3939+ install -Dm444 ${src}/apt/paretosecurity-user.timer $out/lib/systemd/user/paretosecurity-user.timer
4040+ install -Dm444 ${src}/apt/paretosecurity-user.service $out/lib/systemd/user/paretosecurity-user.service
4141+ substituteInPlace $out/lib/systemd/user/paretosecurity-user.service \
4242+ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity"
4343+ install -Dm444 ${src}/apt/paretosecurity-trayicon.service $out/lib/systemd/user/paretosecurity-trayicon.service
4444+ substituteInPlace $out/lib/systemd/user/paretosecurity-trayicon.service \
4545+ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity"
4646+ '';
4747+3548 passthru.tests = {
3649 version = testers.testVersion {
3750 version = "${version}";
···5063 settings such as if you have disk encryption and firewall enabled.
51645265 If you use the `services.paretosecurity` NixOS module, you also get a
5353- root helper, so that you can run the checker in userspace. Some checks
6666+ root helper that allows you to run the checker in userspace. Some checks
5467 require root permissions, and the checker asks the helper to run those.
55685669 Additionally, if you enable `services.paretosecurity.trayIcon`, you get a
5770 little Vilfredo Pareto living in your systray showing your the current
5858- status of checks.
7171+ status of checks. This will also enable a systemd timer to update the
7272+ status of checks once per hour.
59736074 Finally, you can run `paretosecurity link` to configure the agent
6175 to send the status of checks to https://dash.paretosecurity.com to make