summaryrefslogtreecommitdiff
path: root/example/borgmatic/media-to-borg-patterns.py
diff options
context:
space:
mode:
authorLibravatar Daenney <daenney@users.noreply.github.com>2023-07-07 11:45:42 +0200
committerLibravatar GitHub <noreply@github.com>2023-07-07 11:45:42 +0200
commit9ff4c20374ae112c6e7a598d5888e51783038ffe (patch)
treec303a4468f124ea95afd20be22e3efc37cc2efa8 /example/borgmatic/media-to-borg-patterns.py
parent[feature] Add media list command (#1943) (diff)
downloadgotosocial-9ff4c20374ae112c6e7a598d5888e51783038ffe.tar.xz
[docs] Rework backups a bit (#1942)
* [docs] Rework backups a bit This changes the existing backup documentation to: * Push a bit harder on people to perform backups, it's not really just a nice to have * Removes the language about migrating to/from GoToSocial and a different ActivityPub server since that's really not supported * Adds a section about using backup software and provides an example on how to do this using Borgmatic * [docs] Remove too much info in db section * [docs] Add docs on how to backup local media This adds documentation pointing people at the media list-local command in order to determine what media files they need to include as part of their backups. Provides a Python script that people can use to transform the media listing from the CLI into Borg patterns. It also includes a Borgmatic config.yaml in the repository so people can easily fetch it instead of copy-pasting from the docs. * [bugfix] Ensure we emit an absolute path prefix It works either way, as a pattern like data/files/<ID> would match a file on /data/files/<ID>. But it would potentially also match any path that happens to include data/files/<ID> but not rooted at the storage-local-base-path. * [docs] Add more links to media list CLI reference
Diffstat (limited to 'example/borgmatic/media-to-borg-patterns.py')
-rwxr-xr-xexample/borgmatic/media-to-borg-patterns.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/example/borgmatic/media-to-borg-patterns.py b/example/borgmatic/media-to-borg-patterns.py
new file mode 100755
index 000000000..289c2281a
--- /dev/null
+++ b/example/borgmatic/media-to-borg-patterns.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+import argparse
+import os
+import pathlib
+import sys
+
+def main():
+ cli = argparse.ArgumentParser(
+ prog="media-to-borg-patterns",
+ description="""Generate Borg patterns to backup media files belonging to
+ this instance. You can pass the output to Borg or Borgmatic as a patterns file.
+ For example: gotosocial admin media list-local | media-to-borg-patterns
+ <storage-local-base-path>. You can pass a second argument, the destination file, to
+ write the patterns in. If it's ommitted the patterns will be emitted on stdout
+ instead and you can redirect the output to a file yourself.
+ """,
+ epilog="Be gay, do backups. Trans rights!"
+ )
+ cli.add_argument("storageroot", type=pathlib.Path, help="same value as storage-local-base-path in your GoToSocial configuration")
+ cli.add_argument("destination", nargs="?", type=pathlib.Path, help="file to write patterns to, or stdout if ommitted")
+ args = cli.parse_args()
+
+ output = open(args.destination, 'w') if args.destination else sys.stdout
+ # Start recursing from the storage root, including the storage root itself
+ output.write("R "+str(args.storageroot)+"\n")
+
+ prefixes=set()
+
+ for line in sys.stdin:
+ # Skip any log lines
+ if "msg=" in line:
+ continue
+ # Reduce the path to the storage path plus the account ID. By
+ # doing this we can emit path-prefix patterns, one for each account,
+ # instead of a path-file pattern for each file.
+ prefixes.add(os.path.join(*line.split("/")[:-3]))
+
+ for prefix in prefixes:
+ # Add a path-prefix, pp:, for each path we want to include.
+ output.write("+ pp:"+os.path.join(os.path.sep, prefix)+"\n")
+
+ # Exclude every file and directory under the storage root. This excludes
+ # everything that wasn't matched by any of our prior patterns. This turns
+ # the emitted patterns into an "include only" list.
+ output.write("- "+os.path.join(args.storageroot, "*")+"\n")
+
+ if output is not sys.stdout:
+ output.close()
+
+if __name__ == "__main__":
+ main()