{"id":25736945,"url":"https://github.com/phdenzel/btrsnap","last_synced_at":"2026-04-18T03:31:20.090Z","repository":{"id":146779611,"uuid":"480564326","full_name":"phdenzel/btrsnap","owner":"phdenzel","description":"A lightweight btrfs snapshot script as an alternative to timeshift or snapper","archived":false,"fork":false,"pushed_at":"2022-04-20T10:19:38.000Z","size":92,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-26T06:35:03.741Z","etag":null,"topics":["btrfs","btrfs-snapshots","systemd-service","systemd-timer"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phdenzel.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-11T21:56:12.000Z","updated_at":"2022-04-20T10:09:56.000Z","dependencies_parsed_at":"2023-04-23T20:31:46.540Z","dependency_job_id":null,"html_url":"https://github.com/phdenzel/btrsnap","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/phdenzel/btrsnap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phdenzel%2Fbtrsnap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phdenzel%2Fbtrsnap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phdenzel%2Fbtrsnap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phdenzel%2Fbtrsnap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phdenzel","download_url":"https://codeload.github.com/phdenzel/btrsnap/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phdenzel%2Fbtrsnap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31955601,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btrfs","btrfs-snapshots","systemd-service","systemd-timer"],"created_at":"2025-02-26T06:31:56.061Z","updated_at":"2026-04-18T03:31:20.064Z","avatar_url":"https://github.com/phdenzel.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+AUTHOR: phdenzel\n#+TITLE: btrsnap\n#+DATE: 2022-04-12 Tue\n#+OPTIONS: author:nil title:t date:nil timestamp:nil toc:nil num:nil \\n:nil\n\n\nThis is yet another btrfs snapshotting program. Ever since I've been\nusing btrfs as the filesystem of my daily driver, I took advantage of\nthe main feature of btrfs: (almost) instantaneous snapshots. I created\nthem through [[https://github.com/teejee2008/timeshift][timeshift]], then I eventually switched to [[https://github.com/openSUSE/snapper][snapper]], never\nrealizing that btrfs-progs already ships with a pretty usable\nsnapshotting utility itself. The advantage of btrfs-progs over\ntimeshift or snapper, is that it leaves decisions to the user and\ndoesn't impose specific filesystem configurations or naming\nconventions. Over the time, I accumulated several bash scripts\nwrapping these utility functions, most of which I used to run as cron\njobs.\n\nThis is a unified re-write of these separate functions into a proper\nframework unimaginatively called ~btrsnap~. It imposes my\nconfiguration as defaults, but integrates environment variables and a\nconfiguration file, giving the user the option to fully customize to\nany setup.  Moreover, it provides systemd service and timer templates\nwhich can be used to run timed and automated snapshots.\n\n\n* Install\n\nInstall ~btrsnap~ using\n#+begin_src shell\nsudo make install\n#+end_src\nThis will install the script to ~/usr/local/bin/~ which should already\nbe in your PATH.\n\nAlternatively you can run\n#+begin_src shell\nPREFIX=/path/of/your/choice make install\n#+end_src\nwhich might need sudo priviliges depending on your choice.\nDon't forget to add the chosen prefix to your PATH.\n\nIn case you're running on ~systemd~ (I have no opinions on the matter,\nand I'm not interested in discussions about it) and you want to\nautomate btrsnap, use\n#+begin_src shell\nsudo btrsnap gentemp / root --delay 0\n#+end_src\nor for snapshotting your home directories\n#+begin_src shell\nsudo btrsnap gentemp /home home --delay 10\n#+end_src\nThese commands create a directory ~services~ and\n~btrsnap-root@.service~ and ~btrsnap-home@.service~ with corresponding\n~btrsnap-*@.timer~ templates within.\n\nThey can be installed with\n#+begin_src shell\nsudo make install-services\n#+end_src\nwhich copies the service files and their corresponding timers to\n~/etc/systemd/system/~.\n\nServices can then be timed with e.g.\n#+begin_src shell\nsudo systemctl enable --now btrsnap-root@weekly.timer\n#+end_src\nwhich will run weekly snapshots of your root subvolume.\nYou can also enable the following timers:\n- ~btrsnap-root@hourly.timer~\n- ~btrsnap-root@daily.timer~\n- ~btrsnap-root@monthly.timer~\n- ~btrsnap-root@yearly.timer~\n- analogously for other service templates\n\nThese service templates enable you to periodically snapshot your root\nsubvolume mounted at ~/~ (or in case of ~btrsnap-home@.service~ to\nsnapshot ~/home~). If you have a different setup simply add analogous\nfiles with your specifications using ~btrsnap-gentemp~.\nNote that to avoid any issues with deadlocks due to simultaneously\nwriting to the log files, it is advisable to choose different delays\nfor different btrsnap tasks using the ~--delay~ flag.\n\nTo uninstall ~btrsnap~ (from any location) and installed btrsnap\nservices and timers, simply run\n#+begin_src shell\nsudo make uninstall\n#+end_src\n\n\n* Usage\n\n~btrsnap~ has several subcommands which can be inspected using\n\n#+begin_src shell\nsudo btrsnap help\n#+end_src\n\n#+begin_src shell\nUsage: sudo btrsnap \u003csubcommand\u003e [options]\n\nSubcommands:\n    e(nv)\n        - Print all environment variables\n\n    l(i)[s](t) [options] [source]\n        - List all snapshots (and updates logs)\n\n    i(nfo) [options] [snapshot]\n        - Print info about a specific snapshot (wrapper for btrfs subvol show)\n\n    c(reate) [options] [source] [target]\n        - Create a snapshot in the target directory\n\n    r(e)m(ove) [options] [snapshot]\n        - Delete specific snapshots\n\n    d(iff) [options] [snapshot-a] [snapshot-b]\n        - Show diffs between two snapshots\n\n    u(ndo) \u003cfile\u003e [snapshot]\n        - Undo changes to a specific file from a snapshot\n\n    r(estore) [options] [snapshot] [subvolume]\n        - Restore the filesystem to a former snapshot\n\n    s(crub) [options] [source]\n        - Scrub the oldest snapshots above the limits\n\n    g(en)t(emp) [options] [source] [target]\n        - Generate systemd service and timer templates\n\nFor help with each subcommand run:\n    btrsnap \u003csubcommand\u003e -h|--help\n\nThe current basedir for btrsnap is BTRSNAP_BASEDIR=/snapshots\nIf arguments are given as relative paths, the BTRSNAP_BASEDIR variable\nis used as base path, otherwise it is ignored.\n\nbtrsnap configuration and logs are in\n    - .btrsnap/btrsnap.conf\n    - .btrsnap/btrsnap.log\n#+end_src\n\n\n*** btrsnap-create\n\nThe most frequently used command would probably be\n#+begin_src\nsudo btrsnap create / /snapshots/root\n#+end_src\nwhich saves a snapshot of the root subvolume mounted at ~/~ to\n~/snapshots/root/%y%m%dT%H:%M:%S.%2N~ (this happens to be the default\nwhich is why ~sudo btrsnap c~ yields the same result).\n\nYou can also add a different name format and some description to the\nsnapshot with\n#+begin_src shell\nsudo btrsnap c -f special / /mydata/special_dir -m \"A really special snapshot\"\n#+end_src\nThis saves the snapshot of ~/~ to ~/mydata/special_dir/special~.\n\n\n*** btrsnap-list\n\nAll snapshots, their most important attributes, and their description\ncan be inspected using\n#+begin_src shell\nsudo btrsnap ls\n#+end_src\n\n#+begin_src shell\n#  Snapshot                            Source  Time                        Flags  Mode    Description\n1  /snapshots/root/220418T22:31:23.37  /       22-04-18 22:31:23.37 +0200  r      manual  \n2  /mydata/special_dir/special         /       22-04-19 22:32:01.68 +0200  r      manual  A really special snapshot\n#+end_src\n\n\n*** btrsnap-remove\n\nIf at any point you decide to delete a snapshot, use\n#+begin_src shell\nsudo btrsnap rm /mydata/special_dir/special\n#+end_src\n\nYou can also select snapshots by index\n#+begin_src shell\nsudo btrsnap rm 2\n#+end_src\nor since in this case it is the latest snapshot\n#+begin_src shell\nsudo btrsnap rm -1\n#+end_src\n\n\n*** btrsnap-scrub\n\n~btrsnap~ works with modes and limit parameters (which of course can\nbe reconfigured). Each mode has different limit defaults:\n\n- manual: 12\n- hourly: 4\n- daily: 3\n- weekly: 6\n- monthly: 4\n- yearly: 1\n\nThe ~scrub~ subcommand enforces these limits and deletes the oldest\nsnapshots when the number of snapshots with that mode is exceeded.\n\nFor instance,\n#+begin_src shell\nsudo btrsnap scrub /\n#+end_src\nclears all snapshots of root with all modes.\n\n#+begin_src shell\nsudo btrsnap scrub --mode hourly\n#+end_src\nclears all snapshots taken in 'hourly' mode regardless of its source.\n\n\n** Configuration file\n\n~btrsnap~ integrates with environment variables and configuration\nfiles. In case you don't want to change the program's source code\nitself, add\n#+begin_src shell\nexport BTRSNAP_CONF=/snapshots/.btrsnap/btrsnap.conf~\n#+end_src\nto your ~.bashrc~ or ~.zshrc~. In the configuration file you can\ndefine your own default values for\n#+begin_src conf\nBTRSNAP_BASEDIR=\"/snapshots\"\nBTRSNAP_LOG=\".$PROGNAME/$PROGNAME.log\"\nBTRSNAP_SRC='/'\nBTRSNAP_TARGET=\"root\"\nBTRSNAP_MODE=\"manual\"\nBTRSNAP_WRITABLE=0\nBTRSNAP_TIMEFORMAT=\"+%y%m%dT%H:%M:%S.%2N\"\nBTRSNAP_WARNINGS=1\n\nBTRSNAP_MANUAL_LIMIT=12\nBTRSNAP_MONTHLY_LIMIT=4\nBTRSNAP_WEEKLY_LIMIT=3\nBTRSNAP_DAILY_LIMIT=6\nBTRSNAP_HOURLY_LIMIT=4\nBTRSNAP_YEARLY_LIMIT=1\n\nDRY_RUN=0\nVERBOSE=0\n#+end_src\n\n\n**** TODO\n\nNote, for now, snapshots have to reside on the same btrfs device.\n\n- [ ] btrsnap-remove: * w/ mode selection\n- [ ] compatibility with external devices/drives\n  (for external devices you need to manually use btrfs send/receive\n   and `btrfs property set` ro to false)\n- [ ] pacman hooks to automatically run btrsnap on installs or upgrades\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphdenzel%2Fbtrsnap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphdenzel%2Fbtrsnap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphdenzel%2Fbtrsnap/lists"}