How I'm sending incremental Btrfs snapshots on a Asustor NAS to a LUKS disk


Hi, I recently finished setting up my Asustor NAS, and I found the snapshotting setup in it a bit confusing, so I'm writing this as a quick reference that might be hopefully useful to others.

For context, my device is a AS1102TL, and it's running ADM 4.3.3, but I imagine it should apply to all recent Asustor devices.

First of all, the reason I picked Asustor instead of e.g. Synology... it's because it was not clear if the latter actually supported LUKS full disk encryption on an external usb hd. In Asustor you have to ssh into your NAS, but you can definitely do it.

The only gotcha: If you created the LUKS volume recently on another system, it's likely that it'll be using Argon2 for key stretching. A memory-intensive algorithm, for which the 1GB of memory provided by my AS1102TL is not enough. The solution is simply to add another key with a different algo, e.g. PBKDF2, or just create the volume on your Asustor. Either way, you're going to be able to read and write it both from the NAS and another Linux on your pc.

$ sudo $(which cryptsetup) luksOpen /dev/sdb1 encrypted # "encrypted" is just the name that I gave to the device, pick anything... remember the `-S` flag if you need to select a key in a different slot
$ sudo mount /dev/mapper/encrypted /mnt/USB1
... do what you want ...
$ sudo umount /mnt/USB1/
$ sudo $(which cryptsetup) luksClose encrypted

Unfortunately, this doesn't mean that once mounted, the disk will be integrated in the ADM ui (you're not going to be able to see it in the "External Devices" ui, nor be able to select it as a destination in the "Backup & Restore" ui).

Normally, mounted external drives are available on paths like /share/USB0, /share/USB1. Maybe it could be possible to mount (or symlink your mount point for) your disk there, to make it usable to ADM, but by default /share is an immutable loop mount of /volume0/.@system/sharebase.loop

$ lsattr -d /share/
-----i------- /share/

Trying to workaround that with chattr and maybe manually modifying sharebase.loop felt a bit more risky than needed, so I didn't attempt that (the ADM ui doesn't provide a btrfs send functionality, so it's not very interesting for our purposes anyhow).

Now, you have two different approaches to accomplish incremental backups of btrfs snapshots, one where you just create them yourself from the CLI, and one where you can try to reuse the snapshots created in ADM.

  1. Create snapshot from the cli


sudo btrfs subvolume snapshot -r /volume1 /volume1/.@snapshots/v20250710-0951

pick a parent snapshot, and send the incremental changes:
sudo btrfs send -p /volume1/.@snapshots/v20250710-0936 /volume1/.@snapshots/v20250710-0951/ | sudo btrfs receive -v /mnt/USB1/

I'm using the same naming convention, and same location that is used for snapshots created by ADM (you wouldn't get conflicts anyhow, unless you're creating another one in the exact same minute).

I recommend the -v verbose flag for btrfs receive, otherwise you're not going to see progress while the operation is ongoing.

That's it! Of course, the first send will have to happen without specifying a parent with -p, to do a full clone.

  1. Reuse snapshots created in ADM

There are two problems with this: the snapshots created by ADM are not read-only and they are mounted right under the toplevel.

To address these issues:

sudo mount /dev/md1 -o subvol=/ /mnt/rootvol
sudo btrfs property set /mnt/rootvol/v2025079-2324/ ro true

then pick a parent snapshot, and send the incremental changes:
sudo btrfs send -p /mnt/rootvol/v2025079-0824/ /mnt/rootvol/v2025079-2324 | sudo btrfs receive -v /mnt/USB1/

As above, use the -p and -v flags as needed. That's it!

If you're wondering why did we have to mount the / subvol, you can try without:

You can mount the snapshots directly in ADM's Snapshot Center, by toggling the Preview toggle for a snapshot. In that case, they are still going to be RW, though mounted as RO. You can deal with that by remounting: sudo mount -o remount,rw /volume1/.@snapshots/v2025079-2324/ && sudo btrfs property set /volume1/.@snapshots/v2025079-2324/ ro true,

You can then try to send the changes, but what you're going to get is:

$ sudo btrfs send -p /volume1/.@snapshots/v2025079-0824/ /volume1/.@snapshots/v2025079-2324
ERROR: not on mount point: /volume1/.@snapshots/v2025079-2324

The error is a bit confusing (you have mounted the volume! why is that not good enough?), but you can get a bit of clarity with btrfs subvolume list.
$ sudo btrfs subvolume list /volume1 -qua
ID 256 gen 159842 top level 5 parent_uuid -                                    uuid cbc37b20-901f-b043-8cf1-59b814814140 path <FS_TREE>/base
ID 258 gen 151914 top level 5 parent_uuid -                                    uuid 5039c206-1a89-dc45-a9fe-43f8959cb672 path <FS_TREE>/.iscsi
ID 259 gen 159840 top level 5 parent_uuid -                                    uuid 06d46207-9aa2-2944-ba38-e5736963ec12 path <FS_TREE>/.@plugins
ID 2758 gen 157876 top level 5 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 256c36c5-7033-a945-a2db-b6a334a8419f path <FS_TREE>/v2025079-0824
ID 2759 gen 157859 top level 5 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 88942ee6-8b52-3d4d-b972-5de2d6764728 path <FS_TREE>/v2025079-2324
ID 2762 gen 159833 top level 256 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 6d636914-35a0-3f42-9486-bf5d673b94c5 path base/.@snapshots/v20250710-0936
ID 2763 gen 159836 top level 256 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid e99df217-4946-a740-bba9-99f64f1a0d69 path base/.@snapshots/v20250710-0951

Now, compare with the output when listing /mnt/rootvol:
$ sudo btrfs subvolume list /mnt/rootvol/ -qua
ID 256 gen 159867 top level 5 parent_uuid -                                    uuid cbc37b20-901f-b043-8cf1-59b814814140 path base
ID 258 gen 151914 top level 5 parent_uuid -                                    uuid 5039c206-1a89-dc45-a9fe-43f8959cb672 path .iscsi
ID 259 gen 159840 top level 5 parent_uuid -                                    uuid 06d46207-9aa2-2944-ba38-e5736963ec12 path .@plugins
ID 2758 gen 157876 top level 5 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 256c36c5-7033-a945-a2db-b6a334a8419f path v2025079-0824
ID 2759 gen 157859 top level 5 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 88942ee6-8b52-3d4d-b972-5de2d6764728 path v2025079-2324
ID 2762 gen 159833 top level 256 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid 6d636914-35a0-3f42-9486-bf5d673b94c5 path <FS_TREE>/base/.@snapshots/v20250710-0936
ID 2763 gen 159836 top level 256 parent_uuid cbc37b20-901f-b043-8cf1-59b814814140 uuid e99df217-4946-a740-bba9-99f64f1a0d69 path <FS_TREE>/base/.@snapshots/v20250710-0951

as you can see, the snapshots created in ADM are directly under top level 5 and if you list them under /volume1 (which is just the mount point for the /base subvolume), they are not found directly underneath (despite them being mounted there), which is why you see them being under their own <FS_TREE>.

Conversely, the ones that you can create directly from the cli under volume1, appear as top level 256 and they are under /base if you list the subvolumes under /mnt/rootvol.

I hope this has been useful.

This entry was edited (8 hours ago)
in reply to berdario

PS, while I was closing the dozens of tabs that I opened to investigate how everything fits together, a note on what I wrote earlier:

once mounted, the disk will be integrated in the ADM ui (you’re not going to be able to see it in the “External Devices” ui, nor be able to select it as a destination in the “Backup & Restore” ui).


mounting the disk on a path already accessible by ADM file explorer doesn't work because of permission issues, similar to the immutable flag that you can see with lsattr... but someone on Reddit had another workaround:

reddit.com/r/asustor/comments/…

I mounted the opened device to another path already accessible by ADM file explorer. I don't think it will matter where really. But in my case I made two partitions on an external USB drive. The first partition is a small exFat formatted (10GB). The second partition takes up the rest of the drive and is formatted with cryptsetup (LUKS). Finally, to use this I open the LUKS device and mount it to a location in the first partition (which is automatically mounted by ADM)

Yet another distro choice help post


So sitrep:

Newish desktop
- i7-13700K
- 64Gb DDR5 6000Mhz
- RTX 3070Ti
- MSI PRO Z790-P
(WiFi is not a factor, permanent ethernet connection.)

Needs:
- Gaming
- Music composing
- Coding (Mostly python)
- Video editing

I've been using Linux on and off throughout the years, but lately I've fallen out of the loop somewhat. Started with Slackware around 1998, Kubuntu in the 2000's, Ubuntu 2010's, Kali and Mandrake 2020's -> on my laptop, Ubuntu server on my RasPi. At work, we have a few Fedora servers I have to maintain. So not a complete novice, but somewhat obsolete info.

I have been looking at the immutable distros, like Bazzite and Pop!_OS as I've done the whole song and dance of constantly repairing my distro because of various issues, and I'd like my main recreational machine & distro to be low maintenance, I get to fix linux servers at work enough already, I don't want to bring that home.

With gaming, I've understood that linux has come a loooooong way since I last tried sometime around TBC Launch for WoW when Wine barely worked with it.

Music composing is a little annoying, since apparently both Ableton and FL studio are not an option. I've heard good things about Reaper, but I'll have to do some more research. Feel free to educate me on this topic if you have some insider info. I don't play live sets, just compose and mix.

Video editing, currently I use Davinci Resolve, and apparently it works fine on Linux, just some limitations and shenanigans with codecs. Alternatives are welcome, I don't need 90% of what resolve offers, I can make do with a simpler software as well.

Thank you kindly in advance for departing thine wisdom.

in reply to Rappe

Honestly, Bazzite seems to fit like a glove:

  • RTX 3070Ti


Nvidia can be an ass to work with on a lot of distros, but Bazzite delivers the right drivers OOTB.

Needs:
- Gaming


Bazzite is setup for gaming OOTB; it's bundled with Steam and Lutris, makes use of custom kernels/schedulers to optimize performance for gaming and contains many other goodies like excellent controller/peripheral support.

  • Coding (Mostly python)


Provides a specialized DX (i.e. Developer Experience) image that comes with all the goodies you might expect.

  • Video editing


Has a built-in just script that downloads, installs and sets up Davinci Resolve for ya: ujust install-resolve

  • Music composing


This is the only I'm not 100% sure yet because you haven't provided explicitly yet what you'd like to use. But, I can't image it would be harder to get this running on Bazzite compared to other distros.

And last, but not least:

I'd like my main recreational machine & distro to be low maintenance


Through utilizing the bootc model, Bazzite is as low maintenance as they come.

Introduction - Steve's Tutorial on Jujutsu, an alternative front-end to git


Jujutsu is essentially an alternative front-end or "porcelain" to git, both magnificiently simplified and powerful.

I tried it after using Emacs Magit for about six or seven years, and jujutsu is really easier to use than git and useful if one wants a tidy public history of changes (with "tidy" and "public" as Linus Torvalds recommends). Plus it is fully compatible to git as backend - other contributors will not even note you are using it.

This entry was edited (14 hours ago)
in reply to paequ2

Another useful property is that while jujutsu does have worktrees, like git, in many cases where one would use git worktrees (for example when writing accompanying documentation ) it is just easier to use another line of changes (what is a branch in git).

Alas, that jujutsu does not store local change sets automatically on a remote git repo (this happens only when you update and push a git branch), means that still-mutable local changes are not automatically transferred to another computer you work on. And unpublished changes are naturally mutable in jujutsu. But you can safely copy a jj repo via rsync, as changes in jj metadata are thread-safe and atomic. The other way is of course to push a work-in-progress ("WIP") git branch which can mutate and is therefore not allowed to be merged by other people.

This entry was edited (12 hours ago)
in reply to HaraldvonBlauzahn

That’s not really how one would use worktrees in git. Worktrees are useful in the case when e.g. you are working on version 0.15 of your software that has many breaking changes to version 0.14 (perhaps even on a build system level) and you need to release a 0.14.1 patch. Worktrees separate directories which means you don’t need to stash or do a wip commit, nor clear you 0.15 build artefacts. Just cd to a different worktree, checkout the 0.14 branch, create and checkout the 0.14.1 branch, clear build artifacts in a different directory from your main development one, and start working.

When done, just cd back and keep working again without switching branches, clearing artifacts, or doing full rebuilds of the in-development 0.15 version.

Plus, git does not store change sets or branches or anything on any remote unless you push them either, so if you’re having that problem just stop pushing things you don’t want to push. You can totally rsync a git repo, just ensure it’s at rest. Otherwise do what you should be doing anyway: set the repo on another machine as a remote of the other repo, so you can git pull my_private_machine feature/my_private_branch without needing to push to a central repo.

I’m sure jujutsu has many advantages, but it also reads to me like you’re misunderstanding the git model. Which can be a fair critique of git to be fair, but then we would need to talk about what about the git model people have trouble with, why, and how to address those issues, and so far I haven’t seen any kind of research in that direction from jujutsu (not that I’ve been looking particularly hard)

This entry was edited (12 hours ago)
in reply to ugo

One difference between using worktrees and branches in git is that in git you usually have uncommited stuff that's not finished, and worktrees are a way to avoid committing this. And you want to avoid committing early because it is hard to clean-up later. This hesistsnce to commit is not necessary at all in jujutsu - any change to the source files is already captured and will be restored once you go back to that changeset. There are other cases where you use worktrees in git e.g. to isolate a build and an hour-long integration test running it in parallel to your ongoing work, and in thar cases, you'd use workspaces in jujutsu like you'd in git.

but then we would need to talk about what about the git model people have trouble with, why


Too many commands that do subtly and irreversivly things on the repo, with potentially messed-up interim states, only to do the conceptually much simpler task to edit and manipulate the directed acyclic graph of commits.

In short, jujutsu is a commit graph editor and does the same with perhaps 10% of the complexity of git. The man pages on the git reset, branch and merge commands are already larger than the whole - and detailed!- documentation of jujutsu.

Steve Klabnik explains this much better than I can here in his blog that I posted.

This entry was edited (11 hours ago)
in reply to HaraldvonBlauzahn

It is simply not my experience that cleaning up commits after committing early is difficult in git. Amending a commit is a single -a flag away from the git commit command. The opposite problem is when you do too much work and want to split it into multiple commit rather than a huge one, in which case git add -p is again a single flag away from git add.

In general, git’s entire model is to allow you to work first, and do administrative tasks (including tidying up your commit history etc) later.

And almost nothing is truly destructive in git, the vast majority of cases can be fixed by judicious use of git reflog.

The only cases I’ve ran into where git repos became corrupted were caused by external tools, mainly GUIs that label buttons with git commands that do something different when clicked (like the button labeled push actually doing git push —all for no good reason, and such things) with users that have no idea how git works that have been trained just by telling them “click this to save your work, click this to get the last version of the code”

in reply to paequ2

Technically true - but it looks like jj does a lot of history re-writing which would require a lot of care to be taken when working on a shared codebase.

The page on remotes has some cautions in it.

We need the --allow-backwards flag to set the trunk branch to the previous commit because it is a dangerous operation: if we had pushed trunk, things would get weird when we try and push now. We've kept it all local, so there's no issues with doing this.
in reply to HaraldvonBlauzahn

Hrm... It looks interesting but it seems too dedicated to crafting "the perfect commit".

Changing our description changed the commit ID! This is why we have both IDs: the change ID has not changed, but the commit ID has. This allows us to evolve our commit over time, but still have a stable way to refer to all versions of it.


I don't want to "evolve a commit" - I want to capture my changes over time. If I decide later that I want to prepare the commit for merging I will.

I hate it because it's different - but even trying to give it a "benefit of the doubt" I really can't see this as better. It's not like it's difficult to create a "tidy" commit with git as is.

And as far as "easier to use goes"... well... Here's how you get a list of anonymous branches

jj log -r 'heads(all())'

And since they eschew branches with names you get to memorize hash strings instead of branch names that describe the thing you were doing?
jj new pzoqtwuv yykpmnuq -m "merge better documentation"
# vs. 
git merge my_branch_Name

I'm unconvinced. Though jj undo looks neat (and also crazy dangerous unless you can undo an undo?).
This entry was edited (4 hours ago)
in reply to atzanteol

And since they eschew branches with names you get to memorize hash strings instead of branch names that describe the thing you were doing?


No trouble, you can still name branches if you want. And no, you don't have to type the whole changeset hash, the first one to three letters are usually sufficient.

Also, branch names are not a permanent thing, they disappear after you merged them.

If you want, to can put an empty commit with the description of what you want to do at the top of your changes, and then use "jj split" to move changes to different commits before it.
There are several common work flows which are explained in Klabnik's blog post.

in reply to HaraldvonBlauzahn

If the readability of the commit history really does not matter to you - for exsmple, nobody needs to read this code again - it’s possible that jj does not give you enough advantage. Everyone works different.


I mean... It does and I will use git to manage commit histories as necessary. I don't see jj as solving that problem or even making it easier. Doing a single squash-commit or a rebase -i when I merge a branch is relatively trivial.

And from what I can tell it's much easier to do a git pull upstream master than to do jj new skdfsld dskfjas since you'll likely have to lookup those hashes? I mean I wouldn't remember them.

Looking for a music player


I'm looking for a music player on Pop!_OS that supports playlists, repeating a single track while still being able to swap tracks in the playlist, and also supports fading between songs and when stopping playback. And ideas on what to try?

So far I've tried VLC, Audacious, and Rhythmbox, but none of those seem to support all of those requirements. (Rhythmbox was close but the repeat one from the toolbar plugin doesn't work.)

Edit: Got it working in Rhythmbox after toggling the repeat options a few more times. Still curious if there are other options out there though.

This entry was edited (15 hours ago)

Intel axes another 2,400 jobs in Oregon announced Friday.


Even with all those incentive dollars, tax breaks, and innumerable concessions this will always be what happens. Governments are captured by corporate money, power and influence and then governments give away the people's wealth and corporations take.