| runme |
|
|---|
Nix flake-based system configuration managing multiple NixOS hosts and home-manager configurations. Uses flake-parts + import-tree to auto-import all modules from ./modules/. Also manages Kubernetes manifests via nixidy, pushing generated YAML to a private argo-manifests repo for ArgoCD to sync.
| Hostname | Type | Description |
|---|---|---|
| edgenix | NixOS x86_64 | k3s node, Plasma6 + specialisations |
| inspernix | NixOS x86_64 | Laptop |
| nasnix | NixOS x86_64 | Virtualized server on NAS, k3s node |
| nixmini | NixOS x86_64 | k3s node |
| powerspecnix | NixOS x86_64 | Primary gaming PC |
| steamdeck | home-manager only | user: deck |
| vavirl-pw0bwnq8 | NixOS-WSL | WSL on Ubuntu, user: drenfer |
| pixel8 | feature/syncthing config only | Android phone; no NixOS or home-manager build target |
The default and recommended location is ~/dotfiles. The Nushell config derives all internal paths from $env.DOTFILES_DIR, which defaults to ~/dotfiles but can be overridden by setting it in the environment before launching Nushell.
git clone git@github.com:duck1123/dotfiles.git ~/dotfilesNixOS machines already have Nix. For non-NixOS hosts (steamdeck), use the Determinate Nix installer, which handles upgrades cleanly and supports WSL out of the box:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install \
--extra-conf "trusted-users = root $USER"The trusted-users flag is required to allow this user to specify substituters (binary caches). Without it, cachix/attic caches are silently ignored and every package builds from source.
Flake support is enabled automatically by the Determinate installer. If you ever need to add local Nix settings, edit /etc/nix/nix.custom.conf (Determinate's user-editable overlay — /etc/nix/nix.conf is managed by the installer and will be overwritten on upgrade).
vavirl-pw0bwnq8 runs as a NixOS-WSL distro, replacing the plain Ubuntu WSL base.
Step 1 — build the tarball builder:
nur build --tarball --host vavirl-pw0bwnq8This produces result/bin/nixos-wsl-tarball-builder — a self-contained script.
Step 2 — run the builder as root to produce the image (writes nixos.wsl to the current directory):
sudo result/bin/nixos-wsl-tarball-builderStep 3 — import it into WSL from inside the Ubuntu WSL shell:
# cmd.exe is always available in WSL; tr strips the Windows carriage return
WIN_HOME=$(cmd.exe /c "echo %USERPROFILE%" 2>/dev/null | tr -d '\r')
mkdir -p "$(wslpath "$WIN_HOME")/wsl/NixOS"
wsl.exe --unregister NixOS 2>/dev/null || true # remove any previous failed import
wsl.exe --import NixOS "$WIN_HOME\\wsl\\NixOS" "$(wslpath -w "$(pwd)/nixos.wsl")"
wsl.exe -s NixOS # set as default distro (optional)After first boot, apply the home-manager config from inside the NixOS WSL shell:
nur switch homeSubsequent NixOS updates deploy via the normal nur switch os command.
Tasks are defined in scripts/nur.nu and run with nur, a Nushell-based task runner (similar to just, but tasks are plain Nushell defs). The nurfile at the repo root loads the tasks module via overlay use scripts/nur.nu; nur discovers it automatically as long as your CWD is the repo root (or a subdirectory of it).
On hosts with the nushell home-manager feature enabled, nur is already on PATH. On a fresh machine, before home-manager has been applied, get a Nushell session with the tasks preloaded instead:
nix run .#pnuthen run nur <task> inside that shell.
.envrc is gitignored — copy the example and edit it before allowing:
cp .envrc.example .envrc
# Review and fill in any secrets (e.g. TAILSCALE_API_KEY)
direnv allowuse flake in the file loads the repo's devShell, which provides nur, nh, sops, age, kubectl, and the other tools listed in modules/flake/devShells.nix. Entering the directory activates the environment; leaving it deactivates it.
If direnv is not yet installed, the direnv home-manager feature handles that on managed hosts. On a fresh machine before home-manager has run, use nix run .#pnu to get a shell with the tools available instead.
All secrets are encrypted with sops using age keys. You need the private key available for decryption.
export KEEPASS_DB_PATH="${HOME}/keepass/passwords.kdbx"
export SECRET_PATH="/Kubernetes/Age-key"
mkdir -p ~/.config/sops/age
keepassxc-cli show -s -a Password ${KEEPASS_DB_PATH?} ${SECRET_PATH?} > ~/.config/sops/age/keys.txtmkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txtnur secrets list-keysnix flake updatenur formatnur lintnur switch # apply both home-manager and NixOS
nur switch home # home-manager only
nur switch os # NixOS only
nur switch k8s # build and push k8s manifests only (no --host)
nur switch os --boot # set NixOS as boot default instead of activating (safe for slow activations)All builds happen locally (with nom for better progress display), then the result is copied and activated on the remote host.
nur build --host edgenix
nur build --host nasnixnur diff-os --host edgenix
nur diff-os --host nasnixnur dry-run-os --host edgenix
nur dry-run-os --host nasnixnur switch --host edgenix # both home-manager and NixOS
nur switch --host nasnix
nur switch --host edgenix os # NixOS only
nur switch --host edgenix home # home-manager onlyPrerequisites:
- SSH key-based auth configured for the target host (e.g.
edgenix,nasnix) - Remote user has sudo access (tasks prompt for the sudo password when switching NixOS)
Kubernetes applications are defined in k3s-fleetops (app definitions + library). This repo holds the environment configuration, secrets, and automation for building and pushing generated YAML manifests to the private argo-manifests repo. ArgoCD on the cluster syncs from there.
k3s-fleetops/ ← application definitions, library (read-only dependency)
dotfiles/
modules/kubernetes/
_env/dev.nix ← cluster environment config (services, domains, storage)
secrets/k8s.enc.yaml ← encrypted cluster secrets (sops/age)
kubernetes/manifests/← checkout of argo-manifests (gitignored here)
nur k8s deploy # build manifests + push to argo-manifests (most common)
# or step by step:
nur k8s switch-charts # build nixidy manifests → write to kubernetes/manifests/
nur k8s push # commit + push kubernetes/manifests/ to argo-manifests
nur k8s edit-secrets # edit cluster secrets in-place with sopsArgoCD reads manifests from argo-manifests. Clone it inside this repo (it is gitignored here):
git clone git@github.com:duck1123/argo-manifests.git kubernetes/manifestssops --decrypt secrets/k8s.enc.yaml > /dev/null && echo "OK"nur k8s deployRun these steps when setting up ArgoCD on a fresh cluster for the first time.
nur install argocdArgoCD needs an SSH deploy key to pull from the private manifests repo. This credential must be applied directly (ArgoCD cannot sync it from the repo it does not yet have access to).
If you already have a deploy key stored in secrets:
nur k8s bootstrap-argocd-repoIf you need to create a new deploy key:
# 1. Generate the key pair
nur k8s generate-deploy-key
# 2. Add the printed PUBLIC key to GitHub:
# argo-manifests → Settings → Deploy keys → Add deploy key (read-only)
# 3. Store the printed PRIVATE key in secrets:
nur k8s edit-secrets
# Add under key:
# argocd:
# sshDeployKey: |
# -----BEGIN OPENSSH PRIVATE KEY-----
# ...
# -----END OPENSSH PRIVATE KEY-----
# 4. Apply the credential to the cluster
nur k8s bootstrap-argocd-reponur k8s deploy
# Apply the generated ArgoCD Application manifests so ArgoCD starts tracking them
kubectl apply -f kubernetes/manifests/dev/apps/Each Application-*.yaml is self-managed (automated sync + prune), so once applied ArgoCD will keep syncing all applications from the manifests repo on its own.
argocd admin initial-password -n argocdkubectl port-forward svc/argocd-server -n argocd 8080:443Then open https://localhost:8080/
All cluster secrets live in secrets/k8s.enc.yaml (encrypted with sops/age).
Edit in-place (no plaintext file written to disk):
nur k8s edit-secrets
# or directly: sops secrets/k8s.enc.yamlDecrypt → edit → re-encrypt:
nur k8s decrypt # → secrets/k8s.yaml (DO NOT commit)
# edit secrets/k8s.yaml
nur k8s encrypt # → secrets/k8s.enc.yaml
rm secrets/k8s.yamlnur check # nix flake check
nur lint # lint .nix files with statix
nur build --all # build all configurationssudo reboot