Manjaro Installation with btrfs and snapper - change subvolume layout

I use linux as my default OS for more than 2 years. Now my manjaro system is installed on btrfs and use snapper instead of timeshift, but is it a good way to use snapper while still using manjaro defaults subvolume layout? I planing to reinstall manjaro and use snapper (I hope) in the correct way. But I have some confusion related to snapper and btrfs subvolume layout.

My plan is to install manjaro-kde with btrfs file system, wich manjaro default btrfs subvolume is look like this:

subvolume   |mountpoint
@           |/
@home       |/home
@cache      |/var/cache
@log        |/var/log

What I want to do after installation is:

  • Complately remove timeshift and install snapper.
  • Change the defaults subvolume layout into flat layout.

I want use flat layout according to these posts:

I’ll do this way(chroot mode):

  • Create new @var and @snapshots subvolume
  • Move everything in @/var/ to new @var
  • Move everything in @cache to @var/cache/
  • Move everything in @log to @var/log/
  • Last but but least edit fstab file to mount @var → /var

Now the subvolume layout will look like this:

subvolume   |mountpoint
@           |/
@home       |/home
@var        |/var
@snapshots  |will be used latter for saving snapshots mount at /.snapshots
@cache      |not used
@log        |not used
  • 1st question: did I chage the defaults layout to flat layout in the correct way? and is it right to call that a flat layout?
  • 2nd question: why it is necessary to add attribute +C to /var? can I set no-COW for @var by mount options in fstab instead?

With the above subvolume layout, it will exclude @var from being snapshoted by snapper since it is a subvolume, but Hagen also explain:

/var/lib must be snapshotted with our root system because we don’t have to break dependencies of installed library configuration or more important the pacman/pamac config files of installed packages of our current system

So I need to include /var/lib in every snapshot, to do so I need to copy all in /var/lib/ to /usr/var/lib/ then add a line in fstab to make a bind-mount from /usr/var/lib to /var/lib.

/usr/var/lib    /var/lib    none    defaults,bind 0 0
  • 3rd question: is bind-mount the same as we mount a partition or subvolume into a directory? so if I bind-mount /usr/var/lib to /var/lib and then I create a file in /var/lib that file will actually saved in /usr/var/lib?

If I’m not wrong, after all that steps that means all preparation to use snapper is set up correctly, and ready for boot into new manjaro system and then create snapper config for /

Acording to archwiki if I use snapper-timeline.timer rather than default cronie deamon I can be able to change snapshot and cleanup frequencies, problem come if snapper-timeline.timer is running, snapper will take 2 snapsots in every hour, 1 is created by default cronie deamon and another one by snapper-timeline.timer. To prevent that happend, I follow this post. Problem Solve, but I want snapper to only take snapshot in every 6hours, and I dont know how to do that. I have try to understand the steps from some wiki pages:

ArchWiki - Snapper#Change_snapshot_and_cleanup_frequencies
ArchWiki - Systemd#Editing_provided_units
ArchWiki - systemd.time.7

But always ended up with faileure.

Please have a look at:

Btrfs

https://wiki.manjaro.org/index.php/Btrfs

And you may search for posts about btrfs from me (german and english)

This already is a flat layout !

Mountpoints do not count in determining flat or nested.
flat:

@            /
@home  /home

nested:

@                 /
@/home     /home

also see @ SysadminGuide - btrfs Wiki

Actually, that is not a flat layout. A flat layout uses a separate subvolume for the root directory, i.e.: :arrow_down:

@          - not mounted     <==
@rootdir   - mounted at /    <==
@home      - mounted at /home
...

If flat or nested depends only of your BTRFS setup, to check it

// sudo btrfs su li /                                                                                                                                                            
ID 3202 gen 230117 top level 5 path @
ID 1153 gen 230117 top level 5 path @home
ID 260 gen 230117 top level 5 path @var
ID 736 gen 155504 top level 5 path @snapshots
ID 737 gen 230083 top level 736 path @snapshots/root
ID 738 gen 230082 top level 736 path @snapshots/home

ID 3953 gen 228922 top level 737 path @snapshots/root/649/snapshot

Your layout depends on the Top Level used of each subvolume. The first four subvolumes have top level = 5, thus his parent is the BTRFS root, a flat layout The last snapshot subvolume have top level = 737 thus is a nested subvolume into @snapshoots/root, and subvolume @snapshots/root is a child of @snapshots subvolume. Anything into @snapshots i setup nested, eg. tree a non-flat layout.

When you create in CLI a new BTRFS subvolume then it depends where you are in current path. Thats why i mount in FSTAB the BTRFS root, eg. SubVolID=5 into folder /btrfs. Any subvolume changes i made directly after into /btrfs. I ensure in this way not to misconfigure my system. This mount is the only one wich i mount with subvolid=xxx mount options, al others i mount by name with subvol=name. This is importend when you later will work with bootable snapshots and rollback copies of it. Never, except above BTRFS root mount, mount with subvolid=xxx.

Strictly speaking: there exists only nested layout in BTRFS. The root of BTRFS have ID=5 and any other subvolumes are childs of this parent, that’s a nested layout, always. What we means when we talk about flat or nested layouts are the point where we configure our snapshots location of the other subvolumes like @->/, @home->/home, @var->/var and so on. Flat means then we store our snapshots as example of subvolme @home outside, as non-nested subvolume of @home. We want this only because of one point → rollbacks. When we use nested snapshots of @home, eg. we store snapshots of @home as subvolumes into @home then we get some compilated rollbacks. Because on a rollback we have to shift/move any nested snapshot taken of @home to the new location of @home after this rollback of @home. This is more complicated as when we use a so called “flat” layout, where our snapshots of @home are outside of @home located. Then we have on rollback only to move/delete/rename the actual @home subvolume to a safety point, an make a new snapshot, called @home of a older snapshot we want to restore. Any order of the @home snapshots taken are remaining. Thus we are done with a rollback with only two commands into CLI.
If we use snapper’s default configuration, with “nested” snapshots=subvolumes of as example @home, we have on manual rollback move all the prior taken snapshots of @home to the new location of our rollback subvolume made.

Thus nested or flat is only a definition, physicaly are all subvolume of BTRFS nested as child into BTRFS Root.

2 Likes

Yes :slight_smile: You mount the physical folder /usr/var/lib into /var/lib thats all A physical existing /var/lib folder is then hidden. With a BTRFS root mount to /btrfs i can access this hidden /var/lib folder with /btrfs/@/var/lib to check if it is empty.
More important because of that /usr is a childfolder of / = @ subvolume any snapshot of “root” → @ subvolume will even snapshot anything into /usr/var/lib within root snapshots. With this little trick i only have to support this one folder and the bind mount in fstab, instead of many separate subvolumes of every part/subfolder in /var lib, like OpenSuse’s old BTRFS layout does.

Of course yes it is the better way, in my opinion :wink: With snapper you have more directly support if you like to work in CLI, you need it not often. And tools like snap-pac and snap-sync work directly with snapper configurations. This is important if you want to setup a full automated BTRFS system with snapshots before/after installations and backups.

1 Like

Three reasons:
1.) the FSTAB mount options is not working, eg. ignored by BTRFS system. BTRFS ues for all FSTAB mounts the first seen mount options. Thus, it is important to setup in FSTAB the first BTRFS mount with the options you want for all other following mounts. In my setup i include into @var mount options the “nodatacow” because if later BTRFS have correct this behavior i’am already done.
2.) because of 1.) you have to setup for any folder and it’s files separately the +C file attributes to ensure BTRFS use no copy on write on these files/folders.
3.) you want to setup +C on everthing into /var to save space and time. Any COW enabled file/folder will save on each modfications the modificated parts into separate copies in BTRFS, thats the essential working of BTRFS we want to use. But not for files/folders into @var subvolume.
You can use all this without such setup, but then you risk that you later run out of space. And this provocate some problems with BTRFS.

I use cronie thaths easier in my opinion. The timeline is provided by snapper and his configuration it self and not by external timers.

My setup “root->@” and “home”->@home snapper configuration:

// cat /etc/snapper/configs/root

# subvolume to snapshot
SUBVOLUME="/"
# filesystem type
FSTYPE="btrfs"
# btrfs qgroup for space aware cleanup algorithms
QGROUP=""
# fraction of the filesystems space the snapshots may use
SPACE_LIMIT="0.5"
# fraction of the filesystems space that should be free
FREE_LIMIT="0.2"
# users and groups allowed to work with config and snapper without use of sudo
ALLOW_GROUPS="wheel"
# sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots
# directory
SYNC_ACL="yes"
# start comparing pre- and post-snapshot in background after creating
# post-snapshot
BACKGROUND_COMPARISON="yes"
# run daily number cleanup
NUMBER_CLEANUP="yes"
# limit for number cleanup
NUMBER_MIN_AGE="1800"
NUMBER_LIMIT="32"
NUMBER_LIMIT_IMPORTANT="4"
# create hourly snapshots
TIMELINE_CREATE="no"
# cleanup hourly snapshots after some time
TIMELINE_CLEANUP="yes"
# cleanup empty pre-post-pairs
EMPTY_PRE_POST_CLEANUP="yes"
# limits for empty pre-post-pair cleanup
EMPTY_PRE_POST_MIN_AGE="1800"

// cat /etc/snapper/configs/home

# subvolume to snapshot
SUBVOLUME="/home"
# filesystem type
FSTYPE="btrfs"
# btrfs qgroup for space aware cleanup algorithms
QGROUP=""
# fraction of the filesystems space the snapshots may use
SPACE_LIMIT="0.5"
# fraction of the filesystems space that should be free
FREE_LIMIT="0.2"
# users and groups allowed to work with config
ALLOW_GROUPS="wheel"
# sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots
# directory
SYNC_ACL="yes"
# start comparing pre- and post-snapshot in background after creating
# post-snapshot
BACKGROUND_COMPARISON="yes"
# run daily number cleanup
NUMBER_CLEANUP="yes"
# limit for number cleanup
NUMBER_MIN_AGE="1800"
NUMBER_LIMIT="32"
NUMBER_LIMIT_IMPORTANT="4"
# 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="12"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="4"
TIMELINE_LIMIT_MONTHLY="12"
TIMELINE_LIMIT_YEARLY="2"
# cleanup empty pre-post-pairs
EMPTY_PRE_POST_CLEANUP="yes"
# limits for empty pre-post-pair cleanup
EMPTY_PRE_POST_MIN_AGE="1800"

As you can see my snapper config for @=root make no timeline snapshots. Most snapshots taken with snapper are external triggered by snap-pac before/after installations of software/updates with pamac/pacman/AUR.
My setup for @home=home make the same but additional use timeline snapshots, and more important cleanup of older snapshots made by snapper. For @home i let snapshot every hour for the last 12 hours, every day for the last 7 days, every week for the last 4 weeks, every month for the last 12 months and every year for the last 2 years.

The NUMBER_XXX options define the limits of standard snapshots, for example made by snap-pac. I need 32 of them and for all snapshots made manualy and configured as “important” i let only 4 of them. These snapshots of “root” will be seen on GRUB as bootable snapshots if you have grub-btrfs installed.

For managing of your snapper snapshots let snapper work for you. You have only to activate the cronie job.
To setup these configs you can use snapper CLI it self or manualy edit these files after ypu have created configurations for snapper. I use this way, it’s easier as per CLI.

No, thats a non-flat eg. nested layout. @rootdir and @home have top-level=@ as parent and not BTRFS-Root → SubVolID=5 as parent. Above i shown a flat-layout where any subvolume there have top-level set to 5 are flat and any other are neseted and non-flat.
But only with subvolume names shown we can’t realy judge if is it nested or flat layout. We have to use BTRFS to check it, as above shown.

1 Like