72 lines
7.3 KiB
Markdown
72 lines
7.3 KiB
Markdown
# Approved failure-path fixes
|
||
|
||
This note covers proposal items 1, 2, 4 and 5. Item 3 is now implemented and documented in [deployment.md](deployment.md); the migration backup script remains last. Camera configuration is unchanged.
|
||
|
||
- **Firewall startup:** shared configuration now uses NixOS's early firewall startup. The mediaserver continues to own its separate nftables firewall.
|
||
- **WAN forwarding:** forwarded Docker traffic must match the original protocol/port in `ports.toml`. TCP and UDP 25565–25600 remain available automatically for Pelican allocations. SFTP binds to 10.0.0.1:2022. Forward names, LAN destinations, overlaps and SSH/HTTPS destinations are validated both by the UI and during Nix evaluation.
|
||
- **Login and locking:** greetd runs the Quickshell greeter as `greeter` inside Cage and authenticates before creating Fred's session. The existing visual layout is shared with an independent Quickshell lock process. The greeter uses the default wallpaper and the desktop's GB/Norwegian keyboard layouts; the lock reads the current wallpaper. Greetd unlocks the login keyring before Spotify starts. The old boot marker and IPC unlock method are removed. `fred-lock` waits for compositor-confirmed screen coverage; failure or timeout fails the required pre-sleep service and prevents sleep.
|
||
- **Media storage:** missing data disks no longer make the mounts mandatory for router boot. Device waits are bounded at 15 seconds. The pool requires every branch, and media consumers require a readiness service bound to all four mounts. Directory creation and the existing recursive permission rules run only after mount checks. These consumers stop when a required mount disappears. Routing and services outside the media pool remain independent.
|
||
|
||
## Validation
|
||
|
||
All four physical hosts were evaluated. The authentication bundle and media-readiness unit were built without activating a system. Tests cover:
|
||
|
||
- Existing router UI round trips plus malformed destinations/names, overlaps and redirected management ports; equivalent Nix checks reject 13 invalid inventories.
|
||
- Evaluated nftables rules in private user/network namespaces, with a second NAT table modeling Docker publications: WAN TCP/UDP at both Pelican range endpoints succeeds; unlisted ports fail; LAN SFTP succeeds. This is a packet-level test of the rules, not a running Pelican instance.
|
||
- The actual greeter QML against a fake greetd socket: a rejected password never requests a session launch; successful retry requests the session with Wayland metadata. The pinned Quickshell logs an unexpected-response message for the cancellation acknowledgement; retry and launch still succeed.
|
||
- The actual lock QML on a private headless Sway compositor: coverage is confirmed; the helper fails when IPC disappears or reports that coverage never became secure.
|
||
- The generated media-readiness script in a private mount namespace: missing pool, missing branch and subsequently lost branch all fail; a complete mounted fixture receives its directories; the underlying root directory stays empty.
|
||
|
||
The broader `nix flake check --no-build` still fails on the existing `mediaserver-vm` output's root-filesystem/bootloader assertions. The configured nixos MCP server did not complete initialization; options were checked against the pinned module sources and host evaluations instead.
|
||
|
||
These checks do not substitute for a physical login, keyring unlock, lid-close/resume or disk-disconnection test. No configuration has been activated, no production service has been restarted, and no production firewall or mount has been changed.
|
||
|
||
## Repeating the focused tests
|
||
|
||
The Python tests document their required tools and arguments in their opening docstrings. Use packages from the flake's pinned package set. New files must be included in the source; `path:.` includes the working tree before they are committed.
|
||
|
||
Build the authentication fixture:
|
||
|
||
```sh
|
||
nix build --no-link --print-out-paths path:.#nixosConfigurations.FredOS-Gaming.config.system.build.auth
|
||
```
|
||
|
||
Run `scripts/greeter-check.py` and `scripts/session-lock-check.py` with that output path. Put `qs` and `sway` on PATH and set `QML2_IMPORT_PATH` to the pinned `qt6.qt5compat` package's `lib/qt-6/qml` directory.
|
||
|
||
Build the media-readiness fixture:
|
||
|
||
```sh
|
||
nix build --no-link --print-out-paths --impure --expr \
|
||
'(builtins.getFlake ("path:" + toString ./.)).nixosConfigurations.FredOS-Mediaserver.config.systemd.units."media-storage-ready.service".unit'
|
||
```
|
||
|
||
Pass its output path to `sudo python3 scripts/media-storage-check.py`. The script creates a private mount namespace before making any mount changes.
|
||
|
||
Run the Nix forwarding checks:
|
||
|
||
```sh
|
||
nix eval --impure --expr \
|
||
'import ./scripts/router-forwards-check.nix { lib = (builtins.getFlake ("path:" + toString ./.)).inputs.nixpkgs.lib; }'
|
||
```
|
||
|
||
For packet tests, export the evaluated tables and pass the file to `python3 scripts/router-firewall-check.py`; that script creates its own private user/network namespace:
|
||
|
||
```sh
|
||
nix eval --raw path:.#nixosConfigurations.FredOS-Mediaserver.config.networking.nftables.tables \
|
||
--apply 'tables: builtins.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: table: "table ${table.family} ${name} {\n${table.content}\n}") tables))' \
|
||
> /tmp/router-rules.nft
|
||
```
|
||
|
||
## Operational behavior
|
||
|
||
The new greeter takes effect on the next login or boot. It supports the configured password authentication; unusual PAM conversations such as forced password changes require a text console. The independent locker starts on the first lock request. Restarting that locker reacquires the lock, while ordinary bar reloads leave it alone.
|
||
|
||
The boot greeter explicitly disables window decorations and rejects window-close requests. On Gaming, its Cage client applies the first desktop monitor rule's output, mode and scale before launching Quickshell (currently DP-3, 3440x1440 at 180 Hz, scale 1). This avoids maintaining separate greeter and desktop mode settings. The mode command is bounded to five seconds plus a one-second kill grace; an unavailable connector or mode is logged and login continues using Cage's current mode. MacBook retains its preferred-mode behavior. Switching compositors can still cause a brief display transition.
|
||
|
||
Greeter compositor/Quickshell output and desktop launcher output are routed to the journal instead of the login VT. Inspect them with `journalctl -b -t fred-greeter` and `journalctl -b -t fred-desktop`. This prevents those messages from appearing when Cage releases the display; it does not promise a zero-frame compositor handover.
|
||
|
||
The greeter test verifies close rejection, frameless flags, password failure/retry and authenticated exit. The generated Gaming client was also checked with successful and failed mode-command fixtures to verify ordering and fallback. Both desktop configurations evaluate and both auth bundles build; the physical 180 Hz handover still needs checking on Gaming after deployment.
|
||
|
||
If media storage is unavailable, restore and verify the missing disks first, then start the affected media services. Their dependencies retry mounts and directory preparation. Services deliberately stay stopped after losing storage; they do not automatically resume merely because a disk returns. Inspect `journalctl -u media-storage-ready` and `systemctl status mnt-storage.mount` when diagnosing this.
|
||
|
||
The shared deployment transaction is documented separately in [deployment.md](deployment.md).
|