BTRFS + snapshots on Arch Linux / CachyOS: step by step guide
Full tutorial for BTRFS configuration with @ and @home subvolumes, Timeshift and Snapper snapshots, zstd compression. For Arch Linux, CachyOS and Manjaro. Working commands.
BTRFS + snapshots on Arch Linux / CachyOS
BTRFS gives you something ext4 does not: system rollback. You installed something that broke Xorg? Go back to 10 minutes ago. Kernel panic after update? Reboot into the previous snapshot. Database corrupted? Restore a file from before the crash.
This guide is my configuration I have used for 3 years on 4 machines (work laptop, home server, test station, VPS).
Installing the system on BTRFS (CachyOS / Arch)
I use a partition layout that gives me full control:
# Partition layout (UEFI + LUKS optional)
# /dev/sda1 - 512MB - EFI partition (FAT32)
# /dev/sda2 - rest - LUKS encrypted BTRFS
# After installing CachyOS / Arch: create subvolumes
mount /dev/sda2 /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@snapshots
btrfs subvolume create /mnt/@var_log
btrfs subvolume create /mnt/@var_cache
umount /mnt
Why 5 subvolumes, not one? Snapshots copy data. If you have one
@ subvolume with /var inside, the snapshot also copies logs and
cache. Performance drops, size grows. Separate subvolumes = snapshot
only what you want.
Mounting with zstd compression and noatime
Add to /etc/fstab:
# /etc/fstab
UUID=xxxx-xxxx / btrfs subvol=@,compress=zstd:3,noatime,ssd,discard=async 0 1
UUID=xxxx-xxxx /home btrfs subvol=@home,compress=zstd:3,noatime,ssd,discard=async 0 2
UUID=xxxx-xxxx /snapshots btrfs subvol=@snapshots,compress=zstd:3,noatime,ssd,discard=async 0 2
UUID=xxxx-xxxx /var/log btrfs subvol=@var_log,compress=zstd:3,noatime,ssd,discard=async 0 2
UUID=xxxx-xxxx /var/cache btrfs subvol=@var_cache,compress=zstd:3,noatime,ssd,discard=async 0 2
UUID=xxxx-xxxx /boot/efi vfat umask=0077 0 2
Three options that make a difference:
compress=zstd:3— transparent compression. Gain: 10-30% space for free, CPU overhead negligible. Level 3 is the sweet spot (level 1 is faster but compresses less, 9+ gives 2% more for 3x CPU).noatime— do not write the last access time of a file. Gain: fewer writes, longer SSD life. Without this option the kernel updates atime on everyread().discard=async— TRIM for SSD in the background, does not block I/O. Alternative: cron withfstrim -A.
Timeshift: desktop snapshots
Timeshift is a GUI + CLI tool that takes snapshots of the whole
system (except /home) and restores with one click. Ideal for
laptop/desktop.
Installation and configuration
# CachyOS / Arch
sudo pacman -S timeshift
# Initialize (auto-detects BTRFS)
sudo timeshift --snapshot-device /dev/sda2
# Settings:
# - type: BTRFS (not RSYNC — on BTRFS that wastes space)
# - location: subvolume @snapshots
# - schedule: Daily (7 days) + Weekly (4 weeks) + Monthly (3 months)
# - exclude: nothing (Timeshift+BTRFS copies only changes)
First snapshot and restore
# Manual snapshot before a major change
sudo timeshift --create --comments "Before kernel 6.10 update"
# List snapshots
sudo timeshift --list
# Restore from the running system (reboot required)
sudo timeshift --restore
# Restore from GRUB (when the system does not boot)
# Reboot → GRUB → "Arch Linux snapshots" → pick a snapshot
That last point is the key. GRUB integrates with BTRFS — at boot
it shows a list of snapshots you can boot from. Kernel panic after
pacman -Syu? Reboot, pick yesterday's snapshot, fix, return to the
current one.
Snapper: per-transaction snapshots (pre/post pacman)
Snapper is a low-level tool that automatically creates snapshots
before and after every pacman operation. Plus a timeline (hourly,
daily). It needs more configuration than Timeshift, but gives you
precise control.
Configuration for / and /home
sudo pacman -S snapper snap-pac
# Create config for subvolume @
sudo snapper -c root create-config /
# Create config for subvolume @home
sudo snapper -c home create-config /home
# Edit timeline cleanup so you do not bloat
sudo nano /etc/snapper/configs/root
# Change:
# TIMELINE_LIMIT_HOURLY="10"
# TIMELINE_LIMIT_DAILY="7"
# TIMELINE_LIMIT_WEEKLY="4"
# TIMELINE_LIMIT_MONTHLY="3"
# TIMELINE_LIMIT_YEARLY="0"
# Enable systemd timers
sudo systemctl enable --now snapper-timeline.timer
sudo systemctl enable --now snapper-cleanup.timer
snap-pac integrates snapper with pacman. From now on every
pacman -S creates a "pre" and "post" snapshot automatically. If an
update breaks the system:
# List snapshots
sudo snapper list
# Diff between two snapshots
sudo snapper status 42..43
# Restore a single file
sudo snapper undochange 42..43 --filename /etc/fstab
# Restore everything
sudo snapper undochange 42..43
Disabling COW for databases and VMs
BTRFS uses Copy-on-Write — every file modification creates a new block. For databases (PostgreSQL, MySQL, SQLite) this is a performance disaster: instead of one write you get 10. Fix:
# For new files in a directory
chattr +C /var/lib/postgresql/data
chattr +C /var/lib/mysql
chattr +C /var/lib/libvirt/images
# For existing files: you must defragment
btrfs filesystem defragment -czstd /var/lib/postgresql/data
After chattr +C new files do not use COW. Database performance
returns to ext4 levels. Snapshots still work (they copy the whole
subvolume, not individual COW blocks).
Off-site backup: btrfs send/receive
BTRFS has a built-in incremental backup mechanism — btrfs send
and btrfs receive. You send only the delta, not the whole snapshot.
# On the backup server: create subvolume to receive
btrfs subvolume create /backup/laptop/@
# On the laptop: send the first snapshot
sudo btrfs send /.snapshots/1/snapshot | ssh backup@server "btrfs receive /backup/laptop/@"
# Subsequent snapshots: only delta
sudo btrfs send -p /.snapshots/1/snapshot /.snapshots/5/snapshot | \
ssh backup@server "btrfs receive /backup/laptop/@"
This is 10-100x faster than rsync on large snapshots, because
you send only changed blocks. Backing up a 200GB snapshot with 2GB of
changes = 2GB transfer, not 200GB.
Monitoring: how much space do snapshots take
# How much space snapshots take
sudo btrfs filesystem du -s /.snapshots/*/snapshot
# Overall disk usage
btrfs filesystem usage /
# How much space you would free by deleting snapshots
sudo snapper list --columns number,description,used-space
Rule: at least 20-30% free space. BTRFS needs free blocks for COW allocation. When you fill the disk 95%+, the system starts failing in non-obvious ways (allocation fails, snapshots stop working, performance drops).
What is next
If you want me to configure BTRFS with snapshots on your existing server (without reinstalling) — get in touch.
Najczęściej zadawane pytania
Is BTRFS stable in 2025?
Timeshift vs Snapper — which to choose?
Does BTRFS need defragmentation?
How much space do snapshots take?
Related posts
- devops
Cloudflare for WordPress: full performance and security optimization
How to configure Cloudflare (Free/Pro) for WordPress step by step: cache, APO, WAF, Bot Fight Mode, page rules, CDN. Real measurement results and configuration for Poland.
8 min - devops
Own mail server: Postfix + Dovecot + SPF/DKIM/DMARC on Debian 12
Full tutorial to set up your own mail server on Debian 12 with Postfix, Dovecot, OpenDKIM, SPF and DMARC. Step-by-step configuration, troubleshooting, real pitfalls.
6 min