Increasing Disk Space of a Linux-based Vagrant Box on Provisioning

This post shows you how to increase disk space of a Linux-based Vagrant box automatically on provisioning.

Why would you need additional disk space in a Vagrant box?

The following challenges possibly brought you here:

  • Software installation: Your Vagrant base box of choice does not provide large enough disks by default for some sophisticated software you need to install inside the box.
  • Swap space: The jobs you want to run in the box require a large amount of swap space (such as loading, transforming and analyzing large amounts of data).
  • Testing: You want to play around with Linux file systems and you need a lab environment in which you can break stuff and quickly restore the starting point.

Requirements

The next steps assume that you have a working Vagrant environment running on you system. Writing this article I used the following setup:

  • Vagrant (I am using version 2.2.2 at the moment)
  • Oracle VirtualBox 5.2.x (as of the date writing this article, Vagrant does not yet support VirtualBox 6.x)
  • Vagrant Plugin vagrant-disksize (find more details below)
  • Vagrant Base Box bento/ubuntu-18.04 (The explanations are essentially working for any other distribution, but one of the scripts provided below assumes that the root file system is managed by LVM.)


My VirtualBox and Vagrant installations are running on a Windows 10 device, but the instructions should also work if you are using another host system for the Vagrant-built VMs.

Preparing the Vagrant environment

Simon Protheroe created a Vagrant plugin that allows you to easily resize a disk with one line in your Vagrantfile. Plugins cannot be automatically installed by Vagrant if it recognizes, that a plugin used in the Vagrantfile is actually missing. Therefore, you have to install before being able to use it:

$ vagrant plugin install vagrant-disksize

A successful installation of the plugin will result in the following output:

Installing the 'vagrant-disksize' plugin. This can take a few minutes...
Fetching: vagrant-disksize-0.1.3.gem (100%)
Installed the plugin 'vagrant-disksize (0.1.3)'!

This plugin has a few limitations, which are documented by the developer of the plugin:

  • It can only change the size of the first and primary disk of the VirtualBox VM.
  • It is only possible to increase the size, but not to shrink the disk. If the requested new disk size is lower than the existing size, then disk will not be touched and a warning message will be displayed during the building process of the box.
  • The plugin does not take care of resizing the filesystem(s) on the disk. This is a task we will solve later on with a provisioning script.

However, for building a Vagrant box for development and testing purposes, this works fine.

Vagrantfile

The following Vagrantfile shows an example of how to tell the vagrant-disksize plugin to resize the first disk of the resulting VirtualBox VM:

# Fail if the vagrant-disksize plugin is not installed
unless Vagrant.has_plugin?("vagrant-disksize")
  raise 'vagrant-disksize is not installed!'
end

Vagrant.configure("2") do |config|
  config.vm.provider "virtualbox" do |vb|
    vb.name = "DISKEXTEND"
	vb.memory = 2048
	vb.cpus = 2 
  end
    config.vm.define :"DISKEXTEND" do |t|
  end
  config.vm.hostname = "DISKEXTEND"
  config.vm.box = "bento/ubuntu-18.04"
  # Increase the default disk size of the bento image (64GB) to 96GB
  config.disksize.size = "96GB"
  # Run a script on provisioning the box to format the file system
  config.vm.provision "shell", path: "disk-extend.sh"
end

So, what will happen, when we build a box with this Vagrantfile?

The base box “bento/ubuntu-18.04” by default has a primary disk with a size of 64GB. We want to increase this by 32GB to 96GB. On “vagrant up” this will be confirmed by the output:

==> DISKEXTEND: Resized disk: old 65536 MB, req 98304 MB, new 98304 MB
==> DISKEXTEND: You may need to resize the filesystem from within the guest.

After booting of the box has completed, we want to immediately run a script that increases the existing filesystem (still 64GB) and use all additional disk space that we’ve just added.

Provisioning Script: disk-extend.sh

What is the script doing?

After the disk size has been changed and the box has been booted, this script kicks in and takes care of increasing the existing root file system’s size to 100% of the available disk space of the underlying disk:

#!/bin/bash

echo "> Installing required tools for file system management"
if  [ -n "$(command -v yum)" ]; then
    echo ">> Detected yum-based Linux"
    sudo yum makecache
    sudo yum install -y util-linux
    sudo yum install -y lvm2
    sudo yum install -y e2fsprogs
fi

if [ -n "$(command -v apt-get)" ]; then
    echo ">> Detected apt-based Linux"
    sudo apt-get update -y
    sudo apt-get install -y fdisk
    sudo apt-get install -y lvm2
    sudo apt-get install -y e2fsprogs
fi

ROOT_DISK_DEVICE="/dev/sda"
ROOT_DISK_DEVICE_PART="/dev/sda1"
LV_PATH=`sudo lvdisplay -c | sed -n 1p | awk -F ":" '{print $1;}'`
FS_PATH=`df / | sed -n 2p | awk '{print $1;}'`

ROOT_FS_SIZE=`df -h / | sed -n 2p | awk '{print $2;}'`
echo "The root file system (/) has a size of $ROOT_FS_SIZE"

echo "> Increasing disk size of $ROOT_DISK_DEVICE to available maximum"
sudo fdisk $ROOT_DISK_DEVICE <<EOF
d 
n
p
1
2048

no
w
EOF
sudo pvresize $ROOT_DISK_DEVICE_PART
sudo lvextend -l +100%FREE $LV_PATH
sudo resize2fs -p $FS_PATH

ROOT_FS_SIZE=`df -h / | sed -n 2p | awk '{print $2;}'`
echo "The root file system (/) has a size of $ROOT_FS_SIZE"

exit 0

How is the partitioning working?

Most Vagrant boxes by default are partitioned using LVM, which is why this script also expects LVM file systems. The script also tries to install the required tools on apt-based (Ubuntu, Debian) and yum-based (RedHat, CentOS) Linux systems.

How are we interacting with fdisk?

fdisk is a command line tool that’s meant to be used interactively, and not with a one-line command. It gives you a list of choices and let’s you make a selection with a short code confirmed with ENTER (a linefeed) to navigate you through its procedures. The good things is: To emulate interaction with the fdisk command line, we can use so-called “Here Documents“. That is what you see from line 29 to 38. The blank line on (line number 35) is crucial, as it’s not really empty, but contains a linefeed and is similar to confirming the default selection of the interactive fdisk command line.

Output

Using the “vagrant up” command with the Vagrantfile and script shown in this post, the Vagrant box will be built and our script will be automatically executed to finish our changes to the disk size:

$ vagrant up

Here is an example of the last part of Vagrant’s output:

[...]
DISKEXTEND: The root file system (/) has a size of 62G
DISKEXTEND: > Increasing disk size of /dev/sda to available maximum
DISKEXTEND:
DISKEXTEND: Welcome to fdisk (util-linux 2.31.1).
DISKEXTEND: Changes will remain in memory only, until you decide to write them.
DISKEXTEND: Be careful before using the write command.
DISKEXTEND:
DISKEXTEND:
DISKEXTEND: Command (m for help):
DISKEXTEND: Selected partition 1
DISKEXTEND: Partition 1 has been deleted.
DISKEXTEND:
DISKEXTEND: Command (m for help): Partition type
DISKEXTEND:    p   primary (0 primary, 0 extended, 4 free)
DISKEXTEND:    e   extended (container for logical partitions)
DISKEXTEND: Select (default p): Partition number (1-4, default 1): First sector (2048-201326591, default 2048): Last sector, +sectors or +size{K,M,G,T,P} (2048-201326591, default 201326591):
DISKEXTEND:
DISKEXTEND: Created a new partition 1 of type 'Linux' and of size 96 GiB.
DISKEXTEND:
DISKEXTEND: Command (m for help):
DISKEXTEND: Partition #1 contains a LVM2_member signature.
DISKEXTEND:
DISKEXTEND: All space for primary partitions is in use.
DISKEXTEND:
DISKEXTEND: Command (m for help):
DISKEXTEND: The partition table has been altered.
DISKEXTEND: Syncing disks.
DISKEXTEND:   Physical volume "/dev/sda1" changed
DISKEXTEND:   1 physical volume(s) resized / 0 physical volume(s) not resized
DISKEXTEND:   Size of logical volume vagrant-vg/root changed from <63.04 GiB (16138 extents) to <95.04 GiB (24330 extents).
DISKEXTEND:   Logical volume vagrant-vg/root successfully resized.
DISKEXTEND: resize2fs 1.44.1 (24-Mar-2018)
DISKEXTEND: Filesystem at /dev/mapper/vagrant--vg-root is mounted on /; on-line resizing required
DISKEXTEND: old_desc_blocks = 8, new_desc_blocks = 12
DISKEXTEND: The filesystem on /dev/mapper/vagrant--vg-root is now 24913920 (4k) blocks long.
DISKEXTEND: The root file system (/) has a size of 94G

Conclusion

This post showed you a quick and easy way to automatically increase the disk size in your Vagrant box. I am sure that there is room for optimization of the provisioning script, as this script make some assumptions on how the Linux system of the Vagrant box is configured. Also, we don’t have possibilities to add and resize multiple disks on provisioning. But from my point of view it’s still sufficient for the daily work with Vagrant for development and testing purposes.

If you have any comments or ideas, let me know in the below comments.


4 Comments

Mike 2021-12-02 Reply

This is the Vagrantfile that ended up working for me with a Chef test-kitchen:

“`
$script = < Installing required tools for file system management”
sudo apt-get update -y
sudo apt-get install -y fdisk
sudo apt-get install -y lvm2
sudo apt-get install -y e2fsprogs

ROOT_DISK_DEVICE=”/dev/sda”
ROOT_DISK_DEVICE_PART=”/dev/sda5″
LV_PATH=`sudo lvdisplay -c | sed -n 1p | awk -F “:” ‘{print $1;}’`
FS_PATH=`df / | sed -n 2p | awk ‘{print $1;}’`
ROOT_FS_SIZE=`df -h / | sed -n 2p | awk ‘{print $2;}’`
echo “The root file system (/) has a size of $ROOT_FS_SIZE”
echo “> Increasing disk size of $ROOT_DISK_DEVICE to available maximum”
sudo parted /dev/sda resizepart 2 100%
sudo parted /dev/sda resizepart 5 100%
sudo pvresize $ROOT_DISK_DEVICE_PART
sudo lvextend -l +100%FREE $LV_PATH
sudo resize2fs -p $FS_PATH
ROOT_FS_SIZE=`df -h / | sed -n 2p | awk ‘{print $2;}’`
echo “The root file system (/) has a size of $ROOT_FS_SIZE”
exit 0
SCRIPT

# Fail if the vagrant-disksize plugin is not installed
unless Vagrant.has_plugin?(“vagrant-disksize”)
raise ‘vagrant-disksize is not installed!’
end

Vagrant.configure(“2”) do |config|
config.disksize.size = “150GB”
config.vm.provision “shell”, inline: $script
end
“`

and this little modification to kitchen.yml within the `driver` stanza under `name: vagrant`:
“`
vagrantfiles:
– Vagrantfile
provision: True
“`

Marc 2021-12-04 Reply

Thank you, Mike! I also realized that whem current base images (like ubuntu/jammy64) the vagrant-disksize plugin seems to expand the disks automatically, without the provisioning script. But I’m not sure if this is only related to the base images or maybe also to the version of Vagrant and/or the vagrant-disksize plugin.

Wenyu Shi 2023-06-21 Reply

Hello Marc, thank you very much for the post. Sorry about my newbie question: Where did you save your disk-extend.sh file and how did you kick it off to run? Thanks, Wenyu

Marc 2023-06-22 Reply

Hey Wenyu! This is indeed a good question as I am not mentionining in the article where this shell script should reside. For all base boxes I worked with during provisioning, Vagrant was executing scripts from the same directory as in which the “Vagrantfile” sits. So for the example in the article, you can simply drop it right next to the Vagrangfile. –Marc

Leave a Reply to Mike Cancel reply

CAPTCHA


The following GDPR rules must be read and accepted:
This form collects your name, email and content so that I can keep track of the comments placed on the website. Your current IP address will also be collected in order to prevent spam comments from automated bots. For more info check the privacy policy where you can educate yourself on where, how and why your data is stored.