Merge pull request #24700 from poettering/ssh-creds

support easy provisioning for SSH key of root user
This commit is contained in:
Lennart Poettering 2022-09-23 16:01:09 +02:00 committed by GitHub
commit dd5533801b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 789 additions and 410 deletions

96
TODO
View file

@ -119,11 +119,9 @@ Deprecations and removals:
Features:
* systemd-measure: only require private key to be set when signing. iiuc we can
generate the public key from it anyway.
* automatically propagate LUKS password credential into cryptsetup from host,
so that one can unlock LUKS via VM hypervisor supplied password.
* automatically propagate LUKS password credential into cryptsetup from host
(i.e. SMBIOS type #11, …), so that one can unlock LUKS via VM hypervisor
supplied password.
* add ability to path_is_valid() to classify paths that refer to a dir from
those which may refer to anything, and use that in various places to filter
@ -166,9 +164,6 @@ Features:
systemd.import_encrypted_creds=foobar.waldo,tmpfiles.extra to protect locked
down kernels from credentials generated on the host with a weak kernel
* tmpfiles: currently if we fail to create an inode, we stat it first, and only
then O_PATH open it. Reverse that.
* Add support for extra verity configuration options to systemd-repart (FEC,
hash type, etc)
@ -218,8 +213,6 @@ Features:
* sd-bus: document that sd_bus_process() only returns messages that non of the
filters/handlers installed on the connection took possession of.
* sd-device: add an API for opening a child device, given a device object
* sd-device: add an API for acquiring list of child devices, given a device
objects (i.e. all child dirents that dirs or symlinks to dirs)
@ -236,9 +229,6 @@ Features:
portabled/… up to udev to watch block devices coming up with the flags set, and
use it.
* portabled: read a credential "portable.extra" or so, that takes a list of
file system paths to enable on start.
* sd-boot should look for information what to boot in SMBIOS, too, so that VM
managers can tell sd-boot what to boot into and suchlike
@ -277,27 +267,34 @@ Features:
this to remove auxiliary files, and never remove them explicitly. Benefit:
resources such as initrds/kernels/dtb can be shared between entries.
* networkd/udevd: add a way to define additional .link, .network, .netdev files
via the credentials logic.
* fstab-generator: allow defining additional fstab-like mounts via
credentials (similar: crypttab-generator, verity-generator,
integrity-generator)
* getty-generator: allow defining additional getty instances via a credential
* run-generator: allow defining additional commands to run via a credential
* resolved: allow defining additional /etc/hosts entries via a credential (it
might make sense to then synthesize a new combined /etc/hosts file in /run
and bind mount it on /etc/hosts for other clients that want to read it.
Similar, allow picking up DNS server IP addresses from credential.
* repart: allow defining additional partitions via credential
* tmpfiles: add snippet that provisions /root/.ssh/authorized_keys from credential
* timesyncd: pick NTP server info from credential
* Process credentials in:
• networkd/udevd: add a way to define additional .link, .network, .netdev files
via the credentials logic.
• fstab-generator: allow defining additional fstab-like mounts via
credentials (similar: crypttab-generator, verity-generator,
integrity-generator)
• getty-generator: allow defining additional getty instances via a credential
• run-generator: allow defining additional commands to run via a credential
• resolved: allow defining additional /etc/hosts entries via a credential (it
might make sense to then synthesize a new combined /etc/hosts file in /run
and bind mount it on /etc/hosts for other clients that want to read it.
Similar, allow picking up DNS server IP addresses from credential.
• repart: allow defining additional partitions via credential
• timesyncd: pick NTP server info from credential
• portabled: read a credential "portable.extra" or so, that takes a list of
file system paths to enable on start.
• make systemd-fstab-generator look for a system credential encoding root= or
usr=
• systemd-homed: when initializing, look for a credential
systemd.homed.register or so with JSON user records to automatically
register if not registered yet. Usecase: deploy a system, and add an
account one can directly log into.
• initialize machine ID from systemd credential picked up from the ESP via
sd-stub, so that machine ID is stable even on systems where unified kernels
are used, and hence kernel cmdline cannot be modified locally
• in gpt-auto-generator: check partition uuids against such uuids supplied via
sd-stub credentials. That way, we can support parallel OS installations with
pre-built kernels.
* define a JSON format for units, separating out unit definitions from unit
runtime state. Then, expose it:
@ -326,9 +323,6 @@ Features:
UEFI firmware (for example, ovmf supports that via qemu cmdline option), and
use it to load stuff from the ESP.
* make tmpfiles read lines from creds, so that we can provision SSH host keys
via creds. Similar: sysusers, sysctl, homed
* mount /var/ from initrd, so that we can apply sysext and stuff before the
initrd transition. Specifically:
1. There should be a var= kernel cmdline option, matching root= and usr=
@ -361,9 +355,6 @@ Features:
comes from, but we can still derive that from the stdin socket its output
came from. We apparently don't do that right now.
* make systemd-fstab-generator look for a system credential encoding root= or
usr=
* add ability to set hostname with suffix derived from machine id at boot
* ask dracut to generate usr= on the kernel cmdline so that we don't need to
@ -393,10 +384,6 @@ Features:
inode first, then connect to /proc/self/fd/XYZ. When binding, create symlink
to target dir in /tmp, and bind through it.
* systemd-homed: when initializing, look for a credential sysemd.homed.register
or so with JSON user records to automatically register if not registered yet.
Usecase: deploy a system, and add an account one can directly log into.
* add a proper concept of a "developer" mode, i.e. where cryptographic
protections of the root OS are weakened after interactive confirmation, to
allow hackers to allow their own stuff. idea: allow entering developer mode
@ -541,14 +528,6 @@ Features:
the real kernel. benefit: downloading these stubs would be tiny and quick,
hence cheap for enumeration.
* initialize machine ID from systemd credential picked up from the ESP via
sd-stub, so that machine ID is stable even on systems where unified kernels
are used, and hence kernel cmdline cannot be modified locally
* in gpt-auto-generator: check partition uuids against such uuids supplied via
sd-stub credentials. That way, we can support parallel OS installations with
pre-built kernels.
* sysext: measure all activated sysext into a TPM PCR
* maybe add a "syscfg" concept, that is almost entirely identical to "sysext",
@ -624,7 +603,7 @@ Features:
* systemd-dissect: show GPT disk UUID in output
* Enable RestricFileSystems= for all our long-running services (similar:
* Enable RestrictFileSystems= for all our long-running services (similar:
RestrictNetworkInterfaces=)
* Add systemd-analyze security checks for RestrictFileSystems= and
@ -644,9 +623,6 @@ Features:
such as masking out /usr/lib/ or so. We should probably refuse if existing
inodes are replaced by other types of inodes or so.
* sysext: ensure one can build a sysext that can safely apply to *any* system
(because it contains only static go binaries in /opt/ or so)
* userdb: when synthesizing NSS records, pick "best" password from defined
passwords, not just the first. i.e. if there are multiple defined, prefer
unlocked over locked and prefer non-empty over empty.
@ -1270,7 +1246,8 @@ Features:
"systemd-gdb" for attaching to the start-up of any system service in its
natural habitat.
* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
* gpt-auto logic: support encrypted swap, add kernel cmdline option to force
it, and honour a gpt bit about it, plus maybe a configuration file
* add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and
then use that for the setting used in user@.service. It should be understood
@ -1609,11 +1586,6 @@ Features:
* mount: turn dependency information from /proc/self/mountinfo into dependency information between systemd units.
* firstboot: allow provisioning of /etc/hosts entries, so that we can via the
credentials logic insert host name to resolve into containers/hosts. Usecase:
fork a container, and make it ping some specific address which is defined by
the host on invocation
* systemd-firstboot: make sure to always use chase_symlinks() before
reading/writing files

View file

@ -1086,6 +1086,7 @@ manpages = [
['systemd.special', '7', [], ''],
['systemd.swap', '5', [], ''],
['systemd.syntax', '7', [], ''],
['systemd.system-credentials', '7', [], ''],
['systemd.target', '5', [], ''],
['systemd.time', '7', [], ''],
['systemd.timer', '5', [], ''],

View file

@ -0,0 +1,192 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd.system-credentials">
<refentryinfo>
<title>systemd.system-credentials</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd.system-credentials</refentrytitle>
<manvolnum>7</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd.system-credentials</refname>
<refpurpose>System Credentials</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para><ulink url="https://systemd.io/CREDENTIALS">System and Service Credentials</ulink> are data objects
that may be passed into booted systems or system services as they are invoked. They can be acquired from
various external sources, and propagated into the system and from there into system services. Credentials
may optionally be encrypted with a machine-specific key and/or locked to the local TPM2 device, and are
only decrypted when the consuming service is invoked.</para>
<para>System credentials may be used to provision and configure various aspects of the system. Depending
on the consuming component credentials are only used on initial invocations or are needed for all
invocations.</para>
<para>Credentials may be used for any kind of data, binary or text, and may carry passwords, secrets,
certificates, cryptographic key material, identity information, configuration, and more.</para>
</refsect1>
<refsect1>
<title>Well known system credentials</title>
<variablelist>
<varlistentry>
<term><varname>firstboot.keymap</varname></term>
<listitem>
<para>The console key mapping to set (e.g. <literal>de</literal>). Read by
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
and only honoured if no console keymap has been configured before.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>firstboot.locale</varname></term>
<term><varname>firstboot.locale-message</varname></term>
<listitem>
<para>The system locale to set (e.g. <literal>de_DE.UTF-8</literal>). Read by
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
and only honoured if no locale has been configured before. <varname>firstboot.locale</varname> sets
<literal>LANG</literal>, while <varname>firstboot.locale-message</varname> sets
<literal>LC_MESSAGES</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>firstboot.timezone</varname></term>
<listitem>
<para>The system timezone to set (e.g. <literal>Europe/Berlin</literal>). Read by
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
and only honoured if no system timezone has been configured before.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>login.issue</varname></term>
<listitem>
<para>The data of this credential is written to
<filename>/etc/issue.d/50-provision.conf</filename>, if the file doesn't exist
yet. <citerefentry><refentrytitle>agetty</refentrytitle><manvolnum>8</manvolnum></citerefentry>
reads this file and shows its contents at the login prompt of terminal logins. See <citerefentry
project='man-pages'><refentrytitle>issue</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
<para>Consumed by <filename>/usr/lib/tmpfiles.d/provision.conf</filename>, see
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>login.motd</varname></term>
<listitem>
<para>The data of this credential is written to <filename>/etc/motd.d/50-provision.conf</filename>,
if the file doesn't exist
yet. <citerefentry><refentrytitle>pam_motd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
reads this file and shows its contents as "message of the day" during terminal logins. See
<citerefentry
project='man-pages'><refentrytitle>motd</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
<para>Consumed by <filename>/usr/lib/tmpfiles.d/provision.conf</filename>, see
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>network.hosts</varname></term>
<listitem>
<para>The data of this credential is written to <filename>/etc/hosts</filename>, if the file
doesn't exist yet. See <citerefentry
project='man-pages'><refentrytitle>hosts</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
<para>Consumed by <filename>/usr/lib/tmpfiles.d/provision.conf</filename>, see
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>passwd.hashed-password.root</varname></term>
<term><varname>passwd.plaintext-password.root</varname></term>
<listitem>
<para>May contain the password (either in UNIX hashed format, or in plaintext) for the root users.
Read by both
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>systemd-sysusers</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
and only honoured if no root password has been configured before.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>passwd.shell.root</varname></term>
<listitem>
<para>The path to the shell program (e.g. <literal>/bin/bash</literal>) for the root user. Read by
both
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>systemd-sysusers</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
and only honoured if no root shell has been configured before.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ssh.authorized_keys.root</varname></term>
<listitem>
<para>The data of this credential is written to <filename>/root/.ssh/authorized_keys</filename>, if
the file doesn't exist yet. This allows provisioning SSH access for the system's root user.</para>
<para>Consumed by <filename>/usr/lib/tmpfiles.d/provision.conf</filename>, see
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>sysusers.extra</varname></term>
<listitem>
<para>Additional
<citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
lines to process during boot.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>sysctl.extra</varname></term>
<listitem>
<para>Additional
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> lines
to process during boot.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>tmpfiles.extra</varname></term>
<listitem>
<para>Additional
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
lines to process during boot.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -531,27 +531,24 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
<refsect2>
<title>Mode</title>
<para>The file access mode to use when creating this file or
directory. If omitted or when set to <literal>-</literal>, the
default is used: 0755 for directories, 0644 for all other file
objects. For <varname>z</varname>, <varname>Z</varname> lines,
if omitted or when set to <literal>-</literal>, the file access
mode will not be modified. This parameter is ignored for
<varname>x</varname>, <varname>r</varname>,
<varname>R</varname>, <varname>L</varname>, <varname>t</varname>,
and <varname>a</varname> lines.</para>
<para>The file access mode to use when creating this file or directory. If omitted or when set to
<literal>-</literal>, the default is used: 0755 for directories, 0644 for all other file objects. For
<varname>z</varname>, <varname>Z</varname> lines, if omitted or when set to <literal>-</literal>, the
file access mode will not be modified. This parameter is ignored for <varname>x</varname>,
<varname>r</varname>, <varname>R</varname>, <varname>L</varname>, <varname>t</varname>, and
<varname>a</varname> lines.</para>
<para>Optionally, if prefixed with <literal>~</literal>, the
access mode is masked based on the already set access bits for
existing file or directories: if the existing file has all
executable bits unset, all executable bits are removed from the
new access mode, too. Similarly, if all read bits are removed
from the old access mode, they will be removed from the new
access mode too, and if all write bits are removed, they will be
removed from the new access mode too. In addition, the
sticky/SUID/SGID bit is removed unless applied to a
directory. This functionality is particularly useful in
conjunction with <varname>Z</varname>.</para>
<para>Optionally, if prefixed with <literal>~</literal>, the access mode is masked based on the already
set access bits for existing file or directories: if the existing file has all executable bits unset,
all executable bits are removed from the new access mode, too. Similarly, if all read bits are removed
from the old access mode, they will be removed from the new access mode too, and if all write bits are
removed, they will be removed from the new access mode too. In addition, the sticky/SUID/SGID bit is
removed unless applied to a directory. This functionality is particularly useful in conjunction with
<varname>Z</varname>.</para>
<para>Optionally, if prefixed with <literal>:</literal>, the configured access mode is only used when
creating new inodes. If the inode the line refers to already exists, its access mode is left in place
unmodified.</para>
</refsect2>
<refsect2>
@ -571,6 +568,10 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
url="https://systemd.io/UIDS-GIDS/#notes-on-resolvability-of-user-and-group-names">Notes on
Resolvability of User and Group Names</ulink> for more information on requirements on system user/group
definitions.</para>
<para>Optionally, if prefixed with <literal>:</literal>, the configured user/group information is only
used when creating new inodes. If the inode the line refers to already exists, its user/group is left
in place unmodified.</para>
</refsect2>
<refsect2>

View file

@ -432,7 +432,7 @@ int symlink_idempotent(const char *from, const char *to, bool make_relative) {
return 0;
}
int symlink_atomic_full(const char *from, const char *to, bool make_relative) {
int symlinkat_atomic_full(const char *from, int atfd, const char *to, bool make_relative) {
_cleanup_free_ char *relpath = NULL, *t = NULL;
int r;
@ -451,18 +451,19 @@ int symlink_atomic_full(const char *from, const char *to, bool make_relative) {
if (r < 0)
return r;
if (symlink(from, t) < 0)
if (symlinkat(from, atfd, t) < 0)
return -errno;
if (rename(t, to) < 0) {
unlink_noerrno(t);
return -errno;
r = RET_NERRNO(renameat(atfd, t, atfd, to));
if (r < 0) {
(void) unlinkat(atfd, t, 0);
return r;
}
return 0;
}
int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
int mknodat_atomic(int atfd, const char *path, mode_t mode, dev_t dev) {
_cleanup_free_ char *t = NULL;
int r;
@ -472,58 +473,36 @@ int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
if (r < 0)
return r;
if (mknod(t, mode, dev) < 0)
if (mknodat(atfd, t, mode, dev) < 0)
return -errno;
if (rename(t, path) < 0) {
unlink_noerrno(t);
return -errno;
}
return 0;
}
int mkfifo_atomic(const char *path, mode_t mode) {
_cleanup_free_ char *t = NULL;
int r;
assert(path);
r = tempfn_random(path, NULL, &t);
if (r < 0)
r = RET_NERRNO(renameat(atfd, t, atfd, path));
if (r < 0) {
(void) unlinkat(atfd, t, 0);
return r;
if (mkfifo(t, mode) < 0)
return -errno;
if (rename(t, path) < 0) {
unlink_noerrno(t);
return -errno;
}
return 0;
}
int mkfifoat_atomic(int dirfd, const char *path, mode_t mode) {
int mkfifoat_atomic(int atfd, const char *path, mode_t mode) {
_cleanup_free_ char *t = NULL;
int r;
assert(path);
if (path_is_absolute(path))
return mkfifo_atomic(path, mode);
/* We're only interested in the (random) filename. */
r = tempfn_random_child("", NULL, &t);
r = tempfn_random(path, NULL, &t);
if (r < 0)
return r;
if (mkfifoat(dirfd, t, mode) < 0)
if (mkfifoat(atfd, t, mode) < 0)
return -errno;
if (renameat(dirfd, t, dirfd, path) < 0) {
unlink_noerrno(t);
return -errno;
r = RET_NERRNO(renameat(atfd, t, atfd, path));
if (r < 0) {
(void) unlinkat(atfd, t, 0);
return r;
}
return 0;

View file

@ -58,13 +58,20 @@ static inline int touch(const char *path) {
int symlink_idempotent(const char *from, const char *to, bool make_relative);
int symlink_atomic_full(const char *from, const char *to, bool make_relative);
int symlinkat_atomic_full(const char *from, int atfd, const char *to, bool make_relative);
static inline int symlink_atomic(const char *from, const char *to) {
return symlink_atomic_full(from, to, false);
return symlinkat_atomic_full(from, AT_FDCWD, to, false);
}
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
int mkfifo_atomic(const char *path, mode_t mode);
int mknodat_atomic(int atfd, const char *path, mode_t mode, dev_t dev);
static inline int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
return mknodat_atomic(AT_FDCWD, path, mode, dev);
}
int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode);
static inline int mkfifo_atomic(const char *path, mode_t mode) {
return mkfifoat_atomic(AT_FDCWD, path, mode);
}
int get_files_in_directory(const char *path, char ***list);

View file

@ -71,7 +71,7 @@ int symlink_atomic_full_label(const char *from, const char *to, bool make_relati
if (r < 0)
return r;
r = symlink_atomic_full(from, to, make_relative);
r = symlinkat_atomic_full(from, AT_FDCWD, to, make_relative);
mac_selinux_create_file_clear();
if (r < 0)

File diff suppressed because it is too large Load diff

37
test/units/testsuite-22.14.sh Executable file
View file

@ -0,0 +1,37 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Tests for the ":" uid/gid/mode modifier
#
set -eux
rm -rf /tmp/someinode
systemd-tmpfiles --create - <<EOF
d /tmp/someinode :0123 :1 :1
EOF
test "$(stat -c %F:%u:%g:%a /tmp/someinode)" = "directory:1:1:123"
systemd-tmpfiles --create - <<EOF
d /tmp/someinode :0321 :2 :2
EOF
test "$(stat -c %F:%u:%g:%a /tmp/someinode)" = "directory:1:1:123"
systemd-tmpfiles --create - <<EOF
d /tmp/someinode 0321 2 2
EOF
test "$(stat -c %F:%u:%g:%a /tmp/someinode)" = "directory:2:2:321"
systemd-tmpfiles --create - <<EOF
d /tmp/someinode :0123 :1 :1
EOF
test "$(stat -c %F:%u:%g:%a /tmp/someinode)" = "directory:2:2:321"
rm -rf /tmp/someinode
systemd-tmpfiles --create - <<EOF
d /tmp/someinode :0123 :1 :1
EOF
test "$(stat -c %F:%u:%g:%a /tmp/someinode)" = "directory:1:1:123"
rm -rf /tmp/someinode

View file

@ -15,3 +15,8 @@ f^ /etc/issue.d/50-provision.conf - - - - login.issue
# Provision a /etc/hosts file from credentials.
f^ /etc/hosts - - - - network.hosts
# Provision SSH key for root
d /root :0700 root :root -
d /root/.ssh :0700 root :root -
f^ /root/.ssh/authorized_keys :0600 root :root - ssh.authorized_keys.root

View file

@ -27,3 +27,4 @@ LoadCredential=tmpfiles.extra
LoadCredential=login.motd
LoadCredential=login.issue
LoadCredential=network.hosts
LoadCredential=ssh.authorized_keys.root