diff --git a/.gitignore b/.gitignore index 66ecee4..ea12eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ !.envrc +!.sops.yaml + !/flake.nix !/flake.lock @@ -17,5 +19,6 @@ !modules/ !docs/ !images/ +!secrets/ !/flake/ diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..27698bb --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,14 @@ +keys: + - &admin_yubikey1 age1yubikey1qvy5y8kxqc63y7fk0tfv43u499a8z8q332ff087lythry9cc6hdxxkznc6t + - &host_x1g13_old age1xfc7ksg69l5kwsxxgtynsuxgpwltcf9gmqlhfl7efq0clc8lwspqnveyx3 +creation_rules: + - path_regex: ^secrets/common/[^/]+\.ya?ml$ + key_groups: + - age: + - *admin_yubikey1 + - *host_x1g13_old + - path_regex: ^secrets/hosts/x1g13/[^/]+\.ya?ml$ + key_groups: + - age: + - *admin_yubikey1 + - *host_x1g13_old diff --git a/docs/sops-key.md b/docs/sops-key.md new file mode 100644 index 0000000..8dbc9d3 --- /dev/null +++ b/docs/sops-key.md @@ -0,0 +1,17 @@ +# Generate Sops key file + +```bash +mkdir -p ~/.config/sops/age +chmod 700 ~/.config/sops/age + +age-plugin-yubikey --identity --slot 1 \ + > ~/.config/sops/age/yubikey-identity.txt + +chmod 600 ~/.config/sops/age/yubikey-identity.txt +``` + +## Edit sops file + +```bash +sops secrets/common/system.yaml +``` diff --git a/flake.lock b/flake.lock index b693604..837b384 100644 --- a/flake.lock +++ b/flake.lock @@ -959,6 +959,7 @@ "noctalia": "noctalia", "quickshell": "quickshell", "services-flake": "services-flake", + "sops-nix": "sops-nix", "stylix": "stylix", "systems": "systems_6", "treefmt-nix": "treefmt-nix_3", @@ -1002,6 +1003,26 @@ "type": "github" } }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780547341, + "narHash": "sha256-Gq8KNx5A7hBB3uGJaj6eQfLDIz5YdLu92gqBcvHvoUo=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "9ed65852b6257fbeae4355bc24ecfea307ca759a", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, "stylix": { "inputs": { "base16": "base16", diff --git a/flake.nix b/flake.nix index c766709..95922bb 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,12 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + # Secrets management + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # Disk management disko = { url = "github:nix-community/disko"; diff --git a/modules/system/default.nix b/modules/system/default.nix index a16f8ce..2206bcd 100644 --- a/modules/system/default.nix +++ b/modules/system/default.nix @@ -13,7 +13,9 @@ ./nix.nix ./power.nix ./secure-boot.nix + ./sops.nix ./user ./version.nix + ./secret.nix ]; } diff --git a/modules/system/secret.nix b/modules/system/secret.nix new file mode 100644 index 0000000..bb393d2 --- /dev/null +++ b/modules/system/secret.nix @@ -0,0 +1,14 @@ +_: +let + commonSyetemSecrets = ../../secrets/common/system.yaml; +in +{ + sops.secrets = { + "users/moons/hashedPassword" = { + sopsFile = commonSyetemSecrets; + + # need before user creation + neededForUsers = true; + }; + }; +} diff --git a/modules/system/sops.nix b/modules/system/sops.nix new file mode 100644 index 0000000..caf3184 --- /dev/null +++ b/modules/system/sops.nix @@ -0,0 +1,41 @@ +{ + inputs, + pkgs, + ... +}: +{ + imports = [ + inputs.sops-nix.nixosModules.sops + ]; + + environment.systemPackages = with pkgs; [ + # sops / age + sops + age + ssh-to-age + + # YubiKey edit key + age-plugin-yubikey + yubikey-manager + pcsc-tools + + # password hash generation + mkpasswd + ]; + + # age-plugin-yubikey depend + services.pcscd.enable = true; + + services.openssh.enable = true; + + sops = { + defaultSopsFormat = "yaml"; + + age = { + # system keys + sshKeyPaths = [ + "/etc/ssh/ssh_host_ed25519_key" + ]; + }; + }; +} diff --git a/modules/system/user/moons.nix b/modules/system/user/moons.nix index c4c2f76..47d70c2 100644 --- a/modules/system/user/moons.nix +++ b/modules/system/user/moons.nix @@ -1,8 +1,15 @@ -{ pkgs, ... }: { + pkgs, + config, + ... +}: +{ + users.mutableUsers = false; + users.users.moons = { isNormalUser = true; description = "moons-14"; + hashedPasswordFile = config.sops.secrets."users/moons/hashedPassword".path; extraGroups = [ "adbusers" "docker" diff --git a/secrets/common/system.yaml b/secrets/common/system.yaml new file mode 100644 index 0000000..e9f7735 --- /dev/null +++ b/secrets/common/system.yaml @@ -0,0 +1,28 @@ +users: + moons: + hashedPassword: ENC[AES256_GCM,data:QtZei/BXPn/PDxUlOu0ZVrAfRM5jiHChAE5j5NVscPmm4OWjr94nPVOmJlYjL2WAiJY3/JSthmbrEIqiUF6E9qv10HQzAxzmZQ==,iv:ksshJX9S/20lw/8IDZYadNZLLE/gNgENZJ3/wRgJCds=,tag:xJPiO8O/q4rKmb+YNnpZdg==,type:str] +sops: + age: + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHBpdi1wMjU2IGxWc2NMZyBBM09Pclhu + K0ozcS90TG9Qam1YUjdCUGw5QjRoNXNGMU92WVdJOVluUk0vNQpjb3AxeGVpaFBT + L2hLYnZ1WWtOQjdyRFR1SnNMb1JITTVwWlNXb003YUFJCi0tLSBPNnowdm00ZEhR + b2VGZ1drRG4rU01TODk5Rm5KbXJjVkNhQ0hNeUxwdXBzCqKtUyprjagTVajskgXg + OBMMuflEZQH+mtFWsBc0k1Mm7MAS8DpMVLNZnkfNNPpFTP4pAOWFd2LhuMkDONFQ + vnA= + -----END AGE ENCRYPTED FILE----- + recipient: age1yubikey1qvy5y8kxqc63y7fk0tfv43u499a8z8q332ff087lythry9cc6hdxxkznc6t + - enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPU0d5bVUrditWVCtDbyt6 + WFpJTVdLOGpqZ1hLZTJGZi83MXZLMzR6RVhFCnBZRU53V3NvYXFpVXVJaDJHdlhz + SlV4NFUvTDZUQWdTaUJNZElidk1zMjgKLS0tIEd3QTRldzBJamp0OWhNUTBFMExC + dlhiMGp4b1JqY2JVTG5vSitadXI4cEUKvhqw+A5CXktuHR3JBDNKg2SrNIy4++l8 + e58uQoTjJab1ivvLVAZOdtIdoulca50W9+ALNOFqBn9j5VD0BfFeKg== + -----END AGE ENCRYPTED FILE----- + recipient: age1xfc7ksg69l5kwsxxgtynsuxgpwltcf9gmqlhfl7efq0clc8lwspqnveyx3 + lastmodified: "2026-06-15T10:20:19Z" + mac: ENC[AES256_GCM,data:Tw58FneoksiOuol1aUOFXoAnFiTzddmFfYAA0B0RfPPyj6UKQbBvRYJhOMuOMRE1fVlDhqxxDiqZI5y14vJg8gLusAZt1JKi7ODR7MqcImvxboaee8DIj4uIcN254g0c0cmZWsGrt7yTYoSLDUc3QdAxj9/Az/CMls6XjM+RL8E=,iv:XGgWgbexCUxzuJzRVG3V2GZGwmwjAtowgz+NRPxk1+o=,tag:FwYJXfwS2f70okl0bhS+Sw==,type:str] + unencrypted_suffix: _unencrypted + version: 3.13.1 diff --git a/shells/dotnix.nix b/shells/dotnix.nix index 1afb4b2..bef8bb2 100644 --- a/shells/dotnix.nix +++ b/shells/dotnix.nix @@ -9,12 +9,27 @@ _: { devShells.dotnix = pkgs.mkShell { packages = [ config.treefmt.build.wrapper - pkgs.gitleaks + pkgs.git + pkgs.gitleaks pkgs.pre-commit + + # sops-nix / age + pkgs.sops + pkgs.age + pkgs.ssh-to-age + + # YubiKey for sops editing + pkgs.age-plugin-yubikey + pkgs.yubikey-manager + pkgs.pcsc-tools ]; - shellHook = config.pre-commit.settings.shellHook; + shellHook = '' + ${config.pre-commit.settings.shellHook} + + export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/yubikey-identity.txt" + ''; }; }; }