diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml
index 97507cf252..ceb84d29b9 100644
--- a/man/systemd.system-credentials.xml
+++ b/man/systemd.system-credentials.xml
@@ -208,6 +208,15 @@
systemd1.
+
+
+ system.machine_id
+
+ Takes a 128bit ID to initialize the machine ID from (if it is not set yet). Interpreted by
+ the service manager (PID 1). For details see
+ systemd1.
+
+
diff --git a/man/systemd.xml b/man/systemd.xml
index d63e70f0c8..2cffe01aff 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -1069,6 +1069,16 @@
notification via VSOCK when a virtual machine has finished booting.
+
+
+ system.machine_id
+
+ Takes a 128bit hexadecimal ID to initialize /etc/machine-id from, if the
+ file is not set up yet. See
+ machine-id5 for
+ details.
+
+
diff --git a/src/core/main.c b/src/core/main.c
index 3f78f035d0..6290ec131c 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -2224,10 +2224,15 @@ static int initialize_runtime(
return r;
}
+ /* Pull credentials from various sources into a common credential directory (we do
+ * this here, before setting up the machine ID, so that we can use credential info
+ * for setting up the machine ID) */
+ (void) import_credentials();
+
(void) os_release_status();
(void) hostname_setup(true);
/* Force transient machine-id on first boot. */
- machine_id_setup(NULL, /* force_transient= */ first_boot, arg_machine_id, NULL);
+ machine_id_setup(/* root= */ NULL, /* force_transient= */ first_boot, arg_machine_id, /* ret_machine_id */ NULL);
(void) loopback_setup();
bump_unix_max_dgram_qlen();
bump_file_max_and_nr_open();
@@ -2306,10 +2311,6 @@ static int initialize_runtime(
(void) bump_rlimit_nofile(saved_rlimit_nofile);
(void) bump_rlimit_memlock(saved_rlimit_memlock);
- /* Pull credentials from various sources into a common credential directory */
- if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM && !skip_setup)
- (void) import_credentials();
-
return 0;
}
diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c
index f27c3d768b..e059c71105 100644
--- a/src/shared/machine-id-setup.c
+++ b/src/shared/machine-id-setup.c
@@ -9,6 +9,7 @@
#include "alloc-util.h"
#include "chase.h"
+#include "creds-util.h"
#include "fd-util.h"
#include "id128-util.h"
#include "io-util.h"
@@ -27,6 +28,24 @@
#include "umask-util.h"
#include "virt.h"
+static int acquire_machine_id_from_credential(sd_id128_t *ret) {
+ _cleanup_free_ char *buf = NULL;
+ int r;
+
+ r = read_credential_with_decryption("system.machine_id", (void**) &buf, /* ret_size= */ NULL);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to read system.machine_id credential, ignoring: %m");
+ if (r == 0) /* not found */
+ return -ENXIO;
+
+ r = sd_id128_from_string(buf, ret);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to parse system.machine_id credential, ignoring: %m");
+
+ log_info("Initializing machine ID from credential.");
+ return 0;
+}
+
static int generate_machine_id(const char *root, sd_id128_t *ret) {
_cleanup_close_ int fd = -EBADF;
int r;
@@ -41,6 +60,11 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) {
}
if (isempty(root) && running_in_chroot() <= 0) {
+ /* Let's use a system credential for the machine ID if we can */
+ r = acquire_machine_id_from_credential(ret);
+ if (r >= 0)
+ return r;
+
/* If that didn't work, see if we are running in a container,
* and a machine ID was passed in via $container_uuid the way
* libvirt/LXC does it */