rustic
rustic copied to clipboard
Using `one-file-system = true` with a sources of `/` causes nothing to be found
Seems I've hit a bit of an edge case. I appear to have narrowed it down to the one-file-system option, but it wouldn't surprise me if it has something to do with my excludes too.
Situation: I'm trying to backup my / root directory for a system files backup. I already have other backups for each mounted drive, so I want to use one-file-system so that I don't have to worry about potential leaks into backing up other drives, also virtual file systems. So I construct a Sys.toml as follows:
[repository]
repository = <path to external drive here>
[forget]
# elided
[backup]
exclude-if-present = ["CACHEDIR.TAG"]
one-file-system = true
git-ignore = false
[[backup.snapshots]]
sources = ["/"]
# Exclude system directories that shouldn't be backed up
# Some of these, like /proc or /sys are virtual file systems and therefore
# excluded via `one-file-system`, but we list them anyway
globs = [
'!/proc',
'!/sys',
'!/tmp',
'!/var/tmp',
'!/var/cache',
'!/dev',
'!/mnt',
'!/lost+found',
'!/home/',
]
With a / directory structure as follows
$ ls -l | tail -n +2 | sed 's/\([^ ]\+ \+\)\{8\}//'
bin -> usr/bin
boot # This is also a mount point
dev
etc
home
lib -> usr/lib
lib64 -> usr/lib
lost+found
mnt
opt
proc
root
run
sbin -> usr/bin
srv
sys
tmp
usr
var
Running rustic -P Sys --log-level debug -n backup as a non-root user leads then to:
$ rustic -P Sys --log-level debug -n backup
[INFO] using config # elided
# elided
[00:00:00] backing up... ████████████████████████████████████████ 0 B 0 B/s [DEBUG] (1) globset: built glob set; 9 literals, 0 basenames, 0 extensions, 0 prefixes, 0 suffixes, 0 required extensions, 0 regexes
[DEBUG] (1) ignore::gitignore: opened gitignore file: < global git ignore file >
# A whole lot of debug output about processing my global gitignore, despite explicitly disabling gitignore
[DEBUG] (29) ignore::walk: ignoring /dev: Ignore(IgnoreMatch(Override(Glob(Matched(Glob { from: None, original: "!/dev", actual: "dev", is_whitelist: true, is_only_dir: false })))))
[00:00:00] backing up... ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0 B/7 B 0 B/s (ETA -)[DEBUG] (41) ignore::walk: ignoring /dev: Ignore(IgnoreMatch(Override(Glob(Matched(Glob { from: None, original: "!/de[00:00:00] backing up... ████████████████████████████████████████ 7 B/7 B 3.77 KiB/s (ETA -)[DEBUG] (1) rustic_core::archiver::tree_archiver: unchanged file: "/bin"
[DEBUG] (1) rustic_core::archiver::tree_archiver: unchanged tree: "/boot"
[00:00:00] backing up... ████████████████████████████████████████ 7 B/7 B 3.04 KiB/s (ETA -)Files: 0 new, 0 changed, 1 unchanged
Dirs: 0 new, 0 changed, 2 unchanged
[DEBUG] (1) rustic_rs::commands::backup: Data Blobs: 0 new
[DEBUG] (1) rustic_rs::commands::backup: Tree Blobs: 0 new
Added to the repo: 0 B (raw: 0 B)
processed 1 files, 7 B
snapshot 00000000 successfully saved.
[INFO] backup of / done.
(This run was after running once before, so it already has the two files it can do)
So a backup just containing two empty files:
$ rustic -P Sys ls < hash >
...
[INFO] getting snapshot ...
bin
boot
Which is interesting in its own way since I saw there's an open bug about rustic not copying empty directories, and /boot is an empty directory here due to being another mount point.
Removing one-file-system immediately causes the command to do the expected thing, as does not listing /. So for now my solution is to explicitly list out every directory under / to attempt to backup. Note that sources = ['/', '/usr'] for example actually continues to be broken in this manner, so / needs to not be in the sources array.