Hetzner recently introduced Block Volumes for their cloud product. It's a very useful feature that allows to add tons of fast and redounded storage to VMs.

I wanted to move my Nextcloud over Hetzner Cloud for quite some time now, but was unable to do so because of the available storage. Now I can!

Since my Nextcloud contains sensitive and personal data, I don't really want to my files to be written on a public Ceph storage cluster... Fortunately, I can encrypt my volume very easily thanks to cryptsetup. In this tutorial, I will show you how.

I use Debian 9 but this will also work for Ubuntu and any other distro with the good packages installed.

Create the volume

On the Hetzner Cloud console, choose the manual mount option.

You should see your volume from the server:

root@server:~# fdisk -l
Disk /dev/sda: 19.1 GiB, 20480786432 bytes, 40001536 sectors
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: 0x44c5162c

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1  *     2048 40001502 39999455 19.1G 83 Linux


Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

It is /dev/sdb here.

Install cryptsetup

It is no harder than:

apt install busybox cryptsetup

It will automatically install and load a module to your kernel.

Setup the encrypted container on the volume

Create an encrypted LUKS container on your volume:

root@server:~# cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --key-size 512 /dev/sdb

WARNING!
========
This will overwrite data on /dev/sdb irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:

Open it:

root@server:~# cryptsetup open /dev/sdb cryptvol
Enter passphrase for /dev/sdb:

You should be able to see it:

root@server:~# fdisk -l
Disk /dev/sda: 19.1 GiB, 20480786432 bytes, 40001536 sectors
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: 0x44c5162c

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1  *     2048 40001502 39999455 19.1G 83 Linux


Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/mapper/cryptvol: 10 GiB, 10735321088 bytes, 20967424 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Create the filesystem and mount the volume

Now we can create a filesystem in the container:

root@server:~# mkfs.ext4 /dev/mapper/cryptvol
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 2620928 4k blocks and 655360 inodes
Filesystem UUID: 0be6182d-a34c-462a-ad2a-cf49390dc6c3
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

And mount it:

root@server:~# mount -o discard,defaults /dev/mapper/cryptvol /mnt
root@server:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
udev                  968M     0  968M   0% /dev
tmpfs                 196M  2.9M  193M   2% /run
/dev/sda1              19G  1.2G   17G   7% /
tmpfs                 979M     0  979M   0% /dev/shm
tmpfs                 5.0M     0  5.0M   0% /run/lock
tmpfs                 979M     0  979M   0% /sys/fs/cgroup
tmpfs                 196M     0  196M   0% /run/user/0
/dev/mapper/cryptvol  9.8G   37M  9.3G   1% /mnt

That's it! ☺️

The only downside of using an encrypted volume is that when rebooting the server, it is needed to login and manually open and mount the encrypted container on the volume (the volume is still attached automatically to the server).

Resize the volume

Over time, it is possible that you will need more space. Let see how to handle that.

Fisrt, you will need to add space via the Hetzner Cloud Console. Once it's done, you will see the volume has an increased size on your server:

root@server:~# fdisk -l
Disk /dev/sda: 19.1 GiB, 20480786432 bytes, 40001536 sectors
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: 0x44c5162c

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1  *     2048 40001502 39999455 19.1G 83 Linux


Disk /dev/sdb: 15 GiB, 16106127360 bytes, 31457280 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/mapper/cryptvol: 10 GiB, 10735321088 bytes, 20967424 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Your encrypted volume has not updated its size yet, but you just need to reopen it:

root@server:~# umount /mnt
root@server:~# cryptsetup luksClose cryptvol
root@server:~# cryptsetup open /dev/sdb cryptvol
Enter passphrase for /dev/sdb:
root@server:~# fdisk -l
Disk /dev/sda: 19.1 GiB, 20480786432 bytes, 40001536 sectors
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: 0x44c5162c

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1  *     2048 40001502 39999455 19.1G 83 Linux


Disk /dev/sdb: 15 GiB, 16106127360 bytes, 31457280 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/mapper/cryptvol: 15 GiB, 16104030208 bytes, 31453184 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Finally, we need to resize the filesystem. You can do it while the container is mounted, but since it's not yet, let's do it offline:

root@server:~# resize2fs /dev/mapper/cryptvol
resize2fs 1.43.4 (31-Jan-2017)
Resizing the filesystem on /dev/mapper/cryptvol to 3931648 (4k) blocks.
The filesystem on /dev/mapper/cryptvol is now 3931648 (4k) blocks long.

root@server:~# mount -o discard,defaults /dev/mapper/cryptvol /mnt
root@server:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
udev                  968M     0  968M   0% /dev
tmpfs                 196M  2.9M  193M   2% /run
/dev/sda1              19G  1.2G   17G   7% /
tmpfs                 979M     0  979M   0% /dev/shm
tmpfs                 5.0M     0  5.0M   0% /run/lock
tmpfs                 979M     0  979M   0% /sys/fs/cgroup
tmpfs                 196M     0  196M   0% /run/user/0
/dev/mapper/cryptvol   15G   41M   14G   1% /mnt

Enjoy ✌️