diff --git a/flakes/common/hm_modules/tmux/default.nix b/flakes/common/hm_modules/tmux/default.nix index 6d67f512..3b11d0ed 100644 --- a/flakes/common/hm_modules/tmux/default.nix +++ b/flakes/common/hm_modules/tmux/default.nix @@ -30,7 +30,7 @@ }; }); extraConfig = '' - set -g @catppuccin_flavour 'mocha' + set -g @catppuccin_flavor 'mocha' set -g @catppuccin_window_left_separator "" set -g @catppuccin_window_right_separator " " set -g @catppuccin_window_middle_separator " █" diff --git a/flakes/secrets-bao/nixos-module.nix b/flakes/secrets-bao/nixos-module.nix index 1538c859..08a46cd1 100644 --- a/flakes/secrets-bao/nixos-module.nix +++ b/flakes/secrets-bao/nixos-module.nix @@ -488,84 +488,181 @@ in sec ]; - systemd.tmpfiles.rules = [ - "d /run/openbao 0700 root root - -" - "f /run/openbao/zitadel.jwt 0400 root root - -" - "d /run/secrets 0711 root root - -" - ]; + systemd.tmpfiles.rules = + [ + "d /run/openbao 0700 root root - -" + "f /run/openbao/zitadel.jwt 0400 root root - -" + "d /run/secrets 0711 root root - -" + ] + # Create empty placeholder files for all secret destinations so + # services that reference env files don't fail when offline. + ++ (lib.unique ( + lib.concatLists ( + lib.mapAttrsToList ( + _: secret: + let + dir = builtins.dirOf secret.path; + in + # Ensure the parent dir exists if a custom path is used. + [ "d ${dir} 0755 root root - -" ] + ) cfg.secrets + ) + )) + ++ (lib.mapAttrsToList ( + _: secret: + "f ${secret.path} ${secret.mode} ${secret.owner} ${secret.group} - -" + ) cfg.secrets); - systemd.paths = lib.mapAttrs' ( - name: secret: - lib.nameValuePair "openbao-secret-${name}" { - description = "Path unit for OpenBao secret ${name}"; - wantedBy = [ "multi-user.target" ]; - pathConfig = { - PathChanged = secret.path; - Unit = "openbao-secret-changed-${name}.service"; - TriggerLimitIntervalSec = 30; - TriggerLimitBurst = 3; + systemd.paths = + (lib.mapAttrs' ( + name: secret: + lib.nameValuePair "openbao-secret-${name}" { + description = "Path unit for OpenBao secret ${name}"; + wantedBy = [ "multi-user.target" ]; + + pathConfig = { + PathChanged = secret.path; + Unit = "openbao-secret-changed-${name}.service"; + TriggerLimitIntervalSec = 30; + TriggerLimitBurst = 3; + }; + } + ) cfg.secrets) + // { + openbao-zitadel-jwt = { + description = "React to Zitadel JWT changes (restart vault-agent)"; + wantedBy = [ "multi-user.target" ]; + + pathConfig = { + PathChanged = cfg.zitadelJwtPath; + Unit = "openbao-jwt-changed.service"; + TriggerLimitIntervalSec = 30; + TriggerLimitBurst = 3; + }; }; - } - ) cfg.secrets; + + openbao-secrets-ready = { + description = "Re-check OpenBao secrets readiness"; + wantedBy = [ "multi-user.target" ]; + + pathConfig = { + PathChanged = "/run/secrets"; + Unit = "openbao-secrets-ready.service"; + TriggerLimitIntervalSec = 30; + TriggerLimitBurst = 3; + }; + }; + }; systemd.timers.zitadel-mint-jwt = { description = "Refresh Zitadel JWT for OpenBao"; wantedBy = [ "timers.target" ]; timerConfig = { - OnBootSec = "1min"; - OnUnitActiveSec = "10min"; + OnBootSec = "30s"; + OnUnitInactiveSec = "10min"; Unit = "zitadel-mint-jwt.service"; }; }; - systemd.services = lib.mkMerge [ - ( - lib.mkMerge ( - lib.concatLists ( - lib.mapAttrsToList ( - secretName: secret: - map ( - svc: { - ${svc} = { - unitConfig.ConditionPathExists = secret.path; - wants = lib.mkAfter [ "openbao-secret-${secretName}.path" ]; - after = lib.mkAfter [ "openbao-secret-${secretName}.path" ]; - }; - } - ) secret.hardDepend - ) cfg.secrets - ) - ) - ) - { - zitadel-mint-jwt = { - description = "Mint Zitadel access token (JWT) for OpenBao"; + systemd.services = lib.mkMerge [ + ( + lib.mkMerge ( + lib.concatLists ( + lib.mapAttrsToList ( + secretName: secret: + map ( + svc: { + ${svc} = { + unitConfig.ConditionPathExists = secret.path; + wants = lib.mkAfter [ "openbao-secret-${secretName}.path" ]; + after = lib.mkAfter [ "openbao-secret-${secretName}.path" ]; + partOf = lib.mkAfter [ "openbao-secret-changed-${secretName}.service" ]; + }; + } + ) secret.hardDepend + ) cfg.secrets + ) + ) + ) + { + openbao-secrets-ready = { + description = "OpenBao: all configured secrets present"; + wantedBy = [ "multi-user.target" ]; + wants = [ "vault-agent.service" ]; + after = [ "vault-agent.service" ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = "root"; + Group = "root"; + UMask = "0077"; + ExecStart = pkgs.writeShellScript "openbao-secrets-ready" '' + #!/usr/bin/env bash + set -euo pipefail + + ${lib.concatStringsSep "\n" ( + lib.mapAttrsToList (name: secret: '' + if [ ! -s ${lib.escapeShellArg secret.path} ]; then + echo "Missing secret: ${secret.path}" >&2 + exit 1 + fi + '') cfg.secrets + )} + + echo "All configured OpenBao secrets present." >&2 + ''; + }; + }; + + openbao-jwt-changed = { + description = "Restart vault-agent after Zitadel JWT refresh"; + wants = [ "vault-agent.service" ]; + after = [ "vault-agent.service" ]; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + Group = "root"; + UMask = "0077"; + ExecStart = pkgs.writeShellScript "openbao-jwt-changed" '' + #!/usr/bin/env bash + set -euo pipefail + systemctl try-restart --no-block vault-agent.service || true + ''; + }; + }; + + zitadel-mint-jwt = { + description = "Mint Zitadel access token (JWT) for OpenBao"; + + after = [ + "network-online.target" + "nss-lookup.target" + "NetworkManager-wait-online.service" + "systemd-resolved.service" + "time-sync.target" + ]; + wants = [ + "network-online.target" + "NetworkManager-wait-online.service" + "systemd-resolved.service" + ]; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + Group = "root"; + Restart = "on-failure"; + RestartSec = "30s"; + TimeoutStartSec = "2min"; + UMask = "0077"; + StartLimitIntervalSec = 0; - after = [ - "network-online.target" - "nss-lookup.target" - "NetworkManager-wait-online.service" - "systemd-resolved.service" - "time-sync.target" - ]; - wants = [ - "network-online.target" - "NetworkManager-wait-online.service" - "systemd-resolved.service" - ]; + ExecStart = pkgs.writeShellScript "zitadel-mint-jwt-service" '' - serviceConfig = { - Type = "oneshot"; - User = "root"; - Group = "root"; - Restart = "on-failure"; - RestartSec = "30s"; - TimeoutStartSec = "2min"; - UMask = "0077"; - - ExecStart = pkgs.writeShellScript "zitadel-mint-jwt-service" '' #!/usr/bin/env bash set -euo pipefail @@ -651,28 +748,33 @@ in }; }; - vault-agent = { - description = "OpenBao agent for rendering secrets"; - wantedBy = [ "multi-user.target" ]; - after = [ - "network-online.target" - ]; - wants = [ - "network-online.target" - "zitadel-mint-jwt.service" - ]; + vault-agent = { + description = "OpenBao agent for rendering secrets"; + wantedBy = [ "multi-user.target" ]; + + after = [ + "network-online.target" + "zitadel-mint-jwt.service" + ]; + wants = [ + "network-online.target" + "zitadel-mint-jwt.service" + ]; + + serviceConfig = { + Type = "simple"; + User = "root"; + Group = "root"; + Restart = "always"; + RestartSec = "10s"; + TimeoutStartSec = "30s"; + UMask = "0077"; + StartLimitIntervalSec = 0; + ExecStart = "${pkgs.openbao}/bin/bao agent -log-level=${lib.escapeShellArg cfg.vaultAgentLogLevel} -config=${mkAgentConfig}"; + }; + + }; - serviceConfig = { - Type = "simple"; - User = "root"; - Group = "root"; - Restart = "on-failure"; - RestartSec = "10s"; - TimeoutStartSec = "30s"; - UMask = "0077"; - ExecStart = "${pkgs.openbao}/bin/bao agent -log-level=${lib.escapeShellArg cfg.vaultAgentLogLevel} -config=${mkAgentConfig}"; - }; - }; } (lib.mapAttrs' ( @@ -713,6 +815,9 @@ in systemctl start --no-block ${lib.escapeShellArg (svc + ".service")} || true '') secret.hardDepend )} + + # Mark overall readiness when all secrets exist. + systemctl try-restart --no-block openbao-secrets-ready.service || true ''; }; } diff --git a/hosts/juni/flake.lock b/hosts/juni/flake.lock index 6a2132f0..673ca4d4 100644 --- a/hosts/juni/flake.lock +++ b/hosts/juni/flake.lock @@ -6,11 +6,11 @@ }, "locked": { "dir": "flakes/beszel", - "lastModified": 1767760069, - "narHash": "sha256-wNt+AACETzVAEXUd0pYVLjRS2NSP+uaFdo0Rnvaz3Cc=", + "lastModified": 1768000280, + "narHash": "sha256-JegPSldfsBcANqnV53mEAQOx/Fv22hUd0G2VTZGUR8Y=", "ref": "refs/heads/master", - "rev": "ee6fa6cd9b7507d04ef232e794bf0e82f60d50e6", - "revCount": 1094, + "rev": "a4e2cc00d86d2f3401918cfdf9f0643939871a42", + "revCount": 1115, "type": "git", "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" }, @@ -38,28 +38,40 @@ }, "common": { "locked": { - "path": "../../flakes/common", - "type": "path" + "dir": "flakes/common", + "lastModified": 1768000280, + "narHash": "sha256-JegPSldfsBcANqnV53mEAQOx/Fv22hUd0G2VTZGUR8Y=", + "ref": "refs/heads/master", + "rev": "a4e2cc00d86d2f3401918cfdf9f0643939871a42", + "revCount": 1115, + "type": "git", + "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" }, "original": { - "path": "../../flakes/common", - "type": "path" - }, - "parent": [] + "dir": "flakes/common", + "type": "git", + "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + } }, "de_plasma": { "inputs": { "plasma-manager": "plasma-manager" }, "locked": { - "path": "../../flakes/de_plasma", - "type": "path" + "dir": "flakes/de_plasma", + "lastModified": 1768000280, + "narHash": "sha256-JegPSldfsBcANqnV53mEAQOx/Fv22hUd0G2VTZGUR8Y=", + "ref": "refs/heads/master", + "rev": "a4e2cc00d86d2f3401918cfdf9f0643939871a42", + "revCount": 1115, + "type": "git", + "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" }, "original": { - "path": "../../flakes/de_plasma", - "type": "path" - }, - "parent": [] + "dir": "flakes/de_plasma", + "type": "git", + "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + } }, "flatpaks": { "inputs": { @@ -67,11 +79,11 @@ }, "locked": { "dir": "flakes/flatpaks", - "lastModified": 1767760069, - "narHash": "sha256-wNt+AACETzVAEXUd0pYVLjRS2NSP+uaFdo0Rnvaz3Cc=", + "lastModified": 1768000280, + "narHash": "sha256-JegPSldfsBcANqnV53mEAQOx/Fv22hUd0G2VTZGUR8Y=", "ref": "refs/heads/master", - "rev": "ee6fa6cd9b7507d04ef232e794bf0e82f60d50e6", - "revCount": 1094, + "rev": "a4e2cc00d86d2f3401918cfdf9f0643939871a42", + "revCount": 1115, "type": "git", "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" }, @@ -108,11 +120,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1767619900, - "narHash": "sha256-KpoCBPvwHz3gAQtIUkohE2InRBFK3r0/FM6z5SPWfvM=", + "lastModified": 1767910483, + "narHash": "sha256-MOU5YdVu4DVwuT5ztXgQpPuRRBjSjUGIdUzOQr9iQOY=", "owner": "rycee", "repo": "home-manager", - "rev": "6bd04da47cfb48dfd15eabf08364b78ad894f5b2", + "rev": "82fb7dedaad83e5e279127a38ef410bcfac6d77c", "type": "github" }, "original": { @@ -122,13 +134,38 @@ "type": "github" } }, - "impermanence": { + "home-manager_3": { + "inputs": { + "nixpkgs": [ + "impermanence", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1737831083, - "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", + "lastModified": 1747978958, + "narHash": "sha256-pQQnbxWpY3IiZqgelXHIe/OAE/Yv4NSQq7fch7M6nXQ=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "7419250703fd5eb50e99bdfb07a86671939103ea", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "impermanence": { + "inputs": { + "home-manager": "home-manager_3", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1767822991, + "narHash": "sha256-iyrn9AcPZCoyxX4OT8eMkBsjG7SRUQXXS/V1JzxS7rA=", "owner": "nix-community", "repo": "impermanence", - "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", + "rev": "82e5bc4508cab9e8d5a136626276eb5bbce5e9c5", "type": "github" }, "original": { @@ -187,11 +224,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1767640445, - "narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=", + "lastModified": 1767892417, + "narHash": "sha256-dhhvQY67aboBk8b0/u0XB6vwHdgbROZT3fJAjyNh5Ww=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5", + "rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba", "type": "github" }, "original": { @@ -203,11 +240,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1767325753, - "narHash": "sha256-yA/CuWyqm+AQo2ivGy6PlYrjZBQm7jfbe461+4HF2fo=", + "lastModified": 1767799921, + "narHash": "sha256-r4GVX+FToWVE2My8VVZH4V0pTIpnu2ZE8/Z4uxGEMBE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "64049ca74d63e971b627b5f3178d95642e61cedd", + "rev": "d351d0653aeb7877273920cd3e823994e7579b0b", "type": "github" }, "original": { @@ -219,11 +256,27 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1767634882, - "narHash": "sha256-2GffSfQxe3sedHzK+sTKlYo/NTIAGzbFCIsNMUPAAnk=", + "lastModified": 1748026106, + "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3c9db02515ef1d9b6b709fc60ba9a540957f661c", + "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1767799921, + "narHash": "sha256-r4GVX+FToWVE2My8VVZH4V0pTIpnu2ZE8/Z4uxGEMBE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d351d0653aeb7877273920cd3e823994e7579b0b", "type": "github" }, "original": { @@ -233,7 +286,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { "lastModified": 1767364772, "narHash": "sha256-fFUnEYMla8b7UKjijLnMe+oVFOz6HjijGGNS1l7dYaQ=", @@ -249,7 +302,7 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_6": { "locked": { "lastModified": 1766309749, "narHash": "sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC+2IVK0NoVEzDoOh4DA4=", @@ -1131,34 +1184,14 @@ }, "opencode": { "inputs": { - "opencode": "opencode_2" + "nixpkgs": "nixpkgs_5" }, "locked": { - "dir": "flakes/opencode", - "lastModified": 1767760069, - "narHash": "sha256-wNt+AACETzVAEXUd0pYVLjRS2NSP+uaFdo0Rnvaz3Cc=", - "ref": "refs/heads/master", - "rev": "ee6fa6cd9b7507d04ef232e794bf0e82f60d50e6", - "revCount": 1094, - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - }, - "original": { - "dir": "flakes/opencode", - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - } - }, - "opencode_2": { - "inputs": { - "nixpkgs": "nixpkgs_4" - }, - "locked": { - "lastModified": 1767719914, - "narHash": "sha256-xAQhyRB/tDIH7nkWdJVYCP6xFFfHoOP29RF8T6bmYDI=", + "lastModified": 1767994684, + "narHash": "sha256-UIijTI9ndnvhRC4tJDiSc19iMxeZZbDjkYTnfCbJpV8=", "owner": "sst", "repo": "opencode", - "rev": "1016a52cf1c28656ddd5c66689cf97b6d028c2f6", + "rev": "563b4c33f2bace782403de88e60de4f9167a3c93", "type": "github" }, "original": { @@ -1195,7 +1228,7 @@ "home-manager": "home-manager_2", "impermanence": "impermanence", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_4", "nixpkgs-unstable": "nixpkgs-unstable", "opencode": "opencode", "ros_neovim": "ros_neovim", @@ -1204,7 +1237,7 @@ }, "ros_neovim": { "inputs": { - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_6", "nvim_plugin-Almo7aya/openingh.nvim": "nvim_plugin-Almo7aya/openingh.nvim", "nvim_plugin-CopilotC-Nvim/CopilotChat.nvim": "nvim_plugin-CopilotC-Nvim/CopilotChat.nvim", "nvim_plugin-JoosepAlviste/nvim-ts-context-commentstring": "nvim_plugin-JoosepAlviste/nvim-ts-context-commentstring", @@ -1262,11 +1295,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1767195473, - "narHash": "sha256-xL3DZSWiNSvW58LsJwFIpQ9i3Vs5uaYUjbL60rpFxPk=", + "lastModified": 1767816828, + "narHash": "sha256-5V1nbL52dBUNs8VzxB7MxfVtNYmT71LpPwb2ccmSvOE=", "ref": "refs/heads/master", - "rev": "88e86b5a7d40697ade905f534dcd5372a67b8102", - "revCount": 328, + "rev": "3517caecde71f96305a3eec2880daeed18881d5b", + "revCount": 329, "type": "git", "url": "https://git.joshuabell.xyz/ringofstorms/nvim" }, diff --git a/hosts/juni/flake.nix b/hosts/juni/flake.nix index d7648dd3..1a5e3e20 100644 --- a/hosts/juni/flake.nix +++ b/hosts/juni/flake.nix @@ -9,21 +9,18 @@ impermanence.url = "github:nix-community/impermanence"; # Use relative to get current version for testin - common.url = "path:../../flakes/common"; - # common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common"; + # common.url = "path:../../flakes/common"; + common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common"; # secrets-bao.url = "path:../../flakes/secrets-bao"; - # NOTE: using an absolute path so this works before you commit/push. - # After you add `flakes/secrets-bao` to the repo, switch to a git URL like your other flakes. secrets-bao.url = "path:../../flakes/secrets-bao"; # flatpaks.url = "path:../../flakes/flatpaks"; flatpaks.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/flatpaks"; # beszel.url = "path:../../flakes/beszel"; beszel.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/beszel"; - de_plasma.url = "path:../../flakes/de_plasma"; - # de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma"; - # opencode.url = "path:../../flakes/opencode"; - opencode.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/opencode"; + # de_plasma.url = "path:../../flakes/de_plasma"; + de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma"; + opencode.url = "github:sst/opencode"; ros_neovim.url = "git+https://git.joshuabell.xyz/ringofstorms/nvim"; }; @@ -73,7 +70,6 @@ ({ ringofstorms-nvim.includeAllRuntimeDependencies = true; }) - inputs.opencode.nixosModules.default inputs.flatpaks.nixosModules.default @@ -87,6 +83,18 @@ inputs.common.nixosModules.tty_caps_esc inputs.common.nixosModules.zsh inputs.common.nixosModules.tailnet + ( + { pkgs, ... }: + { + environment.systemPackages = [ + inputs.opencode.packages.${pkgs.system}.default + ]; + environment.shellAliases = { + "oc" = "all_proxy='' http_proxy='' https_proxy='' opencode"; + "occ" = "oc -c"; + }; + } + ) ( { pkgs, lib, ... }: {