Home / Alt manpages / systemd-firstboot(1)

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

Prepare an Offline Linux Root with systemd-firstboot

Building a base image and need the hostname, locale, time zone and root password set before it ever boots? systemd-firstboot writes first-boot settings straight into a mounted root or image, without touching the host's own files.

Give it 10 minutes, plus however long it takes to find the right 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 never calls localectl, timedatectl or hostnamectl, and it does not configure a running service, which is exactly why it works on an image that is mounted but not booted.

Set the target once and inspect it before going any further. Swap the example path for the root of the system you actually 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 that check names the wrong machine or /etc is missing. --root prefixes the files the command touches; it does not turn an arbitrary directory into a complete operating system.

1. Check the installed version

The installed package here is systemd 255.4-1ubuntu8.17, reporting itself as systemd 255. Version matters: --root-shell, --force and --reset arrived in systemd 246, 246 and 254 respectively, so check the binary on the machine you will actually run this on:

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

2. Write the ordinary first-boot settings

Pass every non-secret value explicitly. Existing configuration is kept by default, so this will not overwrite anything already populated. --setup-machine-id creates a random ID and only works alongside --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 clean run returns 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 need a different locale, add --locale-messages=LOCALE and the file gains a separate LC_MESSAGES entry. The keymap is set separately:

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

3. Set the root password without it showing up in ps

Never put a plaintext password directly in --root-password=: other users on the box can see command-line arguments through ps. Instead, drop it in a temporary file with tight permissions, point --root-password-file at it, then delete the file straight away:

$ 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"

That file is local input, not the target's actual password database. If the command fails, remove it before you go digging further. For automated image builds, a precomputed hash works through --root-password-hashed, but treat the hash itself as a credential.

4. Verify the target, never the host

Read these files back through the target path; none of the following changes anything:

$ 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

Your root line may have different fields, but the shell field should end in /bin/bash. Do not compare hostname or /etc/locale.conf on the running host: those are entirely different files from the ones you just wrote.

5. Know when to reach for image mode

For a disk image or block device, use --image=/path/to/image instead of --root. The image needs a supported filesystem, or filesystems laid out per the Discoverable Partitions Specification. Image dissection can need elevated privileges and can affect the image directly, so back it up first:

$ 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

Preparing a directory tree? Stick with --root. Do not mix a host path and an image path unless you have deliberately checked which option targets which.

Warnings and recovery

Warning

--force overwrites existing configuration, so only use it after reviewing the target files. --reset removes everything systemd-firstboot configured, even where you supply no replacement, and it is deliberately destructive: copy the target first, then restore the affected files from that copy if you need it back.

Never use --delete-root-password on a normal system image without a controlled recovery plan; it can let root log in with no password at all when the account is not locked. Running this tool against an already-configured live system is also the wrong recovery path: change a live system with the tool meant for that setting instead.

If a setting was already initialised, the command normally leaves it alone rather than prompting. Explicit command-line values always win over prompt options. For a deliberately interactive offline setup, use --prompt, but remember it asks about locale, keymap, time zone, hostname, root password and root shell, in that order.

Done means

  • The version and target root were checked before writing anything.
  • 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 a lingering temp file.
  • The target is backed up before any image change or destructive option.
  • The prepared root is ready to boot or hand off to the image-building workflow.