mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:46 +01:00
docs: review and correct comments and documentation (#436)
This commit is contained in:
1 parent
f32d67a5cc
commit
9c38819517
50 files changed
+148
-148
No files matched your search
@@ -35,7 +35,7 @@ projects live in [agents/](./agents/README.md).
|
|||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
- For Nix changes, run `just fmt` and inspect the diff: it formats all Nix files. Nix style is
|
- For Nix changes, run `just fmt` and inspect the diff: it formats all Nix files. Nix style is
|
||||||
`nixfmt` with width 100.
|
`nixfmt`, whose default width is 100.
|
||||||
- For supported non-Nix files, use `prettier --write <file>` and `prettier --check <file>`;
|
- For supported non-Nix files, use `prettier --write <file>` and `prettier --check <file>`;
|
||||||
configuration lives in `.prettierrc.yaml`. Spelling checks use `typos` and `.typos.toml`.
|
configuration lives in `.prettierrc.yaml`. Spelling checks use `typos` and `.typos.toml`.
|
||||||
- Run `just test` for configuration changes; it evaluates `.#evalTests` across Linux and Darwin and
|
- Run `just test` for configuration changes; it evaluates `.#evalTests` across Linux and Darwin and
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ verify-store:
|
|||||||
repair-store *paths:
|
repair-store *paths:
|
||||||
nix store repair {{paths}}
|
nix store repair {{paths}}
|
||||||
|
|
||||||
# Update all Nixpkgs inputs
|
# Update the secondary nixpkgs inputs (the primary `nixpkgs` needs `just up`)
|
||||||
[group('nix')]
|
[group('nix')]
|
||||||
up-nix:
|
up-nix:
|
||||||
nix flake update --commit-lock-file nixpkgs-stable nixpkgs-master nixpkgs-darwin nixpkgs-patched
|
nix flake update --commit-lock-file nixpkgs-stable nixpkgs-master nixpkgs-darwin nixpkgs-patched
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ For macOS (nix-darwin):
|
|||||||
# If you are deploying for the first time,
|
# If you are deploying for the first time,
|
||||||
# 1. install nix & homebrew manually.
|
# 1. install nix & homebrew manually.
|
||||||
# 2. prepare the deployment environment with essential packages available
|
# 2. prepare the deployment environment with essential packages available
|
||||||
nix-shell -p just nushell
|
nix shell nixpkgs#just nixpkgs#nushell
|
||||||
# 3. comment home-manager's code in lib/macosSystem.nix to speed up the first deployment.
|
# 3. comment home-manager's code in lib/macosSystem.nix to speed up the first deployment.
|
||||||
|
|
||||||
# Deploy the darwinConfiguration by hostname match (fern, frieren)
|
# Deploy the darwinConfiguration by hostname match (fern, frieren)
|
||||||
|
|||||||
+20
-20
@@ -33,18 +33,18 @@ small, reversible controls and narrow exceptions; benchmark before adopting expe
|
|||||||
|
|
||||||
## Architecture and trust boundaries
|
## Architecture and trust boundaries
|
||||||
|
|
||||||
| Boundary | Current design | Limitation |
|
| Boundary | Current design | Limitation |
|
||||||
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| Administration | Key-based SSH; root key login retained for Colmena/MicroVM deployment | Deployment credentials are root-equivalent; password login being disabled does not restrict stolen keys |
|
| Administration | Key-based SSH; root key login retained for Colmena/MicroVM deployment | Deployment credentials are root-equivalent; password login being disabled does not restrict stolen keys |
|
||||||
| Host network | Shared nftables firewall trusts the home LAN, tailnet interface and local Podman bridge; IPv6 link-local is accepted | These are broad trust zones, not service-level least privilege; router exposure and tailnet ACLs require separate verification |
|
| Host network | Shared nftables firewall trusts the home LAN, tailnet interface and local Podman bridge; IPv6 link-local is accepted | These are broad trust zones, not service-level least privilege; router exposure and tailnet ACLs require separate verification |
|
||||||
| Monitoring | node/smartctl exporters bind the host LAN IPv4 (9100/9633); firewall rules restrict exporter ports 9100, 9835 and 9633 to the monitoring host over IPv4 | nvidia_gpu_exporter (9835) still binds wildcard; IPv6 denial is planned in the baseline implementation; current running hosts require separate verification |
|
| Monitoring | node/smartctl exporters bind the host LAN IPv4 (9100/9633); firewall rules restrict exporter ports 9100, 9835 and 9633 to the monitoring host over IPv4 | nvidia_gpu_exporter (9835) still binds wildcard; the IPv6 denial for those three ports is in the shared firewall; current running hosts require separate verification |
|
||||||
| VM hosts | shoryu, shushou and youko run guests behind `br0`; ruby/kana are libvirt guests | A bridge is not network isolation; host compromise affects its guests |
|
| VM hosts | shoryu, shushou and youko run guests behind `br0`; ruby/kana are libvirt guests | A bridge is not network isolation; host compromise affects its guests |
|
||||||
| k3s | Three control-plane and three worker MicroVMs; Cilium, API VIP and NFS CSI | Cluster-admin, privileged/host-mounted pods and writable NFS data are powerful trust boundaries |
|
| k3s | Three control-plane and three worker MicroVMs; Cilium, API VIP and NFS CSI | Cluster-admin, privileged/host-mounted pods and writable NFS data are powerful trust boundaries |
|
||||||
| MicroVM storage | Host store shared read-only through virtiofs; guest `/etc`, `/var` and `/home` persisted in separate images | Read-only store does not isolate the host-side virtiofs implementation or protect writable guest state |
|
| MicroVM storage | Host store shared read-only through virtiofs; guest `/etc`, `/var` and `/home` persisted in separate images | Read-only store does not isolate the host-side virtiofs implementation or protect writable guest state |
|
||||||
| Desktop apps | Selected apps use nixpak/bubblewrap; Podman is rootless | Rules and shared directories vary per app; user namespaces are needed for these sandboxes |
|
| Desktop apps | Selected apps use nixpak/bubblewrap; Podman is rootless | Rules and shared directories vary per app; user namespaces are needed for these sandboxes |
|
||||||
| Secrets | agenix declarations here, encrypted data in the private nix-secrets repository | Recipients and plaintext file permissions must be reviewed; root on a recipient can read its decrypted secrets |
|
| Secrets | agenix declarations here, encrypted data in the private nix-secrets repository | Recipients and plaintext file permissions must be reviewed; root on a recipient can read its decrypted secrets |
|
||||||
| Supply chain | Locked flake inputs; explicit binary-cache trust keys; normal user is not a Nix trusted-user | A trusted cache or imported Nix module can supply code executed as root; a lock file is not a security audit |
|
| Supply chain | Locked flake inputs; explicit binary-cache trust keys; normal user is not a Nix trusted-user | A trusted cache or imported Nix module can supply code executed as root; a lock file is not a security audit |
|
||||||
| Recovery | NixOS generations, btrbk/restic, hourly read-only snapshots of the REST store, and documented backup procedures | A rollback does not undo compromised data or secrets; backup configuration alone does not prove restore works; the offsite immutable copy is still planned |
|
| Recovery | NixOS generations, btrbk/restic, hourly read-only snapshots of the REST store, and documented backup procedures | A rollback does not undo compromised data or secrets; backup configuration alone does not prove restore works; the offsite immutable copy is still planned |
|
||||||
|
|
||||||
Sources: [host layout](hosts/README.md), [k3s deployment](hosts/k8s/README.md),
|
Sources: [host layout](hosts/README.md), [k3s deployment](hosts/k8s/README.md),
|
||||||
[firewall](modules/nixos/base/networking/firewall.nix), [SSH](modules/nixos/base/ssh.nix),
|
[firewall](modules/nixos/base/networking/firewall.nix), [SSH](modules/nixos/base/ssh.nix),
|
||||||
@@ -153,14 +153,14 @@ configuration and certificate lifecycle procedures. Never bypass TLS verificatio
|
|||||||
hostname mismatch. Eval tests protect the domain join endpoint and server SAN declarations; live TLS
|
hostname mismatch. Eval tests protect the domain join endpoint and server SAN declarations; live TLS
|
||||||
checks remain necessary after deployment.
|
checks remain necessary after deployment.
|
||||||
|
|
||||||
## Implementation plan and completed audit findings
|
## Implementation status and completed audit findings
|
||||||
|
|
||||||
### Implementation status
|
### Implementation status
|
||||||
|
|
||||||
| Component | Status | Runtime verification |
|
| Component | Status | Runtime verification |
|
||||||
| ---------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------- |
|
| ---------------------------------------------------------------- | --------------------------------------- | --------------------------------------------------- |
|
||||||
| Architecture, agent-first policy, audits and canonical API tests | Included in this documentation change | Only the dated observations below were checked live |
|
| Architecture, agent-first policy, audits and canonical API tests | In this repository | Only the dated observations below were checked live |
|
||||||
| Explicit sysctl baseline and IPv6 exporter defence | Implemented in this baseline change | Not deployed or verified on running hosts |
|
| Explicit sysctl baseline and IPv6 exporter defence | In `hardening/` and the shared firewall | Not deployed or verified on running hosts |
|
||||||
|
|
||||||
### Baseline implementation checks
|
### Baseline implementation checks
|
||||||
|
|
||||||
@@ -168,11 +168,11 @@ checks remain necessary after deployment.
|
|||||||
- IPv6 exporter denial precedes broad LAN/tailnet/container rules. The monitoring configuration uses
|
- IPv6 exporter denial precedes broad LAN/tailnet/container rules. The monitoring configuration uses
|
||||||
IPv4 targets for these ports, so no scrape endpoint migration is needed.
|
IPv4 targets for these ports, so no scrape endpoint migration is needed.
|
||||||
- x86_64/aarch64 eval checks cover baseline values, normal host overrides and generated exporter
|
- x86_64/aarch64 eval checks cover baseline values, normal host overrides and generated exporter
|
||||||
rules. Canonical API endpoint checks for all six cluster nodes already accompany this document.
|
rules. Canonical API endpoint checks cover all six cluster nodes.
|
||||||
- A reusable isolated VM check exercises allowed monitoring IPv4 access, denied other IPv4/IPv6
|
- A reusable isolated VM check exercises allowed monitoring IPv4 access, denied other IPv4/IPv6
|
||||||
access to all three exporter ports, retained IPv6 loopback and a reachable ordinary IPv4/IPv6
|
access to all three exporter ports, retained IPv6 loopback and a reachable ordinary IPv4/IPv6
|
||||||
service. Run `nix build .#checks.x86_64-linux.security-exporters`, importing only the shared
|
service. Run it with `nix build .#checks.x86_64-linux.security-exporters`. It imports only the
|
||||||
firewall, not real-host secrets or workloads, and does not replace deployment-time checks.
|
shared firewall, not real-host secrets or workloads, and does not replace deployment-time checks.
|
||||||
|
|
||||||
### Read-only audit snapshot — 2026-10-03
|
### Read-only audit snapshot — 2026-10-03
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -48,7 +48,8 @@ A setting that works around a bug or a hardware quirk.
|
|||||||
| WA-029 | mihomo `fake-ip-range6` is `2001:2::/64`, not the shipped ULA default — `modules/nixos/desktop/networking/mihomo/generate.nu` | the default `fdfe:dcba:9876::/64` sits in `fc00::/7`, which Local Network Access calls local, so a public page loaded over the v4 fake pool and pulling a dual-stack subresource prompts for local-network access (Chrome 154, Firefox). The same range also stalled ssh: a session to a fake AAAA authenticated and then never closed, on both `gvisor` and `mips`. `2001:2::/48` is RFC 5180 benchmarking -- the v6 twin of the `198.18.0.0/15` v4 default, absent from that table -- and both symptoms went with the move | Go back to the upstream default once mihomo ships a pool outside the LNA non-public table; the ULA default brings the ssh stall back | 2026-10-09 | on a browser or mihomo bump -- that table already grew to cover `2001:db8::/32` and `198.18.0.0/15` | active |
|
| WA-029 | mihomo `fake-ip-range6` is `2001:2::/64`, not the shipped ULA default — `modules/nixos/desktop/networking/mihomo/generate.nu` | the default `fdfe:dcba:9876::/64` sits in `fc00::/7`, which Local Network Access calls local, so a public page loaded over the v4 fake pool and pulling a dual-stack subresource prompts for local-network access (Chrome 154, Firefox). The same range also stalled ssh: a session to a fake AAAA authenticated and then never closed, on both `gvisor` and `mips`. `2001:2::/48` is RFC 5180 benchmarking -- the v6 twin of the `198.18.0.0/15` v4 default, absent from that table -- and both symptoms went with the move | Go back to the upstream default once mihomo ships a pool outside the LNA non-public table; the ULA default brings the ssh stall back | 2026-10-09 | on a browser or mihomo bump -- that table already grew to cover `2001:db8::/32` and `198.18.0.0/15` | active |
|
||||||
| WA-030 | mihomo unit sets `SKIP_SYSTEM_IPV6_CHECK=1` — `modules/nixos/desktop/networking/mihomo/default.nix` | mihomo checks at startup whether another NIC already holds an IPv6 address and, finding none, skips the TUN's v6 half -- but `strict-route` still installs its v6 blackhole (`ip -6 rule add priority 9000 unreachable`). On a cold boot that rule lands before networkd's Router Solicitation is answered, so the host can never send RS/NS, never gets a GUA, and mihomo never re-checks: self-locking until the core restarts. The env var forces the TUN v6 address up, which installs mihomo's normal v6 rules whose `lookup main suppress_prefixlength 0` keeps on-link neighbor discovery and the RA default route off the TUN | Drop once mihomo either re-runs the IPv6 check or skips the v6 strict-route blackhole when the v6 TUN is disabled | 2026-10-10 | on a mihomo bump | active |
|
| WA-030 | mihomo unit sets `SKIP_SYSTEM_IPV6_CHECK=1` — `modules/nixos/desktop/networking/mihomo/default.nix` | mihomo checks at startup whether another NIC already holds an IPv6 address and, finding none, skips the TUN's v6 half -- but `strict-route` still installs its v6 blackhole (`ip -6 rule add priority 9000 unreachable`). On a cold boot that rule lands before networkd's Router Solicitation is answered, so the host can never send RS/NS, never gets a GUA, and mihomo never re-checks: self-locking until the core restarts. The env var forces the TUN v6 address up, which installs mihomo's normal v6 rules whose `lookup main suppress_prefixlength 0` keeps on-link neighbor discovery and the RA default route off the TUN | Drop once mihomo either re-runs the IPv6 check or skips the v6 strict-route blackhole when the v6 TUN is disabled | 2026-10-10 | on a mihomo bump | active |
|
||||||
|
|
||||||
If WA-008 freezes recur, the fallback is to restore
|
If WA-008 freezes recur, the fallback is to restore the parameters commented out in
|
||||||
|
`hosts/idols-ai/hardware-configuration.nix` —
|
||||||
`nvme_core.default_ps_max_latency_us=0 nvme_core.io_timeout=4294967295 pcie_aspm=off`; this is a
|
`nvme_core.default_ps_max_latency_us=0 nvme_core.io_timeout=4294967295 pcie_aspm=off`; this is a
|
||||||
recovery procedure, not its removal condition.
|
recovery procedure, not its removal condition.
|
||||||
|
|
||||||
@@ -71,10 +72,10 @@ A known limitation with no fix yet.
|
|||||||
|
|
||||||
An unfinished feature or gap.
|
An unfinished feature or gap.
|
||||||
|
|
||||||
| ID | What & where | Why | Removal condition | Added | Revisit | Status |
|
| ID | What & where | Why | Removal condition | Added | Revisit | Status |
|
||||||
| ------ | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------- | ----------------------- | ------ |
|
| ------ | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | ---------- | ----------------------- | ------ |
|
||||||
| WA-013 | NixOS tests — `outputs/README.md` | full-host tests still rebuild custom packages (no private cache) and need the host ssh key to decrypt agenix; the shared-firewall security-exporters VM test now runs in CI (KVM) | Resolve when a private cache exists and tests can run per-service | 2024-03-13 | quarterly | active |
|
| WA-013 | NixOS tests — `outputs/README.md` | full-host tests still rebuild custom packages (no private cache) and need the host ssh key to decrypt agenix; the shared-firewall security-exporters VM test now runs in CI (KVM); `outputs/x86_64-linux/nixos-tests/idols-ruby.nix` is exposed as `packages.x86_64-linux.ruby-nixos-tests` but is not in `checks` or CI | Resolve when a private cache exists and tests can run per-service | 2024-03-13 | quarterly | active |
|
||||||
| WA-027 | NFS golden store `no_root_squash` — `hosts/12kingdoms-youko/nfs-golden.nix` | the existing PVC subdirectories are root-owned, so enabling `root_squash` would break running workloads until they are migrated; the CSI node plugin is hostNetwork and sources from the allowlisted node IPs | Drop when the PVC subdirectories are migrated and `root_squash` is enabled | 2026-10-07 | next maintenance window | active |
|
| WA-027 | NFS golden store `no_root_squash` — `hosts/12kingdoms-youko/nfs-golden.nix` | the existing PVC subdirectories are root-owned, so enabling `root_squash` would break running workloads until they are migrated; the CSI node plugin is hostNetwork and sources from the allowlisted node IPs | Drop when the PVC subdirectories are migrated and `root_squash` is enabled | 2026-10-07 | next maintenance window | active |
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -102,11 +102,11 @@ recorded in [#428](https://github.com/ryan4yin/nix-config/pull/428).
|
|||||||
door, and blast radius for PR bodies.
|
door, and blast radius for PR bodies.
|
||||||
- **Write a `testing-strategy` skill**: E2E of real workflows first, unit tests for logic and edge
|
- **Write a `testing-strategy` skill**: E2E of real workflows first, unit tests for logic and edge
|
||||||
cases E2E cannot reach.
|
cases E2E cannot reach.
|
||||||
- **Merge `ponytail-review` with a comment and doc pruning pass** (reference:
|
- **Merge `ponytail-review` into the shipped `review-comments-and-docs` skill** (its doc-pruning
|
||||||
`MidAutumnMoon/TaysiTsuki` `home/agents/skills/prune-comments-and-docs`). Worth borrowing from
|
half came from `MidAutumnMoon/TaysiTsuki` `home/agents/skills/prune-comments-and-docs`). Worth
|
||||||
`garrytan/gstack` `review/checklist.md`: a critical pass before an informational one, reading
|
borrowing from `garrytan/gstack` `review/checklist.md`: a critical pass before an informational
|
||||||
consumers outside the diff for a new enum value or loosened validator, a do-not-flag list, and
|
one, reading consumers outside the diff for a new enum value or loosened validator, a do-not-flag
|
||||||
"zero findings is valid". Keep review report-only.
|
list, and "zero findings is valid". Keep review report-only.
|
||||||
- **Adapt `wayfinder` in the fork** so its map and tickets default to local Markdown and research
|
- **Adapt `wayfinder` in the fork** so its map and tickets default to local Markdown and research
|
||||||
stays local, instead of GitHub issues and pushed `research/` branches.
|
stays local, instead of GitHub issues and pushed `research/` branches.
|
||||||
- **Adapt `domain-modeling` in the fork** to record decisions in the repository's existing documents
|
- **Adapt `domain-modeling` in the fork** to record decisions in the repository's existing documents
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ repository already runs** or **unlocks a concrete need**. "It exists and is newe
|
|||||||
|
|
||||||
## A1. Tailscale Serve instead of caddy vhosts
|
## A1. Tailscale Serve instead of caddy vhosts
|
||||||
|
|
||||||
**Current:** one caddy instance on `youko` fronts 12 vhosts on `*.writefor.fun` by Host/SNI, with
|
**Current:** one caddy instance on `youko` fronts 17 vhosts on `*.writefor.fun` by Host/SNI, with
|
||||||
two TLS chains — a private `ecc-ca` (only repo machines trust it) and a lego/Cloudflare DNS-01
|
two TLS chains — a private `ecc-ca` (only repo machines trust it) and a lego/Cloudflare DNS-01
|
||||||
wildcard for phone/TV clients — plus `file_server`, `header_up Host` (SigV4), a wildcard 404
|
wildcard for phone/TV clients — plus `file_server`, `header_up Host` (SigV4), a wildcard 404
|
||||||
fallback, and a root-readable Cloudflare token in agenix.
|
fallback, and a root-readable Cloudflare token in agenix.
|
||||||
@@ -56,8 +56,9 @@ LAN-only client can run Tailscale.
|
|||||||
|
|
||||||
## A2. systemd-resolved
|
## A2. systemd-resolved
|
||||||
|
|
||||||
**Current:** `services.resolved.enable` is set **nowhere**; hosts use dhcpcd or static config and
|
**Current:** `services.resolved.enable` is set **nowhere**; hosts get DNS from systemd-networkd or
|
||||||
the default `/etc/resolv.conf`. Note `modules/nixos/base/networking/mdns.nix` already sets
|
NetworkManager (or static config) and use the default `/etc/resolv.conf`. Note
|
||||||
|
`modules/nixos/base/networking/mdns.nix` already sets
|
||||||
`services.resolved.settings.Resolve.MulticastDNS = false` — currently inert, and it will activate
|
`services.resolved.settings.Resolve.MulticastDNS = false` — currently inert, and it will activate
|
||||||
the moment resolved is enabled. mDNS itself is provided by avahi.
|
the moment resolved is enabled. mDNS itself is provided by avahi.
|
||||||
|
|
||||||
@@ -83,14 +84,16 @@ changes.
|
|||||||
|
|
||||||
## A3. systemd-networkd instead of dhcpcd
|
## A3. systemd-networkd instead of dhcpcd
|
||||||
|
|
||||||
**Current:** physical hosts use `networking.useDHCP` (dhcpcd script); VM hosts and MicroVM guests
|
**Current:** dhcpcd is not used anywhere in this repo. `ai`, `kana` and `ruby` already set
|
||||||
use static config with `useDHCP = false`; the `br0` bridge on VM hosts is declared through
|
`networking.useNetworkd = true`; `shoukei` and `akane` run NetworkManager; VM hosts and MicroVM
|
||||||
|
guests use static config with `useDHCP = false`. The `br0` bridge on VM hosts is declared through
|
||||||
`systemd.network.netdevs/networks` already.
|
`systemd.network.netdevs/networks` already.
|
||||||
|
|
||||||
**Proposed:** `networking.networkd.enable = true` with `networking.networks`/`networkdOptions`.
|
**Proposed:** `networking.networkd.enable = true` with `networking.networks`/`networkdOptions`.
|
||||||
|
|
||||||
**Pros:** declarative per-interface config, one implementation for stage 1 and stage 2, no dhcpcd
|
**Pros:** declarative per-interface config, one implementation for stage 1 and stage 2, no dhcpcd
|
||||||
shell script in the path, and VM hosts already speak `systemd.network` for the bridge.
|
anywhere in the path (nothing in this repo uses it), and VM hosts already speak `systemd.network`
|
||||||
|
for the bridge.
|
||||||
|
|
||||||
**Cons:** bigger blast radius than any other item — a mistake on a `br0` VM host cuts the guests and
|
**Cons:** bigger blast radius than any other item — a mistake on a `br0` VM host cuts the guests and
|
||||||
possibly remote reachability; migration touches every DHCP host; behaviour differences around
|
possibly remote reachability; migration touches every DHCP host; behaviour differences around
|
||||||
@@ -152,8 +155,10 @@ the gain over a working `zramSwap` is mostly cosmetic.
|
|||||||
|
|
||||||
## A6. nixos-facter instead of hand-written hardware-configuration.nix
|
## A6. nixos-facter instead of hand-written hardware-configuration.nix
|
||||||
|
|
||||||
**Current:** 8 hosts carry hand-written `hardware-configuration.nix` (plus deliberate per-host
|
**Current:** 3 hosts carry hand-written `hardware-configuration.nix` (`shoryu`, `shoukei`, `ai`;
|
||||||
quirks such as the NVMe APST workaround WA-008 and USB-SATA mitigations WA-009).
|
`shushou` and `youko` import `shoryu`'s, and the qemu guests use the shared
|
||||||
|
`modules/nixos/server/qemu-guest-hardware-configuration.nix`), plus deliberate per-host quirks such
|
||||||
|
as the NVMe APST workaround WA-008 and USB-SATA mitigations WA-009.
|
||||||
|
|
||||||
**Proposed:** `hardware.facter` from nixpkgs (nixos-facter-modules upstreamed), report generated on
|
**Proposed:** `hardware.facter` from nixpkgs (nixos-facter-modules upstreamed), report generated on
|
||||||
the machine.
|
the machine.
|
||||||
@@ -294,8 +299,9 @@ validates); no benefit for hosts without Secure Boot.
|
|||||||
|
|
||||||
## B3. Declarative images with systemd-repart
|
## B3. Declarative images with systemd-repart
|
||||||
|
|
||||||
**Current:** guest images come from the existing pipeline (nixos-generators / disko-based); k8s
|
**Current:** libvirt guest images are one-time reflink copies of the VMs' former KubeVirt disks
|
||||||
guests are MicroVMs booting declared state images.
|
(`hosts/12kingdoms-shoryu/libvirtd.nix`); k8s guests are MicroVMs booting declared state images
|
||||||
|
against a read-only host store, with no OS image built at all.
|
||||||
|
|
||||||
**Proposed:** `image.repart.enable` + `system.build.images.{qemu,raw-efi,raw,sd-card}`.
|
**Proposed:** `image.repart.enable` + `system.build.images.{qemu,raw-efi,raw,sd-card}`.
|
||||||
|
|
||||||
@@ -479,7 +485,7 @@ only.
|
|||||||
| B5 | sysupdate | | | |
|
| B5 | sysupdate | | | |
|
||||||
| B6 | measured boot / FIDO2 | | | |
|
| B6 | measured boot / FIDO2 | | | |
|
||||||
| B7 | systemd-vmspawn | | | |
|
| B7 | systemd-vmspawn | | | |
|
||||||
| C1–C4 | tooling + cleanups | | | |
|
| C1–C5 | tooling + cleanups | | | |
|
||||||
| D1–D7 | lab-only group | | | |
|
| D1–D7 | lab-only group | | | |
|
||||||
| E | rejected set | | | |
|
| E | rejected set | | | |
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -72,8 +72,8 @@ hardening/
|
|||||||
- https://gitlab.com/apparmor/apparmor/-/wikis/Documentation
|
- https://gitlab.com/apparmor/apparmor/-/wikis/Documentation
|
||||||
- AppArmor.d is a set of over 1500 AppArmor profiles whose aim is to confine most Linux based
|
- AppArmor.d is a set of over 1500 AppArmor profiles whose aim is to confine most Linux based
|
||||||
applications and processes.
|
applications and processes.
|
||||||
- But all the profiles of AppArmor assume a FHS filesystem, which caused all apparmor policies
|
- But its profiles assume an FHS filesystem, so most of them never match the Nix store paths a
|
||||||
takes no effect on NixOS.
|
NixOS system actually executes.
|
||||||
- Apparmor on NixOS Roadmap:
|
- Apparmor on NixOS Roadmap:
|
||||||
- https://discourse.nixos.org/t/apparmor-on-nixos-roadmap/57217
|
- https://discourse.nixos.org/t/apparmor-on-nixos-roadmap/57217
|
||||||
- https://github.com/LordGrimmauld/aa-alias-manager
|
- https://github.com/LordGrimmauld/aa-alias-manager
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
# AppArmor in complain mode: log violations instead of blocking.
|
# AppArmor policy for D-Bus.
|
||||||
services.dbus.apparmor = "enabled";
|
services.dbus.apparmor = "enabled";
|
||||||
|
|
||||||
security.apparmor = {
|
security.apparmor = {
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ appimageTools.wrapAppImage {
|
|||||||
substituteInPlace $out/share/applications/wechat.desktop --replace-fail AppRun wechat
|
substituteInPlace $out/share/applications/wechat.desktop --replace-fail AppRun wechat
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Add these root paths to FHS sandbox to prevent WeChat from accessing them by default
|
# Prepare the WeChat data dirs before the sandbox starts. The isolation itself
|
||||||
|
# is the `--tmpfs /home` / `--tmpfs /root` in `extraBwrapArgs` below.
|
||||||
# Adapted from https://aur.archlinux.org/cgit/aur.git/tree/wechat-universal.sh?h=wechat-universal-bwrap
|
# Adapted from https://aur.archlinux.org/cgit/aur.git/tree/wechat-universal.sh?h=wechat-universal-bwrap
|
||||||
extraPreBwrapCmds = ''
|
extraPreBwrapCmds = ''
|
||||||
XDG_DOCUMENTS_DIR="''${XDG_DOCUMENTS_DIR:-$(xdg-user-dir DOCUMENTS)}"
|
XDG_DOCUMENTS_DIR="''${XDG_DOCUMENTS_DIR:-$(xdg-user-dir DOCUMENTS)}"
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ let
|
|||||||
# Shared NSS client-certificate store (imported outside Firefox).
|
# Shared NSS client-certificate store (imported outside Firefox).
|
||||||
(sloth.concat' sloth.homeDir "/.pki/nssdb")
|
(sloth.concat' sloth.homeDir "/.pki/nssdb")
|
||||||
|
|
||||||
# Unsure
|
# dconf settings. Not verified as needed; candidate for removal.
|
||||||
(sloth.concat' sloth.xdgConfigHome "/dconf")
|
(sloth.concat' sloth.xdgConfigHome "/dconf")
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ home/
|
|||||||
│ │ └── ...
|
│ │ └── ...
|
||||||
│ └── ...
|
│ └── ...
|
||||||
├── hosts/ # Host-specific home manager entry modules
|
├── hosts/ # Host-specific home manager entry modules
|
||||||
│ ├── linux/ # Linux host home modules (idols-ai, 12kingdoms-shoukei, idols-kana, idols-ruby, k3s-test-1-worker-*, etc.)
|
│ ├── linux/ # Linux host home modules (idols-ai, 12kingdoms-shoukei, idols-kana, idols-ruby)
|
||||||
│ └── darwin/ # macOS host home modules (fern, frieren)
|
│ └── darwin/ # macOS host home modules (fern, frieren)
|
||||||
└── darwin/ # macOS-specific home manager configurations
|
└── darwin/ # macOS-specific home manager configurations
|
||||||
├── proxy/ # Proxy configurations
|
├── proxy/ # Proxy configurations
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Run `:tutor` inside Helix, or `hx --tutor` from the shell
|
|||||||
|
|
||||||
### Terminal related
|
### Terminal related
|
||||||
|
|
||||||
tuios shortcuts used often (leader is `Ctrl + B`; same idea as in the Neovim notes):
|
tuios shortcuts used often (leader is `Ctrl + B`):
|
||||||
|
|
||||||
| Action | tuios shortcut |
|
| Action | tuios shortcut |
|
||||||
| ----------------- | -------------------------- |
|
| ----------------- | -------------------------- |
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
min-release-age=2
|
min-release-age=2
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# npm - set min release age (in minutes) for supply-chain security
|
# pnpm - same supply-chain policy as the npm setting above; its value is in minutes, not days
|
||||||
xdg.configFile."pnpm/config.yaml".text = ''
|
xdg.configFile."pnpm/config.yaml".text = ''
|
||||||
minimumReleaseAge: 2880
|
minimumReleaseAge: 2880
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ in
|
|||||||
# `work` for the ~/work tree, `personal` for everything else (a host with no
|
# `work` for the ~/work tree, `personal` for everything else (a host with no
|
||||||
# ~/work gets `personal` everywhere).
|
# ~/work gets `personal` everywhere).
|
||||||
programs.nushell.extraConfig = ''
|
programs.nushell.extraConfig = ''
|
||||||
# auto start tuios
|
|
||||||
if $nu.is-interactive and (not ("TUIOS_SESSION" in $env)) {
|
if $nu.is-interactive and (not ("TUIOS_SESSION" in $env)) {
|
||||||
# Exit 3 means the daemon is stopped; stdout still lists saved sessions.
|
# Exit 3 means the daemon is stopped; stdout still lists saved sessions.
|
||||||
let listing = (^tuios ls --json | complete)
|
let listing = (^tuios ls --json | complete)
|
||||||
|
|||||||
@@ -83,8 +83,7 @@ Noctalia consolidates functionality that previously required multiple tools:
|
|||||||
- **[`desktop-tools.nix`](./desktop-tools.nix)**: Wayland session tools (clipboard, brightness,
|
- **[`desktop-tools.nix`](./desktop-tools.nix)**: Wayland session tools (clipboard, brightness,
|
||||||
screen recording, auto-mount, virt-manager/virt-viewer, `wlogout` emergency fallback)
|
screen recording, auto-mount, virt-manager/virt-viewer, `wlogout` emergency fallback)
|
||||||
- **[`browsers.nix`](./browsers.nix)**: Web browsers
|
- **[`browsers.nix`](./browsers.nix)**: Web browsers
|
||||||
- **[`vscode.nix`](./vscode.nix)**: VS Code (GUI editor; the primary Zed config is shared from
|
- **[`vscode.nix`](./vscode.nix)**: VS Code
|
||||||
[`home/base/gui/zed-editor.nix`](../../../base/gui/zed-editor.nix))
|
|
||||||
- **[`media.nix`](./media.nix)**: Media players
|
- **[`media.nix`](./media.nix)**: Media players
|
||||||
- **[`gaming.nix`](./gaming.nix)**: Gaming applications
|
- **[`gaming.nix`](./gaming.nix)**: Gaming applications
|
||||||
- **[`creative.nix`](./creative.nix)**: Creative software
|
- **[`creative.nix`](./creative.nix)**: Creative software
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
# discord # update too frequently, use the web version instead
|
# discord # update too frequently, use the web version instead
|
||||||
];
|
];
|
||||||
|
|
||||||
# allow fontconfig to discover fonts and configurations installed through home.packages
|
# Fonts install at system level, not user level, so fontconfig does not
|
||||||
# Install fonts at system-level, not user-level
|
# scan home.packages for them.
|
||||||
fonts.fontconfig.enable = false;
|
fonts.fontconfig.enable = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# XDG stands for "Cross-Desktop Group", with X used to mean "cross".
|
# XDG stands for "X Desktop Group", the former name of freedesktop.org.
|
||||||
# It's a bunch of specifications from freedesktop.org intended to standardize desktops and
|
# It's a bunch of specifications from freedesktop.org intended to standardize desktops and
|
||||||
# other GUI applications on various systems (primarily Unix-like) to be interoperable:
|
# other GUI applications on various systems (primarily Unix-like) to be interoperable:
|
||||||
# https://www.freedesktop.org/wiki/Specifications/
|
# https://www.freedesktop.org/wiki/Specifications/
|
||||||
|
|||||||
@@ -88,13 +88,11 @@ in
|
|||||||
"/home/${username}/.terraform.d".d = permission;
|
"/home/${username}/.terraform.d".d = permission;
|
||||||
};
|
};
|
||||||
|
|
||||||
# systemd-machine-id-commit.service would fail but it is not relevant
|
# Mask the commit service: /etc/machine-id is persisted by preservation
|
||||||
# in this specific setup for a persistent machine-id so we disable it
|
# (see the `files` entry above), so there is no transient ID to commit.
|
||||||
#
|
|
||||||
# see the firstboot example below for an alternative approach
|
|
||||||
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
|
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
|
||||||
|
|
||||||
# let the service commit the transient ID to the persistent volume
|
# Inert while the unit is masked above; kept as the alternative approach.
|
||||||
systemd.services.systemd-machine-id-commit = {
|
systemd.services.systemd-machine-id-commit = {
|
||||||
unitConfig.ConditionPathIsMountPoint = [
|
unitConfig.ConditionPathIsMountPoint = [
|
||||||
""
|
""
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ in
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
# supported file systems, so we can mount any removable disks with these filesystems
|
# supported file systems, so we can mount any removable disks with these filesystems.
|
||||||
|
# mkForce replaces the whole list, so entries added by any other module are lost here.
|
||||||
boot.supportedFilesystems = lib.mkForce [
|
boot.supportedFilesystems = lib.mkForce [
|
||||||
"ext4"
|
"ext4"
|
||||||
"btrfs"
|
"btrfs"
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ in
|
|||||||
keyFile = cryptKeyFile;
|
keyFile = cryptKeyFile;
|
||||||
# The maximum size of the keyfile is 8192 KiB
|
# The maximum size of the keyfile is 8192 KiB
|
||||||
# type `cryptsetup --help` to see the compiled-in key and passphrase maximum sizes
|
# type `cryptsetup --help` to see the compiled-in key and passphrase maximum sizes
|
||||||
# to generate a key file:
|
# The key file must be at least keyFileOffset + keyFileSize bytes.
|
||||||
# dd bs=512 count=1024 iflag=fullblock if=/dev/random of=./hdd-luks-crypt-key
|
# dd bs=512 count=1024 iflag=fullblock if=/dev/random of=./hdd-luks-crypt-key
|
||||||
keyFileSize = 512 * 64; # match the `bs * count` of the `dd` command
|
keyFileSize = 512 * 64;
|
||||||
keyFileOffset = 512 * 128; # match the `bs * skip` of the `dd` command
|
keyFileOffset = 512 * 128;
|
||||||
fallbackToPassword = true;
|
fallbackToPassword = true;
|
||||||
allowDiscards = true;
|
allowDiscards = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ document is the agreed design and the rationale.
|
|||||||
|
|
||||||
## Rollout
|
## Rollout
|
||||||
|
|
||||||
|
Applied — immich runs on youko. The steps below are the procedure as deployed:
|
||||||
|
|
||||||
1. `../valkey.nix`: the shared Valkey instance.
|
1. `../valkey.nix`: the shared Valkey instance.
|
||||||
2. `./default.nix`: the `services.immich` configuration (server, database, machine-learning,
|
2. `./default.nix`: the `services.immich` configuration (server, database, machine-learning,
|
||||||
tmpfiles).
|
tmpfiles).
|
||||||
|
|||||||
@@ -30,15 +30,15 @@ in
|
|||||||
# HDR/DoVi transcoding needs OpenCL for `tonemap_opencl`. With only Mesa
|
# HDR/DoVi transcoding needs OpenCL for `tonemap_opencl`. With only Mesa
|
||||||
# installed, ffmpeg cannot create an OpenCL device (`Failed to get number of
|
# installed, ffmpeg cannot create an OpenCL device (`Failed to get number of
|
||||||
# OpenCL platforms: -1001`) and the transcode aborts with exit code 237, so
|
# OpenCL platforms: -1001`) and the transcode aborts with exit code 237, so
|
||||||
# HDR titles fail to play. ROCm's clr provides the ICD for the Barceló iGPU
|
# HDR titles fail to play. ROCm's clr provides the ICD for the AMD Radeon iGPU
|
||||||
# (reported as `gfx90c`); `ocl-icd` finds it under
|
# (Vega, `gfx90c`); `ocl-icd` finds it under
|
||||||
# /run/opengl-driver/etc/OpenCL/vendors.
|
# /run/opengl-driver/etc/OpenCL/vendors.
|
||||||
hardware.graphics.extraPackages = [ pkgs.rocmPackages.clr.icd ];
|
hardware.graphics.extraPackages = [ pkgs.rocmPackages.clr.icd ];
|
||||||
|
|
||||||
services.jellyfin = {
|
services.jellyfin = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
# AMD Barceló iGPU: VA-API hardware transcoding. renderD128 is world
|
# AMD Radeon iGPU (Vega, `gfx90c`): VA-API hardware transcoding. renderD128 is world
|
||||||
# readable/writable, and the user is in `render`/`video` as well.
|
# readable/writable, and the user is in `render`/`video` as well.
|
||||||
hardwareAcceleration = {
|
hardwareAcceleration = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -55,7 +55,7 @@ in
|
|||||||
# for decode/scale and falls back to the CPU `libx264`, which pins
|
# for decode/scale and falls back to the CPU `libx264`, which pins
|
||||||
# several cores per stream.
|
# several cores per stream.
|
||||||
enableHardwareEncoding = true;
|
enableHardwareEncoding = true;
|
||||||
# Vega (Barceló) decodes these.
|
# Vega decodes these.
|
||||||
hardwareDecodingCodecs = {
|
hardwareDecodingCodecs = {
|
||||||
h264 = true;
|
h264 = true;
|
||||||
hevc = true;
|
hevc = true;
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
chat_id = 586169186; # My Telegram ID
|
chat_id = 586169186; # My Telegram ID
|
||||||
# Whether to notify about resolved alerts.
|
# Whether to notify about resolved alerts.
|
||||||
send_resolved = true;
|
send_resolved = true;
|
||||||
# Disable notifications for resolved alerts
|
# Not disabled: resolved alerts are still notified (see send_resolved).
|
||||||
disable_notifications = false;
|
disable_notifications = false;
|
||||||
# Telegram's MarkdownV2 & Markdown are all very painful, we use html instead.
|
# Telegram's MarkdownV2 & Markdown are all very painful, we use html instead.
|
||||||
# https://core.telegram.org/bots/api#formatting-options
|
# https://core.telegram.org/bots/api#formatting-options
|
||||||
|
|||||||
+7
-6
@@ -20,9 +20,9 @@ Named after characters from "Oshi no Ko":
|
|||||||
On 2026-04-27 `ai` was rebuilt on a new platform. The MSI board and i5-13600KF it was added with in
|
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 +
|
2023-05 (the host was originally named `msi-rtx4090`) gave way to the Colorful CVN Z890 ARK FROZEN +
|
||||||
Intel Core Ultra 7 270K Plus. The traces in the history are PR #257 (the NIC moved from `enp5s0` to
|
Intel Core Ultra 7 270K Plus. The traces in the history are PR #257 (the NIC moved from `enp5s0` to
|
||||||
`enp130s0`) and PR #258 (Niri output names renamed, `hardware-intel.nix` added with the Arrow Lake
|
`enp130s0`) and PR #258 (Niri output names renamed, `hardware-intel.nix` added). The kernel moved to
|
||||||
NPU, kernel moved to `linuxPackages_latest`). The 2×48G DDR5 kit was already in place at that point;
|
`linuxPackages_latest` in `77ca37ea`, the same day but outside #258. The 2×48G DDR5 kit was already
|
||||||
the repo has no record of when it went in.
|
in place at that point; the repo has no record of when it went in.
|
||||||
|
|
||||||
On 2026-10-06 `ai` grew from 2×48G (96G) to 2×48G + 2×16G (128G) across all four DIMM slots, at
|
On 2026-10-06 `ai` grew from 2×48G (96G) to 2×48G + 2×16G (128G) across all four DIMM slots, at
|
||||||
DDR5-4800 with XMP off — the only stable setting with four DIMMs on this board. The 16G pair must be
|
DDR5-4800 with XMP off — the only stable setting with four DIMMs on this board. The 16G pair must be
|
||||||
@@ -71,7 +71,8 @@ disks.
|
|||||||
|
|
||||||
#### `k8s` - Kubernetes Infrastructure
|
#### `k8s` - Kubernetes Infrastructure
|
||||||
|
|
||||||
- **VM Cluster**: 3 physical mini PCs (shoryu, shushou, youko) running all VMs
|
- **VM Cluster**: 3 physical mini PCs (shoryu, shushou, youko) run the k3s VMs; `akane` is a NixOS
|
||||||
|
VM under UTM on macOS
|
||||||
- **K3s Testing**: `k3s-test-1` control plane and workers, running as microVMs; placement and
|
- **K3s Testing**: `k3s-test-1` control plane and workers, running as microVMs; placement and
|
||||||
rollout are documented in [`k8s/README.md`](./k8s/README.md)
|
rollout are documented in [`k8s/README.md`](./k8s/README.md)
|
||||||
|
|
||||||
@@ -122,8 +123,8 @@ just build-host <host>
|
|||||||
```
|
```
|
||||||
|
|
||||||
`eval-host` only evaluates the configuration. `build-host` builds the system closure without
|
`eval-host` only evaluates the configuration. `build-host` builds the system closure without
|
||||||
activating it. Host activation remains an explicit Colmena operation such as `just shoryu`,
|
activating it. Host activation is always explicit: Colmena (`just shoryu`, `just shushou`,
|
||||||
`just shushou`, or `just youko`.
|
`just youko`) from another machine, or `just local` on the machine itself.
|
||||||
|
|
||||||
## Distributed Building
|
## Distributed Building
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
#############################################################
|
#############################################################
|
||||||
#
|
#
|
||||||
# Fern - MacBook Pro 2024 14-inch M4 Pro 48G, mainly for business.
|
# Frieren - MacBook Pro 2024 14-inch M4 Pro 48G, mainly for business.
|
||||||
#
|
#
|
||||||
#############################################################
|
#############################################################
|
||||||
let
|
let
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ to run, but compatibility still depends on the game and translation layer.
|
|||||||
|
|
||||||
## First activation and persistence
|
## First activation and persistence
|
||||||
|
|
||||||
Run `just niri` on idols-ai from this branch's worktree, or after merging it. Log out and back in so
|
Run `just niri` on idols-ai. Log out and back in so Steam sees
|
||||||
Steam sees `PRESSURE_VESSEL_IMPORT_OPENXR_1_RUNTIMES=1`. That variable is what makes pressure-vessel
|
`PRESSURE_VESSEL_IMPORT_OPENXR_1_RUNTIMES=1`. That variable is what makes pressure-vessel mount
|
||||||
mount WiVRn's `$XDG_RUNTIME_DIR/wivrn/comp_ipc` socket into a game's container; without it the
|
WiVRn's `$XDG_RUNTIME_DIR/wivrn/comp_ipc` socket into a game's container; without it the game's
|
||||||
game's OpenXR client fails with `ERROR_RUNTIME_UNAVAILABLE` and the headset stays black.
|
OpenXR client fails with `ERROR_RUNTIME_UNAVAILABLE` and the headset stays black.
|
||||||
|
|
||||||
The root filesystem is a 4 GiB tmpfs. These directories are preserved with mode 0700:
|
The root filesystem is a 4 GiB tmpfs. These directories are preserved with mode 0700:
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
# Zram consumes physical memory for compression, which can cause a deadlock and system hang if the model size approaches the physical memory limit.
|
# Zram consumes physical memory for compression, which can cause a deadlock and system hang if the model size approaches the physical memory limit.
|
||||||
# Disable the whole module (zram device + its swappiness=180 sysctl tunings); this host uses a disk swapfile instead.
|
# Disable the whole module (zram device + its swappiness=180 sysctl tunings); this host uses a
|
||||||
|
# disk swapfile instead, created by disko at /swap (see ./disko-fs.nix). The two must move together.
|
||||||
modules.zram.enable = false;
|
modules.zram.enable = false;
|
||||||
|
|
||||||
# zswap: compressed writeback cache in front of the disk swapfile.
|
# zswap: compressed writeback cache in front of the disk swapfile.
|
||||||
@@ -93,8 +94,9 @@ in
|
|||||||
networking = {
|
networking = {
|
||||||
inherit hostName;
|
inherit hostName;
|
||||||
|
|
||||||
# we use networkd instead
|
# off: this host uses networkd (below). NetworkManager would otherwise
|
||||||
networkmanager.enable = false; # provides nmcli/nmtui for wifi adjustment
|
# provide nmcli/nmtui for wifi adjustment.
|
||||||
|
networkmanager.enable = false;
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,7 +119,7 @@ in
|
|||||||
];
|
];
|
||||||
DNS = nameservers;
|
DNS = nameservers;
|
||||||
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
||||||
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguraton (SLAAC)
|
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguration (SLAAC)
|
||||||
LinkLocalAddressing = "ipv6";
|
LinkLocalAddressing = "ipv6";
|
||||||
# r8169 drops carrier on S3 resume; without this, networkd tears down the
|
# r8169 drops carrier on S3 resume; without this, networkd tears down the
|
||||||
# static address/route and mihomo's TUN auto-detect briefly loses its
|
# static address/route and mihomo's TUN auto-detect briefly loses its
|
||||||
|
|||||||
@@ -469,13 +469,11 @@ in
|
|||||||
"D! /var/lib/systemd/coredump 0755 root root"
|
"D! /var/lib/systemd/coredump 0755 root root"
|
||||||
];
|
];
|
||||||
|
|
||||||
# systemd-machine-id-commit.service would fail but it is not relevant
|
# Mask the commit service: /etc/machine-id is persisted by preservation
|
||||||
# in this specific setup for a persistent machine-id so we disable it
|
# (see the `files` entry above), so there is no transient ID to commit.
|
||||||
#
|
|
||||||
# see the firstboot example below for an alternative approach
|
|
||||||
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
|
systemd.suppressedSystemUnits = [ "systemd-machine-id-commit.service" ];
|
||||||
|
|
||||||
# let the service commit the transient ID to the persistent volume
|
# Inert while the unit is masked above; kept as the alternative approach.
|
||||||
systemd.services.systemd-machine-id-commit = {
|
systemd.services.systemd-machine-id-commit = {
|
||||||
unitConfig.ConditionPathIsMountPoint = [
|
unitConfig.ConditionPathIsMountPoint = [
|
||||||
""
|
""
|
||||||
|
|||||||
@@ -3,9 +3,6 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
# Part 1 of the backup plan: a local restic repository on this machine.
|
|
||||||
# The off-machine target (youko, or a cloud) is a later step.
|
|
||||||
#
|
|
||||||
# Be specific here and keep `exclude` minimal: an allowlist of the
|
# Be specific here and keep `exclude` minimal: an allowlist of the
|
||||||
# irreplaceable directories beats backing up a broad tree and excluding half
|
# irreplaceable directories beats backing up a broad tree and excluding half
|
||||||
# of it. Large files anywhere are skipped by size (excludeLargerThan), which
|
# of it. Large files anywhere are skipped by size (excludeLargerThan), which
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
"auto" # Mount automatically with -a
|
"auto" # Mount automatically with -a
|
||||||
|
|
||||||
# Ownership mapping - all files appear as specified user/group
|
# Ownership mapping - all files appear as specified user/group
|
||||||
"uid=1000" # Map to user ID 1000
|
"uid=1000"
|
||||||
"gid=1000" # Map to group ID 100
|
"gid=1000"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -52,10 +52,12 @@ in
|
|||||||
matchConfig.Name = [ iface ];
|
matchConfig.Name = [ iface ];
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
Address = [ ipv4WithMask ];
|
Address = [ ipv4WithMask ];
|
||||||
|
# DNS goes to the proxy gateway, which resolves through the proxy;
|
||||||
|
# `nameservers` is the plain upstream-DNS alternative.
|
||||||
# DNS = nameservers;
|
# DNS = nameservers;
|
||||||
DNS = [ proxyGateway ];
|
DNS = [ proxyGateway ];
|
||||||
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
||||||
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguraton (SLAAC)
|
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguration (SLAAC)
|
||||||
LinkLocalAddressing = "ipv6";
|
LinkLocalAddressing = "ipv6";
|
||||||
};
|
};
|
||||||
routes = [
|
routes = [
|
||||||
|
|||||||
@@ -61,10 +61,12 @@ in
|
|||||||
matchConfig.Name = [ iface ];
|
matchConfig.Name = [ iface ];
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
Address = [ ipv4WithMask ];
|
Address = [ ipv4WithMask ];
|
||||||
|
# DNS goes to the proxy gateway, which resolves through the proxy;
|
||||||
|
# `nameservers` is the plain upstream-DNS alternative.
|
||||||
# DNS = nameservers;
|
# DNS = nameservers;
|
||||||
DNS = [ proxyGateway ];
|
DNS = [ proxyGateway ];
|
||||||
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
||||||
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguraton (SLAAC)
|
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguration (SLAAC)
|
||||||
LinkLocalAddressing = "ipv6";
|
LinkLocalAddressing = "ipv6";
|
||||||
};
|
};
|
||||||
routes = [
|
routes = [
|
||||||
|
|||||||
@@ -7,25 +7,8 @@
|
|||||||
{
|
{
|
||||||
imports = mylib.scanPaths ./.;
|
imports = mylib.scanPaths ./.;
|
||||||
|
|
||||||
# environment.systemPackages = with pkgs; [
|
|
||||||
# podman-compose
|
|
||||||
# ];
|
|
||||||
|
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
docker.enable = true;
|
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 = {
|
oci-containers = {
|
||||||
backend = "docker";
|
backend = "docker";
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ let
|
|||||||
|
|
||||||
# k3sExtraArgs = [
|
# k3sExtraArgs = [
|
||||||
# # IPv4 Private CIDR(full) - 172.16.0.0/12
|
# # IPv4 Private CIDR(full) - 172.16.0.0/12
|
||||||
# # IPv4 Pod CIDR(full) - fdfd:cafe:00:0000::/64 ~ fdfd:cafe:00:7fff::/64
|
# # IPv6 Pod CIDR(full) - fdfd:cafe:00:0000::/64 ~ fdfd:cafe:00:7fff::/64
|
||||||
# # IPv4 Service CIDR(full) - fdfd:cafe:00:8000::/64 ~ fdfd:cafe:00:ffff::/64
|
# # IPv6 Service CIDR(full) - fdfd:cafe:00:8000::/64 ~ fdfd:cafe:00:ffff::/64
|
||||||
# "--cluster-cidr=172.18.0.0/16,fdfd:cafe:00:0002::/64"
|
# "--cluster-cidr=172.18.0.0/16,fdfd:cafe:00:0002::/64"
|
||||||
# "--service-cidr=172.19.0.0/16,fdfd:cafe:00:8002::/112"
|
# "--service-cidr=172.19.0.0/16,fdfd:cafe:00:8002::/112"
|
||||||
# ];
|
# ];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
etcSize ? 64,
|
etcSize ? 64,
|
||||||
varSize ? 4096,
|
varSize ? 4096,
|
||||||
homeSize ? 4096,
|
homeSize ? 4096,
|
||||||
# extra stateful mounts (e.g. aquamarine's /data on the passed-through HDDs)
|
# extra stateful mounts, e.g. a guest's /data on passed-through HDDs
|
||||||
extraVolumes ? [ ],
|
extraVolumes ? [ ],
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ in
|
|||||||
"nfs"
|
"nfs"
|
||||||
];
|
];
|
||||||
|
|
||||||
# KVM for the microVMs and the libvirt domains.
|
# KVM for the microVMs and the libvirt domains. AMD-specific: an Intel VM host
|
||||||
|
# would need kvm-intel instead (see hosts/idols-ai/hardware-intel.nix).
|
||||||
boot.kernelModules = [ "kvm-amd" ];
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
boot.extraModprobeConfig = "options kvm_amd nested=1"; # for amd cpu
|
boot.extraModprobeConfig = "options kvm_amd nested=1";
|
||||||
|
|
||||||
boot.kernel.sysctl = {
|
boot.kernel.sysctl = {
|
||||||
# --- filesystem --- #
|
# --- filesystem --- #
|
||||||
@@ -92,10 +93,11 @@ in
|
|||||||
matchConfig.Name = [ "br0" ];
|
matchConfig.Name = [ "br0" ];
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
Address = [ ipv4WithMask ];
|
Address = [ ipv4WithMask ];
|
||||||
# DNS = nameservers;
|
# DNS goes to the proxy gateway, which resolves through the proxy; plain
|
||||||
|
# upstream DNS would be myvars.networking.nameservers.
|
||||||
DNS = [ proxyGateway ];
|
DNS = [ proxyGateway ];
|
||||||
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
DHCP = "ipv6"; # enable DHCPv6 only, so we can get a GUA.
|
||||||
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguraton (SLAAC)
|
IPv6AcceptRA = true; # for Stateless IPv6 Autoconfiguration (SLAAC)
|
||||||
LinkLocalAddressing = "ipv6";
|
LinkLocalAddressing = "ipv6";
|
||||||
};
|
};
|
||||||
routes = [
|
routes = [
|
||||||
|
|||||||
+5
-4
@@ -102,8 +102,9 @@ Platform-specific NixOS configuration:
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Modules are imported based on platform detection:
|
There is no automatic platform detection. Each host's entry under `outputs/<system>/src/` lists its
|
||||||
|
imports explicitly:
|
||||||
|
|
||||||
- **NixOS Systems**: Import `nixos/` modules
|
- **NixOS Systems**: import `nixos/` modules
|
||||||
- **macOS Systems**: Import `darwin/` modules
|
- **macOS Systems**: import `darwin/` modules
|
||||||
- **All Systems**: Import `base/` modules for shared configuration
|
- **Both**: import `base/` modules for shared configuration
|
||||||
@@ -4,8 +4,7 @@
|
|||||||
users.users."${myvars.username}" = {
|
users.users."${myvars.username}" = {
|
||||||
home = "/Users/${myvars.username}";
|
home = "/Users/${myvars.username}";
|
||||||
|
|
||||||
# set user's default shell back to zsh
|
# The login shell is set imperatively (`chsh -s /bin/zsh`), not declaratively here.
|
||||||
# `chsh -s /bin/zsh`
|
|
||||||
# DO NOT change the system's default shell to nushell! it will break some apps!
|
# DO NOT change the system's default shell to nushell! it will break some apps!
|
||||||
# It's better to change only kitty/wezterm & other terminal emulator's shell to nushell!
|
# It's better to change only kitty/wezterm & other terminal emulator's shell to nushell!
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ let
|
|||||||
lanAddr = if hostAddr.homeOnly or false then null else hostAddr.ipv4 or null;
|
lanAddr = if hostAddr.homeOnly or false then null else hostAddr.ipv4 or null;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# enable the node exporter on all nixos hosts
|
# node_exporter on every host that has a static LAN IPv4 (see `lanAddr` above)
|
||||||
# https://github.com/NixOS/nixpkgs/blob/nixos-26.05/nixos/modules/services/monitoring/prometheus/exporters/node.nix
|
# https://github.com/NixOS/nixpkgs/blob/nixos-26.05/nixos/modules/services/monitoring/prometheus/exporters/node.nix
|
||||||
services.prometheus.exporters.node = lib.mkIf (lanAddr != null) {
|
services.prometheus.exporters.node = lib.mkIf (lanAddr != null) {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# Secure by default: X11 forwarding off everywhere; desktops re-enable it
|
# Secure by default: X11 forwarding off everywhere; desktops re-enable it
|
||||||
# in modules/nixos/desktop/ssh.nix (needed for GUI forwarding).
|
# in modules/nixos/desktop/ssh.nix (needed for GUI forwarding).
|
||||||
X11Forwarding = lib.mkDefault false;
|
X11Forwarding = lib.mkDefault false;
|
||||||
# root user is used for remote deployment, so we need to allow it
|
# root login stays available for Colmena/MicroVM deployment, keys only
|
||||||
PermitRootLogin = lib.mkDefault "prohibit-password";
|
PermitRootLogin = lib.mkDefault "prohibit-password";
|
||||||
PasswordAuthentication = false; # disable password login
|
PasswordAuthentication = false; # disable password login
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
# misc
|
# misc
|
||||||
uinput = { };
|
uinput = { };
|
||||||
# shared group for services that read/write the same data directory
|
# shared group for services that read/write the same data directory
|
||||||
# (e.g. sftpgo + transmission on aquamarine)
|
# (e.g. sftpgo + transmission on youko)
|
||||||
fileshare = { };
|
fileshare = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -54,9 +54,8 @@ in
|
|||||||
"vm.watermark_boost_factor" = lib.mkDefault 0;
|
"vm.watermark_boost_factor" = lib.mkDefault 0;
|
||||||
|
|
||||||
# vm.watermark_scale_factor - Controls kswapd wakeup frequency (range: 1-1000, default: 10)
|
# vm.watermark_scale_factor - Controls kswapd wakeup frequency (range: 1-1000, default: 10)
|
||||||
# A higher value triggers background memory reclamation earlier (at 12.5% memory pressure).
|
# Units are 1/10000 of total memory: the value below widens the low-to-min watermark gap and
|
||||||
# Value 125 means kswapd becomes active when free memory drops below 1/125 of total memory,
|
# makes kswapd reclaim earlier, which avoids swap storms at the high swappiness above.
|
||||||
# balancing memory more proactively to prevent sudden swap storms at high swappiness values.
|
|
||||||
"vm.watermark_scale_factor" = lib.mkDefault 125;
|
"vm.watermark_scale_factor" = lib.mkDefault 125;
|
||||||
|
|
||||||
# vm.page-cluster - Controls swap readahead (range: 0-6, default: 3)
|
# vm.page-cluster - Controls swap readahead (range: 0-6, default: 3)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
default_session = {
|
default_session = {
|
||||||
# Wayland Desktop Manager is installed only for user ryan via home-manager!
|
# The Wayland session is installed for this user only, via home-manager.
|
||||||
user = myvars.username;
|
user = myvars.username;
|
||||||
# .wayland-session is a script generated by home-manager, which links to the current wayland compositor(sway/hyprland or others).
|
# .wayland-session is a script generated by home-manager, which links to the current wayland compositor(sway/hyprland or others).
|
||||||
# with such a vendor-no-locking script, we can switch to another wayland compositor without modifying greetd's config here.
|
# with such a vendor-no-locking script, we can switch to another wayland compositor without modifying greetd's config here.
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
# security with gnome-kering
|
# security with gnome-kering
|
||||||
services.gnome = {
|
services.gnome = {
|
||||||
gnome-keyring.enable = true;
|
gnome-keyring.enable = true;
|
||||||
# Use gnome keyring's SSH Agent
|
# Not gcr's SSH agent: OpenSSH's own agent runs instead
|
||||||
|
# (programs.ssh.startAgent below).
|
||||||
# https://wiki.gnome.org/Projects/GnomeKeyring/Ssh
|
# https://wiki.gnome.org/Projects/GnomeKeyring/Ssh
|
||||||
gcr-ssh-agent.enable = false;
|
gcr-ssh-agent.enable = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#
|
#
|
||||||
# We write our hardware-configuration.nix, so that we can do some customization more easily.
|
# We write our hardware-configuration.nix, so that we can do some customization more easily.
|
||||||
#
|
#
|
||||||
# the url above is used by `nixos-generator` to generate the guest's qcow2 image file.
|
|
||||||
#
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
|||||||
@@ -249,8 +249,8 @@ cd ~/nix-config/nixos-installer/
|
|||||||
rm -rf /mnt/etc
|
rm -rf /mnt/etc
|
||||||
|
|
||||||
# install nixos
|
# install nixos
|
||||||
# NOTE: --no-root-password leaves root locked; log in as ryan with the password from
|
# NOTE: --no-root-password leaves root locked; log in as ryan with the password whose hash is
|
||||||
# vars/default.nix
|
# `initialHashedPassword` in vars/default.nix
|
||||||
nixos-install --root /mnt --flake .#shoukei --no-root-password --show-trace --verbose # install-1
|
nixos-install --root /mnt --flake .#shoukei --no-root-password --show-trace --verbose # install-1
|
||||||
|
|
||||||
# if you want to use a cache mirror, run this command instead
|
# if you want to use a cache mirror, run this command instead
|
||||||
@@ -259,7 +259,8 @@ nixos-install --root /mnt --flake .#shoukei --no-root-password --show-trace --ve
|
|||||||
|
|
||||||
# enter into the installed system, check password & users
|
# enter into the installed system, check password & users
|
||||||
# `su ryan` => `sudo -i` => enter ryan's password => successfully login
|
# `su ryan` => `sudo -i` => enter ryan's password => successfully login
|
||||||
# if login failed, check ryan's initial password in vars/default.nix, and try again
|
# if login failed, check that the password you typed is the one hashed by
|
||||||
|
# `initialHashedPassword` in vars/default.nix, and try again
|
||||||
nixos-enter
|
nixos-enter
|
||||||
|
|
||||||
|
|
||||||
@@ -327,7 +328,8 @@ cd ~/nix-config
|
|||||||
just niri
|
just niri
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, to enable secure boot, follow the instructions in
|
Secure Boot is not configured for `shoukei` (Apple Silicon, Asahi firmware). The links below are the
|
||||||
|
setup for `ai`, kept here as a reference:
|
||||||
[lanzaboote - Quick Start](https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md)
|
[lanzaboote - Quick Start](https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md)
|
||||||
and
|
and
|
||||||
[hosts/idols-ai/secureboot.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)
|
||||||
+7
-3
@@ -44,7 +44,8 @@ suite passes when every `expr` equals its `expected`.
|
|||||||
#### Which tests cover a new host
|
#### Which tests cover a new host
|
||||||
|
|
||||||
Some tests iterate over every configuration, so a new host is covered automatically and must satisfy
|
Some tests iterate over every configuration, so a new host is covered automatically and must satisfy
|
||||||
them. Others name specific hosts and only cover a new host if you add it.
|
them. Others name specific hosts — or a name prefix, like `k3s-api-endpoint`, which covers every
|
||||||
|
`k3s-test-1-*` configuration — and only cover a new host if you add it.
|
||||||
|
|
||||||
| Kind | Tests |
|
| Kind | Tests |
|
||||||
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
@@ -71,8 +72,11 @@ Problems:
|
|||||||
agenix secrets.
|
agenix secrets.
|
||||||
- [ ] Maybe it's better to test every service separately, not the whole host?
|
- [ ] Maybe it's better to test every service separately, not the whole host?
|
||||||
|
|
||||||
No host defines a NixOS integration test yet: full-host tests are tracked as WA-013 in
|
Full-host tests are tracked as WA-013 in [WORKAROUNDS.md](../WORKAROUNDS.md).
|
||||||
[WORKAROUNDS.md](../WORKAROUNDS.md). What runs today is the eval set above, with `just test`.
|
`outputs/x86_64-linux/nixos-tests/idols-ruby.nix` is exported as
|
||||||
|
`packages.x86_64-linux.ruby-nixos-tests`, but it is not a `checks` entry, so CI never builds it and
|
||||||
|
nothing else runs it. What runs today is the eval set above with `just test`, plus one NixOS-driver
|
||||||
|
check of the shared firewall — `checks.x86_64-linux.security-exporters`, built in CI.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -142,7 +142,8 @@ in
|
|||||||
# Packages
|
# Packages
|
||||||
packages = forAllSystems (system: allSystems.${system}.packages or { });
|
packages = forAllSystems (system: allSystems.${system}.packages or { });
|
||||||
|
|
||||||
# Eval Tests for all NixOS & darwin systems.
|
# Eval Tests for all NixOS & darwin systems. Each system's `evalTests` lists its
|
||||||
|
# failures, so an empty attrset means that system passed.
|
||||||
evalTests = lib.lists.all (it: it.evalTests == { }) allSystemValues;
|
evalTests = lib.lists.all (it: it.evalTests == { }) allSystemValues;
|
||||||
|
|
||||||
checks = forAllSystems (
|
checks = forAllSystems (
|
||||||
|
|||||||
+2
-1
@@ -65,7 +65,8 @@ Placing a secret under `/etc/agenix/` with `environment.etc` has one trap: setti
|
|||||||
`environment.etc` **copy** the file instead of symlinking it, and the copy is owned by root unless
|
`environment.etc` **copy** the file instead of symlinking it, and the copy is owned by root unless
|
||||||
`user` is set too. Widening the mode so the user can read a root-owned copy makes it readable by
|
`user` is set too. Widening the mode so the user can read a root-owned copy makes it readable by
|
||||||
every local account. Always set `user` together with `mode`. nix-darwin ignores both on
|
every local account. Always set `user` together with `mode`. nix-darwin ignores both on
|
||||||
`environment.etc`, so `secrets/darwin.nix` chowns `/etc/agenix/*` after activation instead.
|
`environment.etc`, so `secrets/darwin.nix` re-applies each secret's owner and mode after activation;
|
||||||
|
a blanket chown over `/etc/agenix/*` would make the root-only secrets readable by the login user.
|
||||||
|
|
||||||
## Adding or Updating Secrets
|
## Adding or Updating Secrets
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user