diff --git a/AGENTS.md b/AGENTS.md
index c13499ba..b851983f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -125,7 +125,7 @@ repository, and cross-link them — no need to be told.
change.
- `~/codes/nix-secrets` — the private agenix store behind `secrets/` and the `mysecrets` input:
ciphertext and recipient rules for the secrets declared here.
-- `wallpapers`, `nur-packages`, `pyclipsync`, `nu_scripts` — flake inputs; bump with
+- `wallpapers`, `nur-ryan4yin`, `pyclipsync`, `nu_scripts` — flake inputs; bump with
`just upp ` after their source changes, do not edit them from here.
## Further Context
diff --git a/WORKAROUNDS.md b/WORKAROUNDS.md
index f8fe54c0..6804149a 100644
--- a/WORKAROUNDS.md
+++ b/WORKAROUNDS.md
@@ -25,6 +25,7 @@ A version or revision pinned for a reason that can go away.
| WA-005 | `tuios` input — `flake.nix`; `home/base/tui/tuios/` | nixpkgs lags behind upstream | Use nixpkgs' `tuios` once it is recent enough | 2026-10-03 | on nixpkgs bump | active |
| WA-006 | `nixpkgs-blender` — `flake.nix` | Blender 5.2 LTS + CUDA/OptiX pin; keeps `just up` from triggering a full source rebuild | Bump deliberately when needed; drop the pin if the current nixpkgs build is acceptable | 2026-07-24 | deliberate | active |
| WA-007 | WeChat from `nixpkgs-master` — `hardening/bwraps/default.nix` | newest builds; the pinned channel lags | Fall back to the stable channel once it has a good build | 2026-10-03 | on nixpkgs bump | active |
+| WA-020 | `fcitx5-vinput` pinned to release tag `v2.4.0` — `flake.nix`; consumer `home/linux/gui/base/vinput/default.nix` | Tracks a release tag instead of a branch, so `just up` stays on that release | Bump to a newer release tag when its changes are wanted | 2026-10-04 | on vinput release | active |
## Workarounds
diff --git a/_img/idols-famaily.webp b/_img/idols-family.webp
similarity index 100%
rename from _img/idols-famaily.webp
rename to _img/idols-family.webp
diff --git a/agents/README.md b/agents/README.md
index ab3877d9..805185a0 100644
--- a/agents/README.md
+++ b/agents/README.md
@@ -1,4 +1,4 @@
-# agents
+# Agents
Portable agent resources shared across projects: the global baseline rules, behavioral scenarios for
those rules, and reference snippets for external tooling.
@@ -75,7 +75,3 @@ Ideas worth adopting once a concrete need appears; nothing here is implemented y
- Keep files portable and reviewable.
- Keep secrets and machine-specific credentials out of this directory.
- Keep guidance generic enough to reuse across multiple agent environments.
-
-## Goal
-
-Maintain one reusable source of truth for agent setup that stays simple to sync and easy to evolve.
diff --git a/flake.nix b/flake.nix
index d1c8d6ac..86a296a4 100644
--- a/flake.nix
+++ b/flake.nix
@@ -21,6 +21,7 @@
# https://hydra.nixos.org/jobset/nixpkgs/unstable
# update via nix flake update nixpkgs --override-input nixpkgs github:NixOS/nixpkgs/
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+ # Pinned to release tag v2.4.0 (not a branch); bump deliberately when needed.
fcitx5-vinput = {
url = "github:xifan2333/fcitx5-vinput/v2.4.0";
inputs.nixpkgs.follows = "nixpkgs";
@@ -31,7 +32,9 @@
# input together with that consumer.
nixpkgs-2505.url = "github:nixos/nixpkgs/nixos-25.05";
- # nixpkgs with some custom patches, including the NPU-capable sherpa-onnx package.
+ # ryan4yin/nixpkgs fork for the `.agents/skills/nixpkgs-patched` workflow. It
+ # currently carries no patches (see WORKAROUNDS.md), but `pkgs-patched` is
+ # wired in outputs/default.nix so a temporary carry needs no flake edit.
nixpkgs-patched.url = "github:ryan4yin/nixpkgs/nixos-unstable-patched";
# get some latest packages from the master branch
nixpkgs-master.url = "github:nixos/nixpkgs/master";
diff --git a/hardening/README.md b/hardening/README.md
index cee860ea..6a161f8d 100644
--- a/hardening/README.md
+++ b/hardening/README.md
@@ -12,7 +12,7 @@ for temporary exceptions and known gaps, see [`WORKAROUNDS.md`](../WORKAROUNDS.m
1. Such as browser cookies, SSH keys, etc.
- **Per-App Level**: Prevent untrusted applications(such as closed-source apps) from:
1. Accessing files they shouldn't.
- - Such as a malicious application accessing your browser's cookies, SSH Keys, etc.
+ - Such as a malicious application accessing your browser's cookies, SSH keys, etc.
1. Accessing the network when they don't need to.
1. Accessing hardware devices they don't need.
diff --git a/hardening/bwraps/wechat.nix b/hardening/bwraps/wechat.nix
index a64bac90..ca6bab09 100644
--- a/hardening/bwraps/wechat.nix
+++ b/hardening/bwraps/wechat.nix
@@ -70,6 +70,7 @@ appimageTools.wrapAppImage {
"--setenv GTK_IM_MODULE fcitx"
];
chdirToPwd = false;
+ # WeChat needs outbound network; everything else is unshared
unshareNet = false;
unshareIpc = true;
unsharePid = true;
diff --git a/home/README.md b/home/README.md
index 32f73ae3..607aab6b 100644
--- a/home/README.md
+++ b/home/README.md
@@ -30,7 +30,7 @@ home/
2. **linux**: Linux-specific configuration
- Desktop environments (Noctalia Shell, Niri compositor)
- - Headless computer-use session (see `gui/i3/README.md`)
+ - Headless computer-use session (see `linux/gui/i3/README.md`)
- Linux-specific GUI applications
- System integration tools
diff --git a/home/base/README.md b/home/base/README.md
index ff542ca2..6e34ce58 100644
--- a/home/base/README.md
+++ b/home/base/README.md
@@ -58,10 +58,8 @@ All configurations in this directory are designed to work across:
- **Linux**: All distributions with Nix and Home Manager
- **macOS**: Darwin systems with Home Manager
-- **WSL**: Windows Subsystem for Linux
## Usage
-These base configurations provide the foundation for both Linux and Darwin systems, ensuring
-consistent environments across different platforms while allowing for platform-specific
-customizations.
+These base configurations provide the foundation for both Linux and Darwin systems while allowing
+for platform-specific customizations.
diff --git a/home/base/core/editors/helix/README.md b/home/base/core/editors/helix/README.md
index b9a2d4ef..b6907b81 100644
--- a/home/base/core/editors/helix/README.md
+++ b/home/base/core/editors/helix/README.md
@@ -52,7 +52,7 @@ tuios shortcuts used often (leader is `Ctrl + B`; same idea as in the Neovim not
In Helix, `|` / `!` and variants pipe or insert shell output on selections (see **Changes**).
-This flake’s Helix Home Manager module keeps **almost all default keys** but adds several
+This flake's Helix Home Manager module keeps **almost all default keys** but adds several
normal-mode remaps: **`Ctrl+Shift+o`** → jump backward (leaving `Ctrl+o` free for the shell),
`Space Space` → `:reload-all`, `Space w` / `Space q` → `:w` / `:q`, `Esc` → collapse selection, and
`$` / `0` line jumps (see `home/base/core/editors/helix/default.nix`).
@@ -206,7 +206,7 @@ Some bindings need an **LSP** or **tree-sitter** grammar; see notes on the keyma
1. Neovim has a huge plugin ecosystem.
1. Helix is newer; a stable plugin system is still evolving:
-1. Neovim has an integrated terminal (similar in spirit to VS Code’s).
+1. Neovim has an integrated terminal (similar in spirit to VS Code's).
1. Helix does not ship one; use tuios / tmux / terminal features instead.
1.
1.
@@ -215,7 +215,7 @@ Some bindings need an **LSP** or **tree-sitter** grammar; see notes on the keyma
1. Global substitution is weaker in Helix; run replacements in another pane (tuios) or an external
tool when needed.
1.
- 1. Neovim’s `:s` with preview remains strong for interactive refactors; external tools (e.g.
+ 1. Neovim's `:s` with preview remains strong for interactive refactors; external tools (e.g.
) can fill gaps in Helix-centric flows.
1. Complexity vs batteries-included tradeoffs:
diff --git a/home/base/core/editors/neovim/README.md b/home/base/core/editors/neovim/README.md
index 43f43339..01c4b715 100644
--- a/home/base/core/editors/neovim/README.md
+++ b/home/base/core/editors/neovim/README.md
@@ -135,7 +135,7 @@ Advanced patterns:
Notes:
-- `\v` — “very magic”, less backslash noise in the pattern.
+- `\v` — "very magic", less backslash noise in the pattern.
- `\1` — first capture group.
### Specific line ranges
diff --git a/home/base/core/git.nix b/home/base/core/git.nix
index 38c91217..73896236 100644
--- a/home/base/core/git.nix
+++ b/home/base/core/git.nix
@@ -23,10 +23,6 @@
lfs.enable = true;
signing.format = "openpgp";
- # signing = {
- # key = "xxx";
- # signByDefault = true;
- # };
includes = [
{
@@ -55,9 +51,6 @@
"ssh://git@github.com/ryan4yin" = {
insteadOf = "https://github.com/ryan4yin";
};
- # "ssh://git@bitbucket.com/ryan4yin" = {
- # insteadOf = "https://bitbucket.com/ryan4yin";
- # };
};
alias = {
@@ -98,8 +91,6 @@
diff-so-fancy = true;
line-numbers = true;
true-color = "always";
- # features => named groups of settings, used to keep related settings organized
- # features = "";
};
};
diff --git a/home/base/gui/terminal/README.md b/home/base/gui/terminal/README.md
index 7021a364..6031e421 100644
--- a/home/base/gui/terminal/README.md
+++ b/home/base/gui/terminal/README.md
@@ -1,8 +1,7 @@
# Terminal Emulators
-I used to spend a lot of time on terminal emulators, to make them match my taste, but now I found
-that it's not worth it, **tuios can provide a user-friendly and unified user experience for all
-terminal emulators! without any pain**!
+I used to spend a lot of time tweaking terminal emulators to match my taste. Now **tuios gives me a
+consistent experience across all of them**.
Currently, I only use the most basic features of terminal emulators, such as true color, graphics
protocol, etc. Other features such as tabs, scrollback buffer, select/search/copy, etc, are all
diff --git a/home/base/gui/terminal/ghostty.nix b/home/base/gui/terminal/ghostty.nix
index 010dd869..8093fefd 100644
--- a/home/base/gui/terminal/ghostty.nix
+++ b/home/base/gui/terminal/ghostty.nix
@@ -21,7 +21,6 @@
pkgs.ghostty;
enableBashIntegration = false;
installBatSyntax = false;
- # installVimSyntax = true;
settings = {
font-family = "Maple Mono NF CN";
font-size = 13;
diff --git a/home/base/tui/gpg/README.md b/home/base/tui/gpg/README.md
index d7605d07..0081f23c 100644
--- a/home/base/tui/gpg/README.md
+++ b/home/base/tui/gpg/README.md
@@ -37,8 +37,7 @@ Currently I use both age & GnuPG:
## Practical Cryptography for Developers
-To use GnuGP without seamlessly, Some Practical Cryptography knowledge is required, here is dome
-tutorials:
+To use GnuPG seamlessly, some Practical Cryptography knowledge is required, here are some tutorials:
- English version:
- Chinese version:
@@ -49,7 +48,7 @@ tutorials:
> ArchWiki's GnuPG page:
-### 0. How GnuGP generate & protect your keypair?
+### 0. How does GnuPG generate & protect your keypair?
Related Docs:
@@ -549,12 +548,12 @@ gpg --verify
```bash
# Encrypt a file via recipient's public key, sign it via your private key for signing, and output cleartext.
-# so that the reciiptent can decrypt it via his/her private key.
+# so that the recipient can decrypt it via his/her private key.
gpg --armor --sign --encrypt --recipient ryan4yin@linux.com
# or use this short version
gpg -aser ryan4yin@linux.com
-# Descrypt a file via your private key, and verify the signature via the sender's public key.
+# Decrypt a file via your private key, and verify the signature via the sender's public key.
gpg --decrypt
# or
gpg -d
@@ -630,7 +629,7 @@ sub cv25519/0x9E78E897B6490D6B 2024-01-09 [E]
# encrypt some file before revoke the keypair
› gpg -are test@test.t README.md > README.md.asc
-# try to decrypt the file, it should works
+# try to decrypt the file, it should work
› gpg -d README.md.asc
gpg: encrypted with cv25519 key, ID 0x9E78E897B6490D6B, created 2024-01-09
"test "
diff --git a/home/base/tui/password-store/README.md b/home/base/tui/password-store/README.md
index 2ebe61b8..77b18025 100644
--- a/home/base/tui/password-store/README.md
+++ b/home/base/tui/password-store/README.md
@@ -5,7 +5,7 @@
- : reimplement in go, with more features.
- Clients
- Android:
- - Brosers(Chrome/Firefox):
+ - Browsers(Chrome/Firefox):
## How to change the gpg key of the pass password store?
@@ -31,6 +31,7 @@ To ensure security, we should change the GPG key every two or three years. Here
# then pass will re-encrypt all the passwords with the new key
pass init
```
+ If `pass init` fails, fix the error and run it again before continuing.
6. Check if the key is changed:
```bash
# check which key is used by pass
@@ -38,7 +39,10 @@ To ensure security, we should change the GPG key every two or three years. Here
# check which key is really used to encrypt the password
gpg --list-packets path/to/any/password.gpg
```
-7. Delete the old GPG key pair:
+ If `.gpg-id` still lists the old key, `pass init` did not apply the change. Re-run it from the
+ password store directory and confirm `.gpg-id` contains the new key.
+7. Delete the old GPG key pair, but only after both checks in step 6 show the new key. Files still
+ encrypted to the old key cannot be decrypted after you delete it.
```bash
# delete the old key pair
gpg --delete-secret-keys
diff --git a/home/hosts/README.md b/home/hosts/README.md
index a526ef72..427c065b 100644
--- a/home/hosts/README.md
+++ b/home/hosts/README.md
@@ -11,7 +11,7 @@ This directory contains host-specific Home Manager entry modules.
1. Each host output should reference only one file under `home/hosts/...`.
2. Shared home module imports should be handled in the host file itself.
- - Linux hosts usually import `../../linux/core.nix` or `../../linux/gui.nix`.
- - Darwin hosts import `../../darwin`.
+ - Linux hosts usually import `../linux/core.nix` or `../linux/gui.nix`.
+ - Darwin hosts import `../darwin`.
3. Host-specific overrides (SSH keys, desktop toggles, host-local config links) live in the same
host file.
diff --git a/home/linux/README.md b/home/linux/README.md
index 63ea0205..e6314386 100644
--- a/home/linux/README.md
+++ b/home/linux/README.md
@@ -1,13 +1,12 @@
# Home Manager's Linux Submodules
-This directory contains Linux-specific Home Manager configurations organized for different use
-cases.
+This directory contains Linux-specific Home Manager configurations.
## Configuration Modules
### Core Configurations
-- **core.nix**: Essential Linux-specific configurations and settings
+- **core.nix**: Linux-specific configurations
- **base/**: Base Linux configurations including shell, tools, and utilities
- `shell.nix`: Shell configurations and aliases
- `tools.nix`: Essential command-line tools and utilities
@@ -29,4 +28,3 @@ cases.
- **Lightweight/Terminal**: Use `core.nix` or `tui.nix` for terminal-focused setups
- **Desktops**: Use `gui.nix` for full desktop environments with Noctalia Shell and Niri compositor
-- **Custom**: Mix and match configurations as needed for your specific use case
diff --git a/home/linux/gui/base/README.md b/home/linux/gui/base/README.md
index fc585d76..66755ef0 100644
--- a/home/linux/gui/base/README.md
+++ b/home/linux/gui/base/README.md
@@ -1,21 +1,20 @@
# Base Desktop Environment Configuration
-This directory contains base configurations for Linux desktop environments, providing essential
-components for a complete Wayland desktop experience.
+This directory contains base configurations for Linux desktop environments.
## Overview
-The configuration is organized into modular components that can be selectively enabled:
+The configuration is split into modules:
-- **Desktop Shell**: Noctalia Shell for unified desktop environment
-- **Applications**: Desktop tools, browsers, editors, media players, etc.
-- **Development Tools**: IDEs and development utilities
-- **System Integration**: Input methods, theming, XDG specifications, GPU settings
+- Desktop shell: Noctalia Shell
+- Applications: desktop tools, browsers, editors, media players
+- Development tools: IDEs and development utilities
+- System integration: input methods, theming, XDG specifications, GPU settings
## Noctalia
-**Noctalia** (v5) is a native C++/Wayland all-in-one desktop shell that replaces multiple separate
-tools with a single, unified solution. It is installed through the upstream
+**Noctalia** (v5) is a native C++/Wayland desktop shell that replaces multiple separate tools. It is
+installed through the upstream
[`programs.noctalia`](https://docs.noctalia.dev/noctalia/getting-started/nixos/) Home Manager
module.
@@ -62,9 +61,9 @@ Noctalia consolidates functionality that previously required multiple tools:
- **[`noctalia/config/config.toml`](./noctalia/config/config.toml)**: declarative baseline (v5
TOML), tracked in the repo and hot-reloaded
- Key features: bar and widgets, control center, desktop widgets, night light, wallpaper, session
+ Covers the bar and widgets, control center, desktop widgets, night light, wallpaper, session
panel, screenshots with annotation, system monitor, audio/volume, brightness, calendar/weather,
- color schemes, dock, notifications, OSD, clipboard, and more.
+ color schemes, dock, notifications, OSD, and clipboard.
- **[`hypridle/`](./hypridle/)**: Idle management
diff --git a/home/linux/gui/base/desktop-tools.nix b/home/linux/gui/base/desktop-tools.nix
index d83afc5c..615daaaf 100644
--- a/home/linux/gui/base/desktop-tools.nix
+++ b/home/linux/gui/base/desktop-tools.nix
@@ -39,6 +39,5 @@
# auto mount usb drives
services = {
udiskie.enable = true;
- # syncthing.enable = true;
};
}
diff --git a/hosts/12kingdoms-shoukei/apple-silicon.nix b/hosts/12kingdoms-shoukei/apple-silicon.nix
index 60c0f5b5..f57eea1f 100644
--- a/hosts/12kingdoms-shoukei/apple-silicon.nix
+++ b/hosts/12kingdoms-shoukei/apple-silicon.nix
@@ -14,6 +14,7 @@
# without any authentication whenever the session exits, e.g. logout from the lock
# screen would bypass it entirely). Keep tuigreet from modules/nixos/desktop.nix.
+ # 16G machine: more compressed swap than the 50% default
zramSwap.memoryPercent = lib.mkForce 75;
nix.settings = {
@@ -27,15 +28,8 @@
environment.systemPackages = with pkgs; [
box64 # Linux Userspace x86 and x86_64 Emulator, run x86_64 apps(such as games, gui apps) on aarch64.
- # https://asahilinux.org/2024/12/muvm-x11-bridging/
- # https://github.com/nix-community/nixos-apple-silicon/issues/237
- # muvm # run x86_64 Apps/Games in a microVM, used as a workaround of apple silicon's 16k page size.
];
- # networking.wireless.iwd = {
- # enable = true;
- # settings.DriverQuirks.DefaultInterface = true;
- # };
# configures the network interface(include wireless) via `nmcli` & `nmtui`
networking.networkmanager.enable = true;
@@ -258,8 +252,4 @@
};
};
- # For ` to < and ~ to > (for those with US keyboards)
- # boot.extraModprobeConfig = ''
- # options hid_apple iso_layout=0
- # '';
}
diff --git a/hosts/12kingdoms-shoukei/default.nix b/hosts/12kingdoms-shoukei/default.nix
index 2d0d8d7a..aff64541 100644
--- a/hosts/12kingdoms-shoukei/default.nix
+++ b/hosts/12kingdoms-shoukei/default.nix
@@ -14,11 +14,13 @@ in
{
imports = [
./hardware-configuration.nix
+ # shoukei reuses ai's preservation layout; no host-specific overrides yet
../idols-ai/preservation.nix
];
- # disable sunshine for securrity
+ # disable sunshine for security
services.sunshine.enable = lib.mkForce false;
+ # battery-first: override the profile default
services.tuned.ppdSettings.main.default = lib.mkForce "power-saver";
# Laptop joins untrusted networks and is never scraped (see youko's
diff --git a/hosts/12kingdoms-shushou/microvm.nix b/hosts/12kingdoms-shushou/microvm.nix
index aa9937ec..8e7775df 100644
--- a/hosts/12kingdoms-shushou/microvm.nix
+++ b/hosts/12kingdoms-shushou/microvm.nix
@@ -42,8 +42,8 @@
};
# Attach the guest's tap to the VM bridge, the same way the physical NIC is
- # attached. The tap name is derived from the guest IP (192.168.5.116 -> vm116,
- # 192.168.5.113 -> vm113), as IFNAMSIZ caps interface names at 15 characters.
+ # attached. The name is vm from lib/genMicrovmGuestModule.nix:
+ # 192.168.5.116 -> vm116, 192.168.5.113 -> vm113.
systemd.network.networks."20-vm116" = {
matchConfig.Name = [ "vm116" ];
networkConfig = {
diff --git a/hosts/12kingdoms-youko/homelab-services/README.md b/hosts/12kingdoms-youko/homelab-services/README.md
index 084781df..9ef1041b 100644
--- a/hosts/12kingdoms-youko/homelab-services/README.md
+++ b/hosts/12kingdoms-youko/homelab-services/README.md
@@ -9,20 +9,30 @@ retired `idols-aquamarine` guest):
## Features
-Services:
+### Storage and data
-1. caddy: Reverse proxy / TLS front end and the `file.writefor.fun` file server.
-1. gitea: Self-hosted git service.
-1. sftpgo: SFTP / WebDAV server.
-1. transmission: BitTorrent client.
-1. postgresql: Database for the homelab services.
-1. restic: Encrypted backups; hosts the REST server the desktops push to.
-1. victoriametrics + vmalert + alertmanager + grafana: Monitor the metrics of my homelab.
-1. homepage + uptime-kuma: Service dashboard and uptime checks.
-1. immich: Photo and video library with ML search.
-1. jellyfin: Media server.
-1. rustfs: S3-compatible object storage (Loki chunks and Terraform state).
-1. valkey: Redis-compatible cache for Immich.
+1. gitea: Self-hosted git service (`gitea.nix`).
+1. sftpgo: SFTP / WebDAV server (`sftpgo.nix`).
+1. postgresql: Database for the homelab services (`postgresql.nix`).
+1. valkey: Redis-compatible cache for Immich (`valkey.nix`).
+
+### Backups and object storage
+
+1. restic: Encrypted backups; hosts the REST server the desktops push to (`../default.nix`).
+1. rustfs: S3-compatible object storage (Loki chunks and Terraform state) (`rustfs.nix`).
+
+### Media
+
+1. immich: Photo and video library with ML search (`immich/`).
+1. jellyfin: Media server (`jellyfin.nix`).
+1. transmission: BitTorrent client (`transmission.nix`).
+
+### Network and observability
+
+1. caddy: Reverse proxy / TLS front end and the `file.writefor.fun` file server (`caddy.nix`).
+1. victoriametrics + vmalert + alertmanager + grafana: Monitor the metrics of my homelab
+ (`monitoring/`).
+1. homepage + uptime-kuma: Service dashboard and uptime checks (`oci-containers/`).
All the services assume a reverse proxy in front: they listen on localhost, and a caddy service
listens on the local network interface and proxies requests to them. The exception is transmission,
diff --git a/hosts/12kingdoms-youko/homelab-services/immich/README.md b/hosts/12kingdoms-youko/homelab-services/immich/README.md
index f18d8cbb..c9dce3c6 100644
--- a/hosts/12kingdoms-youko/homelab-services/immich/README.md
+++ b/hosts/12kingdoms-youko/homelab-services/immich/README.md
@@ -100,8 +100,7 @@ document is the agreed design and the rationale.
tmpfiles).
3. `../caddy.nix`: the `immich.writefor.fun` vhost.
4. `../oci-containers/homepage/config/services.yaml`: dashboard entry.
-5. Preview and deploy: `colmena apply dry-activate --on '@youko'`, then
- `colmena apply switch --on '@youko'`.
+5. Preview and deploy: `just youko dry-activate`, then `just youko`.
6. Register the first user (becomes admin), disable open signup, add the external library, trigger a
scan.
diff --git a/hosts/12kingdoms-youko/microvm.nix b/hosts/12kingdoms-youko/microvm.nix
index b09504e2..a2e5db18 100644
--- a/hosts/12kingdoms-youko/microvm.nix
+++ b/hosts/12kingdoms-youko/microvm.nix
@@ -44,8 +44,8 @@
};
# Attach the guest's tap to the VM bridge, the same way the physical NIC is
- # attached. The tap name is derived from the guest IP (192.168.5.115 -> vm115,
- # 192.168.5.112 -> vm112), as IFNAMSIZ caps interface names at 15 characters.
+ # attached. The name is vm from lib/genMicrovmGuestModule.nix:
+ # 192.168.5.115 -> vm115, 192.168.5.112 -> vm112.
systemd.network.networks."20-vm115" = {
matchConfig.Name = [ "vm115" ];
networkConfig = {
diff --git a/hosts/README.md b/hosts/README.md
index c4ae85bd..ad7d89e6 100644
--- a/hosts/README.md
+++ b/hosts/README.md
@@ -10,16 +10,12 @@ This directory contains all host-specific configurations for my NixOS and macOS
Named after characters from "Oshi no Ko":
-| Host | Platform | Hardware | Purpose | Status |
-| ------------ | --------------- | --------------------------------------- | --------------------- | ----------- |
-| `ai` | NixOS | Ultra 7 270K Plus + RTX 4090, 128G DDR5 | Gaming & Daily Use | ✅ Active |
-| `aquamarine` | NixOS (libvirt) | Virtual | Monitoring & Services | ⚪ Not Used |
-| `kana` | NixOS (libvirt) | Virtual | Run AI Agents | ✅ Active |
-| `ruby` | NixOS (libvirt) | Virtual | Run AI Agents | ✅ Active |
-| `akane` | NixOS (aarch64) | Virtual (UTM) | aarch64 test VM | ✅ Active |
-
-`aquamarine` is retired; its services now run directly on `youko`
-(`hosts/12kingdoms-youko/homelab-services/`).
+| Host | Platform | Hardware | Purpose | Status |
+| ------- | --------------- | --------------------------------------- | ------------------ | --------- |
+| `ai` | NixOS | Ultra 7 270K Plus + RTX 4090, 128G DDR5 | Gaming & Daily Use | ✅ Active |
+| `kana` | NixOS (libvirt) | Virtual | Run AI Agents | ✅ Active |
+| `ruby` | NixOS (libvirt) | Virtual | Run AI Agents | ✅ Active |
+| `akane` | NixOS (aarch64) | Virtual (UTM) | aarch64 test VM | ✅ Active |
On 2026-04-27 `ai` was rebuilt on a new platform. The MSI board and i5-13600KF it was added with in
2023-05 (the host was originally named `msi-rtx4090`) gave way to the Colorful CVN Z890 ARK FROZEN +
@@ -34,6 +30,15 @@ installed first; with the 48G pair in first the board does not POST. The bring-u
settings, the stress-test recipe, and how to recover a board that will not POST are in
[`idols-ai/MIXED-MEMORY.md`](./idols-ai/MIXED-MEMORY.md).
+##### Retired
+
+| Host | Platform | Hardware | Purpose | Status |
+| ------------ | --------------- | -------- | --------------------- | ---------- |
+| `aquamarine` | NixOS (libvirt) | Virtual | Monitoring & Services | ⚪ Retired |
+
+`aquamarine` is retired; its services now run directly on `youko`
+(`hosts/12kingdoms-youko/homelab-services/`).
+
#### `darwin` - macOS Systems
Named after characters from "Frieren: Beyond Journey's End":
@@ -138,7 +143,7 @@ cool!
[Oshi no Ko 【推しの子】 - Wikipedia](https://en.wikipedia.org/wiki/Oshi_no_Ko):
- 
+ 
[The Rolling Girls【ローリング☆ガールズ】 - Wikipedia](https://en.wikipedia.org/wiki/The_Rolling_Girls):
diff --git a/hosts/idols-ai/secureboot.nix b/hosts/idols-ai/secureboot.nix
index 7c627753..22c872d6 100644
--- a/hosts/idols-ai/secureboot.nix
+++ b/hosts/idols-ai/secureboot.nix
@@ -22,10 +22,8 @@
pkgs.sbctl
];
- # Lanzaboote currently replaces the systemd-boot module.
- # This setting is usually set to true in configuration.nix
- # generated at installation time. So we force it to false
- # for now.
+ # Lanzaboote replaces the systemd-boot module. NixOS's generated
+ # configuration.nix sets this to true, so force it off.
boot.loader.systemd-boot.enable = lib.mkForce false;
boot.lanzaboote = {
diff --git a/hosts/idols-akane/README.md b/hosts/idols-akane/README.md
index 243bfedc..0fc4812c 100644
--- a/hosts/idols-akane/README.md
+++ b/hosts/idols-akane/README.md
@@ -6,8 +6,7 @@ Steps to install:
```bash
# 1. format & mount the filesystem
-nix-shell -p disko
-sudo disko --mode destroy,format,mount hosts/idols-akane/disko-fs.nix
+sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko -- --mode destroy,format,mount hosts/idols-akane/disko-fs.nix
# 2. install nixos
nixos-install --root /mnt --flake .#akane --no-root-password --show-trace --verbose --option substituters "https://mirrors.ustc.edu.cn/nix-channels/store https://cache.nixos.org/" # install-2
diff --git a/hosts/idols-akane/oci-containers/default.nix b/hosts/idols-akane/oci-containers/default.nix
index 14e90caa..3ecb1f0e 100644
--- a/hosts/idols-akane/oci-containers/default.nix
+++ b/hosts/idols-akane/oci-containers/default.nix
@@ -7,25 +7,8 @@
{
imports = mylib.scanPaths ./.;
- # environment.systemPackages = with pkgs; [
- # podman-compose
- # ];
-
virtualisation = {
docker.enable = true;
- # podman = {
- # enable = true;
- # # Create a `docker` alias for podman, to use it as a drop-in replacement
- # dockerCompat = true;
- # # Required for containers under podman-compose to be able to talk to each other.
- # defaultNetwork.settings.dns_enabled = true;
- # # Periodically prune Podman resources
- # autoPrune = {
- # enable = true;
- # dates = "weekly";
- # flags = [ "--all" ];
- # };
- # };
oci-containers = {
backend = "docker";
diff --git a/hosts/k8s/README.md b/hosts/k8s/README.md
index 2fe72918..e3d41520 100644
--- a/hosts/k8s/README.md
+++ b/hosts/k8s/README.md
@@ -21,8 +21,8 @@ its state in three sparse ext4 images under the host's `/var/lib/microvms/
The guest's root is a tmpfs and `/nix/store` is the host's store shared read-only (virtiofs), so no
image has to be built or uploaded; only the volumes above persist. The guest's tap interface is
-bridged onto `br0`, and its name is derived from the guest IP (e.g. `192.168.5.114` -> `vm114`, as
-`IFNAMSIZ` caps interface names at 15 characters).
+bridged onto `br0`, and its name is derived from the last octet of the guest IP by
+`lib/genMicrovmGuestModule.nix` (e.g. `192.168.5.114` -> `vm114`).
### Updating a running guest
diff --git a/hosts/k8s/disko-config/README.md b/hosts/k8s/disko-config/README.md
index 9a978e4d..5f4cc4f2 100644
--- a/hosts/k8s/disko-config/README.md
+++ b/hosts/k8s/disko-config/README.md
@@ -16,6 +16,7 @@ cd nix-config
# encrypt the root partition with luks2 and argon2id, will prompt for a passphrase, which will be used to unlock the partition.
sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko -- --mode destroy,format,mount hosts/k8s/disko-config/host-disko-fs.nix
## 2. setup the automatic unlock via the tpm2 chip
+# find the LUKS partition with: lsblk -f
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/
## 3. install nixos
@@ -31,6 +32,7 @@ nixos-enter
# otherwise the / will be cleared and data will lost
## NOTE: preservation just create links from / to /persistent
## We need to copy files into /persistent manually!!!
+mkdir -p /persistent/etc
mv /etc/machine-id /persistent/etc/
mv /etc/ssh /persistent/etc/
mkdir -p /persistent/home/ryan
diff --git a/infra/README.md b/infra/README.md
index c28a9e48..4522e464 100644
--- a/infra/README.md
+++ b/infra/README.md
@@ -64,7 +64,10 @@ Each subdirectory contains its own Terraform configuration:
## Security Considerations
-- All storage buckets are configured with appropriate access policies
-- State files are encrypted at rest
-- Access credentials are managed through environment variables
-- Network access is restricted to necessary hosts only
+- Buckets are declared as bare `aws_s3_bucket` resources, with no bucket policy or server-side
+ encryption configuration. The only guard in Terraform is `prevent_destroy` on the `tf-s3-backend`
+ state bucket.
+- IAM users and policies are created by hand with the `rc` client, not Terraform (see
+ [rustfs/README.md](./rustfs/README.md)).
+- Access credentials are managed through environment variables (`AWS_ACCESS_KEY_ID` /
+ `AWS_SECRET_ACCESS_KEY`).
diff --git a/infra/rustfs/README.md b/infra/rustfs/README.md
index 28cd72b2..f95a9d5d 100644
--- a/infra/rustfs/README.md
+++ b/infra/rustfs/README.md
@@ -21,6 +21,9 @@ set -a; . <(sudo cat /run/agenix/rustfs.env); set +a
rc alias set rustfs https://s3.writefor.fun "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY"
```
+Sourcing the file is a deliberate exception to the rule against reading decrypted secrets: `cat`
+runs inside the process substitution, so the values go into the shell and are never printed.
+
## Buckets
```bash
diff --git a/lib/README.md b/lib/README.md
index 7d7df236..93f11fab 100644
--- a/lib/README.md
+++ b/lib/README.md
@@ -28,12 +28,9 @@ reduce code duplication and make it easier to add new machines.
## Usage
-These functions are designed to:
-
-- Generate consistent configurations across different architectures
-- Provide type-safe configuration for complex systems
-- Enable easy scaling of the infrastructure
-- Support both local development and production deployments
+The generators import the shared host modules, so a new machine supplies its own values and
+system-specific attributes. `colmenaSystem` covers remote deployment, and `genLibvirtDomainXml`
+renders the domain XML for one guest.
## Architecture Support
diff --git a/nixos-installer/README.md b/nixos-installer/README.md
index 941fce5d..d6531879 100644
--- a/nixos-installer/README.md
+++ b/nixos-installer/README.md
@@ -1,7 +1,7 @@
# Nix Environment Setup for Host: Idols - Ai
> :red_circle: **IMPORTANT**: **Do not deploy this flake directly on your machine.** Write your own
-> configuration from scratch and use this only as reference.\*\*
+> configuration from scratch and use this only as reference.
This flake prepares a Nix environment for setting up the desktop host
[hosts/idols-ai](../hosts/idols-ai/) (from the main flake) on a new machine.
@@ -52,6 +52,7 @@ nix run github:nix-community/disko -- --mode destroy,format,mount ../hosts/idols
nix run github:nix-community/disko -- --mode destroy,format,mount ../hosts/idols-ai/disko-fs-data.nix
# setup the automatic unlock via the tpm2 chip
+# find the LUKS partition with: lsblk -f
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/
```
@@ -60,8 +61,8 @@ systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/ `sudo -i` => enter ryan's password => successfully login
-# if login failed, check the password you set in install-1, and try again
+# if login failed, check ryan's initial password in vars/default.nix, and try again
nixos-enter
@@ -268,6 +269,7 @@ nixos-enter
# otherwise the / will be cleared and data will lost
## NOTE: preservation just create links from / to /persistent
## We need to copy files into /persistent manually!!!
+mkdir -p /persistent/etc
mv /etc/machine-id /persistent/etc/
mv /etc/ssh /persistent/etc/
@@ -328,4 +330,4 @@ just niri
Finally, to enable secure boot, follow the instructions in
[lanzaboote - Quick Start](https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md)
and
-[nix-config/ai/secure-boot.nix](https://github.com/ryan4yin/nix-config/blob/main/hosts/idols-ai/secureboot.nix)
+[hosts/idols-ai/secureboot.nix](https://github.com/ryan4yin/nix-config/blob/main/hosts/idols-ai/secureboot.nix)
diff --git a/nixos-installer/flake.nix b/nixos-installer/flake.nix
index 08711cc5..c762638a 100644
--- a/nixos-installer/flake.nix
+++ b/nixos-installer/flake.nix
@@ -74,6 +74,7 @@
../modules/nixos/base/ssh.nix
../hosts/12kingdoms-shoukei/hardware-configuration.nix
+ # shoukei reuses ai's preservation layout; no host-specific overrides yet
../hosts/idols-ai/preservation.nix
];
};
diff --git a/outputs/README.md b/outputs/README.md
index ebeac8c8..137ba65a 100644
--- a/outputs/README.md
+++ b/outputs/README.md
@@ -7,18 +7,14 @@ There is no need to do this when you have a small number of machines.
But when you have a large number of machines, it is necessary to manage them in a fine-grained way,
otherwise, it will be difficult to manage and maintain them.
-The number of my machines has grown past a dozen, and the increase in scale has shown signs of
-getting out of control of complexity, so it is a natural and reasonable choice to use this
-fine-grained architecture to manage.
+I have more than a dozen machines now, and a fine-grained layout keeps them manageable.
## Tests
-Testing is not necessary when your configuration is not complex, but with the increase in the number
-and configuration of your machines, testing becomes more and more important.
+Simple configurations do not need tests, but a dozen machines make a broken setting easy to miss.
-We have two types of tests: eval tests and nixos tests, both of which can help us detect many
-obscure errors early, so as to avoid testing directly in the real world, and to avoid failures in
-personal computers and even corporate online environments.
+There are two types of tests: eval tests and NixOS tests. They catch configuration errors before a
+change reaches a real machine.
Related projects & docs:
@@ -121,3 +117,8 @@ All the outputs of this flake are defined here.
└── tests # eval tests (btrbk, computer-use-headless, hostname,
# kernel, security-*, ups-metrics, ...)
```
+
+The tree lists the per-host sources and tests. The flake also exposes a `checks` output: every
+system has `eval-tests` and `pre-commit-check`, and `x86_64-linux` adds `security-exporters`, which
+imports the top-level `tests/security-exporters.nix`. See [`../SECURITY.md`](../SECURITY.md) for
+when to run it.
diff --git a/outputs/default.nix b/outputs/default.nix
index f91c9de4..77f7abc2 100644
--- a/outputs/default.nix
+++ b/outputs/default.nix
@@ -31,12 +31,6 @@ let
pkgs-stable
;
- # use unstable branch for some packages to get the latest updates
- # pkgs-unstable = import inputs.nixpkgs-unstable {
- # inherit system; # refer the `system` parameter form outer scope recursively
- # # To use chrome, we need to allow the installation of non-free software
- # config.allowUnfree = true;
- # };
pkgs-2505 = import inputs.nixpkgs-2505 {
inherit system;
# To use chrome, we need to allow the installation of non-free software
diff --git a/overlays/README.md b/overlays/README.md
index 54d2f5e5..9436172c 100644
--- a/overlays/README.md
+++ b/overlays/README.md
@@ -21,8 +21,7 @@ overlays/
### 1. `default.nix`
-The entrypoint of overlays, it execute and import all overlay files in the current directory with
-the given args.
+The entrypoint imports every overlay file in this directory and applies it to the given arguments.
### 2. Package overlays
diff --git a/secrets/README.md b/secrets/README.md
index ceefe879..de745833 100644
--- a/secrets/README.md
+++ b/secrets/README.md
@@ -62,7 +62,8 @@ every local account. Always set `user` together with `mode`. nix-darwin ignores
> set to a local `~/codes/nix-secrets` checkout, so invoke it from this repository's root.
This task is accomplished using the [agenix](https://github.com/ryantm/agenix) CLI tool with the
-`./secrets.nix` file, so you need to have it installed first:
+`./secrets.nix` file in the private `nix-secrets` repository, so you need to have it installed
+first:
To use agenix temporarily, run:
diff --git a/vars/README.md b/vars/README.md
index 7b82fdc3..8694cddc 100644
--- a/vars/README.md
+++ b/vars/README.md
@@ -24,7 +24,7 @@ Contains user information, SSH keys, and password configuration:
### 2. `networking.nix`
-Comprehensive network configuration including:
+Defines:
- **Gateway settings**: Main router and proxy gateway configurations
- **DNS servers**: IPv4 and IPv6 name servers
@@ -40,5 +40,4 @@ Comprehensive network configuration including:
## Usage
-These variables are imported and used throughout the configuration to ensure consistency across all
-hosts and maintain centralized network and security settings.
+These variables are imported and used throughout the configuration.