From 5bf58e1ff4695750c5f8931d8cf46a5125bb3461 Mon Sep 17 00:00:00 2001 From: FileMagic Date: Fri, 17 Jul 2026 23:21:18 -0400 Subject: [PATCH] agenix: add secret management with agenix - Add agenix flake input - Add NixOS module to both hosts - Create modules/secrets.nix with age identity config - Create secrets/ directory with .gitkeep - Add devShell with agenix CLI - Ignore .age files in git --- .gitignore | 6 +- 13-inch-thin-cannon/configuration.nix | 3 +- flake.lock | 129 +++++++++++- flake.nix | 24 +++ modules/firefox.nix | 282 +++++++++++--------------- modules/secrets.nix | 11 + secrets/.gitkeep | 0 thick-black-cannon/configuration.nix | 1 + 8 files changed, 294 insertions(+), 162 deletions(-) create mode 100644 modules/secrets.nix create mode 100644 secrets/.gitkeep diff --git a/.gitignore b/.gitignore index b3c7c95..e84056c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # OpenTofu *.tfstate* -.terraform/ +kubernetes/.terraform/ # OpenCode opencode.json @@ -20,3 +20,7 @@ kubernetes/ssh-key # Generated Ansible inventory kubernetes/ansible/inventory.ini + +# age-encrypted secrets +secrets/*.age +!secrets/.gitkeep diff --git a/13-inch-thin-cannon/configuration.nix b/13-inch-thin-cannon/configuration.nix index 973dc0b..158a28e 100644 --- a/13-inch-thin-cannon/configuration.nix +++ b/13-inch-thin-cannon/configuration.nix @@ -12,6 +12,7 @@ { imports = [ ./hardware-configuration.nix + ../modules/secrets.nix ] ++ lib.optional (builtins.pathExists ./wireguard.nix) ./wireguard.nix; nix.settings.experimental-features = [ @@ -23,7 +24,7 @@ boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; - networking.hostName = "nixos"; # Define your hostname. + networking.hostName = "13-inch-thin-cannon"; # Define your hostname. #networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. #networking.wireless.networks = { # "Fios-BKP8q" = { # SSID with spaces and/or special characters diff --git a/flake.lock b/flake.lock index 9acfdff..f5fdf0b 100644 --- a/flake.lock +++ b/flake.lock @@ -1,6 +1,93 @@ { "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1770165109, + "narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=", + "owner": "ryantm", + "repo": "agenix", + "rev": "b027ee29d959fda4b60b57566d64c98a202e0feb", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -36,10 +123,48 @@ "type": "github" } }, + "nur": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784238397, + "narHash": "sha256-Reg7V0xbZMwdwtoJ/x1fKGwV025TaERfaZQXchfCNVw=", + "owner": "nix-community", + "repo": "NUR", + "rev": "c2b1b330618d210442be4776a504cc08422d8483", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, "root": { "inputs": { - "home-manager": "home-manager", - "nixpkgs": "nixpkgs" + "agenix": "agenix", + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs", + "nur": "nur" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 5131254..48aaa17 100644 --- a/flake.nix +++ b/flake.nix @@ -7,6 +7,14 @@ url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; + nur = { + url = "github:nix-community/NUR"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = @@ -14,11 +22,19 @@ self, nixpkgs, home-manager, + nur, + agenix, ... }: let lib = nixpkgs.lib; system = "x86_64-linux"; + nurOverlay = final: prev: { + nur = import nur { + nurpkgs = import nixpkgs { system = final.system; }; + pkgs = final; + }; + }; in { checks."${system}" = { @@ -26,11 +42,16 @@ "13-inch-thin-cannon" = self.nixosConfigurations."13-inch-thin-cannon".config.system.build.toplevel; }; + devShells."${system}".default = nixpkgs.legacyPackages.${system}.mkShell { + packages = [ agenix.packages."${system}".agenix ]; + }; + nixosConfigurations = { thick-black-cannon = lib.nixosSystem { inherit system; modules = [ ./thick-black-cannon/configuration.nix + agenix.nixosModules.age home-manager.nixosModules.default { home-manager = { @@ -43,6 +64,7 @@ "/share/applications" "/share/xdg-desktop-portal" ]; + nixpkgs.overlays = [ nurOverlay ]; nixpkgs.config = { allowUnfree = true; permittedInsecurePackages = [ "electron-39.8.10" ]; @@ -55,6 +77,7 @@ inherit system; modules = [ ./13-inch-thin-cannon/configuration.nix + agenix.nixosModules.age home-manager.nixosModules.default { home-manager = { @@ -67,6 +90,7 @@ "/share/applications" "/share/xdg-desktop-portal" ]; + nixpkgs.overlays = [ nurOverlay ]; nixpkgs.config = { allowUnfree = true; permittedInsecurePackages = [ "electron-39.8.10" ]; diff --git a/modules/firefox.nix b/modules/firefox.nix index b28aade..8297c6d 100644 --- a/modules/firefox.nix +++ b/modules/firefox.nix @@ -2,10 +2,10 @@ pkgs, lib, ... -}: -{ +}: { programs.firefox = { enable = true; + configPath = ".mozilla/firefox"; # ---- Policies (locked, can't be overridden in about:config) ---- policies = { @@ -35,183 +35,68 @@ StartDownloadsInTempDirectory = true; }; - # ---- Preferences (can be overridden) ---- - preferences = { - # HTTPS-only - "dom.security.https_only_mode" = true; - "dom.security.https_only_mode_pbm" = true; - "dom.security.https_only_mode_send_http_background_request" = false; - - # DNS over HTTPS - "network.trr.mode" = 3; - "network.trr.uri" = "https://mozilla.cloudflare-dns.com/dns-query"; - "network.trr.bootstrapAddress" = "1.1.1.1"; - - # Privacy / Tracking - "privacy.trackingprotection.fingerprinting.enabled" = true; - "privacy.trackingprotection.cryptomining.enabled" = true; - "privacy.trackingprotection.enabled" = true; - "privacy.resistFingerprinting" = true; - "privacy.firstparty.isolate" = true; - - # Sanitize on shutdown - "privacy.clearOnShutdown.cache" = true; - "privacy.clearOnShutdown.cookies" = true; - "privacy.clearOnShutdown.history" = false; - "privacy.clearOnShutdown.sessions" = true; - "privacy.sanitize.sanitizeOnShutdown" = true; - - # WebRTC — prevent local IP leak - "media.peerconnection.ice.default_address_only" = true; - "media.peerconnection.ice.no_host" = true; - - # OCSP / Certificate checks - "security.OCSP.enabled" = 1; - "security.OCSP.require" = true; - "security.ssl.enable_ocsp_stapling" = true; - "security.certerrors.mitm.auto_enable_enterprise_roots" = false; - "security.certerror.hideAddException" = true; - - # Safe browsing - "browser.safebrowsing.downloads.enabled" = true; - "browser.safebrowsing.malware.enabled" = true; - "browser.safebrowsing.phishing.enabled" = true; - - # Referrer - "network.http.referer.XOriginPolicy" = 2; - "network.http.referer.XOriginTrimmingPolicy" = 2; - - # Clipboard / Permission prompts - "dom.events.asyncClipboard.readText" = false; - "permissions.default.camera" = 2; - "permissions.default.microphone" = 2; - "permissions.default.location" = 2; - "permissions.default.notifications" = 2; - "permissions.default.geo" = 2; - - # Disable password saving (policy handles the prompt, this kills storage) - "signon.rememberSignons" = false; - "signon.autofillForms" = false; - "signon.formlessCapture.enabled" = false; - - # Appearance - "browser.theme.toolbar-theme" = 0; - "ui.systemUsesDarkTheme" = 1; - "browser.compactmode.show" = true; - - # UI tweaks - "browser.uidensity" = 1; - "browser.toolbars.bookmarks.visibility" = "always"; - "browser.urlbar.suggest.history" = false; - "browser.urlbar.suggest.bookmark" = true; - "browser.urlbar.suggest.topsites" = false; - "browser.urlbar.quickaction.enabled" = true; - "extensions.pocket.enabled" = false; - - # Downloads - "browser.download.useDownloadDir" = true; - "browser.download.alwaysOpenPanel" = false; - - # Media - "media.autoplay.default" = 5; - "media.autoplay.enabled" = false; - "media.videocontrols.picture-in-picture.video-toggle.enabled" = true; - - # Developer tools - "devtools.toolbox.host" = "right"; - "devtools.inspector.showUserAgentStyles" = false; - }; - - # ---- Extensions ---- - extensions = with pkgs.nur.repos.rycee.firefox-addons; [ - ublock-origin - bitwarden - vimium - istilldontcareaboutcookies - darkreader - sponsorblock - return-youtube-dislikes - ]; - # ---- Default profile ---- profiles.default = { id = 0; name = "default"; isDefault = true; + extensions = with pkgs.nur.repos.rycee.firefox-addons; { + packages = [ + ublock-origin + bitwarden + vimium + istilldontcareaboutcookies + darkreader + sponsorblock + return-youtube-dislikes + ]; + }; + search = { force = true; - default = "DuckDuckGo"; + default = "ddg"; engines = { "Nix Packages" = { - urls = [ - { - template = "https://search.nixos.org/packages"; - params = [ - { - name = "type"; - value = "packages"; - } - { - name = "query"; - value = "{searchTerms}"; - } - ]; - } - ]; + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; definedAliases = [ "@np" ]; }; "Nix Options" = { - urls = [ - { - template = "https://search.nixos.org/options"; - params = [ - { - name = "type"; - value = "options"; - } - { - name = "query"; - value = "{searchTerms}"; - } - ]; - } - ]; + urls = [{ + template = "https://search.nixos.org/options"; + params = [ + { name = "type"; value = "options"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; definedAliases = [ "@no" ]; }; "Nix Flakes" = { - urls = [ - { - template = "https://search.nixos.org/flakes"; - params = [ - { - name = "type"; - value = "flakes"; - } - { - name = "query"; - value = "{searchTerms}"; - } - ]; - } - ]; + urls = [{ + template = "https://search.nixos.org/flakes"; + params = [ + { name = "type"; value = "flakes"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; definedAliases = [ "@nf" ]; }; "Home Manager Options" = { - urls = [ - { - template = "https://home-manager-options.extranix.com"; - params = [ - { - name = "query"; - value = "{searchTerms}"; - } - ]; - } - ]; + urls = [{ + template = "https://home-manager-options.extranix.com"; + params = [ + { name = "query"; value = "{searchTerms}"; } + ]; + }]; icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; definedAliases = [ "@hm" ]; }; @@ -219,8 +104,89 @@ }; settings = { - # Let the policy handle this instead + # HTTPS-only + "dom.security.https_only_mode" = true; + "dom.security.https_only_mode_pbm" = true; + "dom.security.https_only_mode_send_http_background_request" = false; + + # DNS over HTTPS + "network.trr.mode" = 3; + "network.trr.uri" = "https://mozilla.cloudflare-dns.com/dns-query"; + "network.trr.bootstrapAddress" = "1.1.1.1"; + + # Privacy / Tracking + "privacy.trackingprotection.fingerprinting.enabled" = true; + "privacy.trackingprotection.cryptomining.enabled" = true; + "privacy.trackingprotection.enabled" = true; + "privacy.resistFingerprinting" = true; + "privacy.firstparty.isolate" = true; + + # Sanitize on shutdown + "privacy.clearOnShutdown.cache" = true; + "privacy.clearOnShutdown.cookies" = true; + "privacy.clearOnShutdown.history" = false; + "privacy.clearOnShutdown.sessions" = true; + "privacy.sanitize.sanitizeOnShutdown" = true; + + # WebRTC — prevent local IP leak + "media.peerconnection.ice.default_address_only" = true; + "media.peerconnection.ice.no_host" = true; + + # OCSP / Certificate checks + "security.OCSP.enabled" = 1; + "security.OCSP.require" = true; + "security.ssl.enable_ocsp_stapling" = true; + "security.certerrors.mitm.auto_enable_enterprise_roots" = false; + "security.certerror.hideAddException" = true; + + # Safe browsing + "browser.safebrowsing.downloads.enabled" = true; + "browser.safebrowsing.malware.enabled" = true; + "browser.safebrowsing.phishing.enabled" = true; + + # Referrer + "network.http.referer.XOriginPolicy" = 2; + "network.http.referer.XOriginTrimmingPolicy" = 2; + + # Clipboard / Permission prompts + "dom.events.asyncClipboard.readText" = false; + "permissions.default.camera" = 2; + "permissions.default.microphone" = 2; + "permissions.default.location" = 2; + "permissions.default.notifications" = 2; + "permissions.default.geo" = 2; + + # Disable password saving + "signon.rememberSignons" = false; + "signon.autofillForms" = false; + "signon.formlessCapture.enabled" = false; + + # Appearance + "browser.theme.toolbar-theme" = 0; + "ui.systemUsesDarkTheme" = 1; + "browser.compactmode.show" = true; + + # UI tweaks + "browser.uidensity" = 1; + "browser.toolbars.bookmarks.visibility" = "always"; + "browser.urlbar.suggest.history" = false; + "browser.urlbar.suggest.bookmark" = true; + "browser.urlbar.suggest.topsites" = false; + "browser.urlbar.quickaction.enabled" = true; + "extensions.pocket.enabled" = false; + + # Downloads + "browser.download.useDownloadDir" = true; "browser.download.alwaysOpenPanel" = false; + + # Media + "media.autoplay.default" = 5; + "media.autoplay.enabled" = false; + "media.videocontrols.picture-in-picture.video-toggle.enabled" = true; + + # Developer tools + "devtools.toolbox.host" = "right"; + "devtools.inspector.showUserAgentStyles" = false; }; }; }; diff --git a/modules/secrets.nix b/modules/secrets.nix new file mode 100644 index 0000000..41101ef --- /dev/null +++ b/modules/secrets.nix @@ -0,0 +1,11 @@ +{ + config, + pkgs, + lib, + ... +}: { + age = { + identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; + secrets = { }; + }; +} diff --git a/secrets/.gitkeep b/secrets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/thick-black-cannon/configuration.nix b/thick-black-cannon/configuration.nix index 4b0f39a..f9c7f2b 100644 --- a/thick-black-cannon/configuration.nix +++ b/thick-black-cannon/configuration.nix @@ -11,6 +11,7 @@ { imports = [ ./hardware-configuration.nix + ../modules/secrets.nix ] ++ lib.optional (builtins.pathExists ./wireguard.nix) ./wireguard.nix; -- 2.51.2