diff --git a/bin/secret-translator.jl b/bin/secret-translator.jl deleted file mode 100644 index ce50af8..0000000 --- a/bin/secret-translator.jl +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env julia -using TOML: TOML - -function remove_podman_secrets() - run(`podman secret rm --all`) - return nothing -end #function - -function create_podman_secret(name, secret) - run( - Cmd( - `podman secret create --env=true --replace $name SECRET`; - env = Dict("SECRET" => secret), - ), - ) - return nothing -end #function - -function parse_toml_secrets(file) - foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) - return nothing -end #function - -function main() - remove_podman_secrets() - foreach(parse_toml_secrets, ARGS) - return 0 -end #function - -main() diff --git a/flake.nix b/flake.nix index 204941e..a703651 100644 --- a/flake.nix +++ b/flake.nix @@ -138,13 +138,9 @@ "mcentire" = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { - home-manager-quadlet-nix = quadlet-nix.homeManagerModules.quadlet; - }; modules = [ ./systems/linux/mcentire.nix agenix.nixosModules.default - home-manager.nixosModules.home-manager quadlet-nix.nixosModules.quadlet crowdsec.nixosModules.crowdsec crowdsec.nixosModules.crowdsec-firewall-bouncer diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix deleted file mode 100644 index 41a01c5..0000000 --- a/modules/podman-secrets.nix +++ /dev/null @@ -1,154 +0,0 @@ -# Warning to my future self: This module was "vibe coded" by Claude Sonnet 4.5. -# I originally had a hand-written module in here that did the secrets -# translation as the root user. I knew that I would want to support multiple -# secrets files and multiple users, and thought I should be able to create an -# arbitrary number of them, similar to how you can have an arbitrary number -# of `programs.firefox.profiles`. Unfortunately, even after looking at lots of -# example modules, I could not figure out the syntax (Nix has a serious lack -# of minimum working examples), so I broke down and asked Claude to rewrite it -# for me. Based on everything that I read, this seems to be exactly what I asked -# for. -# -# Here is the prompt I used to get here: -# [@Per service isolation on NixOS with Traefik](zed:///agent/thread/94cb8a22-ff0c-4772-a1a1-018b0107f334?name=Per+service+isolation+on+NixOS+with+Traefik) -# -# [@podman-secrets.nix](file:///home/millironx/.config/home-manager/modules/podman-secrets.nix) -# -# I originally wrote this module assuming that I would use Podman as root for -# all containers. I would like to fix the module to have as many secrets files -# processed as needed with services setup for each secret that is run as the -# appropriate user. Ideally, the syntax for working with secrets to be -# translated would be -# -# ```nix -# { config, ... }: { -# age.secrets = { -# "caddy.toml" = { -# file = ./../secrets/caddy.toml.age; -# owner = "caddy"; -# group = "caddy"; -# }; -# -# "authentik.toml" = { -# file = ./../secrets/authentik.toml.age; -# owner = "authentik"; -# group = "authentik"; -# }; -# -# "freshrss.toml" = { -# file = ./../secrets/freshrss.toml.age; -# owner = "freshrss"; -# group = "freshrss"; -# }; -# }; -# -# millironx.podman-secrets = with config; { -# caddy = { -# user = "caddy"; -# secrets-files = [ -# ./../not-really-secret.toml -# age.secrets."caddy.toml".path -# ]; -# }; -# authentik = { -# user = "authentik"; -# secrets-files = [ -# age.secrets."authentik.toml".path -# ]; -# }; -# freshrss = { -# user = "freshrss"; -# secrets-files = [ -# age.secrets."freshrss.toml".path -# ]; -# }; -# }; -# } -# ``` -# -# Can you help me rewrite the module to accomplish this? -# -{ config, lib, pkgs, ... }: -with lib; -let - cfg = config.millironx.podman-secrets; - - secret-translator = pkgs.writeScriptBin "secret-translator" - (builtins.readFile ./../bin/secret-translator.jl); - - # Submodule type for each service's secrets configuration - serviceSecretsType = types.submodule { - options = { - user = mkOption { - type = types.str; - description = "User account to run the secrets translation service as"; - example = "caddy"; - }; - - secrets-files = mkOption { - type = types.listOf (types.either types.path types.string); - description = - "List of TOML files containing secrets to translate to Podman secrets"; - example = literalExpression '' - [ - "/run/agenix/caddy.toml" - ./../not-really-secret.toml - ] - ''; - default = [ ]; - }; - }; - }; - - # Generate a systemd service for each configured service - mkSecretsService = name: serviceCfg: - nameValuePair "podman-secrets-${name}" { - description = "Podman secrets converter service for ${name}"; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Type = "oneshot"; - User = serviceCfg.user; - ExecStart = "${secret-translator}/bin/secret-translator ${ - lib.concatStringsSep " " serviceCfg.secrets-files - }"; - Path = [ "${pkgs.podman}/bin" "${pkgs.julia-lts-bin}/bin" ]; - }; - }; - - # Filter out services with no secrets-files - enabledServices = - lib.filterAttrs (name: serviceCfg: serviceCfg.secrets-files != [ ]) cfg; - -in { - options.millironx.podman-secrets = mkOption { - type = types.attrsOf serviceSecretsType; - description = '' - Per-service Podman secrets configuration. - Each attribute creates a separate systemd service that translates TOML secrets - files into Podman secrets for the specified user. - ''; - example = literalExpression '' - { - caddy = { - user = "caddy"; - secrets-files = [ - ./../not-really-secret.toml - config.age.secrets."caddy.toml".path - ]; - }; - authentik = { - user = "authentik"; - secrets-files = [ - config.age.secrets."authentik.toml".path - ]; - }; - } - ''; - default = { }; - }; - - config = mkIf (enabledServices != { }) { - systemd.services = lib.mapAttrs' mkSecretsService enabledServices; - }; -} diff --git a/secrets.nix b/secrets.nix index 8042bf6..1de9bc8 100644 --- a/secrets.nix +++ b/secrets.nix @@ -26,8 +26,6 @@ let in { "secrets/ansible-vault-password.age".publicKeys = system-administrators; - "secrets/authentik.toml.age".publicKeys = system-administrators - ++ [ mcentire-host ]; "secrets/borgmatic-passphrase.age".publicKeys = system-administrators ++ [ mcentire-host ]; "secrets/borgmatic-ssh-config.age".publicKeys = system-administrators diff --git a/secrets/authentik.toml.age b/secrets/authentik.toml.age deleted file mode 100644 index 1ef8f6e..0000000 Binary files a/secrets/authentik.toml.age and /dev/null differ diff --git a/services/authentik.nix b/services/authentik.nix deleted file mode 100644 index 30ee781..0000000 --- a/services/authentik.nix +++ /dev/null @@ -1,128 +0,0 @@ -{ config, home-manager-quadlet-nix, ... }: -let - user = "authentik"; - state-directory = "/var/lib/authentik"; - port = "9000"; - -in { - # Secrets are translated in the system scope, but performed by the user, - # so are available in the user's Podman secrets - age.secrets = { - "authentik.toml" = { - file = ./../secrets/authentik.toml.age; - owner = "${user}"; - }; - }; - - millironx.podman-secrets.authentik = { - user = "${user}"; - secrets-files = [ config.age.secrets."authentik.toml".path ]; - }; - - systemd.tmpfiles.rules = [ "d ${state-directory} 1775 ${user} ${user} -" ]; - - services.caddy.virtualHosts."auth.millironx.com".extraConfig = '' - reverse_proxy http://127.0.0.1:${port} - ''; - - # Create a dedicated user for this service - users.users."${user}" = { - group = "${user}"; - isSystemUser = true; - linger = true; - autoSubUidGidRange = true; - }; - users.groups."${user}" = {}; - - home-manager.users."${user}" = { config, ... }: { - imports = [ home-manager-quadlet-nix ]; - - home.stateVersion = "25.05"; - - virtualisation.quadlet.containers = { - authentik-db = { - autoStart = true; - containerConfig = { - image = "docker.io/library/postgres:16"; - environments = { - POSTGRES_DB = "${user}"; - POSTGRES_USER = "${user}"; - }; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=POSTGRES_PASSWORD" - ]; - healthCmd = "pg_isready -d \${POSTGRES_DB} -U \${POSTGRES_USER}"; - healthInterval = "30s"; - healthRetries = 5; - healthStartPeriod = "20s"; - volumes = [ "${state-directory}/database:/var/lib/postgresql/data" ]; - }; - }; - - authentik-worker = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - exec = "worker"; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - ]; - volumes = [ - "${state-directory}/media:/media" - "${state-directory}/custom-templates:/templates" - "${state-directory}/certs:/certs" - ]; - }; - unitConfig.Requires = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - unitConfig.After = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - }; - - authentik = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - "AUTHENTIK_EMAIL__HOST,type=env" - "AUTHENTIK_EMAIL__PORT,type=env" - "AUTHENTIK_EMAIL__USERNAME,type=env" - "AUTHENTIK_EMAIL__PASSWORD,type=env" - "AUTHENTIK_EMAIL__USE_SSL,type=env" - "AUTHENTIK_EMAIL__FROM,type=env" - ]; - publishPorts = [ "127.0.0.1:${port}:${port}" ]; - volumes = [ - "${state-directory}/media:/media" - "${state-directory}/custom-templates:/templates" - ]; - }; - unitConfig.Requires = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - unitConfig.After = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - }; - }; - }; -} diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 4a1b09a..60fd158 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -3,11 +3,9 @@ { imports = [ # Include the results of the hardware scan. ./hardware-configuration/mcentire.nix - ./../../modules/podman-secrets.nix ./../../services/nixos-update.nix ./../../services/borgmatic.nix ./../../services/crowdsec.nix - ./../../services/authentik.nix ]; # Use the GRUB 2 boot loader. @@ -18,7 +16,6 @@ useDHCP = false; interfaces.eth0.useDHCP = true; hostName = "mcentire"; # Define your hostname. - firewall.allowedTCPPorts = [ 80 443 ]; }; # Set your time zone. @@ -58,11 +55,8 @@ services = { openssh.enable = true; tailscale.enable = true; - caddy.enable = true; }; - virtualisation.quadlet.enable = true; - system.stateVersion = "25.05"; # Did you read the comment? nix = { extraOptions = "experimental-features = nix-command flakes"; }; }