[HOWTO] Resizing root partition on x86 (March 2023 edition)

This HOWTO is intended for users who have some experience in general computing and system administration but are relatively new to OpenWrt. It is loosely based on the relevant sections of the official OpenWrt on x86 Hardware page:

https://openwrt.org/docs/guide-user/installation/openwrt_x86

Changes from the previous edition

  • The Diagnostics section added (a big thank-you to @efahl for the suggestion!)
  • The Resize the Root File System section: command listings have been updated to match the current guidance on the wiki

The Root Cause

The origins of OpenWrt lie far outside of the x86 ecosystem. As a result, it is distributed in a way that is not common in the x86 ecosystem. There is no installation media and no installer; rather, one must copy the installation image to the target system's hard drive or SSD. Because of this, a new installation of OpenWrt 22.x.x. typically has a boot drive with approximately 120 MB of total space, regardless of the actual capacity of the drive. There are two ways to reclaim the remaining capacity. One is to resize the root partition of the OpenWrt installation, and this is what this HOWTO is about. The other is to create one or more additional partitions, but we will not cover it here (it's a general Linux topic for which multiple tutorials are available).

The Complication

There are four mainstream images one can use to implement an OpenWrt system on x86 hardware. They form a sort of 2x2 matrix:

  • generic-ext4-combined-efi.img.gz is an image that produces a UEFI system with an ext4 file system on the root partition
  • generic-ext4-combined.img.gz is an image that produces a BIOS system with an ext4 file system on the root partition
  • generic-squashfs-combined-efi.img.gz is an image that produces a UEFI system with a SquashFS file system on the root partition
  • generic-squashfs-combined.img.gz is an image that produces a BIOS system with a SquashFS file system on the root partition

Both the nature of the firmware (BIOS vs. UEFI) and the type of file system on the root partition (ext4 vs. SquashFS) have implications for partition resizing. So the first step in resizing your root partition is to know what kind of system you have or, said another way, which image was used to install the system.

Resizing the root partition on a BIOS system is simpler. Only two steps are required:

  • Resize the root partition (done the same way for ext4 and SquashFS), and
  • Resize the root file system (done differently depending on whether the file system is ext4 or SquashFS)

On a UEFI system, there is an additional step required. UEFI, unlike BIOS, keeps track of partition identifiers. At boot, UEFI will allow the system to load only from a partition it recognizes. When we resize the root partition, its ID will change, so we'll have to communicate those changes to the UEFI. This is done by editing the grub configuration file located at /boot/grub/grub.cfg. In order to know what changes to make to this file, it helps to see how partition configuration has changed. In other words, it is a good idea to have a record of both partition configurations, old and new. So in case of a UEFI system, we end up with a four-step process:

  • Capture the initial partition configuration (done the same way for ext4 and SquashFS),
  • Resize the root partition (done the same way for ext4 and SquashFS),
  • Update /boot/grub/grub.cfg (done the same way for ext4 and SquashFS), and
  • Resize the root file system (done differently depending on whether the file system is ext4 or SquashFS)

A note on safety
Technically, both resizing operations (resizing a partition and resizing a file system), if done on "live" drives, carry a risk of file system corruption. So in a perfect world, we should be doing this with the relevant drive unmounted (this can be achieved by booting the device from a USB stick). In practice, however, this works in an overwhelming majority of cases, especially when the device is essentially idle.

With this in mind, let's get some supplies.

Preparations

You will need a few utilities, which you probably don't have installed. So let's get them:

opkg update && opkg install lsblk fdisk losetup resize2fs

These should take us through the process.

Diagnostics

So far so good, but what if I don't know which image was used to install OpenWrt? Say, someone else did the installation or I simply forgot? Here are two simple tests.

First, let's figure out the ext4 vs. SquashFS question:

df -Th

This command will output a list of filesystems with types indicated. Look for a filesystem named /dev/root. Its type will be either ext4 or squashfs.

How about BIOS vs. UEFI, then? Also not very hard:

ls /sys/firmware/efi

On a UEFI system, a directory named /sys/firmware/efi must exist. So if the command above gives you a normal-looking directory listing, your system is UEFI; if you get an error message that says No such file or directory, your system is BIOS.

Capture the Current Partition Configuration

If you have a BIOS system, skip this section and go straight to Resize the Root Partition. On a UEFI system, run:

lsblk -o PATH,SIZE,PARTUUID

This will tell you the current partition layout, including each partition's unique identifier. Save this for future reference. If you're working over SSH, I would suggest saving it on the administrator's computer. Copy it from the terminal and save it as a text file. If you have a monitor and keyboard connected to your device, save it into a text file on the device. For example:

lsblk -o PATH,SIZE,PARTUUID > /root/lsblk_old.txt

Just in case, you may want to copy this file to a USB stick.

Next, you may want to take a look at the grub configuration file:

cat /boot/grub/grub.cfg

The goal is to see where partitions' unique identifiers are used and, therefore, where you will need to replace them when the time comes. Take a look at this example:

root@OpenWrt:~# lsblk -o PATH,SIZE,PARTUUID
PATH        SIZE PARTUUID
/dev/sda    120M
/dev/sda1    16M c959470f-01
/dev/sda2   104M c959470f-02

root@OpenWrt:~# cat /boot/grub/grub.cfg
serial --unit=0 --speed=38400 --word=8 --parity=no --stop=1 --rtscts=off
terminal_input console serial; terminal_output console serial

set default="0"
set timeout="5"
set root='(hd0,msdos1)'

menuentry "OpenWrt" {
        linux /boot/vmlinuz root=PARTUUID=c959470f-02 rootwait console=tty0 console=ttyS0,38400n8 noinitrd
}
menuentry "OpenWrt (failsafe)" {
        linux /boot/vmlinuz failsafe=true root=PARTUUID=c959470f-02 rootwait console=tty0 console=ttyS0,38400n8 noinitrd
}
root@OpenWrt:~#

It's easy to see that partition /dev/sda2 has a unique identifier c959470f-02, and that identifier is used in grub configuration in two places to designate a root partition, first for the normal boot, then for the failsafe mode. So now you have a mind map of what you will be doing a little later.

Resize the Root Partition

This is done nearly identically in all cases by running an interactive fdisk session. The listing below shows a mix of fdisk output and manual inputs. To distinguish the manual inputs, I have enclosed them [[in double square brackets]]; the [[]] sequence indicates pressing Enter with no visible input. Obviously, when you enter commands or data, you won't need any square brackets; I'm just using them as markers. It's a bit confusing, but I can't come up with a better formatting scheme right now. So here goes:

root@OpenWrt:~# [[fdisk /dev/sda]] 

Welcome to fdisk (util-linux 2.37.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): [[p]]

Disk /dev/sda: 59.63 GiB, 64023257088 bytes, 125045424 sectors
Disk model: ADATA_IM2S3134N-
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc120d9f5

Device     Boot Start       End   Sectors  Size Id Type
/dev/sda1  *      512     33279     32768   16M 83 Linux
/dev/sda2       33792    246783    212992  104M 83 Linux

Command (m for help): [[d]]
Partition number (1,2, default 2): [[2]]

Partition 2 has been deleted.

Command (m for help): [[n]]
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): [[p]]
Partition number (2-4, default 2): [[2]]
First sector (33280-31277231, default 34816): [[33792]]
Last sector, +/-sectors or +/-size{K,M,G,T,P} 
    (33792-125045423, default 125045423): [[]]

Created a new partition 2 of type 'Linux' and of size 59.6 GiB.
Partition #2 contains a squashfs signature.

Do you want to remove the signature? [Y]es/[N]o: [[n]]

Command (m for help): [[w]]

The partition table has been altered.
Syncing disks.

root@OpenWrt:~# 

A few important notes:

  1. This has worked despite the "bad idea" warning.
  2. Technically, we didn't "extend" the partition; rather, we deleted one, then created a new one starting at the same location and gobbling up all available disk space. However, since there was no write command in-between, the net result was a new, larger partition that "inherited" all data located on the old small partition.
  3. The number 33792 specified in response to the First sector prompt came from the disk information table produced in response to the p command.
  4. Depending on what kind of system you have, you may or may not be asked whether you want a primary or extended partition. Otherwise, the process should be identical.

To verify that the partition has been resized, you can run fdisk -l or start another interactive session (fdisk /dev/sda) and issue a p command to show the partition layout followed by a q command to quit.

Update grub Configuration

If you have a BIOS system, skip this section and go straight to Resize the Root File System. On a UEFI system, run:

lsblk -o PATH,SIZE,PARTUUID

Compare the output to its earlier version that you saved. You will see that the unique identifier for the /dev/sda2 partition has changed. Use your new identifier to replace the old one in grub configuration. For example, if you use vi, you can do:

vi /boot/grub/grub.cfg

From your earlier review of grub configuration, you would know how many instances of partition ID require replacement. Make the changes, save the file, and exit the text editor.

Resize the Root File System

This is the final step, and it is done differently depending on whether you have an ext4 file system or a SquashFS file system. You should take care to execute the commands given below one by one (meaning, don't paste all of them into the command line at once; allow one command to finish before entering the next one).

Watch the output of the resize2fs command. Normally, you would see some indication of file system size change. If, on the other hand, resize2fs indicated it has nothing to do, reboot your device and repeat this step in its entirety. Rebooting will ensure that the changes made during the previous steps are applied to the system.

On an ext4 System

BOOT="$(sed -n -e "\|\s/boot\s.*$|{s///p;q}" /etc/mtab)"
PART="${BOOT##*[^0-9]}"
DISK="${BOOT%${PART}}"
ROOT="${DISK}$((PART+1))"
LOOP="$(losetup -f)"
losetup ${LOOP} ${ROOT}
resize2fs -f ${LOOP}
reboot

On a SquashFS System

BOOT="$(sed -n -e "\|\s/boot\s.*$|{s///p;q}" /etc/mtab)"
PART="${BOOT##*[^0-9]}"
DISK="${BOOT%${PART}}"
ROOT="${DISK}$((PART+1))"
LOOP="$(losetup -n -l | sed -n -e "\|\s.*\s${ROOT#/dev}\s.*$|{s///p;q}")"
resize2fs -f ${LOOP}
reboot

Concluding Notes

If all of the above worked, congratulations! You have successfully resized the root partition on your OpenWrt device. You may want to reboot your device to ensure that everything starts up correctly.

Early in this guide, we discussed the two options for reclaiming disk space, extending the root partition and creating additional partitions. Those are not mutually exclusive; it is entirely possible to use them together (extending the root partition part-way and setting up new partition or partitions in the still-free disk space). Read up on fdisk and its use in partition setup; this will allow you to create all kinds of configurations.

26 Likes

Very well written. This howto shouldn't be necessary, but that's another discussion.

You should consider maintaining it on the OpenWrt Wiki site.

4 Likes

Usually when I mentioned it in other threads to the OP, responses are in the categories of:

  • the Wiki doesn't suit OP's writing style
  • people can just find it here

:person_shrugging:

I tend to think the other way around: my writing style doesn't suit the wiki. :smile: The wiki is a great source for users with some experience; it's occasionally terse, but that's not a problem given the audience. I, on the other hand, tend to write for someone new. Also, I tend to disagree with some of the wiki's mantras, specifically 2 (Avoid duplicating information within this wiki) and 3 (Avoid duplicating upstream documentation). In my opinion (and it's only an opinion), they sometimes clash with mantra 1 (Articles must be easy to read), which (again, in my opinion) is the most important mantra.

Perhaps more importantly, since you and I last had this conversation, I actually applied for a wiki account, tried to contribute to the wiki, and quickly found the wiki authoring process to be somewhat on the clunky side. Here on the forum, the author's workflow is such that I actually enjoy writing. On the wiki, it's just not. I guess it's the author's UI showing its age...

2 Likes

Really?

Yep, case in point.

Perhaps the OP can provide more detals on the lack of ease.

I recently migrated Building OpenWrt on OpenWrt from here to the wiki. The reason why I suggested it for this post is that the post here looks eminently suitable for wiki:

  • Already divided into sections
    The sections here look like they could be further hierarchical which can be done there and not here
  • Step by step
  • Is more of a static article than a discussion point

You can gain all the benefits of forum exposure by simply posting here when the article is updated, with links.

If you don't want to yourself, would you give permission for me to transcribe it there? The wiki could really benefit from quality articles like this.

5 Likes

Yes, of course!!! No attribution necessary. This is for everyone to use. If you think you can make it better, take it and rework it as you see fit.

2 Likes

Also, the forum has something that the wiki lacks by design: reader feedback. For example, the opening post in this thread has a Diagnostics section that came to be entirely due to a suggestion made by @efahl, for which I am very grateful.

Again, this is not to diminish the importance of the wiki. The wiki and the forum are highly complementary. Each has its uses.

1 Like

My biggest issue with wikis is their horrible editing facilities. The wiki devs put all sorts of effort into the presentation of the final pages, but seemingly forget that someone has to type all that garbage. I've been using dokuwiki (same as what OpenWrt uses?) for a couple years, and my modus operandi is to ssh to the server, cd to the wiki's data directory and vi dhcp-notes.txt directly, so I can use a real editor and do greps, seds, awks and so on to my heart's content.

It was about 18 years ago (wow time flies) I set up our company website (all hand-edited html at the time) using iirc Filezilla. It had a cool feature where you could ftp-connect to the site, surf to the directory of interest, click "edit" (which was configured to your editor of choice) and it would download the file, launch the editor on the copy, then auto-upload any changes you made. I would love to see that sort of thing on a modern wiki so even if I can't do grep -r something or sed s/some/stuff/ on a bunch of files, at least I could use a real editor.

1 Like

Will there ever be a time that openwrt comes with an installer for x86, in the same way that pfsense or opnsense has one? I am aware of openwrt's origin, still an installer would make life so much easier.

1 Like

Probably not. Too much code that is platform-specific and useless in production...

This said, it's entirely possible to have a standalone installer developed independently from OpenWrt. A kind of Rufus on a USB stick, if you will.

1 Like

I installed OpenWrt on my N5105 from a USB stick using Ventoy. I got it to boot the OpenWrt img using their instructions (https://www.ventoy.net/en/doc_openwrt.html), then somehow (4 months ago and I didn't document it properly) mounted the proper partition on the source USB and simply did

$ mount something something /usb
$ dd if=/usb/openwrt.img of=nvme0n1
$ reboot
# Pull the USB stick out while it reboots...

Seems like it could be a starting point for a simple installer.

That sounds like something very usefull and could safe a lot of users a lot of time. As you said, a kind of bootable imager that copy and resizes the image to a systems hdd/sdd.

"Wiki worthy" or not, @NC1 writes like a seasoned tech writer. Great work and thank you!

What about downloading and creating a bootable gparted system Gparted home Live then boot it and run gparted? It should find your partition which, since it is not mounted, can be extended or shrunk. And it's graphical instead of command line.

As always, backup your disk first (ala Clonezilla).

I strongly suggest you download Ventoy and create a bootable USB with it. Then you can copy multiple ISOs as files to the jump drive - anything from Win11 to Clonezilla Live. You boot the Ventoy, select the ISO and it loads and boots. Easy as all those ISOs are in one place and can be removed and replace by newer versions at will.

It should work if you have an ext4 image. Not sure about SquashFS; I could never figure out how to manage SquashFS overlays with gparted. Truth be told though, I haven't tried very hard... :smile:

Could you elaborate more on the last section? What do those command do exactly, on what environment should I perform those commands? I'm using squashfs file system, where should I execute those commands? External boot environment or directly under the same openwrt OS? I performed this using finnix USB stick, not working for me, it's an old laptop with SATA 2.5 drive.

I managed to expand the sda2 partition, I can't thank you enough for such a thorough guide.
image

Sorry to start at the end, but it appears that you already figured out that this procedure as described should be performed on the working system itself. Great job!

Now for the big question:

Hmm... Where do I start to avoid starting at the Big Bang? :smile:

Background. In Linux, storage devices can be block or loop (if you remember the old DOS, there was a similar dichotomy there, "physical drives" and "logical drives"). Block devices are actual physical devices (hard drives, SSDs, eMMC modules, USB sticks, etc.). A loop device is definable on the system. You can set one up to match a physical device, or to refer to a file system stored in a file (or some other unit of storage) on an existing device. The latter is called overlay.

Base reality. OpenWrt installs on a block device (in your case, sda). That block device includes a boot partition and a root partition; the latter also holds a user-writable overlay (the root partition proper, at least in a SquashFS image, is read-only; this is good for security, disaster recovery, resets, etc.). So the task of properly resizing the root partition includes the resizing of the overlay. The first few commands (those starting with words written IN CAPS) collect information about how all of this is set up and store it in environment variables. After enough information is collected (and formatted in a way that the worker utilities can understand), the losetup utility defines the overlay as a loop device residing on the root partition; then, the resize2fs utility does the actual resizing of that loop device.

Disclaimer. For the sake of brevity, I filtered out a lot of technical details, so my explanation came out a bit hand-wavy. If anyone knows a better (succinct, yet sufficiently technical) way of explaining it, please post it here.

3 Likes

thanks again for explaining, I have successfully resized the filesystem too, I did it while openwrt is running, it works without third party boot media