How to Increase the Size of DigitalOcean Block Storage Volumes

If you need more storage space than your current volume provides, you can attach additional volumes to the same Droplet or you can expand the size of your current volume.

Increasing the size of a volume involves two steps:

  1. Resizing the volume itself to make it larger.
  2. Expanding the filesystem (and partitions, if any) on the volume to use the new space.

Decreasing the size of a volume is not possible due to the high risk of data loss or corruption. Data written to a volume is not guaranteed to be written sequentially at the start of the device, so when reducing the available space, the integrity of the filesystem and the files within can be damaged.

If you no longer require the present capacity of your volume, the safest way to decrease your volume size is to transfer the contents to a smaller volume. After attaching both volumes to a Droplet, tools like rsync can be used to transfer the files safely between the two volumes. Once you have verified that the transfer of the content to the new volume was successful, the larger volume can be destroyed.

Resize the Volume in the Control Panel

From the Volume’s More menu, choose Resize Volume.

Block Storage resize volume menu option

In the modal that opens, select a new size for the volume. You can choose any size ranging from 1 GB larger than the volume’s current size to the maximum size for volumes (16 TB / 16,000 GB). Then, click Resize Volume.

Block Storage resize volume interface

In order to use the additional space, you need to expand any partitions and filesystem structures on the volume.

Determine if the Volume is Partitioned

The process of adjusting your filesystem will depend on whether your volume has been partitioned or not. If your volume has a filesystem written directly to it, without any partition table, you can expand the filesystem directly. If your volume is partitioned, the final partition itself must first be expanded before expanding the filesystem.

You can test if your filesystem is written directly to the volume with the following command, substituting in the name of your volume (like volume-nyc1-01):

sudo lsblk --fs /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01

Some older versions of lsblk do not have a dedicated --fs option. In that case, you can manually specify the output with -o NAME,FSTYPE,LABEL,UUID,MOUNTPOINT.

The output looks like this:

NAME FSTYPE LABEL UUID                                 MOUNTPOINT
sda  ext4         18efad39-6b7c-44d3-ba21-b0778911c4ed /mnt/volume-nyc1-01

The filesystem type in the FSTYPE column will list ext4 if the filesystem is written directly, and will list a variant like sda1 which indicates a partition.

Resizing an Unpartitioned Volume

The command you use to resize will depend on the filesystem you have: Ext4 or XFS.

If the filesystem on the volume is Ext4, pass the volume identifier (like volume-nyc1-01) to the resize2fs command:

sudo resize2fs /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01
resize2fs 1.42.13 (17-May-2015)
Filesystem at /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01 is mounted on /mnt/volume-nyc1-01; on-line resizing required
old_desc_blocks = 25, new_desc_blocks = 32
The filesystem on /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01 is now 131072000 (4k) blocks long.

If the filesystem on the volume is XFS, pass the mount point where the partition is attached to the xfs_growfs tool:

sudo xfs_growfs /mnt/your_mount_point
meta-data=/dev/sda               isize=512    agcount=4, agsize=32768000 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=131072000, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=64000, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 131072000 to 157286400

Either way, you can verify that the larger filesystem is available with df:

df -h -x tmpfs -x devtmpfs
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  1.1G   18G   6% /
/dev/sda        197G   60M  187G   1% /mnt/volume-nyc1-01

Resizing a Partitioned Volume

Resizing a partitioned volume involves the following steps:

  1. Identifying the partitions and mount points and unmount all partitions.
  2. Rewriting the partition table.
  3. Expanding the filesystem.

Identify and Unmount Partitions

First, identify the partitions and mount points on the volume, substituting in the name of your volume.

sudo lsblk /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk 
└sda1   8:1    0  100G  0 part /mnt/volume-nyc1-01-part1

The output shows /dev/sd* names for the volume and its partitions, the partitioning scheme, and the mount points. You can also see that the size of the disk is currently greater than the size of the partitions written to it. This confirms that the volume resize in the Control Panel was successful.

Because we will be rewriting some of the partition information on the volume, we should make sure that all of the volume’s partitions are unmounted.

First, you may need to find and terminate any processes currently accessing the mounted filesystem:

sudo lsof +f -- /mnt/mount_point

Stop the listed processes, then unmount the filesystem:

sudo umount /mnt/mount_point

Repeat this for all of the mounted partitions on the volume.

Rewrite the Partition Table

We recommend gdisk to rewrite partition tables. It supports backups of the existing table, explicitly moves GPT recovery data to the end of the disk, and works with partitions of any size. Tools like growpart are straightforward, but the versions shipped with most distributions can only resize partitions up to 2 TB.

Rewriting the partition table involves four steps:

  1. Backing up the current table.
  2. Moving the backup GPT data structures.
  3. Removing and recreating the partition.
  4. Writing the new partition table to the volume.

At any time during this process, you can type ? to display the help menu of available commands.

Back Up the Current Partition Table

Change to a writable directory (so that we can successfully write the partition table backup file) and start gdisk with the volume identifier, substituting in your volume:

cd ~
sudo gdisk /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01

Use the b command to back up the current partition, and enter the backup filename when prompted:

b
Enter backup filename to save: partition_table.bak

Move the Backup GPT Data Structures

Next, we can move the backup GPT data structures to the end of the volume, which changed when we expanded the resource. Switch to the “experts” menu:

x

Your prompt will change to reflect the new sub-menu.

Then move the GPT table backup structures to the end of the disk:

e
Relocating backup data structures to the end of the disk

Then go back to the main menu:

m

The prompt should change back, indicating that you are no longer in the “experts” menu.

Removing and Recreating the Final Partition

In order to use the new space on the volume, we will expand the last partition into the free area. This actually involves gathering data about the current partition, removing it, and then recreating it to occupy the additional space.

Start by displaying the current partition table:

p
Disk /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01: 419430400 sectors, 200.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 016F1E0A-83C5-4CF2-A78B-150F689CC45A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 419430366
Partitions will be aligned on 2048-sector boundaries
Total free space is 209719229 sectors (100.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048       209713151   100.0 GiB   8300  primary

Note the Number, Start (sector), Code, and Name values of the last partition. In the example above, only a single partition is present. We will be removing this partition and creating a new partition with all of the same properties except for its ending location (and consequently, it’s size).

Use the d command to remove the partition. If you only have a single partition, it will be removed. If you have multiple partitions, you will be prompted to enter the partition number. Select the last partition:

d
Using 1

Start creating the new partition:

n

You will be asked a series of questions about the new partition you wish to create. Use the values from the partition that you just deleted to help you answer these questions.

It is likely that the correct values will be suggested, in which case you can simply press ENTER to accept the default values. For the prompt about the Last sector, accept the default to expand the partition to the end of the disk:

Partition number (1-128, default 1): 
First sector (34-419430366, default = 2048) or {+-}size{KMGTP}: 
Last sector (2048-419430366, default = 419430366) or {+-}size{KMGTP}: 
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

The partition creation process does not prompt for an internal GPT partition name. If this is important to you, you can set the name to its previous value using the c command. Again, you will be prompted for the partition to operate on if you have more than one available:

c
Using 1
Enter name: primary

Writing the New Partition Table to the Volume

When you are finished, verify the new partition table you’ve created. As we stated before, all of the information in the table at the bottom of the output should match the previous table, with the exceptions of the End (sector) and Size columns:

p
Disk /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01: 419430400 sectors, 200.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 016F1E0A-83C5-4CF2-A78B-150F689CC45A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 419430366
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048       419430366   200.0 GiB   8300  primary

After verifying the information, write the partition data to the volume and exit the tool with the w command. You will be prompted to confirm the procedure. Type Y if you are ready:

w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01.
The operation has completed successfully.

This should expand the final partition to consume the rest of the available space on the volume.

Expand the Filesystem

Next, we need to expand the filesystem on the final partition to use the extra available space.

Finding the Partition Identifier and the Filesystem Type

The procedure used to grow the final partition’s filesystem depends on the filesystem type. Find the filesystems of your volume’s partitions, substituting in your volume identifier.

sudo lsblk --fs /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01

Some older versions of lsblk do not have a dedicated --fs option. In that case, you can manually specify the output with -o NAME,FSTYPE,LABEL,UUID,MOUNTPOINT.

The output looks like this:

NAME FSTYPE LABEL UUID                                 MOUNTPOINT
sda  ext4         18efad39-6b7c-44d3-ba21-b0778911c4ed /mnt/volume-nyc1-01

Find the filesystem type of the last partition on your volume by looking at the FSTYPE column.

You can map the /dev/sd* name for the partition back to it’s /dev/disk/by-id identifier by checking the current linking in the /dev/disk/by-id directory:

file /dev/disk/by-id/*
/dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01:       symbolic link to ../../sda
/dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1: symbolic link to ../../sda1

Expanding Ext4 Filesystems on a Partitioned Volume

The Ext4 resize tool requires you to check the partition for inconsistencies that may have happened during the repartitioning procedure before you can expand it. The e2fsck command can safely check unmounted filesystems.

Pass the last partition on the volume to the e2fsck program and use the -f option to force the check:

sudo e2fsck -f /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1
e2fsck 1.42.13 (17-May-2015)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1: 13/6553600 files (0.0% non-contiguous), 459351/26213888 blocks

After checking the filesystem, you can expand it to fill the partition by passing it to resize2fs:

sudo resize2fs /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1
resize2fs 1.42.13 (17-May-2015)
Resizing the filesystem on /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1 to 52428539 (4k) blocks.
The filesystem on /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1 is now 52428539 (4k) blocks long.

The filesystem should now be expanded. You can now mount it and verify the procedure:

mount -a
df -h -x tmpfs -x devtmpfs
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  1.1G   18G   6% /
/dev/sda1       197G   60M  187G   1% /mnt/volume-nyc1-01-part1

Expanding XFS Filesystems on a Partitioned Volume

Although not strictly required, it is a good idea to use the xfs_repair utility to check the filesystem for inconsistencies introduced by repartitioning. Pass in the last partition on the volume:

sudo xfs_repair /dev/disk/by-id/scsi-0DO_Volume_volume-nyc1-01-part1
Phase 1 - find and verify superblock...
Phase 2 - using internal log
        - zero log...
        - scan filesystem freespace and inode maps...
        - found root inode chunk
Phase 3 - for each AG...
        - scan and clear agi unlinked lists...
        - process known inodes and perform inode discovery...
        - agno = 0
        - agno = 1
        - agno = 2
        - agno = 3
        - process newly discovered inodes...
Phase 4 - check for duplicate blocks...
        - setting up duplicate extent list...
        - check for inodes claiming duplicate blocks...
        - agno = 0
        - agno = 1
        - agno = 2
        - agno = 3
Phase 5 - rebuild AG headers and trees...
        - reset superblock...
Phase 6 - check inode connectivity...
        - resetting contents of realtime bitmap and summary inodes
        - traversing filesystem ...
        - traversal finished ...
        - moving disconnected inodes to lost+found ...
Phase 7 - verify and correct link counts...
done

Once the disk has been checked, mount the filesystem. XFS filesystems must be mounted before they can be expanded:

sudo mount -a

Now, the xfs_growfs command can be used to expand the filesystem. The xfs_growfs command takes the mount point as an argument:

sudo xfs_growfs /mnt/volume-nyc1-01-part1
meta-data=/dev/sda1              isize=512    agcount=4, agsize=6553472 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=26213888, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=12799, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 26213888 to 52428539

When you are finished, you can check that the new space is available with the df command:

df -h -x tmpfs -x devtmpfs
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  1.1G   18G   6% /
/dev/sdb1       200G   33M  200G   1% /mnt/volume-nyc1-01-part1