sudo lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
zram0 252:0 0 8G 0 disk [SWAP]
nvme1n1 259:0 0 953.9G 0 disk
├─nvme1n1p1 259:1 0 190M 0 part /boot/efi
├─nvme1n1p3 259:3 0 1G 0 part /boot
└─nvme1n1p7 259:7 0 932.6G 0 part
└─luks-13f88890-0b52-4080-a3b6-b406d616c659 253:0 0 932.6G 0 crypt /home
nvme2n1 259:8 0 931.5G 0 disk
nvme0n1 259:10 0 476.9G 0 disk
└─nvme0n1p1 259:11 0 476.9G 0 partDuplicate the /boot and /boot/efi partition structure of disk one. sudo parted /dev/nvme2n1
Use Disks to create the btrfs with LUKS
sudo lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
zram0 252:0 0 8G 0 disk [SWAP]
nvme1n1 259:0 0 953.9G 0 disk
├─nvme1n1p1 259:1 0 190M 0 part /boot/efi
├─nvme1n1p2 259:3 0 1G 0 part /boot
└─nvme1n1p3 259:7 0 932.6G 0 part
└─luks-13f88890-0b52-4080-a3b6-b406d616c659 253:0 0 932.6G 0 crypt /var/lib/docker/btrfs
nvme2n1 259:8 0 931.5G 0 disk
├─nvme2n1p1 259:1 0 190M 0 part
├─nvme2n1p2 259:3 0 1G 0 part
└─nvme2n1p3 259:9 0 931.5G 0 part
└─luks-429c570c-2743-4cc3-beaa-dfc8facb118c 253:1 0 931.5G 0 crypt
nvme0n1 259:10 0 476.9G 0 disk
└─nvme0n1p1 259:11 0 476.9G 0 partsudo btrfs device usage //dev/mapper/luks-13f88890-0b52-4080-a3b6-b406d616c659, ID: 1
Device size: 932.57GiB
Device slack: 0.00B
Data,single: 85.01GiB
Metadata,single: 8.01GiB
System,single: 4.00MiB
Unallocated: 839.55GiBWe will have to add the -f option to force replacement of the filesystem on the disk if it has an existing filesystem. This is destructive!
I also takes a long time if there is a lot of data. Be patient. You can follow progress by running the usage command from a different terminal.
sudo btrfs device add -f /dev/mapper/luks-429c570c-2743-4cc3-beaa-dfc8facb118c /
sudo btrfs device usage /
sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /
sudo btrfs device usage /Add to /etc/crypttab:
luks-429c570c-2743-4cc3-beaa-dfc8facb118c UUID=429c570c-2743-4cc3-beaa-dfc8facb118c none discardNow we need to add the luks to grub.
Add rd.luks.uuid=luks-429c570c-2743-4cc3-beaa-dfc8facb118c to the GRUB_CMDLINE_LINUX value in /etc/default/grub
Then rebuild grub.
Then rebuild initramfs.
sudo -i
nano /etc/default/grub
grub2-mkconfig -o "$(readlink /etc/grub2.cfg)"
dracut --force
rebootsudo dd if=/dev/nvme1n1p2 of=/dev/nvme2n1p2 bs=1024 status=progress
sudo dd if=/dev/nvme1n1p1 of=/dev/nvme2n1p1 bs=1024 status=progressSnapper is a snapshot management tool for btrfs. It is available here. http://snapper.io/
If you are using Docker's btrfs volume driver you end up with a lot snapshots which necessitates the grep filter used below.
sudo btrfs subvolume list / | grep "level 5"ID 256 gen 1987943 top level 5 path home
ID 257 gen 1987942 top level 5 path rootThis installs snapper and an automatic snapshot before and after each dnf install.
sudo dnf install snapper python-dnf-plugin-snapperHere we create a snapper config for the root subvolume.
sudo snapper -c root create-config /It is not stored at the top level however, so we will move the subvolume from /.snapshots (within the root subvolume) to level 5. We want it at the top level so we can rollback our root partition and boot into it directly.
sudo btrfs subvolume list / | grep snapshots
sudo btrfs subvolume delete /.snapshotsNow we will make a new folder within the root path and create a top level subvolume and mount it there.
sudo mkdir /.snapshots
sudo mkdir /backups
sudo mkdir /mnt/btrfs
sudo mount /dev/dm-0 -o subvolid=5 /mnt/btrfs
cd /mnt/btrfs
sudo btrfs subvolume create snapshots
sudo btrfs subvolume create backups
cd ..
sudo umount /mnt/btrfs
sudo rmdir btrfs/There are now two new top level subvolume.
sudo btrfs subvolume list / | grep "level 5"ID 256 gen 1987943 top level 5 path home
ID 257 gen 1987942 top level 5 path root
ID 10963 gen 1987638 top level 5 path snapshots
ID 10963 gen 1987638 top level 5 path backupssudo nano /etc/fstabWe add a new lines at the bottom which mounts the new subvolumes.
UUID=2402f445-7fd2-4a8b-8b53-6c27c67fb58d / btrfs subvol=root,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=13f88890-0b52-4080-a3b6-b406d616c659 /boot ext4 defaults 1 2
UUID=62A1-49D9 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=2402f445-7fd2-4a8b-8b53-6c27c67fb58d /home btrfs subvol=home,compress=zstd:1,x-systemd.device-timeout=0 0 0
UUID=2402f445-7fd2-4a8b-8b53-6c27c67fb58d /.snapshots btrfs subvol=snapshots,x-systemd.device-timeout=0 0 0
UUID=2402f445-7fd2-4a8b-8b53-6c27c67fb58d /backups btrfs subvol=backups,x-systemd.device-timeout=0 0 0Let's mount it.
sudo mount -aWe will make user folder with user permissions.
sudo mkdir /backups/$USER
sudo chown $USER:$USER /backups/$USER
cd $HOME
ln -s /backups/$HOME backupsThe default subvolume is just top level. This is not specific enough for our needs. We want to be able to set this explicitly to a subvolume ID.
sudo btrfs subvolume get-default /ID 5 (FS_TREE)Recall above our root subvolume ID was 257 we will set that to our default.
sudo btrfs subvolume set-default 257 /
sudo btrfs subvolume get-default /ID 257 gen 1988138 top level 5 path rootNow we need to modify the Grub config.
sudo grubby --info=ALL...
index=2
kernel="/boot/vmlinuz-5.13.14-200.fc34.x86_64"
args="ro rootflags=subvol=root rhgb quiet"
...We want to remove the rootflags=subvol=root argument so it will honor rollbacks requested by snapper.
sudo grubby --update-kernel=ALL --remove-args="rootflags=subvol=root"sudo grubby --info=ALL...
index=2
kernel="/boot/vmlinuz-5.13.14-200.fc34.x86_64"
args="ro rhgb quiet"
...All better, so now we reboot.
rebootsudo snapper ls # | Type | Pre # | Date | User | Cleanup | | Userdata
---+--------+-------+-----------------+------+---------+----------------------------------------+---------
0 | single | | | root | | current |
1 | pre | | Sun 18 Sep 2021 | root | number | /bin/dnf -y install ...fc34.x86_64.rpm |
2 | post | 1 | Sun 19 Sep 2021 | root | number | /bin/dnf -y install ...fc34.x86_64.rpm |Oh no, our install broke everything!
sudo snapper --ambit classic rollback 1
rebootLife is good!
We will create a snapper config for /home and give our personal user access since this is a single user PC.
sudo snapper -c home create-config /home
sudo snapper -c home set-config SYNC_ACL=yes ALLOW_USERS=$USER
sudo snapper list-configsConfig | Subvolume
-------+----------
home | /home
root | /Notice sudo is not required anymore.
snapper -c home create --description "First Snapshot"
snapper -c home ls # | Type | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+-----------------+------+----------+----------------+---------
0 | single | | | root | | current |
1 | single | | Sat 18 Sep 2021 | josh | | First Snapshot |sudo nano /etc/snapper/configs/rootDisable automatic hourly snapshots of root.
# create hourly snapshots
TIMELINE_CREATE="no"
# cleanup hourly snapshots after some time
TIMELINE_CLEANUP="not"sudo nano /etc/snapper/configs/homeConfigure automatic hourly snapshots of home.
# create hourly snapshots
TIMELINE_CREATE="yes"
# cleanup hourly snapshots after some time
TIMELINE_CLEANUP="yes"
# limits for timeline cleanup
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="5"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="1"
TIMELINE_LIMIT_YEARLY="0"Turn on timer for automatic snapshots.
sudo systemctl enable --now snapper-timeline.timer
sudo systemctl enable --now snapper-cleanup.timerAfter waiting an hour...
snapper -c home ls # | Type | Pre # | Date | User | Cleanup | Description | Userdata
---+--------+-------+-----------------+------+----------+----------------+---------
0 | single | | | root | | current |
1 | single | | Sat 18 Sep 2021 | josh | | First Snapshot |
2 | single | | Sun 18 Sep 2021 | root | timeline | timeline |
Thank you very much :)