Skip to content

composefs: Inject root SSH keys at install - #2536

Merged
cgwalters merged 2 commits into
bootc-dev:mainfrom
andrewdunndev:fix/composefs-root-ssh-keys
Oct 6, 2026
Merged

cgwalters merged 2 commits into
bootc-dev:mainfrom
andrewdunndev:fix/composefs-root-ssh-keys

Conversation

@andrewdunndev

@andrewdunndev andrewdunndev commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

bootc install --root-ssh-authorized-keys is accepted with the composefs backend, but the keys never reach the installed system. Only the ostree path calls inject_root_ssh_authorized_keys (from install_container), and setup_composefs_boot never does, so the install succeeds and root key login fails after boot.

A composefs deployment keeps its /etc in state/deploy/<id>/etc, apart from the image that holds the /root symlink the helper resolves. The helper now takes the directory that receives etc/tmpfiles.d separately from the root it reads, and setup_composefs_boot calls it once write_composefs_state has created the deployment's /etc. The ostree call passes the same directory for both, so its behaviour is unchanged.

test-install-composefs-native now passes a key on every install and checks the drop-in's content and mode for whichever backend installed.

Testing: make validate and cargo test -p bootc-lib osconfig pass. In a VM, a Fedora 44 bootc image built from this branch and installed with --composefs-backend --root-ssh-authorized-keys writes state/deploy/<id>/etc/tmpfiles.d/bootc-root-ssh.conf, and root SSH login with the key works after boot with SELinux enforcing. The same install from main writes no drop-in and the login is refused. just test-tmt install-composefs-native passes with this change and, with the setup_composefs_boot hunk reverted, fails at the new drop-in check on the first composefs install.

Fixes #2535

`bootc install --root-ssh-authorized-keys` writes a tmpfiles.d drop-in
that provisions root's authorized_keys on first boot, but only the
ostree install path called the helper. With the composefs backend the
option was accepted and silently dropped: the install succeeded and
root key login failed on the booted system.

A composefs deployment keeps its /etc in state/deploy/<id>/etc, apart
from the image that holds the /root symlink the helper resolves. Let
the helper take the directory that receives etc/tmpfiles.d separately
from the root it reads, and call it once the deployment's /etc exists.
The /etc merge carries the drop-in across upgrades like any other
locally added file.

Assisted-by: AI
Signed-off-by: Andrew Dunn <andrew@dunn.dev>
cgwalters
cgwalters previously approved these changes Oct 5, 2026
Comment thread crates/lib/src/install.rs

if let Some(contents) = state.root_ssh_authorized_keys.as_deref() {
osconfig::inject_root_ssh_authorized_keys(&root, sepolicy, contents)?;
osconfig::inject_root_ssh_authorized_keys(&root, &root, sepolicy, contents)?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For followup, I think this should be moved out into a common place that's "post image layout"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I'll move it in a follow-up once this lands.

Only the ostree-only install tests in tests-integration covered
--root-ssh-authorized-keys, so the composefs backend could drop it
unnoticed. test-install-composefs-native already installs to disk
with both backends; pass a key on every install there and check the
deployment's bootc-root-ssh.conf content and mode.

The drop-in is read with decode utf-8 because nushell 0.99.1, which
Fedora 44 and EPEL 9 ship, drops the trailing newline when an
open --raw stream is collected into a string.

Without the previous commit the composefs installs fail this check.

Assisted-by: AI
Signed-off-by: Andrew Dunn <andrew@dunn.dev>
@andrewdunndev

Copy link
Copy Markdown
Contributor Author

The plan-60 failures were in the new drop-in check, and the Rust side is unchanged. Fedora 44 and EPEL 9 ship nushell 0.99.1, which drops the trailing newline when the open --raw stream is collected into a string, while the 0.103.0 release binary the CentOS 10 jobs fetch keeps it. Piping through decode utf-8 keeps the newline on both, and it's squashed into the tmt commit.

@cgwalters

Copy link
Copy Markdown
Collaborator

Yeah this is not the first time we've been bit by a nushell behavioral change. I now mostly regret using it, filed #2547 which summarizes some thoughts.

@cgwalters
cgwalters enabled auto-merge (rebase) October 5, 2026 19:23
@cgwalters
cgwalters merged commit 82b2f90 into bootc-dev:main Oct 6, 2026
93 of 95 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install Issues related to `bootc install`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

install: --root-ssh-authorized-keys is silently ignored with --composefs-backend

2 participants