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 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 subvolumesmount /dev/sda2 /mntbtrfs subvolume create /mnt/@btrfs subvolume create /mnt/@homebtrfs subvolume create /mnt/@snapshotsbtrfs subvolume create /mnt/@var_logbtrfs subvolume create /mnt/@var_cache
umount /mntWhy 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:
UUID=xxxx-xxxx / btrfs subvol=@,compress=zstd:3,noatime,ssd,discard=async 0 1UUID=xxxx-xxxx /home btrfs subvol=@home,compress=zstd:3,noatime,ssd,discard=async 0 2UUID=xxxx-xxxx /snapshots btrfs subvol=@snapshots,compress=zstd:3,noatime,ssd,discard=async 0 2UUID=xxxx-xxxx /var/log btrfs subvol=@var_log,compress=zstd:3,noatime,ssd,discard=async 0 2UUID=xxxx-xxxx /var/cache btrfs subvol=@var_cache,compress=zstd:3,noatime,ssd,discard=async 0 2UUID=xxxx-xxxx /boot/efi vfat umask=0077 0 2Three 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 / Archsudo 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 changesudo timeshift --create --comments "Before kernel 6.10 update"
# List snapshotssudo 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 snapshotThat 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 @homesudo snapper -c home create-config /home
# Edit timeline cleanup so you do not bloatsudo 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 timerssudo systemctl enable --now snapper-timeline.timersudo systemctl enable --now snapper-cleanup.timersnap-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 snapshotssudo snapper list
# Diff between two snapshotssudo snapper status 42..43
# Restore a single filesudo snapper undochange 42..43 --filename /etc/fstab
# Restore everythingsudo snapper undochange 42..43Disabling 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 directorychattr +C /var/lib/postgresql/datachattr +C /var/lib/mysqlchattr +C /var/lib/libvirt/images
# For existing files: you must defragmentbtrfs filesystem defragment -czstd /var/lib/postgresql/dataAfter 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 receivebtrfs subvolume create /backup/laptop/@
# On the laptop: send the first snapshotsudo btrfs send /.snapshots/1/snapshot | ssh backup@server "btrfs receive /backup/laptop/@"
# Subsequent snapshots: only deltasudo 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 takesudo btrfs filesystem du -s /.snapshots/*/snapshot
# Overall disk usagebtrfs filesystem usage /
# How much space you would free by deleting snapshotssudo snapper list --columns number,description,used-spaceRule: 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.
Frequently asked questions
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