No description
  • Nix 86.9%
  • Python 7.5%
  • Shell 3.9%
  • HTML 1.2%
  • jq 0.3%
  • Other 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Oluf Lorenzen 2e3874ea3a
fix(pi): keep the prompted provider keys off the target
`prompts.<provider>.persist = true` is shorthand for
`files.<provider>.secret = true`, so clan also emitted the raw prompted key as
a generator file — and generator files are deployed by default. That put a
second copy of the API key on olworkstation next to the assembled auth.json.

Mark the per-provider files `deploy = false`: they stay secret inputs for
auth.json (encrypted in the repo, available on the operator machine for
regeneration) but only auth.json is installed under /run/secrets.

Verified by evaluation: files.neuralwatt.deploy is false and the file is no
longer registered as a sops secret, while auth.json still resolves to
/run/secrets/vars/per-machine/olworkstation/pi-providers/auth.json with
owner ol, mode 0400.
2026-10-21 19:55:20 +02:00
.agents/skills/clan-core clan-core skill: add backup.md reference 2026-08-08 18:13:47 +02:00
.kittify spec-kitty 2026-10-09 12:49:26 +02:00
bin fix(podman): remove dead podman-integration service 2026-07-11 23:20:58 +02:00
clanModules feat(WP03): declare searxng/zerotier/tor state; document netbox+opnsense2otel skips 2026-10-09 13:26:56 +02:00
clanServices fix(authelia): never skip a users-db write silently 2026-10-20 20:38:13 +02:00
docs/llms refactor: extract slim-service/proxy/test helpers; remove infra-auth and dead files 2026-10-05 10:34:06 +02:00
homeModules feat(pi): declare the coding agent for user ol 2026-10-20 22:38:16 +02:00
inventory feat(pi): declare the coding agent for user ol 2026-10-20 22:38:16 +02:00
kitty-specs/external-backups-state-01M4G1FB docs: post-merge mission review report (PASS WITH NOTES) 2026-10-09 22:18:27 +02:00
lib feat(WP03): declare searxng/zerotier/tor state; document netbox+opnsense2otel skips 2026-10-09 13:26:56 +02:00
machines add ZT network 2026-10-18 21:26:53 +02:00
nixosModules fix(pi): keep the prompted provider keys off the target 2026-10-21 19:55:20 +02:00
pi fix(pi): keep the prompted provider keys off the target 2026-10-21 19:55:20 +02:00
pkgs fix(grafana): put opnsense2otel alerts in their dashboard folder 2026-10-19 12:57:18 +02:00
scripts feat(monitoring): reconcile dashboards per folder 2026-10-20 20:17:06 +02:00
sops secrets: add machine nixthink 2026-09-25 22:51:30 +02:00
users/ol chore(pi): drop the three patches that match no pin 2026-10-21 15:10:36 +02:00
vars vars: update via generator pi-providers (machine: olworkstation) 2026-10-20 22:41:00 +02:00
websites/h-wildcard fix(caddy): centralize HTTP redirect and error page 2026-08-21 11:48:00 +02:00
.editorconfig chore: formatting 2026-10-19 09:40:01 +02:00
.envrc wip 2026-08-17 02:25:16 +02:00
.gitattributes spec-kitty 2026-10-09 12:49:26 +02:00
.gitignore chore: ignore python stuff 2026-10-18 21:23:25 +02:00
.pre-commit-config.yaml cleanup 2026-08-25 09:48:14 +02:00
clan.nix structure 2026-05-05 11:19:31 +02:00
flake.lock feat(pi): declare the coding agent for user ol 2026-10-20 22:38:16 +02:00
flake.nix feat(pi): carry the local patch-package patches 2026-10-21 14:58:45 +02:00
formatter.nix wip 2026-05-22 13:35:19 +02:00
inventory.json fmt 2026-06-06 17:01:48 +02:00
Justfile refactor(storage): share ZFS ownership repair 2026-08-18 16:31:19 +02:00
Justfile.README.md refactor(storage): share ZFS ownership repair 2026-08-18 16:31:19 +02:00
llm-verification-todo.md wip 2026-08-17 04:18:24 +02:00
mise.toml stuff 2026-09-28 13:56:30 +02:00
README.md docs 2026-10-02 08:51:41 +02:00
renovate.json5 fix(renovate): make Nix image group slugs file-specific 2026-09-01 22:17:12 +02:00
tix.toml feat(pi): declare the coding agent for user ol 2026-10-20 22:38:16 +02:00

zuhausis

NixOS configuration for clan zuhausis (home.arpa), built on clan-core main.

Structure

flake.nix                  # Entry point — clan-core + home-manager + disko-zfs
clan.nix                   # Inventory: machines, service instances, roles
machines/olworkstation/    # Machine config + ZFS disk layout (disko)
modules/                   # Custom clan service modules
clanServices/              # Local clan services
clanModules/               # Reusable NixOS modules
  machine-type/            # Base defaults + tiling-wm (sway/tuigreet)
  zfs-zed-notifications/   # ZFS event push notifications (ntfy/pushover)
nixosModules/              # NixOS modules, including GNOME desktop settings
pkgs/                      # Custom packages overlay (nerdlog, aerospace-marks, etc.)
users/ol/                  # User config (home-manager, devtools, uvx-tools)
sops/                      # AGE-encrypted secrets
vars/                      # Generated variables (SSH keys, passwords, hostid)

Machines

Name Deploy target Disk
olworkstation root@192.168.178.43 Samsung 860 EVO 2TB, ZFS zroot pool

Deployment tags

olworkstation is assigned the following machine tags:

Tag Services or configuration
server General server-side services, including Redis/Valkey, Authelia, NetBox, Paperless-ngx, and data-mesher
workstation Workstation configuration
llm-server The local-llm server role and its llama-swap inference services
server-proxy The ncps server role and Nix binary-cache proxy

Service instances select machines through these tags. Tag-specific service settings are declared with roles.<role>.tags.<tag>.settings, so adding a machine to a specialized deployment requires only assigning the corresponding machine tag.

Clan services

Configured as inventory instances in clan.nix.

Instance Service Docs
admin admin SSH keys + root password
ol-user users User ol with groups
wifi wifi Network credentials
clan-cache trusted-nix-caches Binary cache trust
zerotier zerotier Overlay networking
tor tor Fallback connectivity
machine-type custom (clanModules/machine-type) Base config + tiling WM role
zfs-zed-notifications custom (clanModules/zfs-zed-notifications) ZFS event alerts

Home-manager (standalone)

A standalone home-manager config for macOS is available:

home-manager switch --flake .#ol

Usage

nix develop                                   # Dev shell with clan-cli
clan machines install olworkstation           # Initial install
clan machines update olworkstation            # Deploy changes

Atuin shell history sync

Atuin provides encrypted shell history sync across machines, configured per Linux user.

Configuring a user

In a user's home-manager configuration:

modules.programs.atuin.enable = true;
# varsPrefix defaults to "atuin-${config.home.username}"

In the inventory (inventory/services/atuin.nix), instantiate mkAtuinGenerators once per user on a given machine:

machines.olworkstation.clan.core.vars.generators =
  mkAtuinGenerators { user = "ol"; }
  // mkAtuinGenerators { user = "alice"; };  # add more users here

Each call emits four generators under the atuin-<user> prefix:

Generator Scope Contents
atuin-<user> per-machine sync_address (server URL)
atuin-<user>-shared share=true encryption key (one per atuin account)
atuin-<user>-session per-machine session token (populated by bootstrap)
atuin-<user>-login-creds operator username + password (deploy=false)

Deployed secrets are owned by the corresponding Linux user (mode 0400), so the home-manager module's zsh init can read them.

Initial setup

# 1. Enter the dev shell
nix develop

# 2. Run the bootstrap script for each user
#    Args: <machine> <target-host> [user] [prefix]
#    Defaults: user=ol, prefix=atuin-<user>
bin/atuin-bootstrap olworkstation root@192.168.1.2 ol

The bootstrap script will:

  1. Prompt for atuin sync server URL (e.g., https://atuin.example.com)
  2. Prompt for login credentials (username/password)
  3. Optionally prompt for existing encryption key (leave empty to generate new)
  4. Deploy the configuration and automatically log in to create a session
  5. Set up encrypted history sync between your machines

Multi-machine sync

For additional machines, the encryption key is shared via share = true on the atuin-<user>-shared generator, so you only need to provide login credentials during bootstrap on each new machine.

Manual sync

# On any configured machine
sudo -u <user> atuin sync

See plans/atuin-sync-implementation.md for technical details.

Podman services (container orchestration)

Containerized services run through a 3-layer pattern built on quadlet-nix:

Layer Module Responsibility
Orchestration clanServices/podman-orchestration Container/network/volume definitions, systemd ordering, validation
Storage clanServices/podman-storage Host paths, ZFS datasets, ownership, ensure-path-* units
Slim service clanServices/<name> Service-specific config (images, env, ports)

Active services using this pattern:

  • archivebox — web archiving (inventory/services/archivebox.nix)
  • searxng — meta search engine (inventory/services/searxng.nix)

New services are generated with lib/mkPodmanService.nix — see lib/mkPodmanService-README.md.

Debug script

Every orchestration instance gets a podman-debug-<instance> CLI installed automatically:

# Quick health check (default subcommand)
podman-debug-archivebox

# Verbose deep-dive — systemd units, podman inspect, journal, disk
podman-debug-archivebox debug

# Tail logs (all containers, or specific + line count)
podman-debug-archivebox logs
podman-debug-archivebox logs archivebox-web 200

# Coordinated restart of all containers
podman-debug-archivebox restart

# Reclaim disk space
podman-debug-archivebox prune

For rootless instances, the script automatically dispatches through systemctl --user -M <user>@ and sudo -u <user> podman.

Full reference: clanServices/podman-orchestration/README.md

Code formatting and linting

This project uses treefmt-nix for code formatting and statix for Nix linting.

Formatting

# Format all supported files in the project
nix fmt

# Check formatting without making changes
nix flake check

Supported formats:

  • Nix files (*.nix): nixfmt - Official Nix formatter
  • Markdown, JSON, YAML, TOML: prettier
  • Shell scripts (*.sh): shfmt for formatting, shellcheck for linting

Linting

# Run Nix linter (statix) on all .nix files
statix check .

# Auto-fix issues found by statix
statix fix .

# Explain a specific lint warning
statix explain <lint-name>

# List all available lints
statix list

Updating custom packages

nix-update bumps version + hash (+ vendorHash for Go) on the flake-exported packages under pkgs/ (aerospace-marks, gopass-secret-service, secrets-dispatcher; noctalia-askpass has nothing to update).

PATH=/Users/I556086/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH \
  nix run github:Mic92/nix-update \
    --override-input nixpkgs github:nixos/nixpkgs/$(jq -r '.nodes["nixpkgs"].locked.rev' flake.lock) \
    -- --flake --commit aerospace-marks

For flake inputs use nix flake update <input>, not nix-update.

Option-level diffing with nixos-config-tui

oddlama/nixos-config-tui is an experimental TUI for browsing and diffing NixOS configurations at the option level (which module set which value) rather than at the derivation level.

This flake exposes a tracked variant of olworkstation that evaluates through oddlama/nixpkgs@thunk-origins-v1 (input nixpkgs-tracked):

  • nixosConfigurations.olworkstation-tracked — see machines/olworkstation/tracked.nix

It is excluded from ciBuilds so the patched nixpkgs is only fetched when explicitly requested. It also evaluates only the raw machine module + disko layout (no clan-injected service modules — clan does its own evalModules under the hood that we don't override).

Quick start

# 1. Pull the patched nix CLI + the nixos-config TUI
nix shell github:oddlama/nix/thunk-origins-v1 \
          github:oddlama/nixpkgs/thunk-origins-v1#nixos-config

# 2. Build a tracked toplevel (yields tracking{,-explicit,-deps}.json alongside it)
nix build .#nixosConfigurations.olworkstation-tracked.config.system.build.toplevel \
  --print-out-paths

# 3. Browse / diff
nixos-config show .#olworkstation-tracked
nixos-config diff /nix/store/OLD-toplevel /nix/store/NEW-toplevel
nixos-config diff --explicit OLD NEW            # only explicitly defined values
nixos-config text-diff --explicit OLD NEW       # pseudo configuration.nix diff

⚠️ The patched evaluator is a proof-of-concept — do not rely on a tracked build for actual deploys. Use clan machines update … (which evaluates through the regular nixpkgs input) to deploy.

Secrets & vars

  • Secrets: AGE-encrypted via sops, stored in sops/
  • Variables: auto-generated by clan, stored in vars/ (docs)

Dependency graph

graph TD
    %% Entry point
    flake[flake.nix] --> clan_lib[clan-core.lib.clan]
    flake --> hm_standalone[homeConfigurations.ol<br/><i>aarch64-darwin standalone</i>]
    flake --> devShells

    %% Clan resolution
    clan_lib --> inventory[inventory/]
    inventory --> machines_inv[machines.nix]
    inventory --> svc_access[services/access.nix]
    inventory --> svc_network[services/network.nix]
    inventory --> svc_system[services/system.nix]

    %% Machine
    machines_inv --> olworkstation[machines/olworkstation/<br/><i>configuration.nix + disko.nix</i>]
    olworkstation --> nixosMods[nixosModules/<br/><i>nvidia, local-llm, atuin-vars</i>]

    %% Clan services
    svc_access --> access_svcs[sshd, p2p-ssh-iroh,<br/>user-root, tor]
    svc_access --> user_ol[user-ol]
    svc_network --> net_svcs[wifi, zerotier]
    svc_system --> sys_svcs[ncps (server-proxy), trusted-nix-caches]
    inventory --> svc_local_llm[services/local-llm.nix]
    svc_local_llm --> llm_svc[local-llm (llm-server)]
    svc_system --> machine_type[clanModules/machine-type/<br/><i>base, boot, cpu, tuning, fonts,<br/>tiling-wm, wayland, display-mgmt,<br/>workstation, system-tools, network-tools,<br/>nixos-dev, gaming, peripherals,<br/>docker-base, docker-cuda, kvm</i>]
    svc_system --> zfs_zed[clanModules/<br/>zfs-zed-notifications]

    %% User ol - home-manager (NixOS)
    user_ol -->|extraModules| ol_home[users/ol/home.nix]
    ol_home -->|home-manager.users.ol| ol_homeconfig[home-configuration.nix<br/><i>sway, swayidle, xdg portal</i>]
    ol_home -->|home-manager.users.ol| ol_common[common.nix]

    ol_homeconfig --> hm_desktop[homeModules/<br/><i>desktop-shell, atuin, zsh</i>]

    ol_common --> ol_devtools[devtools.nix<br/><i>vscodium, nodejs, runtimes,<br/>linters, git tools, LSPs</i>]
    ol_common --> ol_uvx[uvx-tools.nix]
    ol_common --> hm_cli[homeModules/<br/><i>cli-tools, git, neovim, fzf,<br/>zoxide, eza, broot, mise,<br/>dircolors, btop</i>]

    %% Standalone macOS reuses common
    hm_standalone --> ol_common

    %% Styling
    classDef clan fill:#4c1d95,color:#fff
    classDef machine fill:#1e3a5f,color:#fff
    classDef home fill:#065f46,color:#fff
    classDef service fill:#7c2d12,color:#fff

    class clan_lib,inventory,machines_inv,svc_access,svc_network,svc_system clan
    class olworkstation,nixosMods machine
    class ol_home,ol_homeconfig,ol_common,ol_devtools,ol_uvx,hm_desktop,hm_cli,hm_standalone home
    class access_svcs,user_ol,net_svcs,sys_svcs,machine_type,zfs_zed service