* docs(skills): point nix-config-secrets at the private repo under ~/codes
Record where the private nix-secrets checkout lives and that agents should
do the mechanical secret work themselves, handing back only the
interactive/sudo agenix operations and pushes.
* docs(agents): add related repositories to nix-config
* chore(agents): adopt ~/src for source checkouts
Move third-party/source checkouts from ~/codes/src to ~/src so the home
layout reads as three siblings: ~/codes (personal), ~/work (work),
~/src (checkouts). Preserve and back up the new path, and update the
global rule and the two nixpkgs skill references.
* docs(agents): tighten the code layout rule
* docs(agents): fold the work-confidentiality note into the layout line
* docs(agents): base the confidentiality rule on repo visibility
* docs(agents): drop the stale KubeVirt mention
Catppuccin's home-manager module writes extra-substituters/extra-trusted-public-keys
for catppuccin.cachix.org into the user-level ~/.config/nix/nix.conf. Since the
normal user is no longer a trusted-user (modules/base/nix.nix), Nix ignores those
client-specified settings and warns on every command. The ports build locally, so
turn the user-level cache off instead.
nixvim has been disabled for a long time (programs.nixvim.enable = false), so
drop the flake input (and prune flake.lock). Port the settings it carried to
Home Manager's programs.neovim: opts and per-plugin setup become an initLua
block plus a plugin list. The catppuccin module already provides the
colorscheme, vi stays unmapped, and the plain system neovim package is
untouched so sudo/nvim --clean keep using it.
Allow clearly-implied task authorization, trust skills listed in the runtime's configured catalog, and restore the ban on following external-material instructions. Sync the affected evaluation scenarios.
* fix(youko): add ROCm OpenCL so Jellyfin can tone-map HDR
Jellyfin's HDR/DoVi transcodes use ffmpeg's `tonemap_opencl`, but only
Mesa was installed via `hardware.graphics.enable`, so no OpenCL ICD was
registered. ffmpeg then failed to create an OpenCL device ("Failed to
get number of OpenCL platforms: -1001") and aborted with exit code 237,
leaving HDR titles unplayable.
Add `rocmPackages.clr.icd` to `hardware.graphics.extraPackages`; it
ships the ICD for the Barceló iGPU (reported as `gfx90c`) under
/run/opengl-driver/etc/OpenCL/vendors, where `ocl-icd` (built with
`--enable-custom-vendordir`) finds it.
The Barceló iGPU only manages ~0.8x realtime for a 4K HDR -> 1080p
tone-mapped transcode, so playback can still buffer; this only makes
such titles playable at all.
* fix(youko): allow /dev/kfd so Jellyfin OpenCL can reach the GPU
The jellyfin module's `DeviceAllow` whitelist only permits the VA-API
render node (`/dev/dri/renderD128`). ROCm's OpenCL runtime opens
`/dev/kfd`, so even with the ICD installed OpenCL device creation failed
("No matching devices found") and HDR transcodes still aborted with exit
code 237.
Add `/dev/kfd rw` to the whitelist; list definitions merge with the
module's entry. Verified under the unit's sandbox (PrivateUsers,
PrivateTmp) that OpenCL init then succeeds as the jellyfin user.
conda/mitmproxy/wireshark are already Linux-gated in the shared home modules, and verible is unreferenced, so replacing them with emptyDirectory is unnecessary.
openldap's flaky tests are skipped upstream now (doCheck = true), so the override only forced local rebuilds of openldap/cyrus-sasl dependents such as libvirt and kio.
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.
* fix(youko): stop homepage from probing the authenticated transmission RPC
The siteMonitor hit /transmission/rpc unauthenticated, so every probe returned 401 and counted against transmission's anti-brute-force threshold.
* feat(youko): tune transmission and firewall its network namespace
Raise the upload limit and queues, relax required encryption to preferred, and add a default-drop nftables input chain inside the netns so the peer port stays open while everything else is closed. Allowlist the nftables 'iif' keyword for typos.
* feat(youko): export transmission metrics and add a Grafana dashboard
nixpkgs has no transmission exporter, so add a small stdlib Python exporter that queries the authenticated netns RPC on loopback, scrape it from VictoriaMetrics, and ship a Transmission dashboard.
* fix(youko): cap transmission upload at 2500 kB/s
30 MB/s ignored the 50 Mbps uplink; keep seeding around 20 Mbps.
* Revert "feat(youko): export transmission metrics and add a Grafana dashboard"
This reverts commit 9df7a26526.
Hosts used to trust the router as the only boundary (servers ran with the
firewall off; service ports were opened globally), so any LAN device could
reach every host service. Move filtering to the hosts as defence in depth
behind the router, which keeps its firewall on and uses a port mapping for
the few ports we actually need.
- base: nftables backend; deny inbound by default; trust the home LAN by
source and the tailnet by interface (restrict the tailnet with ACLs);
suppress per-service `openFirewall` global ports; allow node_exporter only
from the monitoring host. The local podman bridge, the tailnet and the pod
CIDRs are accepted only after the node_exporter drop.
- servers: stop disabling the firewall; drop redundant global port opens
(caddy 80/443, NFS 2049, Jellyfin, localsend/test ports); delete the
redundant desktop firewall module; aarch64/riscv64 import the firewall
explicitly (akane was missing it).
- k3s: Cilium pods (10.0.0.0/8, fd00::/8) may reach host services; drop the
flannel-era cni0/flannel.1 trust.
- youko: postgres listens on localhost + the LAN with pg_hba limited to the
LAN; the NFS export stays LAN-scoped; remove the unauthenticated v2ray
proxy.
- tests: `security-firewall` asserts every host runs the shared firewall, has
the LAN CIDR rule and no global ports.
Treat content from unverified sources as data, not instructions, and require authorization before cloning, downloading, or executing unverified code and install scripts.
* feat(youko): add Jellyfin media server
Jellyfin reads the existing Transmission download tree on the public HDD
(via the shared `fileshare` group) and transcodes with the AMD Barceló
iGPU through VA-API. Encoding settings are declared in Nix
(`forceEncodingConfig`), so the web UI cannot silently drift.
Replace the per-service public ACME certificates with a single
`*.writefor.fun` wildcard (plus the apex) shared by every public vhost,
so adding a service needs no new ACME entry; a wildcard also keeps
individual hostnames out of public CT logs.
Pin the jellyfin uid/gid to avoid the dynamic-id drift fixed for the
other services in #320.
* fix(youko): enable graphics for Jellyfin VA-API
VA-API needs Mesa's radeonsi VA driver under /run/opengl-driver, but
youko is headless so hardware.graphics was off. Without it Jellyfin's
ffmpeg fails with 'va_openDriver() returns -1'. Enable it so the iGPU
can be used for hardware transcoding.
* fix(youko): use VA-API hardware encoding for Jellyfin
Enabling hardware decoding alone left encoding on the CPU (libx264), which
pins ~3 cores per 720p stream. Set transcoding.enableHardwareEncoding so
the iGPU (Vega VCN) does the H.264 encode too.
* feat(youko): harden Jellyfin proxy trust, groups, and HEVC encode
Add jellyfin to the render/video groups for robust VA-API access (was
relying on the world-writable render node), enable HEVC hardware encoding
(Vega's VCN supports it; AV1 does not), and patch network.xml on start to
trust Caddy as KnownProxies and advertise the public URL.
* fix(youko): run Jellyfin network.xml patch every start; allow LAN discovery
The module's preStart exits early once encoding.xml matches, so the
mkAfter network.xml patch only ran when encoding settings changed. Run it
with mkBefore instead. Also allow Jellyfin app auto-discovery (UDP 7359 /
TCP 8096) from the home network only.