From ba34ac0d6729c8df5e05eed7aa04920cc48ea570 Mon Sep 17 00:00:00 2001 From: Abel Luck Date: Fri, 27 Feb 2026 09:27:34 +0100 Subject: [PATCH 1/2] add nixos and darwin-nix modules --- CHANGELOG.md | 2 ++ flake.nix | 48 ++++++++++++++++++++++++++++---------- home-module.nix | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ nixos-test.nix | 29 +++++++++++++++++++++++ 4 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 home-module.nix create mode 100644 nixos-test.nix diff --git a/CHANGELOG.md b/CHANGELOG.md index b728640..4deead8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Changes yet to be released are documented here. +- Add nixos, home-manager, and darwin-nix modules + ## v0.1.0 Initial release. diff --git a/flake.nix b/flake.nix index a5a5919..72df013 100644 --- a/flake.nix +++ b/flake.nix @@ -6,6 +6,7 @@ let systems = [ "x86_64-linux" + "aarch64-linux" "aarch64-darwin" ]; forAllSystems = fn: nixpkgs.lib.genAttrs systems (system: fn nixpkgs.legacyPackages.${system}); @@ -23,18 +24,24 @@ }; }); - checks = forAllSystems (pkgs: { - tests = self.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs (_: { - pname = "nix-cache-login-tests"; - checkPhase = '' - runHook preCheck - go test ./... - runHook postCheck - ''; - doCheck = true; - }); - devShell = self.devShells.${pkgs.stdenv.hostPlatform.system}.default; - }); + checks = forAllSystems ( + pkgs: + { + tests = self.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs (_: { + pname = "nix-cache-login-tests"; + checkPhase = '' + runHook preCheck + go test ./... + runHook postCheck + ''; + doCheck = true; + }); + devShell = self.devShells.${pkgs.stdenv.hostPlatform.system}.default; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux { + nixos-module = pkgs.testers.runNixOSTest (import ./nixos-test.nix self); + } + ); devShells = forAllSystems (pkgs: { default = pkgs.mkShell { @@ -45,6 +52,23 @@ }; }); + homeModules = { + # Workstation (Linux + macOS): home-manager module running `nix-cache-login refresh` + default = + { + config, + lib, + pkgs, + ... + }: + { + imports = [ ./home-module.nix ]; + services.nix-cache-login.package = + lib.mkDefault + self.packages.${pkgs.stdenv.hostPlatform.system}.default; + }; + }; + nixosModules = { # Workstation: systemd user timer+service running `nix-cache-login refresh` default = diff --git a/home-module.nix b/home-module.nix new file mode 100644 index 0000000..90e80ab --- /dev/null +++ b/home-module.nix @@ -0,0 +1,62 @@ +{ + config, + lib, + ... +}: +let + cfg = config.services.nix-cache-login; +in +{ + options.services.nix-cache-login = { + enable = lib.mkEnableOption "nix-cache-login automatic token refresh"; + package = lib.mkOption { + type = lib.types.package; + description = "The nix-cache-login package to use."; + }; + refreshInterval = lib.mkOption { + type = lib.types.ints.positive; + default = 900; + description = '' + How often to attempt token refresh, in seconds. + If no valid session exists, the service logs an error and retries on + the next interval. Run {command}`nix-cache-login` to log in. + ''; + example = 1800; + }; + }; + + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + systemd.user.services.nix-cache-login = { + Unit.Description = "Nix cache login - refresh access token"; + Service = { + Type = "oneshot"; + ExecStart = "${cfg.package}/bin/nix-cache-login refresh"; + }; + }; + + systemd.user.timers.nix-cache-login = { + Unit.Description = "Nix cache login - periodic token refresh"; + Timer = { + OnBootSec = "2min"; + OnUnitActiveSec = "${toString cfg.refreshInterval}s"; + }; + Install.WantedBy = [ "timers.target" ]; + }; + + launchd.agents.nix-cache-login = { + enable = true; + config = { + ProgramArguments = [ + "${cfg.package}/bin/nix-cache-login" + "refresh" + ]; + StartInterval = cfg.refreshInterval; + RunAtLoad = true; + ProcessType = "Background"; + StandardOutPath = "${config.home.homeDirectory}/Library/Logs/nix-cache-login.log"; + StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/nix-cache-login.log"; + }; + }; + }; +} diff --git a/nixos-test.nix b/nixos-test.nix new file mode 100644 index 0000000..9c5840f --- /dev/null +++ b/nixos-test.nix @@ -0,0 +1,29 @@ +self: { + name = "nix-cache-login-nixos-module"; + + nodes.machine = + { ... }: + { + imports = [ self.nixosModules.default ]; + services.nix-cache-login.enable = true; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + + # The module should install timer and service unit files for all users + machine.succeed("test -f /etc/systemd/user/nix-cache-login.timer") + machine.succeed("test -f /etc/systemd/user/nix-cache-login.service") + + # wantedBy = ["timers.target"] should create this symlink + machine.succeed( + "test -L /etc/systemd/user/timers.target.wants/nix-cache-login.timer" + ) + + # Service unit should reference the correct subcommand + unit = machine.succeed("cat /etc/systemd/user/nix-cache-login.service") + assert "nix-cache-login refresh" in unit, ( + f"ExecStart not found in service unit:\n{unit}" + ) + ''; +} From 29fe7f76c122934ca37ef6edae628c8387a4298f Mon Sep 17 00:00:00 2001 From: Abel Luck Date: Fri, 27 Feb 2026 09:27:49 +0100 Subject: [PATCH 2/2] expand the path to support working in systemd service --- CHANGELOG.md | 1 + internal/config/config.go | 27 +++++++++++++++++++++++++-- package.nix | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4deead8..7731311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Changes yet to be released are documented here. +- Fix path expansion when running in systemd - Add nixos, home-manager, and darwin-nix modules ## v0.1.0 diff --git a/internal/config/config.go b/internal/config/config.go index 77faaa1..cc37736 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -37,8 +37,8 @@ func Load(path string) (*Config, error) { return nil, fmt.Errorf("parsing config file: %w", err) } - cfg.NetrcPath = os.ExpandEnv(cfg.NetrcPath) - cfg.ClientSecretFile = os.ExpandEnv(cfg.ClientSecretFile) + cfg.NetrcPath = expandPath(cfg.NetrcPath) + cfg.ClientSecretFile = expandPath(cfg.ClientSecretFile) if cfg.ClientSecretFile != "" { secret, err := os.ReadFile(cfg.ClientSecretFile) @@ -71,6 +71,29 @@ func (c *Config) validate() error { return nil } +// expandPath expands environment variables in a path. XDG base directory +// variables are resolved using the xdg library, which applies the XDG spec +// fallbacks (e.g. $HOME/.config when $XDG_CONFIG_HOME is unset). This ensures +// correct behaviour in systemd user services, which do not set XDG variables. +func expandPath(s string) string { + return os.Expand(s, func(key string) string { + switch key { + case "XDG_CONFIG_HOME": + return xdg.ConfigHome + case "XDG_DATA_HOME": + return xdg.DataHome + case "XDG_CACHE_HOME": + return xdg.CacheHome + case "XDG_STATE_HOME": + return xdg.StateHome + case "XDG_RUNTIME_DIR": + return xdg.RuntimeDir + default: + return os.Getenv(key) + } + }) +} + // RefreshTokenPath returns the path to the stored refresh token. func RefreshTokenPath() string { return filepath.Join(xdg.ConfigHome, "nix-cache-login", "refresh-token") diff --git a/package.nix b/package.nix index cb25f28..e85a434 100644 --- a/package.nix +++ b/package.nix @@ -6,7 +6,7 @@ buildGoModule { pname = "nix-cache-login"; - version = "0.1.1"; + version = "0.1.2"; src = ./.; # src = fetchgit { # url = "https://guardianproject.dev/ops/nix-cache-login.git";