From def062a84cbd441758fbf5c5a395237fda3354ff Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Mon, 9 Feb 2026 03:16:09 +0100 Subject: [PATCH 1/2] feat: add instruction for claude hooks --- .claude/devil-advocate.md | 28 ++++++++++++++++++++++++++++ .claude/lint-fixer.md | 26 ++++++++++++++++++++++++++ .claude/secret-scanner.md | 35 +++++++++++++++++++++++++++++++++++ .claude/test-runner.md | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 .claude/devil-advocate.md create mode 100644 .claude/lint-fixer.md create mode 100644 .claude/secret-scanner.md create mode 100644 .claude/test-runner.md diff --git a/.claude/devil-advocate.md b/.claude/devil-advocate.md new file mode 100644 index 0000000..16195f6 --- /dev/null +++ b/.claude/devil-advocate.md @@ -0,0 +1,28 @@ +# Devil's Advocate Review — Project Conventions + +## Critical rules (must never be violated) + +- **Never update `system.stateVersion`** — it must remain at the original installation version. NixOS upgrades are done by updating the `channel` file, not `stateVersion`. +- **Never modify `secrets.yaml` directly** — these are SOPS-encrypted. Changes must be made via `nix-shell -p sops --run 'sops '`. +- **No plaintext secrets in Nix files** — passwords, API keys, tokens, and private keys must use `sops.secrets`, never hardcoded strings. + +## Architecture rules + +- **Explicit module imports only** — no wildcard or directory-level imports. Each module must be imported by its explicit path. +- **Host structure** — each host in `hosts//` must have `configuration.nix` and `hardware-configuration.nix`. Symlinks `fleet.nix` and `utils/` point to root level. +- **Shared modules** go in `utils/modules/`, not duplicated across hosts. +- **Custom packages** in `utils/pkgs/` must include an `update.sh` script for automated version updates. + +## Code style + +- **Two-space indentation** in all Nix files. +- **Lower kebab-case** for file and directory naming. +- **Conventional Commits** format: `fix:`, `feat:`, `chore:`, with optional scope by host (e.g., `fix(mail):`). +- No "Generated with Claude Code" or "Co-Authored-By: Claude" footers in commits. + +## Common review checks + +- New network services must have corresponding `networking.firewall.allowedTCPPorts` or `allowedUDPPorts` entries. +- New `sops.secrets.` references must have a corresponding entry in the host's `secrets.yaml` (or the relevant module's `secrets.yaml`). +- Changes to `utils/` affect all hosts — verify cross-host compatibility. +- Package modifications should be testable with a direct `nix-build`, not just `test-configuration`. diff --git a/.claude/lint-fixer.md b/.claude/lint-fixer.md new file mode 100644 index 0000000..93af5e7 --- /dev/null +++ b/.claude/lint-fixer.md @@ -0,0 +1,26 @@ +# Lint Fixer Instructions + +## Formatter + +This project uses **nixpkgs-fmt** for Nix file formatting. + +## How to run + +1. Find changed `.nix` files: + ```bash + git diff --name-only --diff-filter=d HEAD | grep '\.nix$' + ``` +2. Format only those files: + ```bash + nix run nixpkgs#nixpkgs-fmt -- ... + ``` +3. Stage any formatting changes: + ```bash + git add + ``` + +## Notes + +- Only format files that were actually modified, not the entire repo. +- There is no `.editorconfig` or other formatter config; `nixpkgs-fmt` uses its own defaults. +- Non-Nix files do not need formatting. diff --git a/.claude/secret-scanner.md b/.claude/secret-scanner.md new file mode 100644 index 0000000..34333af --- /dev/null +++ b/.claude/secret-scanner.md @@ -0,0 +1,35 @@ +# Secret Scanner Allowlist + +## False positive patterns to ignore + +### SOPS-encrypted secrets files +All `secrets.yaml` files in this repo are **SOPS-encrypted** (not plaintext). They contain encrypted ciphertext, not actual secrets. Ignore: +- `hosts/*/secrets.yaml` +- `hosts/*/modules/*/secrets.yaml` +- `utils/modules/*/secrets.yaml` +- Any `.yaml` file matching a `path_regex` in `.sops.yaml` + +### Age public keys +The file `.sops.yaml` contains **age public keys** (prefix `age1...`). These are public keys used for encryption, not private keys. Ignore: +- Age public keys (`age1...`) in `.sops.yaml` +- Age public key references (YAML anchors like `&dominik`, `&fw`, etc.) in `.sops.yaml` + +### Nix hashes and store paths +Nix derivations contain SHA256/SRI hashes for source integrity verification. These are not secrets. Ignore: +- `sha256` / `hash` attributes in `.nix` files (e.g., `sha256 = "sha256-..."` or `hash = "sha256-..."`) +- `npmDepsHash`, `vendorHash`, `cargoHash`, and similar dependency hashes +- Nix store paths (`/nix/store/...`) +- `nix-prefetch-url` output hashes +- SRI hashes (`sha256-...`, `sha512-...`) + +### sops-nix module configuration +Nix files reference sops secret paths as configuration, not actual secret values. Ignore: +- `sops.secrets.` attribute sets +- `sopsFile` path references +- `key` attributes within `sops.secrets` blocks (these are YAML key paths, not cryptographic keys) +- `neededForUsers` attributes + +### Other safe patterns +- `flake.lock` — contains Nix flake input hashes (integrity, not secrets) +- SSH **public** key strings in NixOS configuration (e.g., `openssh.authorizedKeys.keys`) +- Wireguard **public** keys in NixOS configuration diff --git a/.claude/test-runner.md b/.claude/test-runner.md new file mode 100644 index 0000000..63373d0 --- /dev/null +++ b/.claude/test-runner.md @@ -0,0 +1,34 @@ +# Test Runner Instructions + +## Determine affected hosts + +Run `git diff --name-only HEAD` (or `git diff --name-only` for unstaged changes) to find changed files. + +### Scope rules + +- If changes are **only** under `hosts//`, test only that specific host: + ```bash + ./scripts/test-configuration + ``` +- If changes touch `utils/`, root-level `.nix` files, or any shared configuration, test **all** hosts: + ```bash + for host in amzebs-01 dev fw mail nas nb web-arm; do + ./scripts/test-configuration "$host" + done + ``` + +### Custom package changes + +If any files under `utils/pkgs//` were modified, also build the package directly: + +```bash +nix-build -E 'with import { overlays = [ (import ./utils/overlays/packages.nix) ]; config.allowUnfree = true; }; ' +``` + +This catches build failures that `test-configuration` (evaluation-only) would miss. + +## Notes + +- Each `test-configuration` run performs a `nix-instantiate` dry-build (evaluation only, no binary builds). +- A non-zero exit code from any host means the test failed. +- Hosts: `amzebs-01`, `dev`, `fw`, `mail`, `nas`, `nb`, `web-arm`. From 5c67309439c82ceee48b92a52442fd2853fbac6f Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Mon, 9 Feb 2026 03:50:51 +0100 Subject: [PATCH 2/2] feat: add global ssh key configuration --- .claude/test-runner.md | 5 +- CLAUDE.md | 2 +- hosts/amzebs-01/configuration.nix | 6 +- hosts/dev/configuration.nix | 21 ++-- hosts/fw/configuration.nix | 5 +- hosts/fw/modules/forgejo-runner.nix | 152 +++++++++++++------------- hosts/fw/modules/forgejo.nix | 37 +++---- hosts/fw/modules/gitea-vm.nix | 158 ++++++++++++++-------------- hosts/fw/modules/gitea.nix | 39 ++++--- hosts/fw/modules/openclaw-vm.nix | 5 +- hosts/fw/modules/web/default.nix | 33 +++--- hosts/mail/configuration.nix | 7 +- hosts/nas/configuration.nix | 8 +- hosts/web-arm/configuration.nix | 5 +- todos.md | 2 +- utils/ssh-keys.nix | 5 + 16 files changed, 236 insertions(+), 254 deletions(-) create mode 100644 utils/ssh-keys.nix diff --git a/.claude/test-runner.md b/.claude/test-runner.md index 63373d0..07b3ce1 100644 --- a/.claude/test-runner.md +++ b/.claude/test-runner.md @@ -12,7 +12,7 @@ Run `git diff --name-only HEAD` (or `git diff --name-only` for unstaged changes) ``` - If changes touch `utils/`, root-level `.nix` files, or any shared configuration, test **all** hosts: ```bash - for host in amzebs-01 dev fw mail nas nb web-arm; do + for host in amzebs-01 fw mail nas nb web-arm; do ./scripts/test-configuration "$host" done ``` @@ -31,4 +31,5 @@ This catches build failures that `test-configuration` (evaluation-only) would mi - Each `test-configuration` run performs a `nix-instantiate` dry-build (evaluation only, no binary builds). - A non-zero exit code from any host means the test failed. -- Hosts: `amzebs-01`, `dev`, `fw`, `mail`, `nas`, `nb`, `web-arm`. +- Testable hosts: `amzebs-01`, `fw`, `mail`, `nas`, `nb`, `web-arm`. +- `dev` is not independently testable (no `hardware-configuration.nix`); it is deployed as a MicroVM via the `fw` host, so testing `fw` covers `dev`. diff --git a/CLAUDE.md b/CLAUDE.md index e26d6f9..1579b00 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -89,7 +89,7 @@ nix-build -E 'with import { overlays = [ (import ./utils/overlays/pack ## Workflow -**IMPORTANT: Always run `./scripts/test-configuration ` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing. +Run `./scripts/test-configuration ` to verify NixOS configuration changes build successfully. ## Conventions diff --git a/hosts/amzebs-01/configuration.nix b/hosts/amzebs-01/configuration.nix index 1485f94..5cc3a40 100644 --- a/hosts/amzebs-01/configuration.nix +++ b/hosts/amzebs-01/configuration.nix @@ -46,11 +46,7 @@ networking.domain = "cloonar.com"; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFshMhXwS0FQFPlITipshvNKrV8sA52ZFlnaoHd1thKg" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; programs.ssh = { knownHosts = { diff --git a/hosts/dev/configuration.nix b/hosts/dev/configuration.nix index ae62573..d0f3f65 100644 --- a/hosts/dev/configuration.nix +++ b/hosts/dev/configuration.nix @@ -1,7 +1,7 @@ { config, lib, pkgs, ... }: let - projectsDir = "projects"; # Relative to /home/dominik + projectsDir = "projects"; # Relative to /home/dominik repositories = [ { url = "forgejo@git.cloonar.com:Cloonar/wohnservice-wien-typo3.git"; path = "cloonar/wohnservice-wien"; } @@ -46,12 +46,9 @@ in uid = 1000; home = "/home/dominik"; extraGroups = [ "wheel" "docker" ]; - openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; }; - users.groups.users = {}; + users.groups.users = { }; services.openssh.enable = true; programs.zsh.enable = true; @@ -103,12 +100,12 @@ in Group = "users"; }; script = '' - mkdir -p /home/dominik/.ddev - if [ ! -f /home/dominik/.ddev/global_config.yaml ]; then - cat > /home/dominik/.ddev/global_config.yaml << 'EOF' -router_bind_all_interfaces: true -EOF - fi + mkdir -p /home/dominik/.ddev + if [ ! -f /home/dominik/.ddev/global_config.yaml ]; then + cat > /home/dominik/.ddev/global_config.yaml << 'EOF' + router_bind_all_interfaces: true + EOF + fi ''; }; } diff --git a/hosts/fw/configuration.nix b/hosts/fw/configuration.nix index 083913b..d9b8591 100644 --- a/hosts/fw/configuration.nix +++ b/hosts/fw/configuration.nix @@ -184,10 +184,7 @@ zramSwap.enable = true; networking.hostName = "fw"; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; # backups borgbackup.repo = "u149513-sub2@u149513-sub2.your-backup.de:borg"; diff --git a/hosts/fw/modules/forgejo-runner.nix b/hosts/fw/modules/forgejo-runner.nix index c8f93f8..d509d3a 100644 --- a/hosts/fw/modules/forgejo-runner.nix +++ b/hosts/fw/modules/forgejo-runner.nix @@ -1,87 +1,89 @@ -{ config, lib, pkgs, ... }: let +{ config, lib, pkgs, ... }: +let # Short names to fit Linux interface name limit (15 chars for vm-fj-runner-1) - runners = ["fj-runner-1" "fj-runner-2"]; + runners = [ "fj-runner-1" "fj-runner-2" ]; # Offset by 5 to avoid conflicts with Gitea runners (01-02) runnerOffset = 5; -in { - microvm.vms = lib.mapAttrs (runner: idx: { - config = { - microvm = { - mem = 8096; - shares = [ - { - source = "/nix/store"; - mountPoint = "/nix/.ro-store"; - tag = "ro-store"; - proto = "virtiofs"; - } - { - source = "/run/secrets"; - mountPoint = "/run/secrets"; - tag = "ro-token"; - proto = "virtiofs"; - } - ]; - volumes = [ - { - image = "rootfs.img"; - mountPoint = "/"; - size = 51200; - } - ]; - interfaces = [ - { - type = "tap"; - id = "vm-${runner}"; - mac = "02:00:00:00:00:0${toString (idx + runnerOffset)}"; - } - ]; - }; +in +{ + microvm.vms = lib.mapAttrs + (runner: idx: { + config = { + microvm = { + mem = 8096; + shares = [ + { + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + tag = "ro-store"; + proto = "virtiofs"; + } + { + source = "/run/secrets"; + mountPoint = "/run/secrets"; + tag = "ro-token"; + proto = "virtiofs"; + } + ]; + volumes = [ + { + image = "rootfs.img"; + mountPoint = "/"; + size = 51200; + } + ]; + interfaces = [ + { + type = "tap"; + id = "vm-${runner}"; + mac = "02:00:00:00:00:0${toString (idx + runnerOffset)}"; + } + ]; + }; - systemd.network.networks."10-lan" = { - matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString (idx + runnerOffset)}"; - address = [ "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}/24" ]; - gateway = [ "${config.networkPrefix}.97.1" ]; - dns = [ "${config.networkPrefix}.97.1" ]; - }; + systemd.network.networks."10-lan" = { + matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString (idx + runnerOffset)}"; + address = [ "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}/24" ]; + gateway = [ "${config.networkPrefix}.97.1" ]; + dns = [ "${config.networkPrefix}.97.1" ]; + }; - networking.hostName = runner; + networking.hostName = runner; - virtualisation.podman.enable = true; + virtualisation.podman.enable = true; - services.gitea-actions-runner.instances.${runner} = { - enable = true; - url = "https://git.cloonar.com"; - name = runner; - tokenFile = "/run/secrets/forgejo-runner-token"; - labels = [ - "ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0" - ]; - settings = { - container = { - network = "podman"; - }; - cache = { - enabled = true; - host = "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}"; - port = 8088; + services.gitea-actions-runner.instances.${runner} = { + enable = true; + url = "https://git.cloonar.com"; + name = runner; + tokenFile = "/run/secrets/forgejo-runner-token"; + labels = [ + "ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0" + ]; + settings = { + container = { + network = "podman"; + }; + cache = { + enabled = true; + host = "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}"; + port = 8088; + }; }; }; + + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 8088 ]; + }; + + system.stateVersion = "22.05"; }; + }) + (lib.listToAttrs (lib.lists.imap1 (i: v: { name = v; value = i; }) runners)); - services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - ]; - - networking.firewall = { - enable = true; - allowedTCPPorts = [ 8088 ]; - }; - - system.stateVersion = "22.05"; - }; - }) (lib.listToAttrs (lib.lists.imap1 (i: v: { name=v; value=i; }) runners)); - - sops.secrets.forgejo-runner-token = {}; + sops.secrets.forgejo-runner-token = { }; } diff --git a/hosts/fw/modules/forgejo.nix b/hosts/fw/modules/forgejo.nix index afb4cd1..19d1704 100644 --- a/hosts/fw/modules/forgejo.nix +++ b/hosts/fw/modules/forgejo.nix @@ -29,7 +29,7 @@ in privateNetwork = true; hostBridge = "server"; hostAddress = "${networkPrefix}.97.1"; - localAddress = "${networkPrefix}.97.55/24"; # Different from gitea's .50 + localAddress = "${networkPrefix}.97.55/24"; # Different from gitea's .50 bindMounts = { "/var/lib/forgejo" = { hostPath = "/var/lib/forgejo/"; @@ -50,7 +50,7 @@ in ]; environment.systemPackages = with pkgs; [ - vim # my preferred editor + vim # my preferred editor ]; networking = { @@ -96,29 +96,29 @@ in openid = { ENABLE_OPENID_SIGNIN = false; ENABLE_OPENID_SIGNUP = true; - WHITELISTED_URIS = "auth.cloonar.com"; + WHITELISTED_URIS = "auth.cloonar.com"; }; service = { - DISABLE_REGISTRATION = false; - ALLOW_ONLY_EXTERNAL_REGISTRATION = true; - SHOW_REGISTRATION_BUTTON = false; - ENABLE_NOTIFY_MAIL = true; - REQUIRE_SIGNIN_VIEW = false; + DISABLE_REGISTRATION = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + SHOW_REGISTRATION_BUTTON = false; + ENABLE_NOTIFY_MAIL = true; + REQUIRE_SIGNIN_VIEW = false; }; mailer = { - ENABLED = true; - FROM = "Forgejo Cloonar "; - PROTOCOL = "smtp+starttls"; - SMTP_ADDR = "mail.cloonar.com"; - SMTP_PORT = 587; - USER = "gitea@cloonar.com"; + ENABLED = true; + FROM = "Forgejo Cloonar "; + PROTOCOL = "smtp+starttls"; + SMTP_ADDR = "mail.cloonar.com"; + SMTP_PORT = 587; + USER = "gitea@cloonar.com"; }; actions = { ENABLED = true; - DEFAULT_ACTIONS_URL = "github"; # Pull actions from GitHub + DEFAULT_ACTIONS_URL = "github"; # Pull actions from GitHub }; attachment = { - MAX_SIZE = 2048; # 2GB in MB for general attachments + MAX_SIZE = 2048; # 2GB in MB for general attachments }; packages = { ENABLED = true; @@ -130,10 +130,7 @@ in systemd.services.forgejo.serviceConfig.EnvironmentFile = "/run/secrets/forgejo-mailer-password"; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix; users.users.forgejo = user; users.groups.forgejo = group; diff --git a/hosts/fw/modules/gitea-vm.nix b/hosts/fw/modules/gitea-vm.nix index c3afdea..8973661 100644 --- a/hosts/fw/modules/gitea-vm.nix +++ b/hosts/fw/modules/gitea-vm.nix @@ -1,88 +1,90 @@ -{ config, lib, nixpkgs, pkgs, ... }: let +{ config, lib, nixpkgs, pkgs, ... }: +let # hostname = "git-02"; # json = pkgs.formats.json { }; - runners = ["git-runner-1" "git-runner-2"]; - indexedRunners = lib.lists.imap1 (i: v: { name=v; value=i; }) runners; -in { - microvm.vms = lib.mapAttrs (runner: idx: { - config = { - microvm = { - mem = 8096; - shares = [ - { - source = "/nix/store"; - mountPoint = "/nix/.ro-store"; - tag = "ro-store"; - proto = "virtiofs"; - } - { - source = "/run/secrets"; - mountPoint = "/run/secrets"; - tag = "ro-token"; - proto = "virtiofs"; - } - ]; - volumes = [ - { - image = "rootfs.img"; - mountPoint = "/"; - size = 51200; - } - ]; - interfaces = [ - { - type = "tap"; - id = "vm-${runner}"; - mac = "02:00:00:00:00:0${toString idx}"; - } - ]; - }; + runners = [ "git-runner-1" "git-runner-2" ]; + indexedRunners = lib.lists.imap1 (i: v: { name = v; value = i; }) runners; +in +{ + microvm.vms = lib.mapAttrs + (runner: idx: { + config = { + microvm = { + mem = 8096; + shares = [ + { + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + tag = "ro-store"; + proto = "virtiofs"; + } + { + source = "/run/secrets"; + mountPoint = "/run/secrets"; + tag = "ro-token"; + proto = "virtiofs"; + } + ]; + volumes = [ + { + image = "rootfs.img"; + mountPoint = "/"; + size = 51200; + } + ]; + interfaces = [ + { + type = "tap"; + id = "vm-${runner}"; + mac = "02:00:00:00:00:0${toString idx}"; + } + ]; + }; - systemd.network.networks."10-lan" = { - matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString idx}"; - address = [ "${config.networkPrefix}.97.5${toString idx}/24" ]; - gateway = [ "${config.networkPrefix}.97.1" ]; - dns = [ "${config.networkPrefix}.97.1" ]; - }; + systemd.network.networks."10-lan" = { + matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString idx}"; + address = [ "${config.networkPrefix}.97.5${toString idx}/24" ]; + gateway = [ "${config.networkPrefix}.97.1" ]; + dns = [ "${config.networkPrefix}.97.1" ]; + }; - networking.hostName = runner; + networking.hostName = runner; - virtualisation.podman.enable = true; + virtualisation.podman.enable = true; - services.gitea-actions-runner.instances.${runner} = { - enable = true; - url = "https://git.cloonar.com"; - name = runner; - tokenFile = "/run/secrets/gitea-runner-token"; - labels = [ - # "ubuntu-latest:docker://shivammathur/node:latest" - "ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0" - ]; - settings = { - container = { - network = "podman"; - }; - cache = { - enabled = true; - host = "${config.networkPrefix}.97.5${toString idx}"; # LAN IP of the machine running act_runner - port = 8088; # any free TCP port + services.gitea-actions-runner.instances.${runner} = { + enable = true; + url = "https://git.cloonar.com"; + name = runner; + tokenFile = "/run/secrets/gitea-runner-token"; + labels = [ + # "ubuntu-latest:docker://shivammathur/node:latest" + "ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0" + ]; + settings = { + container = { + network = "podman"; + }; + cache = { + enabled = true; + host = "${config.networkPrefix}.97.5${toString idx}"; # LAN IP of the machine running act_runner + port = 8088; # any free TCP port + }; }; }; + + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix; + + networking.firewall = { + enable = true; # default, but being explicit is fine + allowedTCPPorts = [ 8088 ]; + }; + + system.stateVersion = "22.05"; }; - - services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - ]; - - networking.firewall = { - enable = true; # default, but being explicit is fine - allowedTCPPorts = [ 8088 ]; - }; - - system.stateVersion = "22.05"; - }; - }) (lib.listToAttrs (lib.lists.imap1 (i: v: { name=v; value=i; }) runners)); + }) + (lib.listToAttrs (lib.lists.imap1 (i: v: { name = v; value = i; }) runners)); # microvm.vms = { # gitea = { @@ -240,10 +242,10 @@ in { # }; # }; - sops.secrets.gitea-runner-token = {}; + sops.secrets.gitea-runner-token = { }; environment = { - systemPackages = [ + systemPackages = [ pkgs.qemu pkgs.quickemu ]; diff --git a/hosts/fw/modules/gitea.nix b/hosts/fw/modules/gitea.nix index e74c0ce..1a5f4d8 100644 --- a/hosts/fw/modules/gitea.nix +++ b/hosts/fw/modules/gitea.nix @@ -3,7 +3,7 @@ let cids = import ../modules/staticids.nix; domain = "git.cloonar.com"; networkPrefix = config.networkPrefix; - + user = { isSystemUser = true; uid = cids.uids.gitea; @@ -50,7 +50,7 @@ in ]; environment.systemPackages = with pkgs; [ - vim # my preferred editor + vim # my preferred editor ]; networking = { @@ -94,26 +94,26 @@ in openid = { ENABLE_OPENID_SIGNIN = false; ENABLE_OPENID_SIGNUP = true; - WHITELISTED_URIS = "auth.cloonar.com"; + WHITELISTED_URIS = "auth.cloonar.com"; }; service = { - DISABLE_REGISTRATION = false; - ALLOW_ONLY_EXTERNAL_REGISTRATION = true; - SHOW_REGISTRATION_BUTTON = false; - ENABLE_NOTIFY_MAIL = true; - REQUIRE_SIGNIN_VIEW = false; + DISABLE_REGISTRATION = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + SHOW_REGISTRATION_BUTTON = false; + ENABLE_NOTIFY_MAIL = true; + REQUIRE_SIGNIN_VIEW = false; }; mailer = { - ENABLED = true; - FROM = "Gitea Cloonar "; - PROTOCOL = "smtp+starttls"; - SMTP_ADDR = "mail.cloonar.com"; - SMTP_PORT = 587; - USER = "gitea@cloonar.com"; + ENABLED = true; + FROM = "Gitea Cloonar "; + PROTOCOL = "smtp+starttls"; + SMTP_ADDR = "mail.cloonar.com"; + SMTP_PORT = 587; + USER = "gitea@cloonar.com"; }; - actions.ENABLED=true; + actions.ENABLED = true; attachment = { - MAX_SIZE = 2048; # 2GB in MB for general attachments + MAX_SIZE = 2048; # 2GB in MB for general attachments }; packages = { ENABLED = true; @@ -122,10 +122,7 @@ in }; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix; users.users.gitea = user; users.groups.gitea = group; @@ -134,7 +131,7 @@ in }; }; - sops.secrets.gitea-runner = {}; + sops.secrets.gitea-runner = { }; sops.secrets.gitea-mailer-password = { owner = "gitea"; restartUnits = [ "container@git.service" ]; diff --git a/hosts/fw/modules/openclaw-vm.nix b/hosts/fw/modules/openclaw-vm.nix index a4d5508..b835897 100644 --- a/hosts/fw/modules/openclaw-vm.nix +++ b/hosts/fw/modules/openclaw-vm.nix @@ -11,10 +11,7 @@ let gateway = "${config.networkPrefix}.97.1"; tapDevice = "vm-openclaw"; - sshAuthorizedKeys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + sshAuthorizedKeys = import ../utils/ssh-keys.nix; gitRepoUrl = "https://git.cloonar.com/openclawd/config.git"; diff --git a/hosts/fw/modules/web/default.nix b/hosts/fw/modules/web/default.nix index dfc77fd..6b85dd9 100644 --- a/hosts/fw/modules/web/default.nix +++ b/hosts/fw/modules/web/default.nix @@ -1,8 +1,10 @@ -{ lib, pkgs, config, ... }: let +{ lib, pkgs, config, ... }: +let hostname = "web-02"; json = pkgs.formats.json { }; impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz"; -in { +in +{ microvm.vms = { web = { pkgs = import pkgs.path { @@ -96,7 +98,7 @@ in { }; environment.systemPackages = with pkgs; [ - vim # my preferred editor + vim # my preferred editor ]; networking.hostName = hostname; @@ -104,21 +106,18 @@ in { services.openssh = { enable = true; hostKeys = [ - { - path = "/persist/etc/ssh/ssh_host_ed25519_key"; - type = "ed25519"; - } - { - path = "/persist/etc/ssh/ssh_host_rsa_key"; - type = "rsa"; - bits = 4096; - } - ]; + { + path = "/persist/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + { + path = "/persist/etc/ssh/ssh_host_rsa_key"; + type = "rsa"; + bits = 4096; + } + ]; }; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ../../utils/ssh-keys.nix; services.nginx = { enable = true; diff --git a/hosts/mail/configuration.nix b/hosts/mail/configuration.nix index 91b22aa..dff1253 100644 --- a/hosts/mail/configuration.nix +++ b/hosts/mail/configuration.nix @@ -1,5 +1,5 @@ { config, pkgs, ... }: -{ +{ imports = [ ./utils/bento.nix ./utils/modules/sops.nix @@ -29,10 +29,7 @@ environment.systemPackages = with pkgs; [ vim ]; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; # backups borgbackup.repo = "u149513-sub7@u149513-sub7.your-backup.de:borg"; diff --git a/hosts/nas/configuration.nix b/hosts/nas/configuration.nix index 6a6add6..2b43210 100644 --- a/hosts/nas/configuration.nix +++ b/hosts/nas/configuration.nix @@ -2,7 +2,8 @@ { config, lib, pkgs, ... }: let impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz"; -in { +in +{ nixpkgs.config.allowUnfree = true; imports = [ @@ -38,10 +39,7 @@ in { # SSH server services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; # Firewall networking.firewall.enable = true; diff --git a/hosts/web-arm/configuration.nix b/hosts/web-arm/configuration.nix index 932e29e..a5501ac 100644 --- a/hosts/web-arm/configuration.nix +++ b/hosts/web-arm/configuration.nix @@ -81,10 +81,7 @@ networking.hostName = "web-arm"; networking.domain = "cloonar.com"; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" - ]; + users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix; programs.ssh = { knownHosts = { diff --git a/todos.md b/todos.md index b82dd72..1659f82 100644 --- a/todos.md +++ b/todos.md @@ -6,4 +6,4 @@ switch from gitea to forgejo ## chache server https://github.com/zhaofengli/attic -set ssh keys that each server should accept somewhere globally in utils and each server should implement it +# TODO: set ssh keys that each server should accept somewhere globally in utils and each server should implement it diff --git a/utils/ssh-keys.nix b/utils/ssh-keys.nix new file mode 100644 index 0000000..b25756c --- /dev/null +++ b/utils/ssh-keys.nix @@ -0,0 +1,5 @@ +[ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFshMhXwS0FQFPlITipshvNKrV8sA52ZFlnaoHd1thKg" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" +]