From 5f90347e29cdf4bde7375645236cf0838dcffaed Mon Sep 17 00:00:00 2001 From: Collin Diekvoss Date: Fri, 14 Aug 2026 10:00:48 -0500 Subject: [PATCH] ull --- AGENTS.md | 132 +++++++++++++++----- README.md | 34 +++++ configurations/nixos/nas/configuration.nix | 15 +++ homelab.nix | 10 ++ modules/home/programs/gtk.nix | 2 +- modules/home/programs/jujutsu.nix | 22 ++-- modules/home/programs/kde.nix | 2 +- modules/home/programs/shells/zsh.nix | 2 +- modules/home/programs/terminals/ghostty.nix | 2 +- modules/home/programs/terminals/hyper.nix | 6 +- modules/home/session.nix | 4 +- modules/home/sops.nix | 2 +- modules/home/users/briar.nix | 2 +- modules/home/users/chloe.nix | 2 +- modules/home/users/toyvo.nix | 6 +- modules/os/console.nix | 2 +- modules/os/dev.nix | 2 +- modules/os/gui.nix | 6 +- modules/os/users/chloe.nix | 6 +- modules/os/users/hermes.nix | 4 +- modules/os/users/root.nix | 4 +- modules/os/users/toyvo.nix | 8 +- pkgs/setup-sops/default.nix | 4 +- todos.md | 32 +++++ 24 files changed, 239 insertions(+), 72 deletions(-) create mode 100644 todos.md diff --git a/AGENTS.md b/AGENTS.md index 8dddc54..cf1ed42 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ Guidance for AI coding agents working in this Nix/NixOS configuration repository ## Repository Overview -Dual-purpose Nix flake: a **NUR (Nix User Repository)** publishing custom packages, and a **shared system configuration** for 16+ machines across NixOS, nix-darwin, and Home Manager. +Dual-purpose Nix flake: a **NUR (Nix User Repository)** publishing custom packages, and a **shared system configuration** for 20 machines across NixOS, nix-darwin, and Home Manager. - GitHub: `ToyVo/nixcfg` - Primary branch: `main` @@ -55,6 +55,9 @@ nh darwin switch ~/nixcfg # Home Manager home-manager switch --flake .# + +# deploy-rs (remote nodes defined in flake.nix, e.g. nas) +deploy .# ``` **No Traditional Tests**: This repo has no unit tests. Validation is via `nix flake show` (evaluation check) and building outputs. CI builds the aggregate `checks..all` derivation with a single `nix build` (cachix `watch-store` pushes results). @@ -156,7 +159,7 @@ stdenv.mkDerivation rec { ### Module Tree (`modules/`) -Auto-discovered via `lib.importDirRecursive`: +Each tree has a `default.nix` that **explicitly imports** its modules (no auto-discovery): | Directory | Scope | Description | | ----------------- | ------------ | ------------------------------------------------- | @@ -164,58 +167,103 @@ Auto-discovered via `lib.importDirRecursive`: | `modules/nixos/` | NixOS | Linux-specific: services, containers, filesystems | | `modules/darwin/` | Darwin | macOS-specific: ollama, podman | | `modules/home/` | Home Manager | User-level programs, user profiles | - -Reference modules via `self.modules..` (e.g., `self.modules.nixos.systems`). - -### System Configurations (`systems/`) - -Factory functions in `systems/default.nix`: - -- `nixosSystem { system, nixosModules, homeModules }` — NixOS config -- `darwinSystem { system, darwinModules, homeModules }` — nix-darwin config -- `homeConfiguration { system, homeModules }` — Standalone Home Manager - -Each machine has a directory in `systems//` with: - -- `default.nix`: Metadata `{ type = "nixos"; system = "x86_64-linux"; }` -- `configuration.nix` or `home.nix`: Actual configuration +| `modules/flake/` | flake-parts | Flake-level modules | + +Exposed as flake outputs `nixosModules` / `darwinModules` / `homeModules` / `flakeModules` +(plus `modules.` aliases). Machine configs consume them via +`inputs.nixcfg.modules..default`. + +### System Configurations (`configurations/`) + +Machines live in `configurations///`, where class is `nixos`, `darwin`, +or `home`. Each machine directory contains: + +- `default.nix`: Function of flake inputs returning the built configuration + (`nixosSystem` / `darwinSystem` / `homeConfiguration`); wires up `specialArgs` + (`homelab`, `stablePkgs`, `unstablePkgs`, ...) +- `configuration.nix`: System configuration (NixOS/Darwin) +- `home.nix`: Shared Home Manager config, where applicable + +Machines are registered **explicitly** in `configurations/default.nix`, which maps +flake output names (e.g., `nixosConfigurations.nas`) to the directories. + +### Homelab Service Registry (`homelab.nix`) + +`homelab.nix` is the single source of truth for homelab hosts and the services +running on them: IP/MAC addresses plus a `services` attrset per host with fields +like `port`, `subdomain`, `domain` (default `diekvoss.net`), `forwardAuthGate` +(default `true`; gates the vhost behind authentik), `selfSigned`, and homepage +metadata (`displayName`, `description`, `category`, `icon`, `widget`). + +Consumers: + +- `configurations/nixos/router/virtual-hosts.nix` — generates a Caddy vhost + `.` → `http://:` for every service on a + `10.1.0.0/16` or `10.200.0.0/16` host. TLS uses the `*.diekvoss.net` / + `*.toyvo.dev` wildcard ACME certs (Cloudflare DNS challenge). See + "Domains and Public Exposure" below for how vhost listen addresses are chosen. +- `configurations/nixos/nas/homepage.nix` — generates homepage-dashboard + entries grouped by `category`. + +To expose a new service: add its entry to `homelab.nix`, run it on its host, and +open the host firewall port. DNS records for the public domains are managed in +Cloudflare (manually, except `toyvo.dev`, which uses dyndns). + +### Domains and Public Exposure + +- `diekvoss.net` — **internal-only**: only resolvable within the home network. + As defense in depth, its Caddy vhosts listen on localhost/LAN addresses only, + and services are gated behind authentik forward-auth by default + (`forwardAuthGate = true`). Exposure risk is low, but don't treat it as + nonexistent — the network has guest/IoT VLANs. +- `toyvo.dev` and `diekvoss.com` — **public internet-facing**: anything exposed + on these domains is reachable by the entire world, so keep security top of + mind. Their Caddy vhosts listen on all interfaces. Requirements for anything + public: strong authentication (prefer authentik forward-auth or OIDC), no + default/weak credentials, no unauthenticated write access, no sensitive data + on unauthenticated endpoints, and the minimal set of open ports. Think twice + before setting `domain = "toyvo.dev"` or `public = true` on a service. ### Packages (`pkgs/`) -Auto-discovered via `lib.callDirPackageWithRecursive`. Each package: - -- Lives in `pkgs//` -- Entry point is `package.nix` -- Common pattern: `package.nix` calls `derivation.nix` with versions from `versions.json` +NUR-style: each package lives in `pkgs//` (entry point `package.nix` or +`default.nix`) and is registered **explicitly** in the repository root +`default.nix` via `callPackage`. `flake.nix` exposes the result as +`legacyPackages`, filters derivations into `packages.`, and publishes +them via `overlays/`. Common pattern: `package.nix` calls `derivation.nix` with +versions from `versions.json`. ### Custom Library (`lib/`) -Key utilities: +Exposed as `self.lib`. Key utilities: -- `importDirRecursive` — Recursive `.nix` file importer -- `callDirPackageWithRecursive` — Auto-discovers packages -- `flakePackages` / `flakeChecks` — Filters for flake outputs +- `flattenPkgs` / `outputsOf` — Flatten package sets into derivations for checks +- `isBuildable` / `isCacheable` / `isReserved` / `forSystem` — Filter which derivations CI builds +- `platformsOf` — Platform lists for packages +- `mkWrappedProgram` — Wrapper helper for programs with extra args/env +- `maintainers.toyvo` — Maintainer entry, merged into nixpkgs `lib` for packages ## Common Patterns ### Adding a New System -1. Create `systems//` -1. Add `default.nix` with `{ type = "nixos"; system = "x86_64-linux"; }` -1. Add `configuration.nix` (NixOS/Darwin) or `home.nix` (Home Manager) -1. Auto-discovered; no registration needed +1. Create `configurations///` +1. Add `default.nix` (function of inputs returning the `*System` call) and + `configuration.nix` (NixOS/Darwin) or `home.nix` (Home Manager) +1. Register it in `configurations/default.nix` +1. Optionally add a `deploy.nodes.` entry in `flake.nix` for deploy-rs ### Adding a New Package 1. Create `pkgs//` 1. Add `package.nix` (function accepting deps) -1. Auto-discovered; no registration needed +1. Register it in the repository root `default.nix` via `callPackage` ### Adding a New Module -1. Place `.nix` file under appropriate `modules//` -1. Auto-discovered via `importDirRecursive` -1. Reference via `self.modules..` +1. Place the `.nix` file under the appropriate `modules//` +1. Import it from that tree's `default.nix` +1. Reference via `inputs.nixcfg.modules..default` (or `self.modules.`) ## Binary Caches @@ -237,3 +285,19 @@ Hooks configured in `flake.nix` via `devshell` module. ## Downstream Usage Work machine config imports this flake and uses `nixcfg.lib.darwinSystem` to inherit shared modules/overlays. + +## Todo Tracking + +Outstanding follow-up work lives in [`todos.md`](todos.md). + +**Standing instruction for agents: keep `todos.md` up to date automatically.** + +- When you complete work that has an entry in `todos.md`, check it off (or + remove it) in the same change. +- When you defer work, leave a manual step for the user, or notice a worthwhile + improvement you don't implement, add it to `todos.md` before finishing. +- Check `todos.md` when starting related work and pick up open items when asked. + +Likewise, keep this `AGENTS.md` current: when you change the repository +structure, registration patterns, or workflows, update the relevant sections in +the same change. diff --git a/README.md b/README.md index 709a09d..e1db553 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,37 @@ ![Build and populate cache](https://github.com/ToyVo/nixcfg/workflows/Build%20and%20populate%20cache/badge.svg) [![Cachix Cache](https://img.shields.io/badge/cachix-toyvo-blue.svg)](https://toyvo.cachix.org) + +A single Nix flake serving two purposes: + +1. **NUR repository** — custom packages, published via + [NUR](https://github.com/nix-community/NUR) and the + [cache.toyvo.dev](https://cache.toyvo.dev) binary cache. +1. **System configurations** — shared NixOS, nix-darwin, and Home Manager + configurations for my machines (desktops, laptops, NAS, router, VPS, ...), + including the self-hosted services behind `*.diekvoss.net` (e.g. Forgejo at + git.diekvoss.net — resolvable only on my home network). + +## Layout + +| Path | Contents | +| ----------------- | ---------------------------------------------------------------- | +| `configurations/` | Machine configurations (`nixos/`, `darwin/`, `home/`) | +| `modules/` | Shared modules (`os/`, `nixos/`, `darwin/`, `home/`, `flake/`) | +| `pkgs/` | Custom packages (NUR) | +| `lib/` | Custom library functions | +| `homelab.nix` | Homelab host/service registry (drives Caddy vhosts + homepage) | +| `AGENTS.md` | Guidance for AI coding agents (structure, conventions, commands) | +| `todos.md` | Outstanding work and follow-ups | + +## Usage + +```bash +nix flake show # list all outputs +nix build .#nixosConfigurations.nas.config.system.build.toplevel +deploy .#nas # deploy-rs to a remote node +nix run .#setup-sops # provision sops/age keys +``` + +See [AGENTS.md](AGENTS.md) for full build/deploy commands and development +conventions. diff --git a/configurations/nixos/nas/configuration.nix b/configurations/nixos/nas/configuration.nix index 773b821..40ad0b8 100644 --- a/configurations/nixos/nas/configuration.nix +++ b/configurations/nixos/nas/configuration.nix @@ -104,6 +104,7 @@ in 443 5432 8080 + 3000 # forgejo 8642 # hermes-agent API (reachable from open-webui container via veth) 9119 # hermes-dashboard 8787 # hermes-webui @@ -185,6 +186,20 @@ in BASE_URL = "https://toyvo.dev"; }; }; + forgejo = { + enable = true; + stateDir = "/mnt/POOL/forgejo"; + database.type = "postgres"; + settings = { + server = { + DOMAIN = "git.diekvoss.net"; + ROOT_URL = "https://git.diekvoss.net/"; + HTTP_PORT = homelab.${hostName}.services.forgejo.port; + }; + # accounts are created by the admin via CLI, or log in via OAuth + service.DISABLE_REGISTRATION = true; + }; + }; homepage-dashboard.enable = true; nix-serve = { enable = true; diff --git a/homelab.nix b/homelab.nix index f1115e6..dc26b19 100644 --- a/homelab.nix +++ b/homelab.nix @@ -73,6 +73,16 @@ category = "Nas"; displayName = "Discord Bot UI"; }; + forgejo = { + port = 3000; + subdomain = "git"; + # git clients need direct access; forgejo handles its own auth + forwardAuthGate = false; + displayName = "Forgejo"; + description = "Git Hosting"; + category = "Nas"; + icon = "sh-forgejo"; + }; cockpit = { port = 9091; selfSigned = true; diff --git a/modules/home/programs/gtk.nix b/modules/home/programs/gtk.nix index dbca75d..f39ba20 100644 --- a/modules/home/programs/gtk.nix +++ b/modules/home/programs/gtk.nix @@ -8,7 +8,7 @@ let cfg = config.nixcfg; in { - config = lib.mkIf (cfg.gui.enable && pkgs.stdenv.isLinux) { + config = lib.mkIf (cfg.gui.enable && pkgs.stdenv.hostPlatform.isLinux) { catppuccin.cursors = { accent = config.catppuccin.accent; enable = lib.mkDefault true; diff --git a/modules/home/programs/jujutsu.nix b/modules/home/programs/jujutsu.nix index 591a1cb..fa5cdbe 100644 --- a/modules/home/programs/jujutsu.nix +++ b/modules/home/programs/jujutsu.nix @@ -94,16 +94,24 @@ in echo "Error: No diff found for change $CHANGE_ID" >&2 exit 1 fi - PI_ARGS="${ - if cfg.aiDescribe.provider != null then ''--provider "${cfg.aiDescribe.provider}"'' else "" - } ${if cfg.aiDescribe.model != null then ''--model "${cfg.aiDescribe.model}"'' else ""}" + PI_ARGS=() + ${lib.optionalString ( + cfg.aiDescribe.provider != null + ) "PI_ARGS+=(--provider ${lib.escapeShellArg cfg.aiDescribe.provider})"} + ${lib.optionalString ( + cfg.aiDescribe.model != null + ) "PI_ARGS+=(--model ${lib.escapeShellArg cfg.aiDescribe.model})"} FULL_PROMPT=${lib.escapeShellArg cfg.aiDescribe.prompt} if [ -n "$EXTRA_CONTEXT" ]; then - FULL_PROMPT="''${EXTRA_CONTEXT}\\n\\n$FULL_PROMPT" + FULL_PROMPT="$EXTRA_CONTEXT"$'\n\n'"$FULL_PROMPT" fi - MESSAGE=$(pi -p --no-session --mode json $PI_ARGS "$FULL_PROMPT\\n\\n$DIFF_OUTPUT" | jq -r 'select(.type == "message_end" and .message.role == "assistant") | .message.content[0].text' 2>/dev/null | head -c 500) - # Clean up whitespace - MESSAGE=$(echo "$MESSAGE" | tr -d '\\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + # pi's plain print mode writes only the response text to stdout + if ! MESSAGE=$(pi -p --no-session "''${PI_ARGS[@]}" "$FULL_PROMPT"$'\n\n'"$DIFF_OUTPUT"); then + echo "Error: pi failed to generate a commit message" >&2 + exit 1 + fi + # Flatten to one line, cap length, and trim whitespace + MESSAGE=$(printf '%s' "$MESSAGE" | tr -d '\n' | head -c 500 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') if [ -z "$MESSAGE" ]; then echo "Error: Failed to generate commit message" >&2 exit 1 diff --git a/modules/home/programs/kde.nix b/modules/home/programs/kde.nix index a21e7d4..9591982 100644 --- a/modules/home/programs/kde.nix +++ b/modules/home/programs/kde.nix @@ -18,7 +18,7 @@ in options.programs.kde.catppuccin = { enable = lib.mkOption { type = lib.types.bool; - default = config.nixcfg.gui.enable && pkgs.stdenv.isLinux; + default = config.nixcfg.gui.enable && pkgs.stdenv.hostPlatform.isLinux; description = "Enable Catppuccin KDE theme"; }; }; diff --git a/modules/home/programs/shells/zsh.nix b/modules/home/programs/shells/zsh.nix index c3de9aa..18dfe85 100644 --- a/modules/home/programs/shells/zsh.nix +++ b/modules/home/programs/shells/zsh.nix @@ -41,7 +41,7 @@ in unset IFS ''; }; - home.file.".hushlogin" = lib.mkIf pkgs.stdenv.isDarwin { + home.file.".hushlogin" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { text = ""; }; }; diff --git a/modules/home/programs/terminals/ghostty.nix b/modules/home/programs/terminals/ghostty.nix index b911d82..235f957 100644 --- a/modules/home/programs/terminals/ghostty.nix +++ b/modules/home/programs/terminals/ghostty.nix @@ -7,7 +7,7 @@ { home.packages = with pkgs; - lib.mkIf (stdenv.isLinux && config.nixcfg.gui.enable) [ + lib.mkIf (stdenv.hostPlatform.isLinux && config.nixcfg.gui.enable) [ ghostty ]; xdg.configFile."ghostty/config".text = '' diff --git a/modules/home/programs/terminals/hyper.nix b/modules/home/programs/terminals/hyper.nix index 5a2213d..0229cce 100644 --- a/modules/home/programs/terminals/hyper.nix +++ b/modules/home/programs/terminals/hyper.nix @@ -30,7 +30,9 @@ in }; config = lib.mkIf cfg.enable { home.packages = [ cfg.package ]; - home.file.".hyper.js" = lib.mkIf pkgs.stdenv.isDarwin { text = cfg.config_file; }; - xdg.configFile."Hyper/.hyper.js" = lib.mkIf pkgs.stdenv.isLinux { text = cfg.config_file; }; + home.file.".hyper.js" = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin { text = cfg.config_file; }; + xdg.configFile."Hyper/.hyper.js" = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { + text = cfg.config_file; + }; }; } diff --git a/modules/home/session.nix b/modules/home/session.nix index ff956a8..2d88cf8 100644 --- a/modules/home/session.nix +++ b/modules/home/session.nix @@ -40,7 +40,7 @@ in "/opt/homebrew/bin" "/opt/homebrew/sbin" ] - ++ lib.optionals pkgs.stdenv.isDarwin [ + ++ lib.optionals pkgs.stdenv.hostPlatform.isDarwin [ "/System/Cryptexes/App/usr/bin" ] ++ [ @@ -53,7 +53,7 @@ in "/usr/local/games" "/usr/games" ] - ++ lib.optionals pkgs.stdenv.isDarwin [ + ++ lib.optionals pkgs.stdenv.hostPlatform.isDarwin [ "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin" "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin" "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin" diff --git a/modules/home/sops.nix b/modules/home/sops.nix index 31d3e55..71f5c88 100644 --- a/modules/home/sops.nix +++ b/modules/home/sops.nix @@ -18,7 +18,7 @@ in defaultSopsFile = ../../secrets.yaml; age = { keyFile = "${config.home.homeDirectory}/${ - if pkgs.stdenv.isDarwin then "Library/Application Support" else ".config" + if pkgs.stdenv.hostPlatform.isDarwin then "Library/Application Support" else ".config" }/sops/age/keys.txt"; }; }; diff --git a/modules/home/users/briar.nix b/modules/home/users/briar.nix index 3da8a34..52c48b8 100644 --- a/modules/home/users/briar.nix +++ b/modules/home/users/briar.nix @@ -17,6 +17,6 @@ in flavor = "latte"; accent = "pink"; }; - services.easyeffects.enable = pkgs.stdenv.isLinux && cfg.gui.enable; + services.easyeffects.enable = pkgs.stdenv.hostPlatform.isLinux && cfg.gui.enable; }; } diff --git a/modules/home/users/chloe.nix b/modules/home/users/chloe.nix index 7b16e2a..1775f92 100644 --- a/modules/home/users/chloe.nix +++ b/modules/home/users/chloe.nix @@ -23,6 +23,6 @@ in spotify discord ]; - services.easyeffects.enable = pkgs.stdenv.isLinux && cfg.gui.enable; + services.easyeffects.enable = pkgs.stdenv.hostPlatform.isLinux && cfg.gui.enable; }; } diff --git a/modules/home/users/toyvo.nix b/modules/home/users/toyvo.nix index 5a13d48..4e81f5e 100644 --- a/modules/home/users/toyvo.nix +++ b/modules/home/users/toyvo.nix @@ -43,7 +43,7 @@ in export OPENCODE_API_KEY ''; beets = { - enable = pkgs.stdenv.isLinux; + enable = pkgs.stdenv.hostPlatform.isLinux; settings = { plugins = [ "fetchart" @@ -142,7 +142,7 @@ in ]; }; # TODO: undo - rio.enable = cfg.gui.enable && pkgs.stdenv.isLinux; + rio.enable = cfg.gui.enable && pkgs.stdenv.hostPlatform.isLinux; ssh = let identityConfig = { @@ -214,7 +214,7 @@ in export OPENCODE_API_KEY ''; }; - services.easyeffects.enable = pkgs.stdenv.isLinux && cfg.gui.enable; + services.easyeffects.enable = pkgs.stdenv.hostPlatform.isLinux && cfg.gui.enable; sops = { secrets = { github_toyvo_pat = { }; diff --git a/modules/os/console.nix b/modules/os/console.nix index 4b7728c..26ced5a 100644 --- a/modules/os/console.nix +++ b/modules/os/console.nix @@ -74,7 +74,7 @@ in zip zstd ] - ++ lib.optionals stdenv.isLinux [ + ++ lib.optionals stdenv.hostPlatform.isLinux [ aha clinfo fwupd diff --git a/modules/os/dev.nix b/modules/os/dev.nix index 9e1f175..ef6dbd4 100644 --- a/modules/os/dev.nix +++ b/modules/os/dev.nix @@ -55,7 +55,7 @@ in ++ lib.optionals cfg.gui.enable [ jetbrains-toolbox ] - ++ lib.optionals stdenv.isLinux [ + ++ lib.optionals stdenv.hostPlatform.isLinux [ gcc clang ] diff --git a/modules/os/gui.nix b/modules/os/gui.nix index 6a76992..ec49e18 100644 --- a/modules/os/gui.nix +++ b/modules/os/gui.nix @@ -10,7 +10,7 @@ in { options.nixcfg.gui.enable = lib.mkEnableOption "GUI Applications" // { # macs will always have GUI enabled - default = pkgs.stdenv.isDarwin; + default = pkgs.stdenv.hostPlatform.isDarwin; }; config = lib.mkIf cfg.gui.enable { @@ -33,7 +33,7 @@ in brave inkscape ] - ++ lib.optionals stdenv.isLinux [ + ++ lib.optionals stdenv.hostPlatform.isLinux [ element-desktop firefox ghostty @@ -55,7 +55,7 @@ in # [ # logseq # ] - ++ lib.optionals stdenv.isDarwin [ + ++ lib.optionals stdenv.hostPlatform.isDarwin [ appcleaner # gimp2 pinentry_mac diff --git a/modules/os/users/chloe.nix b/modules/os/users/chloe.nix index 8a195e0..4c3fadf 100644 --- a/modules/os/users/chloe.nix +++ b/modules/os/users/chloe.nix @@ -6,7 +6,7 @@ }: let cfg = config.userPresets; - homePath = if pkgs.stdenv.isDarwin then "/Users" else "/home"; + homePath = if pkgs.stdenv.hostPlatform.isDarwin then "/Users" else "/home"; enableGui = config.nixcfg.gui.enable; in { @@ -31,7 +31,7 @@ in home = "${homePath}/${cfg.chloe.name}"; shell = pkgs.fish; } - (lib.mkIf pkgs.stdenv.isLinux { + (lib.mkIf pkgs.stdenv.hostPlatform.isLinux { isNormalUser = true; extraGroups = [ "networkmanager" @@ -43,7 +43,7 @@ in ] ); }; - groups.${cfg.chloe.name} = lib.mkIf pkgs.stdenv.isLinux { + groups.${cfg.chloe.name} = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { gid = config.ids.gids.chloe; }; }; diff --git a/modules/os/users/hermes.nix b/modules/os/users/hermes.nix index 47b0122..861faed 100644 --- a/modules/os/users/hermes.nix +++ b/modules/os/users/hermes.nix @@ -21,7 +21,7 @@ in options.nixcfg.users.hermes.enable = lib.mkEnableOption "hermes system user"; config = lib.mkIf cfg.enable { - users.users.hermes = lib.mkIf pkgs.stdenv.isLinux { + users.users.hermes = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { uid = hermesUid; subUidRanges = [ { @@ -36,7 +36,7 @@ in } ]; }; - users.groups.hermes = lib.mkIf pkgs.stdenv.isLinux { + users.groups.hermes = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { gid = hermesGid; }; }; diff --git a/modules/os/users/root.nix b/modules/os/users/root.nix index 59dc5f9..000139d 100644 --- a/modules/os/users/root.nix +++ b/modules/os/users/root.nix @@ -5,7 +5,7 @@ ... }: let - rootHomeDirectory = if pkgs.stdenv.isDarwin then "/var/root" else "/root"; + rootHomeDirectory = if pkgs.stdenv.hostPlatform.isDarwin then "/var/root" else "/root"; in { options.userPresets.root.enable = lib.mkEnableOption "root user"; @@ -17,7 +17,7 @@ in home = rootHomeDirectory; shell = pkgs.zsh; } - (lib.mkIf pkgs.stdenv.isLinux { + (lib.mkIf pkgs.stdenv.hostPlatform.isLinux { hashedPassword = ""; }) ]; diff --git a/modules/os/users/toyvo.nix b/modules/os/users/toyvo.nix index 7a27a23..fe0bfd2 100644 --- a/modules/os/users/toyvo.nix +++ b/modules/os/users/toyvo.nix @@ -7,7 +7,7 @@ }: let cfg = config.userPresets; - homePath = if pkgs.stdenv.isDarwin then "/Users" else "/home"; + homePath = if pkgs.stdenv.hostPlatform.isDarwin then "/Users" else "/home"; enableGui = config.nixcfg.gui.enable or false; in { @@ -39,7 +39,7 @@ in homelab.publicKeys."yubikey_usba_ed25519_sk.pub" ]; } - (lib.mkIf pkgs.stdenv.isLinux { + (lib.mkIf pkgs.stdenv.hostPlatform.isLinux { isNormalUser = true; extraGroups = [ "networkmanager" @@ -55,7 +55,7 @@ in ] ); }; - groups.${cfg.toyvo.name} = lib.mkIf pkgs.stdenv.isLinux { + groups.${cfg.toyvo.name} = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { gid = config.ids.gids.toyvo; }; }; @@ -76,7 +76,7 @@ in # NixOS activation resets home directory permissions via chmod, # which wipes ACLs. Restore them after the users activation script. - system.activationScripts.fixToyVoACLs = lib.mkIf pkgs.stdenv.isLinux { + system.activationScripts.fixToyVoACLs = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { deps = [ "users" ]; text = '' ${pkgs.acl}/bin/setfacl -m u:hermes:rx ${homePath}/${cfg.toyvo.name} 2>/dev/null || true diff --git a/pkgs/setup-sops/default.nix b/pkgs/setup-sops/default.nix index ebf7a68..b846da9 100644 --- a/pkgs/setup-sops/default.nix +++ b/pkgs/setup-sops/default.nix @@ -6,7 +6,9 @@ ... }: writeShellScriptBin "setup-sops" '' - destination="$HOME/${if stdenv.isDarwin then "Library/Application Support" else ".config"}/sops/age" + destination="$HOME/${ + if stdenv.hostPlatform.isDarwin then "Library/Application Support" else ".config" + }/sops/age" mkdir -p "$destination" echo "$(${age}/bin/age-keygen)" > "$destination/keys.txt" sudo mkdir -p /var/sops/age diff --git a/todos.md b/todos.md new file mode 100644 index 0000000..c631bd0 --- /dev/null +++ b/todos.md @@ -0,0 +1,32 @@ +# TODOs + +Outstanding work and follow-up items for this repository. + +> AI agents: per the "Todo Tracking" section of [AGENTS.md](AGENTS.md), you are +> expected to keep this file up to date — check off completed items, and add +> deferred work or manual steps before finishing a task. + +## Forgejo (git.diekvoss.net) + +### Manual steps to finish the deployment + +- [ ] Deploy the nas and router (`deploy .#nas`; router via `nixos-rebuild switch --flake .#router`) +- [ ] Add a `git.diekvoss.net` A record in Cloudflare pointing at the router (the `*.diekvoss.net` wildcard cert already covers it) +- [ ] Create the initial admin user (self-registration is disabled). On the nas: + ```bash + sudo -u forgejo $(systemctl show forgejo -p ExecStart --value | awk '{print $1}') \ + --work-path /mnt/POOL/forgejo --config /mnt/POOL/forgejo/custom/conf/app.ini \ + admin user create --admin --username toyvo --email collin@diekvoss.com --password 'CHANGEME' + ``` + +### Enhancements + +- [ ] Git over SSH via the domain: forward port 22 on the router and switch the router's ssh port (e.g. `2222` & `22` → `nas:22`) so clone URLs like `ssh://forgejo@git.diekvoss.net/user/repo.git` work +- [ ] Authentik OIDC login for Forgejo +- [ ] Periodic backups via `services.forgejo.dump.enable` +- [ ] Homepage widget (`type: gitea`) with an API key stored in sops as `HOMEPAGE_VAR_FORGEJO_API_KEY` + +## Manually written down by human + +- [ ] allow some ip ranges past forward auth, eg 10.200.x.x +- [ ] setup forwarding to binary cache/nas with nix.settings.post-build-hook -- 2.51.2