Commit Graph
108 Commits
Author SHA1 Message Date
Ryan Yin 01d2e76410 chore(secrets): refresh mysecrets and follow agenix-rules rename
Update the mysecrets lock to 7f93490, which renames secrets.nix to agenix-rules.nix, drops the deprecated ./ key prefixes for agenix 0.18, and re-encrypts the access-token secret. Update the docs and agenix skill to the new filename and path convention.
2026-10-29 21:28:08 +08:00
Ryan Yin 1324131c6d docs: correct statements that no longer match the configuration
Assisted-by: DeepSeek Harness 0.2.1-rc.2 (claude-opus-5-5)
2026-10-21 20:59:07 +08:00
ryan4yin | 二花 9c38819517 docs: review and correct comments and documentation (#436) 2026-10-12 10:02:38 +08:00
ryan4yin | 二花 0e12440148 refactor(secrets): move nushell-secrets.nu out of agenix (#423) 2026-10-09 22:40:50 +08:00
ryan4yin | 二花 3694961e74 fix(postgres,darwin): close the loopback superuser path and scope agenix ownership (#401)
* fix(postgres): require a password for superuser over TCP

* test: assert the postgres loopback auth rules

* fix(darwin): keep root-only agenix secrets root-only

* docs(security): record the local auth boundaries and retire WA-015
2026-10-07 15:22:03 +08:00
ryan4yin | 二花 5f6a1dadf4 docs: fix stale claims and AI-flavored prose (#397) 2026-10-07 14:48:36 +08:00
ryan4yin | 二花 3a5b9ec4c6 docs: README audit fixes and de-duplication (#371) 2026-10-03 18:28:58 +08:00
ryan4yin | 二花 3fdeedaa78 docs(security): document homelab architecture and agent-first audits
Add SECURITY.md covering the threat model, trust boundaries,
proportionate kernel/process hardening, the update/reboot routine and
remaining prioritized work. Record the dated read-only audit findings
(listeners, privileged workloads, effective RBAC, secret metadata and
sandbox/SSH boundaries) separately from planned controls and runtime
verification.

Define agent-first diagnosis: scoped root read-only access on homelab
hosts, and normal-user diagnostics on core desktops with no new sudo
grants. Add canonical domain-based k3s API endpoint regression tests,
record the unverified Darwin secret-ownership concern as WA-015, and
correct comments claiming mode 0000 blocks privileged root.
2026-10-03 16:26:32 +08:00
ryan4yin | 二花 0c8f0fe0c3 feat(secrets): add work gitconfig secret and a no-sudo replace flow (#346)
* feat(secrets): add work gitconfig secret, symlink it in home-manager

* feat(secrets): add a no-sudo replace recipe for new secrets

* refactor(secrets): move work gitconfig symlink into the desktop layer
2026-10-02 13:51:17 +08:00
ryan4yin | 二花 9c44117f75 refactor(editors): standardize on helix, keep neovim as backup (#345) 2026-10-02 13:33:17 +08:00
ryan4yin | 二花 1a10e65221 refactor(secrets): follow the reorganized nix-secrets layout (#344) 2026-10-02 13:07:40 +08:00
ryan4yin | 二花 68ea04f173 fix(docs): correct stale and mismatched documentation (#338) 2026-10-02 10:21:55 +08:00
ryan4yin | 二花 b2ec56db66 docs(skills): add repo-scoped task skills and give each fact one home (#337) 2026-10-02 10:13:03 +08:00
ryan4yin | 二花 4909f6357b security: scope privileges and stop a world-readable secret copy (#335) 2026-10-01 21:18:34 +08:00
Ryan Yin 853747425f chore(idols-ai): drop the davfs WebDAV fileshare mount
davfs2 caches the whole opened file regardless of cache_size, so opening media on /mnt/fileshare downloads it fully and blocks the mount. The share is no longer used.
2026-09-26 23:47:29 +08:00
ryan4yin | 二花 793b636fa5 feat(youko): add Immich photo platform (#317)
Add Immich via the native nixpkgs services.immich module on youko, reusing the host PostgreSQL 16 (pgvector + vectorchord) and a shared Valkey instance for Redis-compatible caching and BullMQ queues (Dragonfly rejected BullMQ's dynamic Lua keys). Media lives on the encrypted HDD at /data/apps/immich; Caddy publishes immich.writefor.fun with a publicly-trusted Let's Encrypt cert (security.acme + Cloudflare DNS-01) so the mobile app connects. OTEL metrics are scraped by VictoriaMetrics, and /var/cache is now preserved on the tmpfs-root hosts so the ML model cache survives reboots.
2026-09-25 20:30:01 +08:00
Ryan Yin 7e0e4aa566 feat(youko): replace MinIO with RustFS S3
Deploy RustFS in place of the retired MinIO and move the S3 consumers over.

- flake.nix / flake.lock / outputs/default.nix: add a nixpkgs-small
  (nixos-unstable-small) input for the rustfs 1.0.0 package (with the web
  console), instantiated as pkgs-small in genSpecialArgs alongside the other
  nixpkgs instances; drop the rustfs flake input. The rest of the system stays
  on the default nixpkgs.
- hosts/12kingdoms-youko/homelab-services/rustfs.nix: use nixpkgs' own
  services.rustfs module, with package = pkgs-small.rustfs and
  environmentFile = the agenix rustfs.env secret.
- caddy.nix: s3.writefor.fun (S3 API) and s3-console.writefor.fun (console,
  redirects / to /rustfs/console/).
- secrets/nixos.nix: declare a single rustfs.env (dotenv) secret holding
  RUSTFS_ACCESS_KEY / RUSTFS_SECRET_KEY, replacing the separate key files.
- infra/minio -> infra/rustfs: buckets are managed with the hashicorp/aws
  provider against the RustFS S3 endpoint; IAM/ILM are applied with rc.
2026-09-25 15:23:50 +08:00
ryan4yin | 二花 97c2d1325d docs: refresh stale docs after the VM and backup refactors 2026-09-21 22:03:21 +08:00
ryan4yin | 二花 260da1ee20 chore: rename the nushell secret, and forbid reading decrypted secrets 2026-09-21 21:13:50 +08:00
Ryan Yin 1cbb52add1 docs(secrets): desktops and recovery_key have identical access
recovery_key is a member of desktop_keys, so every group written as
desktop_keys ++ ... covers both.
2026-09-21 20:51:13 +08:00
Ryan Yin 89e57b5b39 docs(secrets): state that every secret must be decryptable by the desktops
The desktops hold the trusted admin keys and are where secrets are edited and
rekeyed from; narrowing a set to the servers alone breaks agenix -r and drops
the offline recovery key.
2026-09-21 20:50:11 +08:00
Ryan Yin a43aa02a69 docs(secrets): state the recipient invariant
A recipient set must answer two questions: who may read it, and how it is
recovered once those hosts are gone. Dropping recovery_key while narrowing
a secret is easy and silent.
2026-09-21 20:45:47 +08:00
Ryan Yin 2ff93c16ce feat(restic): move idols-ai's off-host backup to the REST server
Split the repository password into desktop and homelab groups, add the
environmentFile/pruneOpts module options, and point the desktop at youko's
REST endpoint.
2026-09-21 20:38:08 +08:00
Ryan Yin 12ac5f45aa feat(idols-ai): restic backup to a local repository
Allowlist of the irreplaceable directories (Documents, work, Pictures,
nix-config, .local/state); project checkouts under ~/codes live in git and
are not backed up. Kept the excludes generic, since this repo is public.

Also move the restic-password secret to a desktop.enable || server.storage
gate so desktops get it without enabling a server group.
2026-09-21 19:04:58 +08:00
ryan4yin | 二花 e37042f61c feat(youko): restic backup of the service state to the HDD (part 1) (#299)
* feat(hosts): per-host restic backups to the SMB remote

Replace the disabled aggregate job (which rsynced every host's /persistent
into /tmp - a tmpfs - and silently produced incomplete backups) with one
restic repo per host, backing up its own data directly:

- shared module lib/genResticBackup.nix: secrets, rclone/SMB target
  (rclone:smb-downloads:/Downloads/homelab-backup/<host>), retention, and
  excludes for the regenerable/bulky paths (podman overlay layers, microvm
  and libvirt disk images, nfs golden images, logs, caches)
- youko additionally backs up the service state under /persistent/var/lib
  and dumps all postgres databases first (a consistent SQL artifact beside
  the crash-consistent data dir)
- shoryu/shushou back up /etc/agenix, /etc/ssh and the k3s token

Needs three agenix secrets before it can run: restic-password,
ssh-key-for-restic-backup and rclone-conf-for-restic-backup.

* refactor(hosts): only restic does off-host; btrbk stays local

btrbk works at the subvolume level, so a  would ship the whole
@persistent - including podman's overlay storage, the microVM/libvirt
images and the nfs golden images - which is exactly the regenerable bulk
we want out of the backups.

So: btrbk keeps making the cheap local CoW snapshots (quick rollbacks),
and restic owns the off-host copies with file-level excludes. Back up the
whole /persistent minus those excludes, so nothing is missed.

Update the btrbk module's comment to say so.

* fix(restic): never back up keys; drop the implicit /etc/agenix

restic's own password lives in /etc/agenix, so backing that up would store
the repository's password inside the repository. Exclude agenix, the ssh
host keys and the usual credential dirs (.ssh, .gnupg, .aws, gcloud).

* refactor(restic): make the backup a proper module

Replace lib/genResticBackup.nix with modules/nixos/base/restic-backup.nix,
which declares modules.restic-backup options (enable, repository, paths,
exclude, requiresMountsFor, postgresDump) like the btrbk module does.
youko just sets the options now.

* refactor(restic): exclude the whole podman storage, trim retention

Exclude /persistent/var/lib/containers wholesale: the image layers are
re-pullable and podman's storage DB is not consistent when copied from a
running podman. uptime-kuma's named volume lives there, but its data is
not wanted anyway.

Retention: daily 3, weekly 2, monthly 2 - no yearly.

* refactor(restic): back up a short-lived btrfs snapshot, drop pg_dump

A live copy of a running postgres data dir is only crash-consistent. Instead
of a daily pg_dumpall (which duplicates the data in the repository and gets
slower as the DB grows), take a short-lived read-only btrfs snapshot in
backupPrepareCommand, back that up, and delete it right after - a
consistency step, not a second backup. The excludes are relative now so they
work for both the snapshot and a direct path.

* feat(secrets): restic-password for modules.restic-backup

With the rekeyed secret in nix-secrets (storage group, alongside
hdd-luks-crypt-key), the module's passwordFile resolves.

* fix(restic): agenix's secret is under /run/agenix, not /etc/agenix

* fix(restic): take the password path from agenix, not a hardcoded one

config.age.secrets."restic-password".path follows agenix's secretsDir, so it
stays correct if that changes.
2026-09-21 19:00:35 +08:00
Ryan Yin 8b1fa3ac87 chore(secrets): drop the unreferenced dae-subscription secret
Nothing consumes it (it was gated on modules.secrets.server.network)
and its only content was the secret definition.
2026-09-21 17:29:36 +08:00
ryan4yin | 二花 01c6b3290a chore: remove the never-deployed k3s-prod-1 cluster (#284)
It was never bootstrapped (no flux deploy key, VMs commented out since
2024-10) and only carried a stale duplicate of the test cluster's config.

- hosts/k8s/k3s-prod-1-{master,worker}-{1,2,3} + flake outputs + the home module
- the k3s-prod-1-token agenix entry (the .age file lives in the private secrets repo)
- the k3s-prod-1-* IPs, the offlineHosts entries, the Justfile recipes and the docs
2026-09-21 12:53:43 +08:00
Ryan Yin 98fbf010b8 docs: fix broken links and editor references in readmes
- root README: VS Code config moved from home/linux/gui/base/editors.nix to vscode.nix
- READMEs now list both GUI editors (Zed, the primary one, plus VS Code)
- base README: xdg is a directory now, nvidia.nix no longer exists, editors.nix -> vscode.nix
- idols-ai README: disko-fs-media.nix -> disko-fs-data.nix (/persistent/data)
- secrets README: password-store moved from home/base/desktop to home/base/tui
- drop unused link definitions (AstroNvim, wl-clipboard, Catppuccin)
- fix a pre-existing typo flagged by the typos hook (keeped -> kept)
2026-09-19 15:23:09 +08:00
Ryan Yin bae7e05a9a fix(aquamarine): remove insecure MinIO service 2026-07-24 15:07:49 +08:00
Ryan Yin c8e76ceff8 fix(darwin): agenix - remove non-exist secret 2026-04-21 10:29:45 +08:00
Ryan Yin b143a89443 feat(ai): add webdav mount (#253)
feat(aquamarine): add group for filesharing, protect /data on subvolume mount failures
2026-03-19 22:25:48 +08:00
Ryan Yin ce99c3e2d3 Update aqua (#252)
* fix: Grafana's secret key doesn't have a default value anymore

flake.lock: Update

Flake lock file updates:

• Updated input 'mysecrets':
    'git+ssh://git@github.com/ryan4yin/nix-secrets.git?ref=refs/heads/main&rev=cfe34c222cf7ee4290438c97e6cc734aa7792346&shallow=1' (2025-12-18)
  → 'git+ssh://git@github.com/ryan4yin/nix-secrets.git?ref=refs/heads/main&rev=86de5313787257806723f03dccabd52bb7501ff3&shallow=1' (2026-03-18)

* fix: gitea sendmail path

* fix: transmission_4
2026-03-19 01:02:42 +08:00
Ryan Yin 87a1d56247 feat: helix - add steel as the plugin system
fix: evaluation warning - 'system' has been renamed to/replaced by 'stdenv.hostPlatform.system'

Signed-off-by: Ryan Yin <xiaoyin_c@qq.com>
2025-11-23 13:40:26 +08:00
Ryan Yin 13bb77108c feat: format via 'ls **/*.nix | each { |it| nixfmt $it.name }' 2025-07-30 12:17:24 +08:00
Ryan Yin db82d2d8c5 feat: remove x86_64-darwin, add new nixos host on macbook pro m2 2025-07-12 23:30:52 +08:00
Ryan Yin ffee47a2de chore: replace impermanence with preservation (#201) 2025-06-29 15:08:12 +08:00
Ryan Yin 8690978d7e feat: replace impermanence with preservation (#198)
* feat: replace impermanence with preservation

* fix: This module cannot be used with scripted initrd.

* fix: permission for /var/lib/private

* chore: boot.initrd.systemd.enable

* docs: boot.initrd.luks.devices.<name>.fallbackToPassword is implied by systemd stage 1

* fix: typo
2025-06-29 13:02:36 +08:00
Ryan Yin 413cc67a4a chore: remove alias-for-work.bash 2025-05-29 17:41:44 +08:00
Ryan Yin e13079f7a8 feat(darwin): new host - frieren 2025-05-13 13:07:47 +08:00
Ryan Yin cfdf12b356 fix: attribute 'nix-access-tokens' missing for homelab 2025-03-01 06:26:23 +08:00
Ryan Yin 935c80ef5a fix: darwin - use XDG base directories, fix secrets 2025-01-27 13:15:14 +08:00
Ryan Yin 0a9697352b fix: darwin - nix-access-token 2024-11-29 23:48:42 +08:00
Ryan Yin f0576ecc88 fix: nix-access-token - permission 2024-11-29 23:26:54 +08:00
Ryan Yin 4503964146 fix(secrets/nixos): assertion 2024-11-17 21:31:53 +08:00
Ryan Yin dd8259ed85 feat: troubleshooting agenix 2024-11-13 23:59:44 +08:00
Ryan Yin cf34ea047c Add postgresql (#163)
* feat: add postgresql

* feat: add grafana dashbaord, fix exporter
2024-09-03 14:32:20 +08:00
Ryan Yin 07b74cd2e5 feat: add minio (#161)
* feat: add minio

* fix: minio's reverse proxy

* fix: minio secrets & reverse proxy
2024-09-02 18:28:56 +08:00
Ryan Yin e28c7565d7 polish: README for secrets 2024-08-18 15:01:13 +08:00
Ryan Yin d853036fb1 feat: data-crypted 2024-08-17 02:26:39 +08:00
Sacabambaspis 87c041f8b4 fix(secrets/README.md): fix nixpkgs does not contain agenix
Closes #125
2024-05-05 18:05:43 +08:00