firstboot: apply hostname via hostnamed varlink API

Previously we just wrote /etc/hostname and returned. The kernel hostname
was left at whatever PID 1 sethostname()'d very early in boot (before
/etc/hostname existed), which meant hostnamectl reported the transient
hostname instead of the static one until the next reboot.

Call io.systemd.Hostname.SetStaticHostname on the running system so
hostnamed writes /etc/hostname and updates the kernel hostname in one
step. If hostnamed is unreachable (masked or absent on minimal images)
fall back to writing /etc/hostname directly. --root=/--image= also keeps
writing the file directly, since hostnamed only manages the running
system.
This commit is contained in:
Arian van Putten
2026-08-28 06:29:58 +09:00
committed by Yu Watanabe
parent 3d0ef4aefe
commit c7837840f5
2 changed files with 32 additions and 4 deletions
+31 -4
View File
@@ -777,19 +777,46 @@ static int process_hostname(int rfd, sd_varlink **mute_console_link) {
* and let it be resolved on each first boot. */
const char *hostname = arg_hostname;
_cleanup_free_ char *resolved = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
if (!arg_root) {
r = hostname_substitute_wildcards(arg_hostname, &resolved);
if (r < 0)
log_warning_errno(r, "Failed to resolve wildcards in hostname '%s', writing it verbatim: %m", arg_hostname);
else if (!hostname_is_valid(resolved, VALID_HOSTNAME_TRAILING_DOT))
log_warning("Resolved hostname '%s' is invalid, writing template '%s' verbatim instead.", resolved, arg_hostname);
else
else {
hostname = resolved;
r = sd_varlink_connect_address(&vl, "/run/systemd/io.systemd.Hostname");
if (r < 0)
log_warning_errno(r, "Failed to connect to systemd-hostnamed, writing /etc/hostname directly: %m");
}
}
r = write_string_file_full_label(pfd, f, hostname,
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL,
/* ts= */ NULL, /* label_fn= */ NULL, arg_label_context);
if (vl) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *reply = NULL;
const char *error_id = NULL;
r = sd_varlink_callbo(
vl,
"io.systemd.Hostname.SetStaticHostname",
&reply,
&error_id,
SD_JSON_BUILD_PAIR_STRING("newValue", hostname));
if (r < 0)
log_warning_errno(r, "Failed to call io.systemd.Hostname.SetStaticHostname, writing /etc/hostname directly: %m");
else if (error_id)
log_warning_errno(sd_varlink_error_to_errno(error_id, reply),
"Failed to set static hostname, writing /etc/hostname directly: %s", error_id);
else {
log_info("Static hostname configured via systemd-hostnamed.");
return 0;
}
}
r = write_string_file_full_label(
pfd, f, hostname,
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL,
/* ts= */ NULL, /* label_fn= */ NULL, arg_label_context);
if (r < 0)
return log_error_errno(r, "Failed to write /etc/hostname: %m");
+1
View File
@@ -23,6 +23,7 @@ After=systemd-sysusers.service systemd-tmpfiles-setup.service
# Let vconsole-setup do its setup before starting user interaction:
After=systemd-vconsole-setup.service
After=systemd-mute-console.socket
After=systemd-hostnamed.socket
Wants=first-boot-complete.target
Before=first-boot-complete.target sysinit.target