From 52dc849c67dcd54a6ce41622a7ba30005936c9cc Mon Sep 17 00:00:00 2001 From: Madeleine Sydney Date: Sat, 28 Dec 2024 22:28:56 -0700 Subject: [PATCH] feat: Manage secrets w/ sops-nix Closes #1 --- .sops.yaml | 13 ++++++++++ README.org | 7 ++++- flake.lock | 37 ++++++++++++++++++++++++++- flake.nix | 6 ++++- hosts/nixos-testbed/configuration.nix | 5 +++- modules/home/sops.nix | 28 ++++++++++++++++++++ modules/nixos/sops.nix | 37 +++++++++++++++++++++++++++ secrets.yaml | 21 +++++++++++++++ users/crumb/default.nix | 20 +++++++++++---- users/crumb/secrets.yaml | 21 +++++++++++++++ 10 files changed, 186 insertions(+), 9 deletions(-) create mode 100644 .sops.yaml create mode 100644 modules/home/sops.nix create mode 100644 modules/nixos/sops.nix create mode 100644 secrets.yaml create mode 100644 users/crumb/secrets.yaml diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..2c7f3cb --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,13 @@ +keys: + - &crumb age1qayk0d0f765v57pedm7mtau6qkmv8rh6jtaqm40g5g9armaty4jqc0v0y2 +creation_rules: + # System secrets + - path_regex: secrets\.(yaml|json|env|ini)$ + key_groups: + - age: + - *crumb + # User secrets + - path_regex: users/[^/]+/secrets\.(yaml|json|env|ini)$ + key_groups: + - age: + - *crumb diff --git a/README.org b/README.org index 961622a..1ffb831 100644 --- a/README.org +++ b/README.org @@ -145,7 +145,12 @@ I don't know anything about either. ** TODO password store 4 firefox -** TODO secrets +** TODO password store w/ age + +https://github.com/FiloSottile/passage + +** DONE secrets +CLOSED: [2024-12-29 Sun 01:41] ** TODO niri diff --git a/flake.lock b/flake.lock index 1eb2875..626ef9b 100644 --- a/flake.lock +++ b/flake.lock @@ -187,13 +187,48 @@ "type": "github" } }, + "nixpkgs_5": { + "locked": { + "lastModified": 1731763621, + "narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "disko": "disko", "home-manager": "home-manager", "impermanence": "impermanence", "niri": "niri", - "nixpkgs": "nixpkgs_4" + "nixpkgs": "nixpkgs_4", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1734546875, + "narHash": "sha256-6OvJbqQ6qPpNw3CA+W8Myo5aaLhIJY/nNFDk3zMXLfM=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "ed091321f4dd88afc28b5b4456e0a15bd8374b4d", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" } }, "xwayland-satellite-stable": { diff --git a/flake.nix b/flake.nix index ea73bdb..009d257 100644 --- a/flake.nix +++ b/flake.nix @@ -11,6 +11,8 @@ home-manager.url = "github:nix-community/home-manager"; niri.url = "github:sodiboo/niri-flake"; + + sops-nix.url = "github:Mic92/sops-nix"; }; outputs = { nixpkgs, ... }@inputs: @@ -47,8 +49,9 @@ inputs.self.nixosModules.default inputs.disko.nixosModules.disko + inputs.sops-nix.nixosModules.sops inputs.impermanence.nixosModules.impermanence - + # Directory name should always match host name. ({ ... }: { networking.hostName = k; }) @@ -125,6 +128,7 @@ }; }) + inputs.sops-nix.homeManagerModules.sops inputs.impermanence.homeManagerModules.impermanence ]; }; diff --git a/hosts/nixos-testbed/configuration.nix b/hosts/nixos-testbed/configuration.nix index adacc83..d32dd92 100644 --- a/hosts/nixos-testbed/configuration.nix +++ b/hosts/nixos-testbed/configuration.nix @@ -8,7 +8,7 @@ sydnix = { filesystemType = "btrfs"; - gpg.enable = true; + # gpg.enable = true; users.users = [ "crumb" @@ -101,6 +101,9 @@ services.openssh.enable = true; services.openssh.settings.PermitRootLogin = "yes"; + # TODO: Move to defaults. + users.mutableUsers = false; + # services.xserver.windowManager.qtile = { # enable = true; # extraPackages = python3Packages: with python3Packages; [ diff --git a/modules/home/sops.nix b/modules/home/sops.nix new file mode 100644 index 0000000..00a6dab --- /dev/null +++ b/modules/home/sops.nix @@ -0,0 +1,28 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.sydnix.sops; +in { + options = { + sydnix.sops = { + enable = mkEnableOption "Sops"; + keyFile = mkOption { + description = "Path to an Age key file."; + type = types.path; + default = config.home.homeDirectory + "/key.txt"; + }; + secrets = mkOption { + description = "Secrets passed directly to sops-nix."; + }; + }; + }; + + config = mkIf cfg.enable { + sops = { + age.keyFile = cfg.keyFile; + defaultSopsFile = ../../users/${config.home.username}/secrets.yaml; + secrets = cfg.secrets; + }; + }; +} diff --git a/modules/nixos/sops.nix b/modules/nixos/sops.nix new file mode 100644 index 0000000..59a149c --- /dev/null +++ b/modules/nixos/sops.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.sydnix.sops; +in { + options = { + sydnix.sops = { + enable = mkEnableOption "Sops secrets"; + keyFile = mkOption { + description = "Path to an Age key file."; + type = types.path; + default = "/persist/key.txt"; + }; + secrets = mkOption { + description = "Secrets passed directly to sops-nix."; + }; + package = mkOption { + description = "Sops CLI package. If null, nothing will be installed."; + type = with types; nullOr package; + default = pkgs.sops; + }; + }; + }; + + config = mkIf cfg.enable { + sops.defaultSopsFile = ../../secrets.yaml; + sops.defaultSopsFormat = "yaml"; + + environment.systemPackages = + mkIf (cfg.package != null) + [ cfg.package ]; + + sops.age.keyFile = cfg.keyFile; + sops.secrets = cfg.secrets; + }; +} diff --git a/secrets.yaml b/secrets.yaml new file mode 100644 index 0000000..16dcd9b --- /dev/null +++ b/secrets.yaml @@ -0,0 +1,21 @@ +example-key: ENC[AES256_GCM,data:ddKerh17p/+kDzSlSQ==,iv:62BgArZBCfcxL/qeVRluaSbY5y1GHtuiAbqXRB3NuG4=,tag:chcteZECw/SHFQctM+swVA==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1qayk0d0f765v57pedm7mtau6qkmv8rh6jtaqm40g5g9armaty4jqc0v0y2 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzSU40YUdJbEh6b01FdHYv + SjhKNFhwTmtiRVVKTC80T3ZjZnI4LzZIY2tBCms3S1lJcHo4M242ZmZBNTQrbmxa + YUxJb085Q2JWc2JNVkNrSU5SQktwbjQKLS0tIEd6aEo2NlNnVjJYZ3FISGVYZGNm + VFh1RFYvMUNnY1QveXF6TkVSMGpOTlUK9HrBWz8BzbA+HJ8XLFc5ji9QDKw1TuGx + pcDUwNy8DdSBhEtYQ7DxQ2U379IRQY1CN5qL3SdZnicg3zMhV5TWSA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-12-29T07:21:13Z" + mac: ENC[AES256_GCM,data:4SO/ho4QYlwwFthsbBhHTsOIwKwq0xPHUaabt+OZbTzETSg9UDTiLi8LZci+CUh9mKDwwh1CKJxIsl4MiOei+pLU0PB9uaudb9n68pPjeIxzJYKjjXwXzpfXipiAYcpSJJybmbJoivHncJoOuerBMmOlZ1HmHK9pcE2aJmGaBDY=,iv:HJF6A4bOJnXpMctHCTV1Cw7T8DAq4AXuBdqJzGo4vVI=,tag:2zD++PfLS6/4sp2SeBZLiw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1 diff --git a/users/crumb/default.nix b/users/crumb/default.nix index 310a660..59e76d2 100644 --- a/users/crumb/default.nix +++ b/users/crumb/default.nix @@ -4,18 +4,28 @@ # TODO: Don't hard-code `persist`. Use # config.sydnix.impermanence.persistGroupName. extraGroups = [ "wheel" "persist" ]; - # Change this immediately after installation! - initialPassword = "password123"; + initialHashedPassword = + "$y$j9T$aEFDDwdTZbAc6VQRXrkBJ0$K8wxTGTWDihyX1wxJ.ZMH//wmQFfrGGUkLkxIU0Lyq8"; }; homeConfiguration = { config, lib, pkgs, ... }: { imports = [ ./programs.nix ]; + + sydnix = { + sops = { + enable = true; + secrets = { + example-user-key = {}; + }; + }; + }; + home = { - stateVersion = "18.09"; packages = [ - pkgs.hello - # pkgs.wezterm ]; + + # Don't touch! + stateVersion = "18.09"; }; }; } diff --git a/users/crumb/secrets.yaml b/users/crumb/secrets.yaml new file mode 100644 index 0000000..09fdfc7 --- /dev/null +++ b/users/crumb/secrets.yaml @@ -0,0 +1,21 @@ +example-user-key: ENC[AES256_GCM,data:zefLZFp/MuxwrhbNhiCRWOCG,iv:IFwI3e2+uq1yv+hWQnHcX25XGiHa3AFqeIr5LW+2KFo=,tag:yS6KzPK7robKJsupZW8a2w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1qayk0d0f765v57pedm7mtau6qkmv8rh6jtaqm40g5g9armaty4jqc0v0y2 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2NE5mTER1OXpadmNzaXV6 + b3RSbS9yWTN0NWR4Z2xBRnRSanQxYXdRT2drClVrSk1raXE4ZUVIVmxoMzJWU1Rj + VmxzdnVSUVEvQk1JcFo4Qjh6YWhiME0KLS0tIHh1OCtzSUZpWWhrbXB4SlA4RVBs + VVBqSEM2bVFBU0M5YzZBQWIwUmVXUXMKvWb57Rc+rO5M8Pf7lvbSjuZB4FrHgT3A + uBQHH3wpv0BVVzL8tucPnwNxDnwpWvFxxwNVy/rtfs6y6HPu6fuOsA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-12-29T08:21:03Z" + mac: ENC[AES256_GCM,data:08lmfeXvrhipenfCO9AjdahGSvfaUO74EVlbtjhNw+Pjlu3SQNlqTBdzPFwpebCphNnryun/WGgT6fopgyITdkd1V7DGQLV184LRe0lD5qA3DEBm+uEPBqFpXT0AYucylWEam8paZYZ8HjdPL91I1H1MTDqGcO2dYhAh59JWXfE=,iv:fY+FxlfexYkkQsYp/On/QEhiKrZyzJ6mzTaXIxY44u0=,tag:U29ULu1vNi2z/MXMz9PkTg==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1