Home / Alt manpages / systemd-firstboot(1)

  • systemd-firstboot(1)
  • User command
  • linux

Prepare an Offline Linux Root with systemd-firstboot

Use systemd-firstboot to put first-boot settings into a mounted Linux root or image before it is started. This guide sets a hostname, locale, time zone, machine ID, root shell and root password without touching the host's corresponding files.

Allow about 10 minutes, plus the time needed to identify the correct image or mount point. The examples use an alternate directory root because it is easier to inspect and undo. You need systemd 255 on this machine, a root directory that is not your live host, and elevated privileges when that directory is owned by root.

Checkpoint: choose the target

systemd-firstboot edits files directly. It does not call localectl, timedatectl or hostnamectl, and it does not configure a running service. That is why it works for an image which is mounted but not booted.

Set the target once and inspect it before continuing. Replace the example path with the root of the system you really intend to prepare.

$ TARGET_ROOT=/srv/images/example-root
$ sudo test -d "$TARGET_ROOT/etc" && echo "target looks like a root filesystem"
target looks like a root filesystem

Stop if the check names the wrong machine or if /etc is absent. --root prefixes the files that the command changes; it does not make an arbitrary directory into a complete operating system.

1. Inspect the installed version

The installed package here is systemd 255.4-1ubuntu8.17, reporting systemd 255. Version matters: --root-shell, --force and --reset were added in systemd versions 246, 246 and 254 respectively. Check the binary on the machine where you will run the command.

$ systemd-firstboot --version
systemd 255 (255.4-1ubuntu8.17)

2. Write the ordinary first-boot settings

Pass all non-secret values explicitly. Existing configuration is kept by default, so this command will not replace an already populated setting. --setup-machine-id creates a random ID and only works with --root or --image.

$ sudo systemd-firstboot \
    --root="$TARGET_ROOT" \
    --locale=en_GB.UTF-8 \
    --timezone=Europe/London \
    --hostname=example-host \
    --setup-machine-id \
    --root-shell=/bin/bash \
    --kernel-command-line='root=UUID=REPLACE-ME ro quiet'

A successful run returns to the shell with exit status 0. The settings land in the target's /etc/locale.conf, /etc/localtime, /etc/hostname, /etc/machine-id, /etc/passwd and /etc/kernel/cmdline as applicable. --locale sets LANG. If messages should use a different locale, add --locale-messages=LOCALE; the file then can contain a separate LC_MESSAGES entry. The keymap, if needed, is separate:

$ sudo systemd-firstboot --root="$TARGET_ROOT" --keymap=uk

3. Set the root password without exposing it in ps

Do not put a plaintext password in --root-password=. Other users may see command-line arguments through ps. Instead, create a temporary file with restrictive permissions, use --root-password-file, then remove that file immediately.

$ PASSWORD_FILE=$(mktemp)
$ chmod 600 "$PASSWORD_FILE"
$ printf '%s\n' 'REPLACE-WITH-A-REAL-TEMPORARY-PASSWORD' >"$PASSWORD_FILE"
$ sudo systemd-firstboot --root="$TARGET_ROOT" --root-password-file="$PASSWORD_FILE"
$ rm -f "$PASSWORD_FILE"

The password file is local input, not the target's final password database. If the command fails, remove it before investigating. For automated image builds, a precomputed hash can be supplied with --root-password-hashed, but treat that hash as a credential.

4. Verify the target, not the host

Read the files below through the target path. These checks do not change state.

$ sudo cat "$TARGET_ROOT/etc/hostname"
example-host
$ sudo cat "$TARGET_ROOT/etc/locale.conf"
LANG=en_GB.UTF-8
$ sudo readlink "$TARGET_ROOT/etc/localtime"
/usr/share/zoneinfo/Europe/London
$ sudo test -s "$TARGET_ROOT/etc/machine-id" && echo "machine ID present"
machine ID present
$ sudo grep '^root:' "$TARGET_ROOT/etc/passwd"
root:x:0:0:root:/root:/bin/bash

The exact root line may contain different fields on your image, but its shell should end in /bin/bash. Do not compare hostname or /etc/locale.conf on the running host: those are different files.

5. Know when to use image mode

For a disk image or block device, use --image=/path/to/image instead of --root. The image must contain a supported filesystem, or filesystems laid out according to the Discoverable Partitions Specification. Image dissection can require elevated privileges and can affect the image directly, so make a backup before changing it.

$ sudo cp --reflink=auto /path/to/system.img /path/to/system.img.bak
$ sudo systemd-firstboot --image=/path/to/system.img \
    --hostname=example-host \
    --timezone=Europe/London

If you are preparing a directory tree, stay with --root. Do not combine a host path and image path unless you have deliberately checked which one each option targets.

Warnings and recovery

--force overwrites existing configuration, so use it only after reviewing the target files. --reset removes all files configured by systemd-firstboot, even where you do not provide a replacement. It is deliberately destructive: take a copy of the target first, then restore the affected files from that copy if you need to undo it.

Never use --delete-root-password on a normal system image unless you have a controlled recovery plan. It can permit root login without a password when the account is not locked. Running this tool on an already configured live system is also the wrong recovery path; change the live system with the tool intended for that setting.

If a setting was already initialised, the command normally leaves it alone and does not prompt for it. Explicit command-line values take precedence over prompt options. For a deliberately interactive offline setup, use --prompt, but remember that it asks for locale, keymap, time zone, hostname, root password and root shell.

Done means

  • The version and target root were checked before writing.
  • The hostname, locale, time zone and machine ID verify inside the target tree.
  • The root password was supplied without leaving plaintext in the process list or temporary file.
  • The target is backed up before any image change or destructive option.
  • The prepared root can now be booted or handed to the image-building workflow.