NixOS, k3s, and OpenTofu configuration for production services. Sinnoh manages hosts, applications, private networking, Cloudflare DNS, and backups.
See also Hoenn for personal machines, Johto for the homelab, and Kanto for shared inference.
| Host | Role |
|---|---|
sunnyshore |
k3s server and control-plane data backup |
canalave |
k3s agent and observability services |
Both hosts run NixOS on OpenStack and communicate over the sinnoh WireGuard
interface.
Comin reconciles host configurations from master. Flux reconciles the
Kubernetes resources in k8s/flux-system/ from the same branch. OpenTofu
manages Cloudflare DNS separately.
The Hoenn WireGuard peer inventory and reusable modules live in
wg-hoenn. This repository keeps its
private keys and host firewall policy. After changing the shared inventory,
update the wg-hoenn input in both Hoenn and Sinnoh.
nix/
├── hosts/nixos/ Host configuration and hardware state
└── nixos/ Shared modules, services, and users
k8s/ Flux and application manifests
secrets/ SOPS-encrypted host secrets
keys/ Public SOPS recipients
terraform/ OpenTofu configuration for Cloudflare DNS
flake.nix imports the flake-parts modules under nix/ and exposes the
sunnyshore and canalave NixOS configurations. Kubernetes secrets live in
k8s/secrets/.
Enter the pinned development shell with nix develop, or run direnv allow to
load it automatically. Then run:
nix fmt
nix flake checkBuild each host affected by a Nix change. Build both hosts after changing a shared NixOS module:
nix build .#nixosConfigurations.sunnyshore.config.system.build.toplevel
nix build .#nixosConfigurations.canalave.config.system.build.toplevelShared validation and metrics helpers come from the pinned dvnpkgs input.
After Kubernetes changes, run just check-k8s. For OpenTofu changes, run
tofu -chdir=terraform init on a fresh checkout, then run:
tofu -chdir=terraform fmt -check
tofu -chdir=terraform planRun just to list the other maintenance commands.
Commit and push validated changes, then let Comin and Flux reconcile master.
Run just flux-status to inspect the cluster through the sinnoh context.
Review the OpenTofu plan before applying DNS changes. The B2 state backend does not lock state, so never run concurrent applies.
The observability runbook explains how to check metrics and logs.
Run just sops-bootstrap once per machine to derive your local age key from
your SSH key. Then edit secrets with SOPS:
just sops-edit tailscale.yaml
just sops-edit k8s/secrets/pg-shared-b2.sops.yamlDirenv loads the encrypted Cloudflare and Backblaze credentials for OpenTofu.
After changing keys/, run just sops-rekey. Commit .sops.yaml and all
re-encrypted files together. Never commit decrypted secrets, private keys,
OpenTofu state, or saved plans.
Licensed under the MIT License.