8
8
// and filesystem setup.
9
9
pub ( crate ) mod baseline;
10
10
pub ( crate ) mod config;
11
+ pub ( crate ) mod osconfig;
11
12
12
13
use std:: io:: BufWriter ;
13
14
use std:: io:: Write ;
@@ -132,6 +133,16 @@ pub(crate) struct InstallConfigOpts {
132
133
/// Add a kernel argument
133
134
karg : Option < Vec < String > > ,
134
135
136
+ /// The path to an `authorized_keys` that will be injected into the `root` account.
137
+ ///
138
+ /// The implementation of this uses systemd `tmpfiles.d`, writing to a file named
139
+ /// `/etc/tmpfiles.d/bootc-root-ssh.conf`. This will have the effect that by default,
140
+ /// the SSH credentials will be set if not present. The intention behind this
141
+ /// is to allow mounting the whole `/root` home directory as a `tmpfs`, while still
142
+ /// getting the SSH key replaced on boot.
143
+ #[ clap( long) ]
144
+ root_ssh_authorized_keys : Option < Utf8PathBuf > ,
145
+
135
146
/// Perform configuration changes suitable for a "generic" disk image.
136
147
/// At the moment:
137
148
///
@@ -261,6 +272,8 @@ pub(crate) struct State {
261
272
pub ( crate ) config_opts : InstallConfigOpts ,
262
273
pub ( crate ) target_imgref : ostree_container:: OstreeImageReference ,
263
274
pub ( crate ) install_config : config:: InstallConfiguration ,
275
+ /// The parsed contents of the authorized_keys (not the file path)
276
+ pub ( crate ) root_ssh_authorized_keys : Option < String > ,
264
277
}
265
278
266
279
impl State {
@@ -566,9 +579,9 @@ async fn initialize_ostree_root_from_self(
566
579
options. proxy_cfg = proxy_cfg;
567
580
println ! ( "Creating initial deployment" ) ;
568
581
let target_image = state. target_imgref . to_string ( ) ;
569
- let state =
582
+ let imgstate =
570
583
ostree_container:: deploy:: deploy ( & sysroot, stateroot, & src_imageref, Some ( options) ) . await ?;
571
- let digest = state . manifest_digest . as_str ( ) ;
584
+ let digest = imgstate . manifest_digest . as_str ( ) ;
572
585
println ! ( "Installed: {target_image}" ) ;
573
586
println ! ( " Digest: {digest}" ) ;
574
587
@@ -596,9 +609,13 @@ async fn initialize_ostree_root_from_self(
596
609
}
597
610
f. flush ( ) ?;
598
611
612
+ if let Some ( contents) = state. root_ssh_authorized_keys . as_deref ( ) {
613
+ osconfig:: inject_root_ssh_authorized_keys ( & root, contents) ?;
614
+ }
615
+
599
616
let uname = rustix:: system:: uname ( ) ;
600
617
601
- let labels = crate :: status:: labels_of_config ( & state . configuration ) ;
618
+ let labels = crate :: status:: labels_of_config ( & imgstate . configuration ) ;
602
619
let timestamp = labels
603
620
. and_then ( |l| {
604
621
l. get ( oci_spec:: image:: ANNOTATION_CREATED )
@@ -607,7 +624,7 @@ async fn initialize_ostree_root_from_self(
607
624
. and_then ( crate :: status:: try_deserialize_timestamp) ;
608
625
let aleph = InstallAleph {
609
626
image : src_imageref. imgref . name . clone ( ) ,
610
- version : state . version ( ) . as_ref ( ) . map ( |s| s. to_string ( ) ) ,
627
+ version : imgstate . version ( ) . as_ref ( ) . map ( |s| s. to_string ( ) ) ,
611
628
timestamp,
612
629
kernel : uname. release ( ) . to_str ( ) ?. to_string ( ) ,
613
630
} ;
@@ -944,6 +961,14 @@ async fn prepare_install(
944
961
let install_config = config:: load_config ( ) ?;
945
962
tracing:: debug!( "Loaded install configuration" ) ;
946
963
964
+ // Eagerly read the file now to ensure we error out early if e.g. it doesn't exist,
965
+ // instead of much later after we're 80% of the way through an install.
966
+ let root_ssh_authorized_keys = config_opts
967
+ . root_ssh_authorized_keys
968
+ . as_ref ( )
969
+ . map ( |p| std:: fs:: read_to_string ( p) . with_context ( || format ! ( "Reading {p}" ) ) )
970
+ . transpose ( ) ?;
971
+
947
972
// Create our global (read-only) state which gets wrapped in an Arc
948
973
// so we can pass it to worker threads too. Right now this just
949
974
// combines our command line options along with some bind mounts from the host.
@@ -954,6 +979,7 @@ async fn prepare_install(
954
979
config_opts,
955
980
target_imgref,
956
981
install_config,
982
+ root_ssh_authorized_keys,
957
983
} ) ;
958
984
959
985
Ok ( state)
0 commit comments