commit a89275f163af744337727fe2f1c5713248a8da41 Author: Nikkuss Date: Tue Feb 3 14:59:16 2026 +0400 init diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdf11bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +/.direnv +/result diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..5fa2c30 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,36 @@ +keys: + - &laptop-laptop age1z9h9dsza2uj3gu795w99r4ze976e0pedc9m00qf6qmw3js5edy7s5qrk28 + - &laptop-laptop-home age1cadp26evf04t7hjrk3yqn05hl72kwv5luzc6mc096rsf2jac3dvsmka8xp + - &laptop-linux age1rqlpv63rkjkty3np7ksagwlq6fkx35x7tq6tmrdxk0ue205dmguqg79sq7 + - &server-old-server-old age18zntyz5vjf8eky95xmm27qct53prrt2pkjst5fgj9h959n20e9tskhf3pt + - &server-server age1pxw0y3z2n5gj0s07hacvr48yvlhhgnfxsnpj958cy823j05eu9sqgm2hjr + - &wawa-wawa age14l694p4kht0d5vr72vvw6d9gvynq0dpm5lmqf6ugwv3dkf09w5qsrz0v6v + - &wawa-wawa-home age1rsczygcq6kqvfc2c5yqw5plw35r6vey8r2n9qm42q744u38auesssu6vx7 + - &raspi-raspi age1d290xw09nkdv6fmenst8sp9uyeppkn2dg9yh4yh2d35gnxfvl45qs4up96 + - &bhyve-vm-bhyve-vm1 age1gw58chzlp0yxfmadkp7d5m4qveqqm6ysws39qekwlren9snu830s98axw3 +creation_rules: + - path_regex: secrets/.+\.(yaml|json|env|ini|bin)$ + key_groups: + - age: + - *laptop-laptop + - *laptop-laptop-home + - *laptop-linux + - *wawa-wawa + - *wawa-wawa-home + - *raspi-raspi + - *server-server + - *server-old-server-old + - *bhyve-vm-bhyve-vm1 + + - path_regex: secrets/.+\.(yaml|json|env|ini|bin)$ + key_groups: + - age: + - *laptop-laptop + - *laptop-laptop-home + - *laptop-linux + - *wawa-wawa + - *wawa-wawa-home + - *raspi-raspi + - *server-server + - *server-old-server-old + - *bhyve-vm-bhyve-vm1 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c9ffee9 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1768135262, + "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1758198701, + "narHash": "sha256-7To75JlpekfUmdkUZewnT6MoBANS0XVypW6kjUOXQwc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0147c2f1d54b30b5dd6d4a8c8542e8d7edf93b5d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1765674936, + "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a6f5730 --- /dev/null +++ b/flake.nix @@ -0,0 +1,89 @@ +{ + description = "A very basic flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + + # crane.url = "github:ipetkov/crane"; + # flake-utils.url = "github:numtide/flake-utils"; + # rust-overlay = { + # url = "github:oxalica/rust-overlay"; + # inputs.nixpkgs.follows = "nixpkgs"; + # }; + }; + outputs = + { flake-parts, ... }@inputs: + flake-parts.lib.mkFlake { inherit inputs; } { + flake.flakeModules.default = ./nix/flakeModule.nix; + }; + + # outputs = + # { + # nixpkgs, + # crane, + # flake-utils, + # rust-overlay, + # ... + # }: + # flake-utils.lib.eachDefaultSystem ( + # system: + # let + # pkgs = import nixpkgs { + # inherit system; + # overlays = [ + # (import rust-overlay) + # ]; + # }; + # inherit (pkgs) lib; + # + # craneLib = (crane.mkLib pkgs).overrideToolchain ( + # p: + # p.rust-bin.nightly.latest.default.override { + # extensions = [ + # "rustc-codegen-cranelift-preview" + # "rust-analyzer" + # "rust-src" + # ]; + # } + # ); + # src = craneLib.cleanCargoSource ./.; + # commonArgs = { + # inherit src; + # strictDeps = true; + # }; + # cargoArtifacts = craneLib.buildDepsOnly commonArgs; + # individualCrateArgs = commonArgs // { + # inherit cargoArtifacts; + # inherit (craneLib.crateNameFromCargoToml { inherit src; }) version; + # }; + # + # fileSetForCrate = + # crate: + # lib.fileset.toSource { + # root = ./.; + # fileset = lib.fileset.unions [ + # ./Cargo.toml + # ./Cargo.lock + # ]; + # }; + # server = craneLib.buildPackage ( + # individualCrateArgs + # // { + # } + # ); + # in + # { + # devShells.default = craneLib.devShell { + # packages = with pkgs; [ + # mold + # llvmPackages.clang + # llvmPackages.lld + # sea-orm-cli + # watchexec + # pnpm + # ]; + # }; + # } + # ); +} diff --git a/nix/flakeModule.nix b/nix/flakeModule.nix new file mode 100644 index 0000000..8223611 --- /dev/null +++ b/nix/flakeModule.nix @@ -0,0 +1,149 @@ +{ + config, + lib, + flake-parts-lib, + inputs, + den, + ... +}: +let + inherit (lib) mkOption types; + cfg = config.secrets; +in +{ + options.secrets = { + masterKeys = mkOption { + type = types.listOf types.str; + default = [ ]; + description = "A list of master keys for encrypting secrets."; + }; + secretsDir = mkOption { + type = types.str; + default = null; + description = "Path to the directory containing secrets relative to flake root."; + }; + formatter = mkOption { + type = lib.types.functionTo lib.types.unspecified; + default = pkgs: pkgs.prettier; + description = "The formatter function to use for formatting sops file"; + }; + nixosModule = mkOption { + type = types.deferredModule; + readOnly = true; + description = "NixOS module configuration for managing sops secrets."; + }; + }; + + config = + let + secrets = builtins.fromJSON (builtins.readFile "${inputs.self}/${cfg.secretsDir}/secrets.json"); + all_keys = lib.flatten (lib.concatAttrValues per_host_keys); + per_host_keys = lib.mergeAttrsList ( + lib.flatten ( + map ( + x: + builtins.mapAttrs ( + name: value: + let + v = value.sopsPublic or [ ]; + type = builtins.typeOf v; + vv = + if type == "string" then + [ v ] + else if type == "list" then + v + else + throw "Unexpected type ${type} for sopsPublic in host ${name}"; + in + vv + ) x + ) (builtins.attrValues den.hosts) + ) + ); + secret_map = lib.mapAttrs ( + name: value: + let + keys = lib.unique ( + lib.flatten (map (k: per_host_keys.${k}) value.hosts) + ++ (lib.optionals value.global all_keys) + ++ cfg.masterKeys + ); + in + { + inherit (value) + format + neededForUsers + hosts + global + ; + inherit keys; + } + ) secrets; + rules = lib.mapAttrsToList (name: value: { + path_regex = "${cfg.secretsDir}/${name}$"; + key_groups = [ { age = value.keys; } ]; + }) secret_map; + sops_secrets_map = lib.concatMapAttrs ( + name: value: + let + hasHost = (lib.elem "wawa" value.hosts) || value.global; + in + if hasHost then + { + ${name} = { + inherit (value) format neededForUsers; + sopsFile = inputs.self + "/${cfg.secretsDir}/${name}"; + }; + } + else + { } + ) secret_map; + in + { + secrets.nixosModule = + { ... }: + { + config.sops.secrets = sops_secrets_map; + }; + perSystem = + { pkgs, self', ... }: + let + formatted = + let + unformatted = (pkgs.formats.yaml { }).generate ".sops.yaml" { + creation_rules = rules; + }; + in + pkgs.stdenvNoCC.mkDerivation { + name = ".sops-yaml-formatted"; + src = unformatted; + phases = [ "format" ]; + format = '' + cp $src .sops.yaml + chmod +w .sops.yaml + ${lib.getExe (cfg.formatter pkgs)} .sops.yaml + cp .sops.yaml $out + ''; + }; + in + { + packages.write-sops-config = pkgs.writeShellApplication { + name = "write-sops-config"; + text = '' + cp ${formatted} .sops.yaml + find ${cfg.secretsDir} -type f ! -name "secrets.json" -exec ${pkgs.lib.getExe pkgs.sops} updatekeys -y {} \; + ''; + }; + checks.check-sops-config = + pkgs.runCommand "check-sops-config" + { + nativeBuildInputs = [ pkgs.diffutils ]; + } + '' + set -e + diff -u ${inputs.self}/.sops.yaml ${formatted} + touch $out + ''; + }; + }; +} diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 0000000..9afb14e --- /dev/null +++ b/treefmt.nix @@ -0,0 +1,14 @@ +{ rust-toolchain }: +{ pkgs, ... }: +{ + # Used to find the project root + projectRootFile = "flake.nix"; + # Enable the terraform formatter + programs = { + nixfmt.enable = true; + rustfmt.enable = true; + rustfmt.package = rust-toolchain pkgs; + leptosfmt.enable = true; + taplo.enable = true; + }; +}