home-shared: migrate programs.ssh.matchBlocks to programs.ssh.settings #79

Closed
opened 2026-09-19 22:07:19 +01:00 by allod-agent · 3 comments
Member

modules/home-shared.nix defines the operator's SSH hosts through programs.ssh.matchBlocks, which Home Manager 26.05 deprecates in favour of programs.ssh.settings. Every VM build and the hypervisor's user profile now print one warning for the option and one more for each host in identity.sshHosts that carries extraOptions. The rendered ~/.ssh/config is unchanged today, but the alias is slated for removal, and the warning wall hides real evaluation output such as the rebuild-nexus preview.

Migrate the module to programs.ssh.settings. identity.sshHosts keeps its current shape, since it is data in the deployment's private secrets fork: the module translates the keys it uses (hostname, user, port, identityFile, identitiesOnly) to the upstream directive names (HostName, User, Port, IdentityFile, IdentitiesOnly) and merges extraOptions into the block directly, since its keys are already upstream directive names. A key the translation does not know fails evaluation naming the host and the key rather than being dropped. The forge host's IdentityFile stays lib.mkDefault so a profile's own definition still wins.

Merge order with the matching profiles change (allod/profiles, migrating hosts/dev/allod-dev/home.nix) must not matter: Home Manager converts any remaining matchBlocks definition into settings, and two definitions of the same host block merge attribute by attribute, so a migrated framework beside an unmigrated profile, or the reverse, renders the same config. The check below pins that.

Validation

A check that builds a fixture home configuration through the real home-shared.nix with a fixture identity whose sshHosts include a plain host, a host with port and identitiesOnly, and a host with extraOptions, plus one legacy programs.ssh.matchBlocks definition of the forge host from a second module standing in for an unmigrated profile. It runs ssh -G <host> -F <generated config> for each host and asserts the resolved hostname, user, port, identityfile and the extra directive, and asserts that the profile's identity file wins for the forge host. Evaluation of the fixture emits no programs.ssh.matchBlocks warning from this module.

Scope

In: modules/home-shared.nix, the check, its registration in flake.nix. Out: identity.sshHosts's shape in the secrets template, the profiles-side matchBlocks (allod/profiles issue), the neovim default warnings (same issue).

`modules/home-shared.nix` defines the operator's SSH hosts through `programs.ssh.matchBlocks`, which Home Manager 26.05 deprecates in favour of `programs.ssh.settings`. Every VM build and the hypervisor's user profile now print one warning for the option and one more for each host in `identity.sshHosts` that carries `extraOptions`. The rendered `~/.ssh/config` is unchanged today, but the alias is slated for removal, and the warning wall hides real evaluation output such as the `rebuild-nexus` preview. Migrate the module to `programs.ssh.settings`. `identity.sshHosts` keeps its current shape, since it is data in the deployment's private secrets fork: the module translates the keys it uses (`hostname`, `user`, `port`, `identityFile`, `identitiesOnly`) to the upstream directive names (`HostName`, `User`, `Port`, `IdentityFile`, `IdentitiesOnly`) and merges `extraOptions` into the block directly, since its keys are already upstream directive names. A key the translation does not know fails evaluation naming the host and the key rather than being dropped. The forge host's `IdentityFile` stays `lib.mkDefault` so a profile's own definition still wins. Merge order with the matching profiles change (allod/profiles, migrating `hosts/dev/allod-dev/home.nix`) must not matter: Home Manager converts any remaining `matchBlocks` definition into `settings`, and two definitions of the same host block merge attribute by attribute, so a migrated framework beside an unmigrated profile, or the reverse, renders the same config. The check below pins that. ### Validation A check that builds a fixture home configuration through the real `home-shared.nix` with a fixture identity whose `sshHosts` include a plain host, a host with `port` and `identitiesOnly`, and a host with `extraOptions`, plus one legacy `programs.ssh.matchBlocks` definition of the forge host from a second module standing in for an unmigrated profile. It runs `ssh -G <host> -F <generated config>` for each host and asserts the resolved `hostname`, `user`, `port`, `identityfile` and the extra directive, and asserts that the profile's identity file wins for the forge host. Evaluation of the fixture emits no `programs.ssh.matchBlocks` warning from this module. ### Scope In: `modules/home-shared.nix`, the check, its registration in `flake.nix`. Out: `identity.sshHosts`'s shape in the secrets template, the profiles-side `matchBlocks` (allod/profiles issue), the neovim default warnings (same issue).
Author
Member

Correction to the issue text. The claim that merge order with the profiles change does not matter is wrong, measured while implementing: with this module still on programs.ssh.matchBlocks and a profile already on programs.ssh.settings, Home Manager's legacy conversion evaluates the module's block first, loses the lib.mkDefault on identityFile, and re-defines settings.<forge host>.IdentityFile at normal priority as a list. The profile's string then conflicts by type (or by value if written as a list), and the machine fails to evaluate. The reverse order, this module migrated with the profile still legacy, is the one that works, because the priority filter drops the module's default before types are compared; that is the order the new check pins.

So the sequencing is: this change lands first, and the deploy lock takes it at or before the profiles change in allod/profiles#8. The PR bodies on both sides state the order.

Correction to the issue text. The claim that merge order with the profiles change does not matter is wrong, measured while implementing: with this module still on `programs.ssh.matchBlocks` and a profile already on `programs.ssh.settings`, Home Manager's legacy conversion evaluates the module's block first, loses the `lib.mkDefault` on `identityFile`, and re-defines `settings.<forge host>.IdentityFile` at normal priority as a list. The profile's string then conflicts by type (or by value if written as a list), and the machine fails to evaluate. The reverse order, this module migrated with the profile still legacy, is the one that works, because the priority filter drops the module's default before types are compared; that is the order the new check pins. So the sequencing is: this change lands first, and the deploy lock takes it at or before the profiles change in allod/profiles#8. The PR bodies on both sides state the order.

Direction change. The migration now lands as part of allod/archetypes#54, which moves the forge entry into the dev VM builder and sends identity.sshHosts to the hypervisor only, so the two-author seam that made merge order matter here no longer exists. The translation and the ssh -G check from allod/archetypes#80 are harvested into that change. Tracking is allod/strategy#56; the allod/archetypes#54 pull request closes this issue as well.

Direction change. The migration now lands as part of allod/archetypes#54, which moves the forge entry into the dev VM builder and sends `identity.sshHosts` to the hypervisor only, so the two-author seam that made merge order matter here no longer exists. The translation and the `ssh -G` check from allod/archetypes#80 are harvested into that change. Tracking is allod/strategy#56; the allod/archetypes#54 pull request closes this issue as well.
Owner

closed in favor of allod/strategy#56

closed in favor of allod/strategy#56
vnprc closed this issue 2026-09-20 01:41:40 +01:00
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
allod/archetypes#79
No description provided.