feat: sops-nix for samba password secret

- add sops-nix input + module (jupiter only, not the VM)
- secrets/jupiter.yaml: age-encrypted samba_password (safe to commit)
- .sops.yaml: encryption rule for admin age key
- secrets.nix: decrypt samba_password to /run/secrets on the host
- provisioning oneshot reads sops secret (host) or plaintext (VM), single value
- .sops private key stays off-repo (~/.config, /var/lib/sops-nix on host)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
erik
2026-07-12 20:16:17 +02:00
co-authored by Claude Opus 4.8
parent 9fb32fd454
commit 10387fdbee
8 changed files with 90 additions and 14 deletions
+1
View File
@@ -5,6 +5,7 @@
imports = [
./hardware-configuration.nix
./disk-config.nix # disko: OS-disk partitions + filesystems
./secrets.nix # sops-nix: samba password etc.
./services.nix
];
+16
View File
@@ -0,0 +1,16 @@
{ ... }:
# sops-nix secret wiring (real host only; not imported by vm.nix).
# Encrypted values live in ../secrets/jupiter.yaml, decrypted at activation to
# /run/secrets/<name>. The host needs the age PRIVATE key at the keyFile path.
#
# Deploy the private key with the install, e.g. nixos-anywhere:
# --extra-files, placing your key at /var/lib/sops-nix/key.txt
# or later derive a host age key from its ssh host key and add it to .sops.yaml.
{
sops.defaultSopsFile = ../secrets/jupiter.yaml;
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
# Decrypts to /run/secrets/samba_password (root-only by default).
sops.secrets.samba_password = { };
}
+12 -6
View File
@@ -68,9 +68,10 @@
# `services.samba` never sets it, so logins fail until provisioned.
# This runs AFTER samba-smbd so its state dir (/var/lib/samba/private) exists
# — an activation script runs too early and smbpasswd fails to init the passdb.
# The secret file must contain the password twice (new + confirm), one per line.
# VM test: vm.nix writes /etc/samba/smb-password with a throwaway value.
# Real host: supply it via sops-nix/agenix — do NOT commit plaintext.
# Reads a single-line password from the first file that exists:
# Real host: /run/secrets/samba_password (sops-nix, see secrets.nix)
# VM test: /etc/samba/smb-password (plaintext, see vm.nix)
# smbpasswd prompts new + confirm, so the value is fed twice.
systemd.services.samba-smbpasswd = {
description = "Provision Samba password for darman";
after = [ "samba-smbd.service" ];
@@ -81,9 +82,14 @@
RemainAfterExit = true;
};
script = ''
if [ -f /etc/samba/smb-password ]; then
${pkgs.samba}/bin/smbpasswd -a -s darman < /etc/samba/smb-password
fi
for f in /run/secrets/samba_password /etc/samba/smb-password; do
if [ -f "$f" ]; then
pw=$(head -n1 "$f")
printf '%s\n%s\n' "$pw" "$pw" | ${pkgs.samba}/bin/smbpasswd -a -s darman
exit 0
fi
done
echo "no samba password source found" >&2
'';
};
services.avahi = {
+3 -6
View File
@@ -18,14 +18,11 @@
users.users.root.initialPassword = "test";
# Throwaway SMB password for testing (samba-smbd login = darman / test).
# Two lines: smbpasswd wants the new password + confirmation.
# Single line — the provisioning oneshot feeds it twice for smbpasswd.
# Real host must NOT do this — plaintext lands in the world-readable Nix
# store. Use sops-nix/agenix to place /etc/samba/smb-password instead.
# store. It uses sops-nix (secrets.nix) instead.
environment.etc."samba/smb-password" = {
text = ''
test
test
'';
text = "test\n";
mode = "0600";
};