Run before_backup once (with multiple repositories) #790
Labels
No labels
blocked
breaking
bug
data loss
design finalized
good first issue
new feature area
question / support
security
waiting for response
No milestone
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
borgmatic-collective/borgmatic#790
Loadingโฆ
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What I'd like to do and why
I have a local and remote borg repo.
For a couple of applications I am backing up, there is a command that I need to run. This exports all of the databases/artefacts/etc to a specific directory. This is not a small operation (~10-25 minutes depending on the application). Getting around this is not possible (or at least not desirable, as it would complicate the restore process).
Using before_backup does work, but I only need this to run once rather than multiplying the time my backup takes to prepare by the amount of repos I have defined.
Current behaviour:
Desired behaviour:
Other notes / implementation ideas
Perhaps we could consider introducing a
before_backup_once, to avoid breaking backwards compatibility for those who rely on this behaviour.This would run once, just before running the backup command associated with the first repository in the list. If borg handles the
before_backupconfig, perhaps the contents ofbefore_backup_allcould be prepended tobefore_backupfor the first repo or something.(Perhaps a matching
after_backup_onceis appropriate, not that I need it)It should be noted that I would still expect multiple configurations to have each of their relevant
before_backup_oncehandled individually.Actually, re-reading the documentation... is this what
before_everythingis supposed to do? I only just noticed the caveat of it only running whencreateis among the operations.Does this mean that if any of the pre-commands fail, the entire backup doesn't run?
Yup,
before_everythingis the closest to what you're looking for. And it does run only when there's an implicit or explicitcreateaction.That's correct!
Hmm. It probably would be nicer to have that single config file fail than all of them...
before_backupactually used to work exactly as you've described above.. Prior to borgmatic 1.6.0 and #473, command hooks ran per-configuration rather than per-repository. The change to be per-repository was made though to better support running timing-sensitive tasks like pausing containers, thereby keeping each hook temporally closer to the action(s) it's wrapping.So short of downgrading borgmatic (which I don't recommend), your best bet for now might be to:
before_everythingand just deal with any failures that affect all configuration files.before_everythingbut invoke borgmatic separately for each configuration file that you want to succeed/fail independently. (See the--configflag.)before_backupand deal with the repetition. (In fact, the built-in borgmatic database dumping feature also repeats dumping per-repository because it streams dumps directly to Borg without hitting disk.)Hope this helps some.
Taking a service down temporarily is a pretty reasonable usecase - so I understand the change.
But do you see value in implementing the old behaviour but as a different option?
For now, I think I'll have to take the before_everything route... but it would be nice to not have all backups fail because of a specific config's prerun.
Actually if we're talking optimisation, in my situation there's nothing really preventing the idea of running the differently config
beforesteps in parallel. I daresay that'd be a complexity jump that doesn't attract huge interest though...I see the value in the old behavior, but I'm hesitant to build directly atop the existing command hook syntax to support it. That's because that approach would end up encoding so much detail into the option name itself, which gets kind of awkward IMO especially as more use cases are added. A more flexible (if less backwards-compatible) approach would be to come up with a new schema for command hooks that better supports these kinds of use cases. Here's a made-up example:
The big downside is verbosity and complexity. The upside is this is way more flexible for a variety of use cases including yours. I'm not 100% sold that the trade-off is worth it, but I thought it's worth continuing the discussion. (This is not the first time this kind of approach has been discussed.)
Yeah, parallelism has come up in other contexts as well, but thus far nobody has worked on it.
My issue is not the same but I think it is very related, and because here you speak about refactoring hooks, I dare to add my use case to be considered. What I'm trying to achieve is
And most sense it makes to have the 1,2,3,5 as hooks valid for only the current configuration file.
Currently the only way I see to implement is by custom
before_backuphook. Because I see no way to add the services start/stop logic to the LVM snapshot logic. This means writing my own script to make the snapshots/mounts and control the services instead of using the built-in LVM feature.wrt running borgmatic separately for each configuration file, this makes using a systemd service not really viable. Would be nice if this mode of operation is well supported.
Interesting. What's your use case for stopping and starting services around the LVM snapshot? Just so you get a consistent picture of the filesystem without the services modifying it? And the snapshot itself isn't sufficient to accomplish that?
Anyway, if there were hooks where you could stop and start services for this use case, and it was using the proposed hook scheme above, it might look something like this:
This is of note because it's effectively a hook that triggers before and after another hook is triggered! Not sure how I feel about that, just conceptually. But one downside I can see to this approach is that it would trigger before/after all data source hooksโincluding database dumpsโwhich might not be what you're hoping for in this use case.
EDIT: Here's a variant of above that may solve this triggering after all data source hooks:
The idea is that this would be restricted to being triggered before/after only the LVM hook dumping data sourcesโand not after any other hooks do.
correct
There are possible inconsistencies that I prefer not to deal with. I'm running atm immich and seafile and some other services. They are reasonably resilient to abrupt interruption with the possibility to leave stale objects or objects that are in the database but not on disk. Depending on whether file was added/removed but the database operation was not fully committed.
Since I don't want to know these services on the very low-level I prefer to err more on the safe side and not have to deal low-level inconsistencies.
Also I use large HDDs. But it turned out database performance was (no surprise) horrible. So I moved the DBs to smaller SSDs.
Now they are two different filesystems that cannot be frozen at exactly the same moment. Also not sure how mysql and postgres like abrupt interruptions. I assume they are also reasonably resilient but don't want to make this a normal course of operation.
I know borgmatic has a database dump function. It seems easier for me to just save the files though. And don't think too much how to restore, resource usage, etc. Minimizes my downtime. Also I don't have hooks around database dumps, which could allow stopping only the services, make snapshot, dump database, restart services. Would be some more downtime.
Probably I'm overly-concerned. But this is the simplest way for me to start and see later where can I further optimize.
wrt hooks, I really don't know. For me it is reasonable to have
before/after_snapshothooks. Like before and after all snapshotting, not around individual snapshots. Snapshotting is not a hook from user point of view. Just part of borgmatic steps. Not sure how it is implemented. And I don't see a big reason not to have many hooks around each execution state.Thank you for the consideration! At the moment my implementation is reasonable. I have only one repository in my services configuration file. Will add another configuration file with another repository for OS backup but I understood they will work independently. So no rush on my end. Just wanted to provide feedback about possible new hooks.
As advised, I'm pasting here my precise hooks that cover my use case pretty well. So that it can be considered for future hooks enablement in borgmatic.
Thanks for adding your thoughts about starting/stopping services around filesystem snapshotting. It's really helpful to get that context from your point of view to better understand the ask! I have a feeling the current hooks approach might be due for an overhaul at some point, and this is certainly another important data point towards that.
This is implemented in main and will be part of the next release! The documentation will be online here shortly: https://torsion.org/borgmatic/docs/how-to/add-preparation-and-cleanup-steps-to-backups/
The TL;DR is that borgmatic command hooks are being replaced with a new hook configuration format that should hopefully be more flexible and address both of the above use cases. Example:
Awesome! I look forward to giving it a whirl. Thanks very much.
So
xfsfreezeandcryptsetupwill possibly be implementable in this way? Sorry it was not clear from the example and it is fine for me to wait until the documentation is ready.Yes, something like this:
This is assumes the built-in LVM snapshotting feature is being used.
Thanks a lot! Would be nice to have these hooks documented. I make some sense out of the examples but I feel like guessing. Not urgent because I'm doing other setup before looking into upgrading borgmatic.
Have you seen the linked documentation here? https://torsion.org/borgmatic/docs/how-to/add-preparation-and-cleanup-steps-to-backups/
I'd be happy to improve the docs if they're not clear/detailed enough.
My bad! I was searching the docs for
hookand didn't spot preparation and cleanup steps.It makes a lot more sense now.
It looks much more robust. Two questions come to mind about the
dump_data_sourceshook.hooks: [zfs,btrfs]will the hook execute for both of these separately or once before/after both?lvmhook is not listed in documentation. It will perform the snapshotting before backup and will remove it after backup. Seems like thebeforehook will run before lvm snapshot and theafterhook will run after snapshot, correct? This is good. I see nothing though to run before/after snapshot being removed. Maybe such commands (e.g.cryptsetup close) could go inafter: action๐คOr if
afterdump_data_sourcesruns only after snapshot is removed, then all services will be down for the whole backup.Or maybe I miss something?
Yeah, I probably need to reorganize the docs to make finding stuff easier. Search would probably help too.
It will execute once before/after the ZFS snapshotting and again before/after the Btrfs snapshotting. I'll clarify in the docs.
That's correct. The LVM hook is documented here: https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/#lvm
Yeah, I haven't implemented a hook for snapshot removal yet. And in fact it might not work like you're expecting, because snapshot removal actually happens twice during any given borgmatic run (assuming a single data source hook). Would running
cryptsetup closework in anafter: dump_data_sourceshook, or is there is a reason that's too early?The
cryptsetup closeshould run betweenumountand lvm snapshot removal (this is also after the actual backup has taken place). Otherwise source will be mounted andcryptsetup closewill fail.But then
cryptsetup openshould run between lvm snapshot create andmount. Which is probably somewhere withindump_data_sourcesand not sure it is supportable. That perhaps make it even more complicated.I'm not too attached to having this functionality. Currently what I have as before/after backup hooks is working pretty well. I see another important detail though. It needs to be known which hooks will execute in case of an error at the different stages.
I'm currently on borgmatic 1.9 and it seems like
after_backupdoes not run in case backup failed. Which leaves the system in an inconsistent state and in my case it causes a second backup attempt to also fail in thebefore_backupstage, and that in turn leaves my services down.Perhaps "after" hooks should always run in case the "before" hook has run (whether such was defined by the user or not). That would probably enable the ability to restore system state in case of a problem.
That's unfortunate that the new
dump_data_sourceshook won't work for your use case after all! I'll probably just remove it since I'm not sure there's currently another use case for it. And you are correct thatafter_backupindeed does not run in the case of a failed backup, but the good news is that the forthcomingaftercommand hooks described in this ticket do run even when an error occurs.Released in borgmatic 2.0.0!