diff --git a/docs/faq.rst b/docs/faq.rst index 51852e910..44f78c99b 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -187,6 +187,26 @@ all the part files and manually concatenate them together. For more details, see :ref:`checkpoints_parts`. +My repository is corrupt, how can I restore from an older copy of it? +--------------------------------------------------------------------- + +If your repositories are encrypted and have the same ID, the recommended method +is to delete the corrupted repository, but keep its security info, and then copy +the working repository to the same location: + +:: + + borg delete --keep-security-info /path/to/repo + rsync -aH /path/to/repo-working/ /path/to/repo # Note the trailing slash. + +A plain delete command would remove the security info in +``~/.config/borg/security``, including the nonce value. In BorgBackup +:ref:`security_encryption` is AES-CTR, where the nonce is a counter. When the +working repo was used later for creating new archives, Borg would re-use nonce +values due to starting from a lower counter value given by the older copy of the +repository. To prevent this, the ``keep-security-info`` option is applied so +that the client-side nonce counter is kept. + Can Borg add redundancy to the backup data to deal with hardware malfunction? ----------------------------------------------------------------------------- diff --git a/docs/internals/security.rst b/docs/internals/security.rst index 3d1717fa2..ac26bc5f0 100644 --- a/docs/internals/security.rst +++ b/docs/internals/security.rst @@ -118,6 +118,8 @@ prompt is a set BORG_PASSPHRASE. See issue :issue:`2169` for details. manifest this way, while a changed layout would have broken compatibility. +.. _security_encryption: + Encryption ---------- diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 6a37d31b6..15be2c2ee 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -1184,6 +1184,7 @@ class Archiver: def _delete_repository(self, args, repository): """Delete a repository""" dry_run = args.dry_run + keep_security_info = args.keep_security_info if not args.cache_only: msg = [] @@ -1208,9 +1209,11 @@ class Archiver: if not dry_run: repository.destroy() logger.info("Repository deleted.") - SecurityManager.destroy(repository) + if not keep_security_info: + SecurityManager.destroy(repository) else: logger.info("Would delete repository.") + logger.info("Would %s security info." % ("keep" if keep_security_info else "delete")) if not dry_run: Cache.destroy(repository) logger.info("Cache deleted.") @@ -3360,9 +3363,10 @@ class Archiver: Important: When deleting archives, repository disk space is **not** freed until you run ``borg compact``. - If you delete the complete repository, the local cache for it (if any) is - also deleted. Alternatively, you can delete just the local cache with the - ``--cache-only`` option. + When you delete a complete repository, the security info and local cache for it + (if any) are also deleted. Alternatively, you can delete just the local cache + with the ``--cache-only`` option, or keep the security info with the + ``--keep-security-info`` option. When using ``--stats``, you will get some statistics about how much data was deleted - the "Deleted data" deduplicated size there is most interesting as @@ -3391,10 +3395,11 @@ class Archiver: help='print statistics for the deleted archive') subparser.add_argument('--cache-only', dest='cache_only', action='store_true', help='delete only the local cache for the given repository') - subparser.add_argument('--force', dest='forced', - action='count', default=0, + subparser.add_argument('--force', dest='forced', action='count', default=0, help='force deletion of corrupted archives, ' 'use ``--force --force`` in case ``--force`` does not work.') + subparser.add_argument('--keep-security-info', dest='keep_security_info', action='store_true', + help='keep the local security info when deleting a repository') subparser.add_argument('--save-space', dest='save_space', action='store_true', help='work slower, but using less space') subparser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE', nargs='?', default='',