How to Use Btrfs Subvolumes, Snapshots, and Send/receive for Incremental Backups on Ubuntu Server
Learning how to use Btrfs subvolumes, snapshots, and send/receive for incremental backups on Ubuntu Server is one of the smartest moves you can make for your server’s data protection strategy. Btrfs (B-tree filesystem) brings built-in snapshot capabilities that traditional filesystems simply can’t match. Instead of copying gigabytes of data every night, you can send only what changed since your last backup. This tutorial walks you through setting up a Btrfs filesystem, creating subvolumes, taking snapshots, and using the btrfs send and btrfs receive commands to build a reliable incremental backup workflow. By the end, you’ll have a working backup system that saves both time and disk space.
Prerequisites and Requirements for Btrfs Incremental Backups
Before you start working with Btrfs subvolumes and snapshots, make sure you have the following in place.
Required access and software:
- Ubuntu Server 20.04 or 22.04 (fresh install recommended)
- Root or sudo access to the server
- At least two block devices or partitions (one for the primary filesystem, one for backups)
- The
btrfs-progspackage installed
Assumed knowledge: You should be comfortable with basic Linux commands, disk partitioning, and mounting filesystems. You don’t need prior Btrfs experience.
Estimated time: 30–45 minutes for initial setup.
Install the required tools before moving on:
sudo apt update
sudo apt install btrfs-progs -y
You’ll also want a second disk or partition available. In this tutorial, /dev/sdb is the primary Btrfs disk and /dev/sdc is the backup destination. Adjust these to match your own setup. For more details on Btrfs features, check the official Btrfs documentation.
How to Set Up Btrfs Subvolumes and Snapshots on Ubuntu Server
For a related walkthrough, see: How to Enable and Configure PHP Opcache for WordPress to Reduce Server Response Time
This section covers formatting your disk, creating subvolumes, and taking your first snapshot.
Step 1: Format your disk with Btrfs
Run the following command to format /dev/sdb as a Btrfs filesystem:
sudo mkfs.btrfs /dev/sdb
This wipes any existing data on the disk. Double-check the device name before running it.
Step 2: Mount the Btrfs filesystem
Create a mount point and mount the disk:
sudo mkdir -p /mnt/btrfs-main
sudo mount /dev/sdb /mnt/btrfs-main
Step 3: Create a subvolume
Subvolumes are like independent directory trees inside a Btrfs filesystem. Create one for your web data:
sudo btrfs subvolume create /mnt/btrfs-main/webdata
You can create as many subvolumes as you need. Common choices include separate subvolumes for /var/www, databases, and configuration files.
Step 4: Add some data to the subvolume
Copy your website files or any test data into the subvolume:
sudo cp -r /var/www/html /mnt/btrfs-main/webdata/
Step 5: Take a read-only snapshot
Snapshots must be read-only before you can use btrfs send. Create your first snapshot like this:
sudo btrfs subvolume snapshot -r /mnt/btrfs-main/webdata /mnt/btrfs-main/webdata-snap-1
The -r flag makes it read-only. Name your snapshots with dates in production. For example: webdata-snap-2024-06-01. This makes it easy to identify restore points later.
Step 6: Prepare the backup destination
Format and mount your backup disk:
sudo mkfs.btrfs /dev/sdc
sudo mkdir -p /mnt/btrfs-backup
sudo mount /dev/sdc /mnt/btrfs-backup
Step 7: Send the initial full backup
Use btrfs send to stream the snapshot to the backup disk:
sudo btrfs send /mnt/btrfs-main/webdata-snap-1 | sudo btrfs receive /mnt/btrfs-backup/
This sends a full copy the first time. Subsequent sends will be incremental. The pipe streams the snapshot data directly into the receive command. No intermediate file is needed.
Step 8: Create an incremental backup
Make changes to your data, then take a second snapshot:
sudo btrfs subvolume snapshot -r /mnt/btrfs-main/webdata /mnt/btrfs-main/webdata-snap-2
Now send only the changes between snapshot 1 and snapshot 2 using the -p (parent) flag:
sudo btrfs send -p /mnt/btrfs-main/webdata-snap-1 /mnt/btrfs-main/webdata-snap-2 | sudo btrfs receive /mnt/btrfs-backup/
Btrfs calculates the difference between the two snapshots and sends only the changed blocks. This is the core of how to use Btrfs subvolumes, snapshots, and send/receive for incremental backups on Ubuntu Server. It’s far more efficient than rsync-based full copies.
Step 9: Automate with a cron job
Create a simple backup script at /usr/local/bin/btrfs-backup.sh:
#!/bin/bash
DATE=$(date +%Y-%m-%d)
PREV_SNAP=$(ls /mnt/btrfs-main/webdata-snap- | tail -n 1)
NEW_SNAP="/mnt/btrfs-main/webdata-snap-$DATE"
btrfs subvolume snapshot -r /mnt/btrfs-main/webdata "$NEW_SNAP"
btrfs send -p "$PREV_SNAP" "$NEW_SNAP" | btrfs receive /mnt/btrfs-backup/
Make it executable and schedule it:
sudo chmod +x /usr/local/bin/btrfs-backup.sh
sudo crontab -e
Add this line to run the backup daily at 2 AM:
0 2 /usr/local/bin/btrfs-backup.sh
For more on scheduling tasks in Linux, see the Ubuntu community cron documentation.
Troubleshooting Common Btrfs Snapshot and Send/Receive Errors
Even a clean setup can hit snags. Here are the most common issues and how to fix them.
Error: “not a Btrfs filesystem”
This means the target disk isn’t formatted as Btrfs. Run sudo blkid /dev/sdb to confirm the filesystem type. Reformat if needed.
Error: “snapshot is not read-only”
You must use the -r flag when creating snapshots for send/receive. Writable snapshots won’t work with btrfs send. Delete the snapshot and recreate it with -r.
Error: “parent subvolume not found”
The parent snapshot referenced with -p must exist on both the source and destination. If you deleted it from either side, the incremental send will fail. Keep at least the last two snapshots on both disks.
Snapshots growing too large
Old snapshots accumulate and eat disk space. Delete them with:
sudo btrfs subvolume delete /mnt/btrfs-main/webdata-snap-2024-05-01
Build snapshot rotation into your backup script to keep only the last 7 days.
Warning: Never send to a non-Btrfs destination. The btrfs receive command only works on Btrfs filesystems. Trying to receive onto ext4 or XFS will fail immediately.
Conclusion
You now know how to use Btrfs subvolumes, snapshots, and send/receive for incremental backups on Ubuntu Server. You’ve formatted disks, created subvolumes, taken read-only snapshots, and sent both full and incremental backups to a separate disk. You’ve also automated the process with a cron job and learned how to handle the most common errors.
This approach gives you fast, space-efficient backups without third-party tools. Your next step could be sending backups over SSH to a remote server using btrfs send | ssh user@remote sudo btrfs receive /path/. You might also look into tools like btrbk
