diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 120000 index 0000000..ca60d86 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +/nix/store/1w2s62i701n28sj08gn1445qr4v3vijp-pre-commit-config.json \ No newline at end of file diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..fd76726 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,38 @@ +# SOPS configuration for StuRa HTW Dresden infrastructure +# +# This file defines which keys can decrypt which secrets. +# Add GPG public keys (.asc files) or age keys to keys/hosts/ and keys/users/ +# to grant decryption access to hosts and users respectively. + +keys: + # Admin/user keys - add GPG public keys here + # Example: + # - &user_admin_key age1... or pgp fingerprint + + # Host keys - add host-specific keys here + # Example: + # - &host_proxy_key age1... or pgp fingerprint + # - &host_git_key age1... or pgp fingerprint + +# Define which keys can access which files +creation_rules: + # Default rule: all secrets can be decrypted by admin keys + - path_regex: secrets/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - age: + # - *user_admin_key + + # Host-specific secrets (example) + # - path_regex: secrets/proxy/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - *host_proxy_key + + # - path_regex: secrets/git/.*\.yaml$ + # key_groups: + # - pgp: + # - *user_admin_key + # - *host_git_key diff --git a/flake.lock b/flake.lock index ea4eb31..5bc0c8b 100644 --- a/flake.lock +++ b/flake.lock @@ -114,6 +114,22 @@ } }, "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { "flake": false, "locked": { "lastModified": 1761588595, @@ -169,12 +185,34 @@ } }, "git-hooks": { + "inputs": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772893680, + "narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "8baab586afc9c9b57645a734c820e4ac0a604af9", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "git-hooks_2": { "inputs": { "flake-compat": [ "mailserver", "flake-compat" ], - "gitignore": "gitignore", + "gitignore": "gitignore_2", "nixpkgs": [ "mailserver", "nixpkgs" @@ -195,6 +233,27 @@ } }, "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { "inputs": { "nixpkgs": [ "mailserver", @@ -219,8 +278,8 @@ "mailserver": { "inputs": { "blobs": "blobs", - "flake-compat": "flake-compat_2", - "git-hooks": "git-hooks", + "flake-compat": "flake-compat_3", + "git-hooks": "git-hooks_2", "nixpkgs": "nixpkgs_2" }, "locked": { @@ -381,6 +440,7 @@ "inputs": { "authentik": "authentik", "disko": "disko", + "git-hooks": "git-hooks", "mailserver": "mailserver", "nixpkgs": "nixpkgs_3", "sops": "sops" diff --git a/flake.nix b/flake.nix index f9b55f5..bdbebd3 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,10 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + git-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = @@ -28,6 +32,7 @@ mailserver, disko, sops, + git-hooks, }: let sshkeys = [ @@ -38,6 +43,39 @@ in rec { formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt-rfc-style; + + devShells.x86_64-linux.default = + let + pkgs = nixpkgs.legacyPackages.x86_64-linux; + pre-commit-check = git-hooks.lib.x86_64-linux.run { + src = ./.; + hooks = { + nixfmt-rfc-style.enable = true; + }; + }; + in + pkgs.mkShell { + # Import GPG keys from keys directory + sopsPGPKeyDirs = [ + "${toString ./.}/keys/hosts" + "${toString ./.}/keys/users" + ]; + + # Isolate sops GPG keys to .git/gnupg (optional) + # sopsCreateGPGHome = true; + + shellHook = '' + ${pre-commit-check.shellHook} + ''; + + nativeBuildInputs = [ + sops.packages.x86_64-linux.sops-import-keys-hook + ]; + + buildInputs = pre-commit-check.enabledPackages ++ [ + pkgs.sops + ]; + }; packages.x86_64-linux = builtins.foldl' ( @@ -47,7 +85,13 @@ # run nixos-rebuild switch on the target system # the config will be built locally and copied over "${name}-update" = nixpkgs.legacyPackages.x86_64-linux.writeShellScriptBin "update" '' - nixos-rebuild switch --flake .#${name} --target-host root@${(builtins.head (nixosConfigurations.${name}.config.networking.interfaces.${builtins.head (builtins.attrNames nixosConfigurations.${name}.config.networking.interfaces)}.ipv4.addresses)).address} + nixos-rebuild switch --flake .#${name} --target-host root@${ + (builtins.head ( + nixosConfigurations.${name}.config.networking.interfaces.${ + builtins.head (builtins.attrNames nixosConfigurations.${name}.config.networking.interfaces) + }.ipv4.addresses + )).address + } ''; } ) diff --git a/keys/.gitignore b/keys/.gitignore new file mode 100644 index 0000000..ce29a38 --- /dev/null +++ b/keys/.gitignore @@ -0,0 +1,18 @@ +# Prevent accidental commit of private keys +*.key +*.priv +*.private +*_priv +*-priv +*.sec +*secret* + +# Only allow public keys +!*.asc +!*.gpg +!*.pub +!*.age + +# Allow this gitignore and README +!.gitignore +!README.md diff --git a/keys/README.md b/keys/README.md new file mode 100644 index 0000000..587f370 --- /dev/null +++ b/keys/README.md @@ -0,0 +1,40 @@ +# Keys Directory + +This directory contains GPG/age public keys for sops encryption. + +## Structure + +- `hosts/` - Host-specific public keys (for servers to decrypt their own secrets) +- `users/` - User/admin public keys (for team members to decrypt secrets) + +## Adding Keys + +### GPG Keys + +Export your GPG public key: +```bash +gpg --export --armor YOUR_KEY_ID > keys/users/yourname.asc +``` + +Export a host's public key: +```bash +gpg --export --armor HOST_KEY_ID > keys/hosts/hostname.asc +``` + +### Age Keys + +For age keys, save the public key to a file: +```bash +echo "age1..." > keys/users/yourname.age +echo "age1..." > keys/hosts/hostname.age +``` + +## Usage + +When you enter the dev shell (`nix develop`), all keys in these directories will be automatically imported into your GPG keyring via the sops-import-keys-hook. + +## Important + +- Only commit **public** keys (.asc, .age files with public keys) +- Never commit private keys +- Update `.sops.yaml` to reference the fingerprints/keys for access control diff --git a/keys/hosts/.gitkeep b/keys/hosts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/keys/users/.gitkeep b/keys/users/.gitkeep new file mode 100644 index 0000000..e69de29