Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions modules/nixos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ in
A list of substituter URLs that Determinate Nixd should treat as edge caches. These URLs are written as the top-level `edgeCacheSubstituters` key in {file}`/etc/determinate/config.json`.
'';
};

determinateNixd.authentication.additionalNetrcSources = lib.mkOption {
type = lib.types.nullOr (
lib.types.listOf (
lib.types.oneOf [
lib.types.path
lib.types.str
]
)
);
default = null;
example = [ "/run/agenix/extra-netrc" ];
description = ''
A list of paths to `netrc` files that are combined by Determinate Nixd and used by
Determinate Nix. These files must exist and not be in `/nix/store` or the daemon refuses to
start. Written as the `authentication.additionalNetrcSources` key in
{file}`/etc/determinate/config.json`.
'';
};
};

config = lib.mkIf cfg.enable {
Expand All @@ -76,11 +95,27 @@ in
# the Determinate Nixd-managed /etc/nix/nix.conf.
environment.etc."nix/nix.conf".target = "nix/nix.custom.conf";

environment.etc."determinate/config.json" = lib.mkIf (cfg.edgeCacheSubstituters != null) {
text = builtins.toJSON {
edgeCacheSubstituters = cfg.edgeCacheSubstituters;
# NOTE: `environment.etc.<name>.text` is `types.lines`, so two definitions of this entry are
# silently concatenated into invalid JSON rather than reported as a conflict. Every key the
# daemon reads must therefore be emitted from this single definition.
environment.etc."determinate/config.json" =
let
netrcSources = cfg.determinateNixd.authentication.additionalNetrcSources;

configAttrs =
lib.optionalAttrs (cfg.edgeCacheSubstituters != null) {
inherit (cfg) edgeCacheSubstituters;
}
// lib.optionalAttrs (netrcSources != null) {
# NOTE: `builtins.toJSON` copies a Nix path value into `/nix/store` and serializes the
# resulting store path. That would publish the netrc contents world-readably and hand
# the daemon a source it refuses, so paths are flattened to plain strings first.
authentication.additionalNetrcSources = map builtins.toString netrcSources;
};
in
lib.mkIf (configAttrs != { }) {
text = builtins.toJSON configAttrs;
};
};

systemd = {
services.nix-daemon.serviceConfig = {
Expand Down
43 changes: 43 additions & 0 deletions tests/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,49 @@
];
}).config.system.build.toplevel;

# Regression test: a path-valued `additionalNetrcSources` entry must be serialized as the
# literal filesystem path. Handing the path straight to `builtins.toJSON` copies it into
# `/nix/store`, which publishes the netrc contents and yields a source the daemon rejects.
x86_64-linux.nixos-determinate-nixd-config =
let
nixos = inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
inputs.determinate.nixosModules.default
{
fileSystems."/" = {
device = "/dev/bogus";
fsType = "ext4";
};
boot.loader.grub.devices = [ "/dev/bogus" ];
system.stateVersion = "24.11";

determinate = {
edgeCacheSubstituters = [ "https://cache.example.com/" ];
determinateNixd.authentication.additionalNetrcSources = [
/etc/extra/netrc
"/run/agenix/extra-netrc"
];
};
}
];
};

actual = nixos.config.environment.etc."determinate/config.json".text;

expected = builtins.toJSON {
edgeCacheSubstituters = [ "https://cache.example.com/" ];
authentication.additionalNetrcSources = [
"/etc/extra/netrc"
"/run/agenix/extra-netrc"
];
};
in
assert inputs.nixpkgs.lib.assertMsg (
actual == expected
) "/etc/determinate/config.json mismatch\n actual: ${actual}\n expected: ${expected}";
nixos.pkgs.runCommand "nixos-determinate-nixd-config" { } "touch $out";

aarch64-darwin = {
home-manager =
(inputs.home-manager.lib.homeManagerConfiguration {
Expand Down