systemd-repart: Declarative Partition Layouts for Linux Images
Model GPT image layouts with repart.d, allocate flexible partition sizes, and separate partition growth from filesystem growth.
A Linux image that boots on one fixed-size disk may leave awkward gaps or fail when provisioned onto a larger device. systemd-repart lets an image define partition types, labels, formats, and size constraints in repart.d files. When its boot-time service is integrated into the image, it can add missing partitions or grow existing ones as space becomes available. In normal incremental operation, existing partitions are not shrunk, moved, or deleted. The separate factory-reset mode can delete partitions explicitly marked for reset, so treat that as a distinct, destructive workflow rather than ordinary layout convergence.
This guide uses upstream systemd v262 documentation as its baseline. Distribution packages can lag or carry patches, so check systemd-repart --version and the local manual before relying on an option or partition type.
Treat definitions as a desired layout, not a disk recipe
A repart.d/*.conf file describes a GPT partition by type and desired properties. systemd-repart matches definitions to existing partitions by type UUID, using the definition filenames in sorted order when several partitions share a type. Unmatched definitions may create new partitions; existing partitions without matching definitions are left alone. That makes definition filenames and duplicate partition types part of the matching behavior, not cosmetic labels.
Two size settings control allocation. SizeMinBytes= and SizeMaxBytes= provide lower and upper constraints. Weight= distributes space left after minimums according to relative weights. Equal minimum and maximum values pin a new partition to one size. An existing partition is never shrunk, however, so a maximum value is not a mechanism for reducing an oversized partition.
For example, these definitions describe a fixed EFI System Partition and an elastic root partition:
# repart.d/00-esp.conf
[Partition]
Type=esp
Label=EFI
Format=vfat
SizeMinBytes=512M
SizeMaxBytes=512M
Weight=0
# repart.d/10-root.conf
[Partition]
Type=root
Label=root
Format=ext4
SizeMinBytes=3G
SizeMaxBytes=16G
Weight=1000
The Format= setting formats a partition only when it is newly created. It does not reformat an existing matching partition. Formatting requires the corresponding filesystem tools in the build environment. In this example, the resulting partitions are empty filesystems: the configuration does not populate a Linux root tree, install a bootloader, or make an image bootable.
Calculate and review before writing an image
First ask systemd-repart for the minimum image size implied by the definitions. Using - as the device argument requests a size calculation without operating on a block device or image file:
systemd-repart --definitions=./repart.d -
This is a useful constraint check, not a full deployment test. Review the definitions for architecture-specific root types, filesystem tool availability, labels, partition order, size limits, and any files copied into new filesystems. If your real layout includes existing partitions, test against a disposable copy of that image with the default dry-run enabled:
systemd-repart --definitions=./repart.d --dry-run=yes ./build/base-copy.raw
The command reports the planned changes without updating that image’s partition table. Keep the copy disposable anyway, and verify the path before running any non-dry-run operation.
To generate a new scratch image, use a new regular-file path and opt in to the write. The existence check prevents accidentally reusing a previous artifact:
mkdir -p ./build
output=./build/repart-lab.raw
if test -e "$output"; then
printf 'Choose a new output path; %s already exists\n' "$output" >&2
exit 1
fi
systemd-repart \
--definitions=./repart.d \
--empty=create \
--size=4G \
--dry-run=no \
"$output"
--empty=create creates a regular file for a new image, and --size=4G sets its initial size. Do not replace the output path with a live block device or a valuable image. The command writes a GPT and formats newly created partitions. Keep generated artifacts in a build directory, record the systemd version and definitions, and hash the finished image if it will be promoted elsewhere.
Keep partition growth separate from filesystem growth
Growing a partition changes its boundary in the partition table. It does not automatically mean that every filesystem inside it has been enlarged. The repart.d manual explicitly notes this distinction. Filesystem growth requires a separate mechanism or a discoverable-partition flag that a compatible tool honors.
GrowFileSystem= sets the Discoverable Partitions Specification flag for supported partition types. It affects automatic mounting paths implemented by systemd-aware tools; it does not change explicit mounts by itself. On an existing system, verify which tool will perform the filesystem operation, when it runs, whether it supports that filesystem, and whether the root partition is writable. For a filesystem or image type outside that supported path, schedule and test its own grow procedure separately.
After building the lab image, inspect the whole GPT with a partition-table tool such as sfdisk --dump, then rerun systemd-repart in dry-run mode against the result. A second plan should show no unexpected additions or growth. Validate filesystem contents and boot behavior separately: a clean partition table is not evidence that the image has the expected root files, initramfs, kernel, or boot entries.
Production rollout checklist
Keep immutable source inputs alongside the output: the sorted repart.d definitions, base image digest, architecture, systemd version, and target size. Test the smallest supported image, the expected first-boot size, and a larger disk. Include existing-partition cases, duplicate partition-type cases if the design uses them, insufficient-space failures, and a release with the oldest supported systemd.
For first-boot repartitioning, preserve a recovery path and confirm whether the target is an image file or the intended physical device before enabling writes. Partition growth can change what the OS discovers at boot, and an incorrect type or size constraint can leave the machine with an unusable layout. Start on disposable images, then stage on a recoverable canary before touching fleet disks.
Related:
- systemd-sysext and confext: Reversible Runtime Extensions for Immutable Linux
- Packer Machine Image Pipelines: Build, Test, and Promote Immutable Images
Sources: