From a59d691c8a237e6928853ed9ea132b51ee2cdab8 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 14:36:44 +0100 Subject: [PATCH 01/18] forgejo: enable runners --- hosts/thegeneralist-central/forgejo/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 30ca4cf..70c2589 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -26,6 +26,9 @@ in }; attachment.ALLOWED_TYPES = "*/*"; + actions = { + ENABLED = true; + }; cache.ENABLED = true; "cron.archive_cleanup" = From a2767fa82952a52846a34c8e2ac5fc606237ad4f Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 14:49:09 +0100 Subject: [PATCH 02/18] forgejo: add runner token --- .../thegeneralist-central/forgejo/default.nix | 27 +++++++++++++++++++ .../forgejo/forgejo-runner-token.age | 5 ++++ secrets.nix | 1 + 3 files changed, 33 insertions(+) create mode 100644 hosts/thegeneralist-central/forgejo/forgejo-runner-token.age diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 70c2589..182a54a 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -7,6 +7,8 @@ in { imports = [ ../../../modules/postgresql.nix ]; + age.secrets.forgejoRunnerToken.file = ./forgejo-runner-token.age; + services.forgejo = { enable = true; stateDir = forgejo_folder "state"; @@ -93,5 +95,30 @@ in }; }; + services.gitea-actions-runner = { + package = pkgs.forgejo-runner; + instances.central = { + enable = true; + name = "thegeneralist-central"; + url = "https://${domain}"; + tokenFile = config.age.secrets.forgejoRunnerToken.path; + labels = [ "central:host" ]; + + # Host-executed jobs need nix + ssh in PATH. + hostPackages = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nodejs + nix + openssh + wget + ]; + }; + }; + networking.firewall.allowedTCPPorts = [ 2222 ]; } diff --git a/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age b/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age new file mode 100644 index 0000000..876544f --- /dev/null +++ b/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age @@ -0,0 +1,5 @@ +age-encryption.org/v1 +-> ssh-ed25519 pp9qdQ xQTY8i7SQWpBxxcrYAzkTuK6p5toOknfXef6JOreZHA +0WAy/WC6eGjW8yb+mVPwIn6BmTxYfgLlYmV0BKVn+8E +--- sfCrXmbA46pPodKC6m3SMmemx8eYMDvp7zqrL0iOfs8 +cj0MԤry~$8h/\~)[}AZ|,ҝ]1 \ No newline at end of file diff --git a/secrets.nix b/secrets.nix index 8ea2f3f..a54671f 100644 --- a/secrets.nix +++ b/secrets.nix @@ -10,6 +10,7 @@ in { "hosts/thegeneralist-central/credentials_personal.age".publicKeys = [ thegeneralist ]; "hosts/thegeneralist-central/cache/key.age".publicKeys = [ thegeneralist ]; "hosts/thegeneralist-central/password.age".publicKeys = [ thegeneralist ]; + "hosts/thegeneralist-central/forgejo/forgejo-runner-token.age".publicKeys = [ thegeneralist ]; "modules/linux/tailscale-marshall.age".publicKeys = [ thegeneralist ]; } From 54f5856164b7b12a1cba2589907b84c9eb517577 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:13:19 +0100 Subject: [PATCH 03/18] forgejo: configure actions runner --- hosts/thegeneralist-central/forgejo/default.nix | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 182a54a..a5c5a1f 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -1,3 +1,5 @@ +{ config, pkgs, ... }: + let forgejo_root_dir = "/var/lib/forgejo"; domain = "git.thegeneralist01.com"; @@ -102,9 +104,13 @@ in name = "thegeneralist-central"; url = "https://${domain}"; tokenFile = config.age.secrets.forgejoRunnerToken.path; - labels = [ "central:host" ]; + labels = [ + "native:host" + # "node-22:docker://node:22-bookworm" + # "nixos-latest:docker://nixos/nix" + ]; - # Host-executed jobs need nix + ssh in PATH. + # Host-executed jobs need nix + ssh in PATH. hostPackages = with pkgs; [ bash coreutils @@ -120,5 +126,7 @@ in }; }; + networking.firewall.trustedInterfaces = [ "br-+" ]; + networking.firewall.allowedTCPPorts = [ 2222 ]; } From faf0bd9b51566d1c642f09e7a6c2feec8a1b989a Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:42:02 +0100 Subject: [PATCH 04/18] nginx: fix domain root --- hosts/thegeneralist-central/site.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/site.nix b/hosts/thegeneralist-central/site.nix index afc83f5..82a1c08 100644 --- a/hosts/thegeneralist-central/site.nix +++ b/hosts/thegeneralist-central/site.nix @@ -55,7 +55,7 @@ in }; virtualHosts."${family_domain}" = { - root = "/var/www/${family_domain}"; + root = "/var/www/${family_domain}/dist"; locations."/".tryFiles = "$uri $uri.html $uri/ $uri/index.html =404"; extraConfig = '' From 55c402c12071a9934bc9d029ea6eb09a921ee94e Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:55:59 +0100 Subject: [PATCH 05/18] forgejo: add known host for central --- hosts/thegeneralist-central/forgejo/default.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index a5c5a1f..a1dcfc8 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -128,5 +128,10 @@ in networking.firewall.trustedInterfaces = [ "br-+" ]; + programs.ssh.knownHosts.central = { + hostNames = [ "central" ]; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMuvjhN26VXntKZdu7/rFc55EGK0B2wDXv6PIiMJSvD"; + }; + networking.firewall.allowedTCPPorts = [ 2222 ]; } From 51ecf21e68647062b86b0f69e2d7accf8ab74310 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 16:03:31 +0100 Subject: [PATCH 06/18] forgejo: fix token --- .../forgejo/forgejo-runner-token.age | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age b/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age index 876544f..43f46c9 100644 --- a/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age +++ b/hosts/thegeneralist-central/forgejo/forgejo-runner-token.age @@ -1,5 +1,6 @@ age-encryption.org/v1 --> ssh-ed25519 pp9qdQ xQTY8i7SQWpBxxcrYAzkTuK6p5toOknfXef6JOreZHA -0WAy/WC6eGjW8yb+mVPwIn6BmTxYfgLlYmV0BKVn+8E ---- sfCrXmbA46pPodKC6m3SMmemx8eYMDvp7zqrL0iOfs8 -cj0MԤry~$8h/\~)[}AZ|,ҝ]1 \ No newline at end of file +-> ssh-ed25519 pp9qdQ 3zI5p1EPKcJdRWK0ZikK7MEwLON9oX2qRy0Ll8+7rXE ++66HhKgUa3AsYO4gHQmlypR7CgkdaQI7goZCPTHGxEE +--- R+2xHNQawIBenqYp5t4s7XGDeDLt9cFZXprJSNHe8dE +74A<0XoexVn#AeDS}bI hD!`QB[:f$C?2ۓM ԉNCU2Nu +@&sؽsDsdӖDX1nJ \ No newline at end of file From 0a8ea8a332a9e74fefd9d05271fbaedb5311825e Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 16:10:26 +0100 Subject: [PATCH 07/18] forgejo(ssh): fix central's key --- hosts/thegeneralist-central/forgejo/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index a1dcfc8..73826c7 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -130,7 +130,7 @@ in programs.ssh.knownHosts.central = { hostNames = [ "central" ]; - publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAMuvjhN26VXntKZdu7/rFc55EGK0B2wDXv6PIiMJSvD"; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkFvw9+AispgqwaYg3ksAZTHJgkCDwFTbWzUh/pVcAS"; }; networking.firewall.allowedTCPPorts = [ 2222 ]; From 4f50ad500f2d0be1b640857bb7bfb69bf96f8198 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:07:42 +0100 Subject: [PATCH 08/18] forgejo: please work --- hosts/thegeneralist-central/forgejo/default.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 73826c7..5e6be59 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -133,5 +133,12 @@ in publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkFvw9+AispgqwaYg3ksAZTHJgkCDwFTbWzUh/pVcAS"; }; + # Avoid /var/lib/private so the runner can write its state. + systemd.services.gitea-runner-central.serviceConfig = { + DynamicUser = false; + StateDirectory = "gitea-runner/central"; + StateDirectoryMode = "0755"; + }; + networking.firewall.allowedTCPPorts = [ 2222 ]; } From 711973945afa3634fc66875cc66246d54cd8ce02 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:09:47 +0100 Subject: [PATCH 09/18] forgejo: run runner state outside /var/lib/private --- hosts/thegeneralist-central/forgejo/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 5e6be59..46a442a 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -135,7 +135,7 @@ in # Avoid /var/lib/private so the runner can write its state. systemd.services.gitea-runner-central.serviceConfig = { - DynamicUser = false; + DynamicUser = lib.mkForce false; StateDirectory = "gitea-runner/central"; StateDirectoryMode = "0755"; }; From b4d3ee87891635ae1804594688d34b98ad33b81d Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:13:25 +0100 Subject: [PATCH 10/18] forgejo: use non-private runner state dir --- hosts/thegeneralist-central/forgejo/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 46a442a..c6d4325 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -136,7 +136,7 @@ in # Avoid /var/lib/private so the runner can write its state. systemd.services.gitea-runner-central.serviceConfig = { DynamicUser = lib.mkForce false; - StateDirectory = "gitea-runner/central"; + StateDirectory = lib.mkForce "gitea-runner/central"; StateDirectoryMode = "0755"; }; From 8ccf9a1e1de9d1a108b5395552a7f9df40286790 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:13:59 +0100 Subject: [PATCH 11/18] forgejo: fix runner state dir + mkForce --- hosts/thegeneralist-central/forgejo/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index c6d4325..e5d17c0 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, lib, pkgs, ... }: let forgejo_root_dir = "/var/lib/forgejo"; From a9cc7b19d859f92d33223ada68f63f71faabf494 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:18:59 +0100 Subject: [PATCH 12/18] forgejo: use static runner user + non-private state dir --- hosts/thegeneralist-central/forgejo/default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index e5d17c0..00530e0 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -140,5 +140,13 @@ in StateDirectoryMode = "0755"; }; + users.groups.gitea-runner = { }; + users.users.gitea-runner = { + isSystemUser = true; + group = "gitea-runner"; + home = "/var/lib/gitea-runner/central"; + createHome = true; + }; + networking.firewall.allowedTCPPorts = [ 2222 ]; } From 921b343c2e6b6dce464ed506a3394d729516afae Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:24:38 +0100 Subject: [PATCH 13/18] forgejo: fix runner state dir + tmpfiles --- hosts/thegeneralist-central/forgejo/default.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 00530e0..c5f0a7f 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -136,7 +136,7 @@ in # Avoid /var/lib/private so the runner can write its state. systemd.services.gitea-runner-central.serviceConfig = { DynamicUser = lib.mkForce false; - StateDirectory = lib.mkForce "gitea-runner/central"; + StateDirectory = lib.mkForce "gitea-runner"; StateDirectoryMode = "0755"; }; @@ -148,5 +148,10 @@ in createHome = true; }; + systemd.tmpfiles.rules = [ + "d /var/lib/gitea-runner 0755 gitea-runner gitea-runner -" + "d /var/lib/gitea-runner/central 0755 gitea-runner gitea-runner -" + ]; + networking.firewall.allowedTCPPorts = [ 2222 ]; } From 5feb3ac81ed88822c8156fd4ce88142cdb2793d1 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:26:20 +0100 Subject: [PATCH 14/18] docs: add forgejo runner state dir notes --- AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index deafdf2..17b608a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -155,6 +155,11 @@ lib: inputs: self: lib.mkSystem "" ./configuration.nix 2. Check file extension is `.nix` 3. Ensure valid Nix syntax +### Forgejo Actions Runner (NixOS) +1. `DynamicUser` conflicts require `lib.mkForce` if overriding module defaults. +2. Runner state dir should be `/var/lib/gitea-runner/`; set `StateDirectory = "gitea-runner"` and let the instance name append. +3. If the register script fails with `permission denied`, ensure `/var/lib/gitea-runner` exists and is owned by `gitea-runner`. + ### Nushell Warnings 1. Deprecated `get -i` warning from direnv integration is a short-term workaround in `modules/common/shell/direnv.nix` (custom Nushell hook with `get -o` and HM integration disabled) until upstream home-manager updates. From 1f3f12b59df11b1bb4af301a54c214b8f6ad784d Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:39:38 +0100 Subject: [PATCH 15/18] forgejo: add deploy token secret --- hosts/thegeneralist-central/forgejo/default.nix | 1 + secrets.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index c5f0a7f..24f2ed5 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -10,6 +10,7 @@ in imports = [ ../../../modules/postgresql.nix ]; age.secrets.forgejoRunnerToken.file = ./forgejo-runner-token.age; + age.secrets.forgejoFamilySiteDeployToken.file = ./forgejo-family-site-deploy-token.age; services.forgejo = { enable = true; diff --git a/secrets.nix b/secrets.nix index a54671f..d73e7ab 100644 --- a/secrets.nix +++ b/secrets.nix @@ -11,6 +11,7 @@ in { "hosts/thegeneralist-central/cache/key.age".publicKeys = [ thegeneralist ]; "hosts/thegeneralist-central/password.age".publicKeys = [ thegeneralist ]; "hosts/thegeneralist-central/forgejo/forgejo-runner-token.age".publicKeys = [ thegeneralist ]; + "hosts/thegeneralist-central/forgejo/forgejo-family-site-deploy-token.age".publicKeys = [ thegeneralist ]; "modules/linux/tailscale-marshall.age".publicKeys = [ thegeneralist ]; } From 9124a64c8c8d535cdd764408e10b919309e431d9 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:41:00 +0100 Subject: [PATCH 16/18] forgejo: add deploy token secret --- .../forgejo/forgejo-family-site-deploy-token.age | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 hosts/thegeneralist-central/forgejo/forgejo-family-site-deploy-token.age diff --git a/hosts/thegeneralist-central/forgejo/forgejo-family-site-deploy-token.age b/hosts/thegeneralist-central/forgejo/forgejo-family-site-deploy-token.age new file mode 100644 index 0000000..01e1185 --- /dev/null +++ b/hosts/thegeneralist-central/forgejo/forgejo-family-site-deploy-token.age @@ -0,0 +1,6 @@ +age-encryption.org/v1 +-> ssh-ed25519 pp9qdQ GJGHfvh/Uxw7ft0YGwY8Opel/kBdmN4SlblkTyEcKjU +r/WBadLWHFf0U/G/777GeOO37a6wER6sje3xk2pv9Do +--- 9y4nJZEmjdmJ1ZNOu/8nYadBPDdvXN0sEnNjkx3a9sU +(h Date: Sat, 24 Jan 2026 17:43:08 +0100 Subject: [PATCH 17/18] forgejo: allow runner to read deploy token --- hosts/thegeneralist-central/forgejo/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hosts/thegeneralist-central/forgejo/default.nix b/hosts/thegeneralist-central/forgejo/default.nix index 24f2ed5..3ba7af7 100644 --- a/hosts/thegeneralist-central/forgejo/default.nix +++ b/hosts/thegeneralist-central/forgejo/default.nix @@ -11,6 +11,9 @@ in age.secrets.forgejoRunnerToken.file = ./forgejo-runner-token.age; age.secrets.forgejoFamilySiteDeployToken.file = ./forgejo-family-site-deploy-token.age; + age.secrets.forgejoFamilySiteDeployToken.owner = "gitea-runner"; + age.secrets.forgejoFamilySiteDeployToken.group = "gitea-runner"; + age.secrets.forgejoFamilySiteDeployToken.mode = "0400"; services.forgejo = { enable = true; From 4826f1fe6410428918afaa90bd94fc503a2cead4 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:57:41 +0100 Subject: [PATCH 18/18] docs: note forgejo runner perms and token --- AGENTS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 17b608a..4cd3e68 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -159,6 +159,8 @@ lib: inputs: self: lib.mkSystem "" ./configuration.nix 1. `DynamicUser` conflicts require `lib.mkForce` if overriding module defaults. 2. Runner state dir should be `/var/lib/gitea-runner/`; set `StateDirectory = "gitea-runner"` and let the instance name append. 3. If the register script fails with `permission denied`, ensure `/var/lib/gitea-runner` exists and is owned by `gitea-runner`. +4. If workflows need to read a home symlink target, `/home/` must be `0750` (group traverse) and the runner user must be in that group. +5. A Forgejo deploy token for HTTPS pulls should be stored in agenix and owned by `gitea-runner`; use env-file format (`TOKEN=...`) and read it at runtime. ### Nushell Warnings 1. Deprecated `get -i` warning from direnv integration is a short-term workaround in `modules/common/shell/direnv.nix` (custom Nushell hook with `get -o` and HM integration disabled) until upstream home-manager updates.