systemd-repart can grow, add or reset a GPT partition table, including with --empty=force, which can erase everything on the target. This guide builds a disposable disk image, describes a partition in repart.d, and lets you watch the tool plan and then apply the change, all without touching a real disk.
These commands target systemd 255.4 on Ubuntu, as installed on the machine used for this guide. Allow about 15 minutes. You need the systemd-repart package, a shell, and enough space for a temporary 512 MiB image. The first commands do not need elevated privileges. Applying changes to a real block device normally does.
systemd-repart --version
workdir=$(mktemp -d)
umask 077
printf 'Workspace: %s\n' "$workdir"
On the reference system, the version command reports systemd 255 (255.4-1ubuntu8.17). Keep the printed workspace path. The image and definition file will be removed when you finish, and anything already in the path must be treated as disposable.
systemd-repart reads files named *.conf from definition directories. For a normal installed system, the search order includes /usr/lib/repart.d, /etc/repart.d and /run/repart.d. The --definitions= option lets this test use a directory that cannot affect the host.
mkdir "$workdir/definitions"
cat > "$workdir/definitions/60-home.conf" <<'EOF'
[Partition]
Type=home
Label=test-home
SizeMinBytes=64M
SizeMaxBytes=64M
EOF
The filename matters when several definitions use the same partition type: files are sorted by name, then matched to existing partitions of that type. Type=home is a recognised GPT partition type identifier. The label is assigned when the partition is new or currently has no label.
SizeMinBytes and SizeMaxBytes make this example predictable. A definition can instead leave room for growth. Existing partitions are not shrunk, moved or deleted during ordinary incremental operation.
By default, systemd-repart uses dry-run mode. --empty=create tells it to create a regular file when the target does not exist, and --size=512M gives that file its initial size.
image="$workdir/test-disk.raw"
systemd-repart \
--definitions="$workdir/definitions" \
--empty=create \
--size=512M \
--dry-run=yes \
--pretty=no \
"$image"
Expected output is a report showing a new partition with type home, label test-home and a size of 64 MiB, followed by a successful exit. Exact formatting varies with the output mode. Check the result explicitly:
test -f "$image" && echo "dry-run completed: $image exists"
echo "exit status was $?"
Do not confuse a created image file with an applied partition table. The default dry run does not touch the device's partition table. Use --dry-run=yes explicitly in scripts so that the safety boundary remains visible.
Only proceed when the target is the disposable file under $workdir. The next command writes the image's partition table. It does not modify a host disk, but it is still a state-changing operation.
systemd-repart \
--definitions="$workdir/definitions" \
--empty=allow \
--dry-run=no \
--pretty=no \
"$image"
The command should exit with status zero. Verify the image without attaching it to the host:
file "$image"
ls -lh "$image"
systemd-repart \
--definitions="$workdir/definitions" \
--dry-run=yes \
--pretty=no \
"$image"
The second systemd-repart call should report no further partition-table change is needed. The command operates on a regular file as if it were a loopback block device. The image is now a test artefact, not a mounted filesystem.
Partitioning and filesystem creation are separate concerns. A definition with only Type=, labels and sizes creates or grows the partition table, but does not create or resize a filesystem inside an existing partition. Add Format=ext4, for example, only when you deliberately want a newly created partition formatted. CopyFiles= can populate a newly formatted filesystem, but it does not add files to an existing partition.
The GrowFileSystem= partition flag is also easy to misread. It marks a partition for filesystem growth by tools that honour the flag; it is not the same as running a filesystem resize command immediately. For an already mounted root or home filesystem, plan the filesystem operation separately and verify that the filesystem supports it.
For a real block device, replace the image path only after checking it several ways:
lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS
findmnt
readlink -f /dev/REPLACE_WITH_A_VERIFIED_DEVICE
Stop if the path is mounted, points at the wrong device, or is supplied by an untrusted variable. --empty=force creates a fresh partition table and can erase all existing partitions. Never use it on a device containing data you need. --factory-reset=yes can remove partitions whose definitions set FactoryReset=yes; it is a reset mechanism, not a routine resize option.
The systemd service uses the same definitions during boot-time repartitioning. Put a deliberate, tested definition in /etc/repart.d when local administration should override vendor files. Use /usr/lib/repart.d for package-provided definitions and /run/repart.d for runtime-generated ones. Test with an explicit --definitions= directory first, then review the service's target device and boot ordering before enabling any wider change.
A dry run leaves the partition table unchanged. For the disposable example, undo is simply removing the temporary workspace after checking its path:
case "$workdir" in
/tmp/tmp.*) rm -rf -- "$workdir" ;;
*) echo "Refusing to remove unexpected path: $workdir" >&2; exit 1 ;;
esac
For a real partition-table change, there is no general undo command. Restore from a verified image or backup, or use the platform's documented recovery process. A partition definition does not make destructive changes reversible.
systemd-repart --version identified the installed systemd release.--dry-run=no was used.