Automating Disk Partitioning: A 6-Month Production Review of systemd-repart

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

The Bottleneck of Static Disk Images

Six months ago, my team hit a wall. We were deploying a fleet of 120 edge devices and various cloud instances using a single, 2.1GB Linux image. While the image was slim, our hardware was a mixed bag. Some units ran on 32GB SD cards, while others packed 1TB NVMe drives. Every time we deployed, we had to manually resize the root partition or maintain fragile shell scripts to trigger growpart and resize2fs on the first boot.

If you have ever managed more than five servers, you know this frustration. You download a generic Ubuntu cloud image, spin it up, and realize the OS only sees 8GB of the 100GB volume you paid for. Cloud-init can handle this, but it often feels like overkill for minimal environments. If you’re building a custom embedded system, you likely want a smaller footprint than a full cloud-init suite provides.

Why Standard Resizing Fails at Scale

The friction stems from the fact that traditional GPT or MBR partition tables are static. When you create a disk image, the partition table is written to the first few sectors of the file. It has no idea how large the physical disk will eventually be. When you flash that 2GB image onto a 64GB disk, the table remains locked at 2GB. The remaining 62GB stays as “unallocated space” until something intervenes.

Manual fixes typically involve:

  • Using fdisk to delete and recreate the partition (a heart-pounding task in production).
  • Running resize2fs or xfs_growfs to expand the actual filesystem.
  • Risking data corruption if a power failure occurs mid-resize.

After managing dozens of Linux nodes over the last few years, I’ve learned that manual steps are just opportunities for human error. I spent weeks searching for a robust, declarative way to handle disk layouts. That search led me to systemd-repart.

Comparing the Contenders: growpart vs. systemd-repart

Before making the switch, I evaluated the standard tools. Most admins use growpart, which is essentially a shell script wrapper around sfdisk. It is an imperative tool. You tell it exactly what to do at a specific moment. If the script hits an edge case and fails halfway through, you are often left with a broken partition table.

systemd-repart takes a different path. It is declarative. You define what the disk should look like using simple configuration files. During early boot, systemd-repart examines the physical disk and compares it to your config. It then makes the necessary changes to reach that state. Because it is idempotent, you can run it repeatedly without fear of breaking anything.

Feature growpart / Manual systemd-repart
Configuration Script-based (Imperative) Conf files (Declarative)
Safety Medium (Script logic varies) High (Atomic GPT updates)
Encryption Manual LUKS resizing needed Native LUKS support
Complexity Requires multiple binaries Built into systemd

Implementing systemd-repart: The Declarative Approach

Instead of running a complex command, you place .conf files in /usr/lib/repart.d/ or /etc/repart.d/. Note that this tool specifically targets GPT partition tables. It does not support the legacy MBR (DOS) format.

1. Growing the Root Partition

The most common task is expanding the root partition to fill the disk. If your root partition is the second entry on the disk, you would create a file named 50-root.conf:

# /etc/repart.d/50-root.conf
[Partition]
Type=root
# Minimum size required
SizeMinBytes=512M
# Leave empty to use all available space
GrowFileSystem=yes

When the service runs, it identifies the partition by its GPT Type GUID. It then expands the partition and the underlying filesystem simultaneously, provided the kernel supports it.

2. Adding a Dedicated Data Partition

One feature I’ve come to rely on is the weight-based system. Suppose you want a dedicated /var/log partition that scales based on the drive size. You don’t have to do the math yourself.

# /etc/repart.d/60-data.conf
[Partition]
Type=linux-generic
Label=Data
# Take up 50% of the remaining free space
Weight=500
Format=ext4
MountPoint=/data

If you have two partitions with Weight=500, systemd-repart splits the remaining space 50/50. This is a lifesaver when deploying the same image to a 32GB SD card and a 1TB NVMe drive.

3. Testing the Configuration

Never commit changes to a live production disk without testing. I always use the --dry-run flag first. It shows a detailed map of the proposed changes without writing a single byte.

systemd-repart --dry-run --pretty

The output gives you a visual representation of the current versus the proposed layout. Once verified, you can apply it manually with --apply=yes. In most production setups, the systemd-repart.service handles this automatically during the initramfs stage.

Lessons from 6 Months in Production

Half a year in, I’ve noticed a few nuances that the man pages don’t highlight.

The GPT Backup Header: When you resize a virtual disk in AWS or Proxmox, the GPT backup header is no longer at the physical end of the disk. systemd-repart fixes this automatically. However, it requires write access to the block device, which might be restricted in some hardened container environments.

Filesystem Support: The GrowFileSystem=yes toggle works flawlessly with Ext4, XFS, and Btrfs. If you use more niche filesystems, systemd-repart will grow the partition, but you might need systemd-growfs to handle the internal resize.

Alpha-Numeric Ordering: Files in repart.d/ are processed alphabetically. If 10-root.conf and 20-data.conf both want to grow, the order determines their physical placement. Stick to a strict numbering convention to avoid layout surprises.

Is It Right for You?

If you manage a single laptop, this is likely overkill. But for anyone building disk images, managing cloud fleets, or shipping IoT devices, it is a significant upgrade. It replaced our 200-line shell scripts with three simple config files.

The deep integration with the systemd ecosystem—specifically LUKS and systemd-growfs—makes your infrastructure predictable. In my experience, predictability is your best friend when a server fails at 3:00 AM. If you are still using fdisk hacks in your boot scripts, give systemd-repart a try. Just remember to run that --dry-run first.

Share: