{"id":13588037,"url":"https://github.com/kiwix/borg-backup","last_synced_at":"2025-05-13T16:31:23.304Z","repository":{"id":42972188,"uuid":"288727363","full_name":"kiwix/borg-backup","owner":"kiwix","description":"Backup easily your system with Bitwarden, BorgBase and Docker","archived":false,"fork":false,"pushed_at":"2024-08-02T19:01:42.000Z","size":158,"stargazers_count":16,"open_issues_count":9,"forks_count":2,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-02T05:02:34.086Z","etag":null,"topics":["backup","bitwarden","borg","borgbase","borgmatic","docker"],"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/kiwix.png","metadata":{"files":{"readme":"README.md","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},"funding":{"github":"kiwix","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-08-19T12:34:33.000Z","updated_at":"2025-03-29T23:20:39.000Z","dependencies_parsed_at":"2024-05-02T16:00:11.358Z","dependency_job_id":"d1db3b85-4f0c-43b9-941c-b798d0cf3b10","html_url":"https://github.com/kiwix/borg-backup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwix%2Fborg-backup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwix%2Fborg-backup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwix%2Fborg-backup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwix%2Fborg-backup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kiwix","download_url":"https://codeload.github.com/kiwix/borg-backup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253981759,"owners_count":21994330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["backup","bitwarden","borg","borgbase","borgmatic","docker"],"created_at":"2024-08-01T15:06:28.655Z","updated_at":"2025-05-13T16:31:19.698Z","avatar_url":"https://github.com/kiwix.png","language":"Shell","readme":"Kiwix's backup companion\n========================\n\n[![CodeFactor](https://www.codefactor.io/repository/github/kiwix/borg-backup/badge)](https://www.codefactor.io/repository/github/kiwix/borg-backup)\n[![Docker](https://img.shields.io/badge/docker-latest-blue)](https://ghcr.io/kiwix/borg-backup)\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n\nA [Docker image](https://hub.docker.com/r/kiwix/borg-backup) to easily backup your services' data into [BorgBase](https://www.borgbase.com/).\n\n## What's this?\n\nThis tool is a Docker image that you launch along your other Docker services, sharing the data volume with it (read-only).\n\nExample:\n\n```sh\n# running your imaginary service\ndocker run -v /data/www:/var/www/html -d nginx\n# running your backup companion\ndocker run -v /data/www:/storage:ro ghcr.io/kiwix/borg-backup backup --name nginx --every 1h\n```\n\nIn this example, the content of `/data/www` on the host will be securely backed-up to BorgBase every hour.\n\n## How it works\n\nThere are three main components to this tool:\n\n- [BorgBase](https://www.borgbase.com/) is an affordable backup hosting service. We use it to store encrypted backups. You can use the free plan which is limited to two repositories or use a paid plan.\n- [Bitwarden](https://bitwarden.com/) is a secured password management service. We only use features from the free plan.\n- [Borg](https://www.borgbackup.org/) is an FOSS backup tool that creates and transmits encrypted backups.\n\nIn BorgBase, everything revolves around the concept of a *repository*. It's a place (~folder) in which your data goes (encrypted). For every *datasource* that you want to backup, you'll have one BorgBase repository and one companion container.\n\nThis tool generates an SSH keypair for your repo, configures BorgBase to allow backups using this key (with *append-only* restriction) and stores the keypair in your Bitwarden account so you don't have to worry much about credentials.\n\n## What do I need?\n\n* Mandatory: One BorgBase account (free or paid)\n* Mandatory: A Bitwarden accounts (a *master*)\n* Optional: A second Bitwarden account (a *backuper* one without the credential to create/read BorgBase repositories)\n\n### Accounts setup (to do once)\n\nThis is the annoying part. You'll have to manually create a couple of accounts and do some manipulations. This is a one-time thing, no matter how many repos you'll setup.\n\n#### BorgBase\n\n1. Create an account at [BorgBase](https://www.borgbase.com/register) (or reuse one)\n1. Once logged it, go to [Acounts » API](https://www.borgbase.com/account?tab=2) then **New Token**.\n1. Choose a name (`kiwix-backup`?) and make sure you select **Create only** (important!)\n1. Securely keep a reference to that created token, you'll need that every time you setup a new repository.\n\n#### Bitwarden\n\nIn order to store what we need in Bitwarden (SSH keypairs, BorgBase token) but without exposing our Bitwarden token to the backup companion, we'll use two different accounts:\n\n- one that is used solely to setup repo. That's the *master* account.\n- one that is used when backing-up. This *backuper* one will have read-only access to the items in the vault.\n\n**Note**: You can use only one account if you want. But using two accounts is safer. That said, it doesn't mean the read-only account should be considered public. Keep it safe!\n\n1. Create one master Bitwarden account (email/password)\n1. Create an *Organization* from that account's UI\n1. Create a single *Collection* to be shared accross this organization\n1. Invite a member to this organization, with:\n - the email adress you'll use to create that second Bitwarden account in a minute\n - choosing `User` mode\n - choising `selected-collections only`\n - check the collection you created earlier\n - check `read-only` (but not hide password)\n1. using the invitation link your received on that email address, create one backup Bitwarden account (email/password)\n1. login to Bitwarden UI using master account and confirm membership\n\nWe'll be using an *API Key* to connect to your read-only bitwarden account so from the bitwarden UI, goto *Settings* and *View API Key*. Note the value for `client_id` and `client_secret`. Those will be referred to later as `BW_CLIENTID` and `BW_CLIENTSECRET`.\n\n## Usage\n\nEvery *repository* or service you want to backup needs to be initialized once before you start backing-up your data.\nThis is a quick step that is separated from the backup one in order to keep your *master* Bitwarden credentials from being moved around.\n\n### Setting up\n\nThis command is intended to be run from your local machine so you don't have to insert your credentials on any other system.\n\nThis tool is **interactive** and will ask for your Bitwarden master API ClientID, API Secret, password and your BorgBase token (both you should have created in *Accounts setup*).\n\n```sh\ndocker run -it ghcr.io/kiwix/borg-backup setup-new-repo \\\n    --name \u003crepo-name\u003e \\\n    --bitwarden \u003cbitwarden-master-email\u003e \\\n    --alert-days \u003cnb-days\u003e\n    --quota \u003cmax-storage\u003e\n    --region \u003cregion\u003e\n```\n\n#### Choosing a repo-name\n\nWe suggest you use reverse-FQDN notation for your repo names as the Bitwarden matching is done using a *search* query meaning that if you have two repositories named `my-service` and `my-service2`, the first one will fail, receiving two results instead of one.\n\n\n**Optional values**:\n\n- `\u003cnb-days\u003e`: periodicity of BorgBase e-mail alert in day(s) (default : `1`)\n- `\u003cmax-storage\u003e`:  quota in MB (default: no quota)\n- `\u003cregion\u003e`: BorgBase server region (`eu` or `us`) (default : `eu`)\n\nThat's it. You should now have a *repoitory* ready to receive backups.\n\n### Backing-up\n\nThe following is unattended and should be configured along your service. It runs forever, backing-up at the given interval.\n\n```sh\ndocker run -v \u003csome-folder\u003e:/storage:ro \\\n    -e BW_CLIENTID=\u003cbitwarden-readonly-apikey-clientid\u003e \\\n    -e BW_CLIENTSECRET=\u003cbitwarden-readonly-apikey-secret\u003e \\\n    -e BW_PASSWORD=\u003cbitwarden-readonly-password\u003e \\\n    ghcr.io/kiwix/borg-backup backup --name \u003crepo-name\u003e --every \u003cperiod\u003e\n```\n\n- `\u003crepo-name\u003e` is the *repository* name configured in the setup step.\n- `\u003cperiod\u003e` is the interval to launch backup on: units are `m` for minutes (`1-30`), `h` for hours (`1-30`), `d` for days (`1-14`), `M` for months (`1-6`).\n\nOther parameters can be configured via Docker environment variables:\n\n- Retention options:\n  - `KEEP_WITHIN`: keep all archives less than this old (no used by default)\n  - `KEEP_DAILY`: keep last archive of this many latest days (default: `7`)\n  - `KEEP_WEEKLY`: keep last archive of this many latest weeks (default: `5`)\n  - `KEEP_MONTHLY`: keep last archive of this many latest months (default: `12`)\n  - `KEEP_YEARLY`: keep last archive of this many latest years (default: `1`)\n- Databases backup:\n  - `DATABASES`: DSNs of the database to backup.\n  - `DATABASES_OPTIONS`: Options passed to all databases hookd. eg: `--ignore-table=wp1.too_large_table`\n\nDatabase DSN should be in the form: `type://user:password@host:port/dbname`. It only supports `mysql`, `postgresql` and `mongodb`. `dbname` can be `all` to backup all databases of that host/connexion.\n\n**Note**: Bitwarden will send you a `New Device Logged In From Linux` email every time you launch that container.\n\n### Single back-up\n\nIf you want to rely on your own scheduling tool, you can use the `single-backup` command which just runs the backup once and exits.\n\nNote that contrary to the regular `backup` command, there is no interactive request for missing credentials. As for invalid credentials, this will simply fail the container.\n\n```sh\ndocker run -v \u003csome-folder\u003e:/storage:ro \\\n    -e BW_CLIENTID=\u003cbitwarden-readonly-apikey-clientid\u003e \\\n    -e BW_CLIENTSECRET=\u003cbitwarden-readonly-apikey-secret\u003e \\\n    -e BW_PASSWORD=\u003cbitwarden-readonly-password\u003e \\\n    ghcr.io/kiwix/borg-backup single-backup --name \u003crepo-name\u003e\n```\n\n### Custom command back-up (cli-mode)\n\nIf you need to execute a command to prepare your backup data you can enable *cli-mode*.\n\nBy setting the `CLI_MODE` variable, you are instructing the tool to run your passed command and, should it succeed, start a single-backup.\n\n- It requires passing all backup-related conf via environment variables.\n- It can be combined with regular data (/storage or databases).\n- It is restricted to single-backup. Container exits after your command and single-backup finishes.\n\n```sh\ndocker run \\\n    -e BW_CLIENTID=\u003cbitwarden-readonly-apikey-clientid\u003e \\\n    -e BW_CLIENTSECRET=\u003cbitwarden-readonly-apikey-secret\u003e \\\n    -e BW_PASSWORD=\u003cbitwarden-readonly-password\u003e \\\n    -e BORGBASE_NAME=\u003crepo-name\u003e \\\n    -e CLI_MODE=y \\\n    -v $HOME/.kube/config:/root/.kube/config:ro \\\n    ghcr.io/kiwix/borg-backup kube-dump all \u003e /storage/\n```\n\n**Note**: [`kube-dump`](https://github.com/WoozyMasta/kube-dump) is installed in the image.\n\n## Restoring data\n\n### Using the extract tool\n\nYour backups are composed of *archives* or *versions* of your data. Use this tool to list and extract them with ease.\n\n```sh\ndocker run \\\n    -v /data/temp:/restore:rw \\\n    -e BW_CLIENTID=\u003cbitwarden-readonly-apikey-clientid\u003e \\\n    -e BW_CLIENTSECRET=\u003cbitwarden-readonly-apikey-secret\u003e \\\n    -e BW_PASSWORD=\u003cbitwarden-readonly-password\u003e \\\n    ghcr.io/kiwix/borg-backup restore --name \u003crepo-name\u003e --list\n```\n\nThis will list all the available archives. Note the name of the one you'll want to extract.\n\n```sh\ndocker run \\\n    -v /data/temp:/restore:rw \\\n    -e BW_CLIENTID=\u003cbitwarden-readonly-apikey-clientid\u003e \\\n    -e BW_CLIENTSECRET=\u003cbitwarden-readonly-apikey-secret\u003e \\\n    -e BW_PASSWORD=\u003cbitwarden-readonly-password\u003e \\\n    ghcr.io/kiwix/borg-backup restore --name \u003crepo-name\u003e --extract \"\u003carchive-name\u003e\"\n```\n\nThis will extract the content of the archive into `/restore` (which you should have mounted accordingly on the host).\n\n`--extract` accepts a special value of `latest` that gets the lasted archive from the list.\n\n### Manually\n\nAs your backup as just regular borg backups, you can follow [these docs](https://docs.borgbase.com/restore/) to restore your data manually.\n\nRestoring requires your SSH keypair stored in bitwarden. In your Bitwarden vault, you'll find one item for each of your *repository*. In this item, you'll find:\n\n- `username`: that's your SSH public key. Save it as `~/.ssh/\u003cmyrepo\u003e.pub`\n- `password`: that's your SSH private key. Save it as `~/.ssh/\u003cmyrepo\u003e`\n- `BORGBASE_TOKEN`: that's your borgbase token. You don't need it for restoring.\n\nYou can now list, retrieve and extract any borg archive using regular tools.\n\n## FAQ\n\n### Can I specify multiple folders to backup?\n\nYes, just mount them as subfolders inside `/storage`:\n\n```sh\ndocker run \\\n    -v /data/media/images:/storage/images:ro \\\n    -v /data/attachments:/storage/attachments:ro \\\n    ghcr.io/kiwix/borg-backup backup --name myservice --every 1h\n```\n\n### Can I backup both a database and files at the same time?\n\nYes, if you specify `DATABASES` env, it's added on top of the mounted volume.\n\n⚠️ There is an important constraint when backing up both databases and files: your `/storage` mounted volume **must be a single volume**. You can not mount any other folder under `/storage` and expect its files to be included. Those will silently be ignored.\n\nIf you would like to mount several volumes inside `/storage` and also backup databases, there is **a trick**: you can do it by setting the `CROSS_FS_GLOB` envrionment variable. Note that there are two catches:\n\n- hidden files/folders in `/storage` (root) will not be included\n- it relies on [undocumented/unexpected](https://projects.torsion.org/borgmatic-collective/borgmatic/issues/520 ) behavior\n\n### Can I backup several databases at the same time?\n\nYes, beside the `all` trick mentionned above, if you need to backup a list of databases or databases on different hosts or of different kinds, just concatenate the DSNs into the `DATABASES` env, separating them with `|||`.\n\n```\n-e DATABASES=\"mysql://root:root@db:3306/all|||mysql://user:pass@prod:3306/clients\"\n```\n\n### Can I replace BorgBase with another host?\n\nNo, at the moment, we use their API so it can't be replaced with another service.\n\n### What if my Bitwarden is compromised?\n\nDon't panic! If your read-only Bitwarden credentials are compromised, you won't loose any data:\n\n- Bitwarden items can't be modified by this account\n- The SSH keypairs stored in Bitwarden are now compromised but it can only do much on BorgBase:\n    - append new data to your repos (but cannot delete those you backed-up)\n    - read backuped data (check and delete those if that happened)\n\nYou should now manually remove the keypairs from BorgBase and remove post-incident archives from your repo (read [this documentation on append-only](https://docs.borgbase.com/faq/#append-only-mode) first).\n\n### Can I use a single Bitwarden account?\n\nYes, but we highly discourage it.\n\nThe sole account is thus the read-write one (*master*) and it means it it gets compromised, one could delete items from your Bitwarden account. As your SSH keypairs are only stored in Bitwarden, loosing them mean you won't be able to retrieve nor decrypt your backups.\n","funding_links":["https://github.com/sponsors/kiwix"],"categories":["Shell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwix%2Fborg-backup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkiwix%2Fborg-backup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwix%2Fborg-backup/lists"}