Merge pull request #8798 from ThomasWaldmann/remove-append-only

remove remainders of append-only support
This commit is contained in:
TW 2025-04-28 22:30:10 +02:00 committed by GitHub
commit d11ba6e7f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
62 changed files with 93 additions and 399 deletions

View file

@ -55,16 +55,6 @@ multiple times to permit access to more than one repository.
The repository may not exist yet; it can be initialized by the user,
which allows for encryption.
**Specificities: Append-only repositories**
Running ``borg init`` via a ``borg serve --append-only`` server will **not**
create a repository that is configured to be append-only by its repository
config.
But, ``--append-only`` arguments in ``authorized_keys`` will override the
repository config, therefore append-only mode can be enabled on a key by key
basis.
Refer to the `sshd(8) <https://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man8/sshd.8>`_
man page for more details on SSH options.
See also :ref:`borg_serve`

View file

@ -247,7 +247,7 @@ to *borg-client* has to have read and write permissions on ``/run/borg``::
On *borg-server*, we have to start the command ``borg serve`` and make its
standard input and output available to a unix socket::
borg-server:~$ socat UNIX-LISTEN:/run/borg/reponame.sock,fork EXEC:"borg serve --append-only --restrict-to-path /path/to/repo"
borg-server:~$ socat UNIX-LISTEN:/run/borg/reponame.sock,fork EXEC:"borg serve --restrict-to-path /path/to/repo"
Socat will wait until a connection is opened. Then socat will execute the
command given, redirecting Standard Input and Output to the unix socket. The
@ -350,7 +350,7 @@ dedicated ssh key:
borgs@borg-server$ install -m 700 -d ~/.ssh/
borgs@borg-server$ ssh-keygen -N '' -t rsa -f ~/.ssh/borg-client_key
borgs@borg-server$ { echo -n 'command="borg serve --append-only --restrict-to-repo ~/repo",restrict '; cat ~/.ssh/borg-client_key.pub; } >> ~/.ssh/authorized_keys
borgs@borg-server$ { echo -n 'command="borg serve --restrict-to-repo ~/repo",restrict '; cat ~/.ssh/borg-client_key.pub; } >> ~/.ssh/authorized_keys
borgs@borg-server$ chmod 600 ~/.ssh/authorized_keys
``install -m 700 -d ~/.ssh/``
@ -365,12 +365,10 @@ dedicated ssh key:
Another more complex approach is using a unique ssh key for each pull operation.
This is more secure as it guarantees that the key will not be used for other purposes.
``{ echo -n 'command="borg serve --append-only --restrict-to-repo ~/repo",restrict '; cat ~/.ssh/borg-client_key.pub; } >> ~/.ssh/authorized_keys``
``{ echo -n 'command="borg serve --restrict-to-repo ~/repo",restrict '; cat ~/.ssh/borg-client_key.pub; } >> ~/.ssh/authorized_keys``
Add borg-client's ssh public key to ~/.ssh/authorized_keys with forced command and restricted mode.
The borg client is restricted to use one repo at the specified path and to append-only operation.
Commands like *delete*, *prune* and *compact* have to be executed another way, for example directly on *borg-server*
side or from a privileged, less restricted client (using another authorized_keys entry).
The borg client is restricted to use one repo at the specified path.
``chmod 600 ~/.ssh/authorized_keys``

View file

@ -146,13 +146,6 @@ How can I restore huge file(s) over an unstable connection?
Try using ``borg mount`` and ``rsync`` (or a similar tool that supports
resuming a partial file copy from what's already copied).
How can I switch append-only mode on and off?
---------------------------------------------
You could do that (via borg config REPO append_only 0/1), but using different
ssh keys and different entries in ``authorized_keys`` is much easier and also
maybe has less potential of things going wrong somehow.
My machine goes to sleep causing `Broken pipe`
----------------------------------------------
@ -371,8 +364,8 @@ Another option is to not consider inode numbers in the files cache by passing
Why are backups slow on a Linux server that is a member of a Windows domain?
----------------------------------------------------------------------------
If a Linux server is a member of a Windows domain, username to userid resolution might be
performed via ``winbind`` without caching, which can slow down backups significantly.
If a Linux server is a member of a Windows domain, username to userid resolution might be
performed via ``winbind`` without caching, which can slow down backups significantly.
You can use e.g. ``nscd`` to add caching and improve the speed.
Security
@ -553,7 +546,6 @@ C to delete all backups residing on S.
These are your options to protect against that:
- Do not allow to delete data permanently from the repo, see :ref:`append_only_mode`.
- Use a pull-mode setup using ``ssh -R``, see :ref:`pull_backup` for more information.
- Mount C's filesystem on another machine and then create a backup of it.
- Do not give C filesystem-level access to S.

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-ANALYZE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-ANALYZE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-analyze \- Analyze archives
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-BENCHMARK-CPU" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-BENCHMARK-CPU" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-benchmark-cpu \- Benchmark CPU bound operations.
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-BENCHMARK-CRUD" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-BENCHMARK-CRUD" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-benchmark-crud \- Benchmark Create, Read, Update, Delete for archives.
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-BENCHMARK" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-BENCHMARK" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-benchmark \- benchmark command
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-BREAK-LOCK" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-BREAK-LOCK" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-break-lock \- Break the repository lock (e.g. in case it was left by a dead borg.
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-CHECK" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-CHECK" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-check \- Check repository consistency
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-COMMON" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-COMMON" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-common \- Common options of Borg commands
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-COMPACT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-COMPACT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-compact \- Collect garbage in repository
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-COMPRESSION" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-COMPRESSION" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-compression \- Details regarding compression
.SH DESCRIPTION

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-CREATE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-CREATE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-create \- Create new archive
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-DELETE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-DELETE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-delete \- Delete archives
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-DIFF" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-DIFF" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-diff \- Diff contents of two archives
.SH SYNOPSIS

View file

@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-EXPORT-TAR" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-EXPORT-TAR" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-export-tar \- Export archive contents as a tarball
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-EXTRACT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-EXTRACT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-extract \- Extract archive contents
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-IMPORT-TAR" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-IMPORT-TAR" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-import-tar \- Create a backup archive from a tarball
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-INFO" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-INFO" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-info \- Show archive details such as disk space used
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-KEY-CHANGE-LOCATION" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-KEY-CHANGE-LOCATION" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-key-change-location \- Change repository key location
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-KEY-CHANGE-PASSPHRASE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-KEY-CHANGE-PASSPHRASE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-key-change-passphrase \- Change repository key file passphrase
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-KEY-EXPORT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-KEY-EXPORT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-key-export \- Export the repository key for backup
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-KEY-IMPORT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-KEY-IMPORT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-key-import \- Import the repository key from backup
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-KEY" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-KEY" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-key \- Manage a keyfile or repokey of a repository
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-LIST" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-LIST" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-list \- List archive contents
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-MATCH-ARCHIVES" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-MATCH-ARCHIVES" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-match-archives \- Details regarding match-archives
.SH DESCRIPTION

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-MOUNT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-MOUNT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-mount \- Mount archive or an entire repository as a FUSE filesystem
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-PATTERNS" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-PATTERNS" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-patterns \- Details regarding patterns
.SH DESCRIPTION

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-PLACEHOLDERS" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-PLACEHOLDERS" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-placeholders \- Details regarding placeholders
.SH DESCRIPTION

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-PRUNE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-PRUNE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-prune \- Prune repository archives according to specified rules
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-RECREATE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-RECREATE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-recreate \- Re-create archives
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-RENAME" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-RENAME" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-rename \- Rename an existing archive
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-COMPRESS" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-COMPRESS" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-compress \- Repository (re-)compression
.SH SYNOPSIS

View file

@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-CREATE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-CREATE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-create \- Create a new, empty repository
.SH SYNOPSIS
@ -248,12 +248,6 @@ other repository is borg 1.x
.BI \-e \ MODE\fR,\fB \ \-\-encryption \ MODE
select encryption key mode \fB(required)\fP
.TP
.B \-\-append\-only
create an append\-only mode repository. Note that this only affects the low level structure of the repository, and running \fIdelete\fP or \fIprune\fP will still be allowed. See \fIappend_only_mode\fP in Additional Notes for more details.
.TP
.BI \-\-storage\-quota \ QUOTA
Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.
.TP
.B \-\-copy\-crypt\-key
copy the crypt_key (used for authenticated encryption) from the key of the other repo (default: new random key).
.UNINDENT

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-DELETE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-DELETE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-delete \- Delete a repository
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-INFO" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-INFO" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-info \- Show repository infos
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-LIST" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-LIST" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-list \- List the archives contained in a repository
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-REPO-SPACE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-REPO-SPACE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-repo-space \- Manage reserved space in repository
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-SERVE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-SERVE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-serve \- Start in server mode. This command is usually not used manually.
.SH SYNOPSIS
@ -59,12 +59,6 @@ restrict repository access to PATH. Can be specified multiple times to allow the
.TP
.BI \-\-restrict\-to\-repository \ PATH
restrict repository access. Only the repository located at PATH (no sub\-directories are considered) is accessible. Can be specified multiple times to allow the client access to several repositories. Unlike \fB\-\-restrict\-to\-path\fP sub\-directories are not accessible; PATH needs to point directly at a repository location. PATH may be an empty directory or the last element of PATH may not exist, in which case the client may initialize a repository there.
.TP
.B \-\-append\-only
only allow appending to repository segment files. Note that this only affects the low level structure of the repository, and running \fIdelete\fP or \fIprune\fP will still be allowed. See \fIappend_only_mode\fP in Additional Notes for more details.
.TP
.BI \-\-storage\-quota \ QUOTA
Override storage quota of the repository (e.g. 5G, 1.5T). When a new repository is initialized, sets the storage quota on the new repository as well. Default: no quota.
.UNINDENT
.SH EXAMPLES
.sp

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-TAG" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-TAG" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-tag \- Manage tags
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-TRANSFER" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-TRANSFER" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-transfer \- archives transfer from other repository, optionally upgrade data format
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-UMOUNT" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-UMOUNT" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-umount \- un-mount the FUSE filesystem
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-UNDELETE" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-UNDELETE" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-undelete \- Undelete archives
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-VERSION" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-VERSION" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-version \- Display the borg client / borg server version
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-WITH-LOCK" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG-WITH-LOCK" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg-with-lock \- run a user specified command with the repository lock held
.SH SYNOPSIS

View file

@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG" "1" "2025-04-21" "" "borg backup tool"
.TH "BORG" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borg \- deduplicating and encrypting backup tool
.SH SYNOPSIS

View file

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORGFS" "1" "2025-04-21" "" "borg backup tool"
.TH "BORGFS" "1" "2025-04-28" "" "borg backup tool"
.SH NAME
borgfs \- Mount archive or an entire repository as a FUSE filesystem
.SH SYNOPSIS

View file

@ -177,10 +177,6 @@ Separate compaction
Borg does not auto-compact the segment files in the repository at commit time
(at the end of each repository-writing command) any more (since borg 1.2.0).
This causes a similar behaviour of the repository as if it was in append-only
mode (see below) most of the time (until ``borg compact`` is invoked or an
old client triggers auto-compaction).
This has some notable consequences:
- repository space is not freed immediately when deleting / pruning archives
@ -197,133 +193,6 @@ This has some notable consequences:
You can manually run compaction by invoking the ``borg compact`` command.
.. _append_only_mode:
Append-only mode (forbid compaction)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A repository can be made "append-only", which means that Borg will never
overwrite or delete committed data (append-only refers to the segment files,
but borg will also reject to delete the repository completely).
If ``borg compact`` command is used on a repo in append-only mode, there
will be no warning or error, but no compaction will happen.
append-only is useful for scenarios where a backup client machine backups
remotely to a backup server using ``borg serve``, since a hacked client machine
cannot delete backups on the server permanently.
To activate append-only mode, set ``append_only`` to 1 in the repository config:
::
borg config append_only 1
Note that you can go back-and-forth between normal and append-only operation with
``borg config``; it's not a "one way trip."
In append-only mode Borg will create a transaction log in the ``transactions`` file,
where each line is a transaction and a UTC timestamp.
In addition, ``borg serve`` can act as if a repository is in append-only mode with
its option ``--append-only``. This can be very useful for fine-tuning access control
in ``.ssh/authorized_keys``:
::
command="borg serve --append-only ..." ssh-rsa <key used for not-always-trustable backup clients>
command="borg serve ..." ssh-rsa <key used for backup management>
Running ``borg repo-create`` via a ``borg serve --append-only`` server will *not* create
an append-only repository. Running ``borg repo-create --append-only`` creates an append-only
repository regardless of server settings.
Example
+++++++
Suppose an attacker remotely deleted all backups, but your repository was in append-only
mode. A transaction log in this situation might look like this:
::
transaction 1, UTC time 2016-03-31T15:53:27.383532
transaction 5, UTC time 2016-03-31T15:53:52.588922
transaction 11, UTC time 2016-03-31T15:54:23.887256
transaction 12, UTC time 2016-03-31T15:55:54.022540
transaction 13, UTC time 2016-03-31T15:55:55.472564
From your security logs you conclude the attacker gained access at 15:54:00 and all
the backups where deleted or replaced by compromised backups. From the log you know
that transactions 11 and later are compromised. Note that the transaction ID is the
name of the *last* file in the transaction. For example, transaction 11 spans files 6
to 11.
In a real attack you'll likely want to keep the compromised repository
intact to analyze what the attacker tried to achieve. It's also a good idea to make this
copy just in case something goes wrong during the recovery. Since recovery is done by
deleting some files, a hard link copy (``cp -al``) is sufficient.
The first step to reset the repository to transaction 5, the last uncompromised transaction,
is to remove the ``hints.N``, ``index.N`` and ``integrity.N`` files in the repository (these
files are always expendable). In this example N is 13.
Then remove or move all segment files from the segment directories in ``data/`` starting
with file 6::
rm data/**/{6..13}
That's all to do in the repository.
If you want to access this rolled back repository from a client that already has
a cache for this repository, the cache will reflect a newer repository state
than what you actually have in the repository now, after the rollback.
Thus, you need to clear the cache::
borg repo-delete --cache-only
The cache will get rebuilt automatically. Depending on repo size and archive
count, it may take a while.
You also will need to remove ~/.config/borg/security/REPOID/manifest-timestamp.
Drawbacks
+++++++++
As data is only appended, and nothing removed, commands like ``prune`` or ``delete``
won't free disk space, they merely tag data as deleted in a new transaction.
Be aware that as soon as you write to the repo in non-append-only mode (e.g. prune,
delete or create archives from an admin machine), it will remove the deleted objects
permanently (including the ones that were already marked as deleted, but not removed,
in append-only mode). Automated edits to the repository (such as a cron job running
``borg prune``) will render append-only mode moot if data is deleted.
Even if an archive appears to be available, it is possible an attacker could delete
just a few chunks from an archive and silently corrupt its data. While in append-only
mode, this is reversible, but ``borg check`` should be run before a writing/pruning
operation on an append-only repository to catch accidental or malicious corruption::
# run without append-only mode
borg check --verify-data && borg compact
Aside from checking repository & archive integrity you may also want to check
backups manually to ensure their content seems correct.
Further considerations
++++++++++++++++++++++
Append-only mode is not respected by tools other than Borg. ``rm`` still works on the
repository. Make sure that backup client machines only get to access the repository via
``borg serve``.
Ensure that no remote access is possible if the repository is temporarily set to normal mode
for e.g. regular pruning.
Further protections can be implemented, but are outside of Borg's scope. For example,
file system snapshots or wrapping ``borg serve`` to set special permissions or ACLs on
new data files.
SSH batch mode
~~~~~~~~~~~~~~

View file

@ -12,25 +12,21 @@ borg repo-create
.. class:: borg-options-table
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| **options** |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--other-repo SRC_REPOSITORY`` | reuse the key material from the other repository |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--from-borg1`` | other repository is borg 1.x |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``-e MODE``, ``--encryption MODE`` | select encryption key mode **(required)** |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--append-only`` | create an append-only mode repository. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details. |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--storage-quota QUOTA`` | Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota. |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--copy-crypt-key`` | copy the crypt_key (used for authenticated encryption) from the key of the other repo (default: new random key). |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| .. class:: borg-common-opt-ref |
| |
| :ref:`common_options` |
+-------------------------------------------------------+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| **options** |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| | ``--other-repo SRC_REPOSITORY`` | reuse the key material from the other repository |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| | ``--from-borg1`` | other repository is borg 1.x |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| | ``-e MODE``, ``--encryption MODE`` | select encryption key mode **(required)** |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| | ``--copy-crypt-key`` | copy the crypt_key (used for authenticated encryption) from the key of the other repo (default: new random key). |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
| .. class:: borg-common-opt-ref |
| |
| :ref:`common_options` |
+-------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------------------------------+
.. raw:: html
@ -48,8 +44,6 @@ borg repo-create
--other-repo SRC_REPOSITORY reuse the key material from the other repository
--from-borg1 other repository is borg 1.x
-e MODE, --encryption MODE select encryption key mode **(required)**
--append-only create an append-only mode repository. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details.
--storage-quota QUOTA Set storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.
--copy-crypt-key copy the crypt_key (used for authenticated encryption) from the key of the other repo (default: new random key).

View file

@ -19,10 +19,6 @@ borg serve
+-------------------------------------------------------+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--restrict-to-repository PATH`` | restrict repository access. Only the repository located at PATH (no sub-directories are considered) is accessible. Can be specified multiple times to allow the client access to several repositories. Unlike ``--restrict-to-path`` sub-directories are not accessible; PATH needs to point directly at a repository location. PATH may be an empty directory or the last element of PATH may not exist, in which case the client may initialize a repository there. |
+-------------------------------------------------------+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--append-only`` | only allow appending to repository segment files. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details. |
+-------------------------------------------------------+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | ``--storage-quota QUOTA`` | Override storage quota of the repository (e.g. 5G, 1.5T). When a new repository is initialized, sets the storage quota on the new repository as well. Default: no quota. |
+-------------------------------------------------------+-----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| .. class:: borg-common-opt-ref |
| |
| :ref:`common_options` |
@ -41,10 +37,8 @@ borg serve
options
--restrict-to-path PATH restrict repository access to PATH. Can be specified multiple times to allow the client access to several directories. Access to all sub-directories is granted implicitly; PATH doesn't need to point directly to a repository.
--restrict-to-repository PATH restrict repository access. Only the repository located at PATH (no sub-directories are considered) is accessible. Can be specified multiple times to allow the client access to several repositories. Unlike ``--restrict-to-path`` sub-directories are not accessible; PATH needs to point directly at a repository location. PATH may be an empty directory or the last element of PATH may not exist, in which case the client may initialize a repository there.
--append-only only allow appending to repository segment files. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details.
--storage-quota QUOTA Override storage quota of the repository (e.g. 5G, 1.5T). When a new repository is initialized, sets the storage quota on the new repository as well. Default: no quota.
--restrict-to-path PATH restrict repository access to PATH. Can be specified multiple times to allow the client access to several directories. Access to all sub-directories is granted implicitly; PATH doesn't need to point directly to a repository.
--restrict-to-repository PATH restrict repository access. Only the repository located at PATH (no sub-directories are considered) is accessible. Can be specified multiple times to allow the client access to several repositories. Unlike ``--restrict-to-path`` sub-directories are not accessible; PATH needs to point directly at a repository location. PATH may be an empty directory or the last element of PATH may not exist, in which case the client may initialize a repository there.
:ref:`common_options`

View file

@ -88,7 +88,6 @@ complete -c borg -l 'rsh' -d 'Use COMMAND instead of s
# borg init options
set -l encryption_modes "none keyfile keyfile-blake2 repokey repokey-blake2 authenticated authenticated-blake2"
complete -c borg -f -s e -l 'encryption' -d 'Encryption key MODE' -a "$encryption_modes" -n "__fish_seen_subcommand_from init"
complete -c borg -f -l 'append-only' -d 'Create an append-only mode repository' -n "__fish_seen_subcommand_from init"
complete -c borg -f -l 'make-parent-dirs' -d 'Create parent directories' -n "__fish_seen_subcommand_from init"
# borg create options
@ -314,7 +313,6 @@ complete -c borg -f -l 'strip-components' -d 'Remove NUMBER of leading
# borg serve
complete -c borg -l 'restrict-to-path' -d 'Restrict repository access to PATH' -n "__fish_seen_subcommand_from serve"
complete -c borg -l 'restrict-to-repository' -d 'Restrict repository access at PATH' -n "__fish_seen_subcommand_from serve"
complete -c borg -f -l 'append-only' -d 'Only allow appending to repository' -n "__fish_seen_subcommand_from serve"
# borg config
complete -c borg -f -s c -l 'cache' -d 'Get/set/list values in the repo cache' -n "__fish_seen_subcommand_from config"

View file

@ -401,7 +401,7 @@ class Archiver(
# client is allowed to specify the allowlisted options,
# everything else comes from the forced "borg serve" command (or the defaults).
# stuff from denylist must never be used from the client.
denylist = {"restrict_to_paths", "restrict_to_repositories", "append_only", "umask"}
denylist = {"restrict_to_paths", "restrict_to_repositories", "umask"}
allowlist = {"debug_topics", "lock_wait", "log_level"}
not_present = object()
for attr_name in allowlist:

View file

@ -30,29 +30,19 @@ from ..logger import create_logger
logger = create_logger(__name__)
def get_repository(location, *, create, exclusive, lock_wait, lock, append_only, args, v1_or_v2):
def get_repository(location, *, create, exclusive, lock_wait, lock, args, v1_or_v2):
if location.proto in ("ssh", "socket"):
RemoteRepoCls = LegacyRemoteRepository if v1_or_v2 else RemoteRepository
repository = RemoteRepoCls(
location,
create=create,
exclusive=exclusive,
lock_wait=lock_wait,
lock=lock,
append_only=append_only,
args=args,
location, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock, args=args
)
elif location.proto in ("sftp", "file", "rclone") and not v1_or_v2: # stuff directly supported by borgstore
repository = Repository(
location, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock, append_only=append_only
)
repository = Repository(location, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock)
else:
RepoCls = LegacyRepository if v1_or_v2 else Repository
repository = RepoCls(
location.path, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock, append_only=append_only
)
repository = RepoCls(location.path, create=create, exclusive=exclusive, lock_wait=lock_wait, lock=lock)
return repository
@ -114,7 +104,6 @@ def with_repository(
raise Error("missing repository, please use --repo or BORG_REPO env var!")
assert isinstance(exclusive, bool)
lock = getattr(args, "lock", _lock)
append_only = getattr(args, "append_only", False)
repository = get_repository(
location,
@ -122,7 +111,6 @@ def with_repository(
exclusive=exclusive,
lock_wait=self.lock_wait,
lock=lock,
append_only=append_only,
args=args,
v1_or_v2=False,
)
@ -190,7 +178,6 @@ def with_other_repository(manifest=False, cache=False, compatibility=None):
exclusive=True,
lock_wait=self.lock_wait,
lock=True,
append_only=False,
args=args,
v1_or_v2=v1_or_v2,
)

View file

@ -4,7 +4,7 @@ from ._common import with_repository, with_other_repository, Highlander
from ..cache import Cache
from ..constants import * # NOQA
from ..crypto.key import key_creator, key_argument_names
from ..helpers import CancelledByUser, CommandError
from ..helpers import CancelledByUser
from ..helpers import location_validator, Location
from ..manifest import Manifest
@ -18,8 +18,6 @@ class RepoCreateMixIn:
@with_other_repository(manifest=True, compatibility=(Manifest.Operation.READ,))
def do_repo_create(self, args, repository, *, other_repository=None, other_manifest=None):
"""Create a new, empty repository"""
if args.append_only:
raise CommandError("append-only is not supported (yet?)")
other_key = other_manifest.key if other_manifest is not None else None
path = args.location.canonical_path()
logger.info('Initializing repository at "%s"' % path)
@ -224,15 +222,6 @@ class RepoCreateMixIn:
action=Highlander,
help="select encryption key mode **(required)**",
)
subparser.add_argument(
"--append-only",
dest="append_only",
action="store_true",
help="create an append-only mode repository. Note that this only affects "
"the low level structure of the repository, and running `delete` "
"or `prune` will still be allowed. See :ref:`append_only_mode` in "
"Additional Notes for more details.",
)
subparser.add_argument(
"--copy-crypt-key",
dest="copy_crypt_key",

View file

@ -36,7 +36,6 @@ class RepoInfoMixIn:
Repository ID: {id}
Location: {location}
Repository version: {version}
Append only: {append_only}
{encryption}
"""
)
@ -45,7 +44,6 @@ class RepoInfoMixIn:
id=bin_to_hex(repository.id),
location=repository._location.canonical_path(),
version=repository.version,
append_only=repository.append_only,
encryption=info["encryption"],
)
)

View file

@ -1,7 +1,6 @@
import argparse
from ..constants import * # NOQA
from ..helpers import CommandError
from ..remote import RepositoryServer
from ..logger import create_logger
@ -12,12 +11,9 @@ logger = create_logger()
class ServeMixIn:
def do_serve(self, args):
"""Start in server mode. This command is usually not used manually."""
if args.append_only:
raise CommandError("append-only is not supported (yet?)")
RepositoryServer(
restrict_to_paths=args.restrict_to_paths,
restrict_to_repositories=args.restrict_to_repositories,
append_only=args.append_only,
use_socket=args.use_socket,
).serve()
@ -71,12 +67,3 @@ class ServeMixIn:
"PATH may be an empty directory or the last element of PATH may not exist, in which case "
"the client may initialize a repository there.",
)
subparser.add_argument(
"--append-only",
dest="append_only",
action="store_true",
help="only allow appending to repository segment files. Note that this only "
"affects the low level structure of the repository, and running `delete` "
"or `prune` will still be allowed. See :ref:`append_only_mode` in Additional "
"Notes for more details.",
)

View file

@ -245,9 +245,7 @@ class LegacyRemoteRepository:
def required_version(self):
return self.args[1]
def __init__(
self, location, create=False, exclusive=False, lock_wait=None, lock=True, append_only=False, args=None
):
def __init__(self, location, create=False, exclusive=False, lock_wait=None, lock=True, args=None):
self.location = self._location = location
self.preload_ids = []
self.msgid = 0
@ -329,12 +327,10 @@ class LegacyRemoteRepository:
lock_wait=lock_wait,
lock=lock,
exclusive=exclusive,
append_only=append_only,
v1_or_v2=True, # make remote use LegacyRepository
)
info = self.info()
self.version = info["version"]
self.append_only = info["append_only"]
except Exception:
self.close()
@ -625,10 +621,9 @@ class LegacyRemoteRepository:
@api(
since=parse_version("1.0.0"),
append_only={"since": parse_version("1.0.7"), "previously": False},
v1_or_v2={"since": parse_version("2.0.0b8"), "previously": True}, # TODO fix version
)
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=False, append_only=False, v1_or_v2=False):
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=False, v1_or_v2=False):
"""actual remoting is done via self.call in the @api decorator"""
@api(since=parse_version("2.0.0a3"))

View file

@ -7,7 +7,6 @@ import struct
import time
from collections import defaultdict
from configparser import ConfigParser
from datetime import datetime, timezone
from functools import partial
from itertools import islice
from typing import Callable, DefaultDict
@ -190,9 +189,7 @@ class LegacyRepository:
exit_mcode = 21
def __init__(
self, path, create=False, exclusive=False, lock_wait=None, lock=True, append_only=False, send_log_cb=None
):
def __init__(self, path, create=False, exclusive=False, lock_wait=None, lock=True, send_log_cb=None):
self.path = os.path.abspath(path)
self._location = Location("file://%s" % self.path)
self.version = None
@ -218,7 +215,6 @@ class LegacyRepository:
self.do_create = create
self.created = False
self.exclusive = exclusive
self.append_only = append_only
self.transaction_doomed = None
# v2 is the default repo version for borg 2.0
# v1 repos must only be used in a read-only way, e.g. for
@ -327,7 +323,6 @@ class LegacyRepository:
config.set("repository", "version", str(self.version))
config.set("repository", "segments_per_dir", str(DEFAULT_SEGMENTS_PER_DIR))
config.set("repository", "max_segment_size", str(DEFAULT_MAX_SEGMENT_SIZE))
config.set("repository", "append_only", str(int(self.append_only)))
config.set("repository", "additional_free_space", "0")
config.set("repository", "id", bin_to_hex(os.urandom(32)))
self.save_config(path, config)
@ -385,8 +380,6 @@ class LegacyRepository:
def destroy(self):
"""Destroy the repository at `self.path`"""
if self.append_only:
raise ValueError(self.path + " is in append-only mode")
self.close()
os.remove(os.path.join(self.path, "config")) # kill config first
shutil.rmtree(self.path)
@ -468,9 +461,6 @@ class LegacyRepository:
raise self.InvalidRepositoryConfig(path, "max_segment_size >= %d" % MAX_SEGMENT_SIZE_LIMIT) # issue 3592
self.segments_per_dir = self.config.getint("repository", "segments_per_dir")
self.additional_free_space = parse_file_size(self.config.get("repository", "additional_free_space", fallback=0))
# append_only can be set in the constructor
# it shouldn't be overridden (True -> False) here
self.append_only = self.append_only or self.config.getboolean("repository", "append_only", fallback=False)
self.id = hex_to_bin(self.config.get("repository", "id").strip(), length=32)
self.io = LoggedIO(self.path, self.max_segment_size, self.segments_per_dir)
@ -484,7 +474,7 @@ class LegacyRepository:
def info(self):
"""return some infos about the repo (must be opened first)"""
info = dict(id=self.id, version=self.version, append_only=self.append_only)
info = dict(id=self.id, version=self.version)
self._load_hints()
return info
@ -506,7 +496,7 @@ class LegacyRepository:
segment = self.io.write_commit()
self.segments.setdefault(segment, 0)
self.compact[segment] += LoggedIO.header_fmt.size
if compact and not self.append_only:
if compact:
self.compact_segments(threshold)
self.write_index()
self.rollback()
@ -632,15 +622,6 @@ class LegacyRepository:
transaction_id = self.io.get_segments_transaction_id()
assert transaction_id is not None
# Log transaction in append-only mode
if self.append_only:
with open(os.path.join(self.path, "transactions"), "a") as log:
print(
"transaction %d, UTC time %s"
% (transaction_id, datetime.now(tz=timezone.utc).isoformat(timespec="microseconds")),
file=log,
)
# Write hints file
hints_name = "hints.%d" % transaction_id
hints_file = os.path.join(self.path, hints_name)
@ -704,7 +685,7 @@ class LegacyRepository:
required_free_space += hints_size
required_free_space += self.additional_free_space
if not self.append_only:
if True:
full_segment_size = self.max_segment_size + MAX_OBJECT_SIZE
if len(self.compact) < 10:
# This is mostly for the test suite to avoid overestimated free space needs. This can be annoying
@ -723,7 +704,7 @@ class LegacyRepository:
)
required_free_space += compact_working_space
else:
# Keep one full worst-case segment free in non-append-only mode
# Keep one full worst-case segment free.
required_free_space += full_segment_size
try:
@ -1002,8 +983,6 @@ class LegacyRepository:
This method verifies all segment checksums and makes sure
the index is consistent with the data stored in the segments.
"""
if self.append_only and repair:
raise ValueError(self.path + " is in append-only mode")
error_found = False
def report_error(msg, *args):

View file

@ -183,7 +183,7 @@ class RepositoryServer: # pragma: no cover
"store_move",
)
def __init__(self, restrict_to_paths, restrict_to_repositories, append_only, use_socket):
def __init__(self, restrict_to_paths, restrict_to_repositories, use_socket):
self.repository = None
self.RepoCls = None
self.rpc_methods = ("open", "close", "negotiate")
@ -193,7 +193,6 @@ class RepositoryServer: # pragma: no cover
# i.e. it reflects local system policy and generally ranks higher than
# whatever the client wants, except when initializing a new repository
# (see RepositoryServer.open below).
self.append_only = append_only
self.client_version = None # we update this after client sends version information
if use_socket is False:
self.socket_path = None
@ -371,7 +370,7 @@ class RepositoryServer: # pragma: no cover
path = os.path.realpath(path)
return path
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=None, append_only=False, v1_or_v2=False):
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=None, v1_or_v2=False):
self.RepoCls = LegacyRepository if v1_or_v2 else Repository
self.rpc_methods = self._legacy_rpc_methods if v1_or_v2 else self._rpc_methods
logging.debug("Resolving repository path %r", path)
@ -395,18 +394,8 @@ class RepositoryServer: # pragma: no cover
break
else:
raise PathNotAllowed(path)
# "borg init" on "borg serve --append-only" (=self.append_only) does not create an append only repo,
# while "borg init --append-only" (=append_only) does, regardless of the --append-only (self.append_only)
# flag for serve.
append_only = (not create and self.append_only) or append_only
self.repository = self.RepoCls(
path,
create,
lock_wait=lock_wait,
lock=lock,
append_only=append_only,
exclusive=exclusive,
send_log_cb=self.send_queued_log,
path, create, lock_wait=lock_wait, lock=lock, exclusive=exclusive, send_log_cb=self.send_queued_log
)
self.repository.__enter__() # clean exit handled by serve() method
return self.repository.id
@ -574,7 +563,7 @@ class RemoteRepository:
def required_version(self):
return self.args[1]
def __init__(self, location, create=False, exclusive=False, lock_wait=1.0, lock=True, append_only=False, args=None):
def __init__(self, location, create=False, exclusive=False, lock_wait=1.0, lock=True, args=None):
self.location = self._location = location
self.preload_ids = []
self.msgid = 0
@ -651,16 +640,10 @@ class RemoteRepository:
raise Exception("Server insisted on using unsupported protocol version %s" % version)
self.id = self.open(
path=self.location.path,
create=create,
lock_wait=lock_wait,
lock=lock,
exclusive=exclusive,
append_only=append_only,
path=self.location.path, create=create, lock_wait=lock_wait, lock=lock, exclusive=exclusive
)
info = self.info()
self.version = info["version"]
self.append_only = info["append_only"]
except Exception:
self.close()
@ -965,10 +948,9 @@ class RemoteRepository:
@api(
since=parse_version("1.0.0"),
append_only={"since": parse_version("1.0.7"), "previously": False},
v1_or_v2={"since": parse_version("2.0.0b8"), "previously": True}, # TODO fix version
)
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=False, append_only=False, v1_or_v2=False):
def open(self, path, create=False, lock_wait=None, lock=True, exclusive=False, v1_or_v2=False):
"""actual remoting is done via self.call in the @api decorator"""
@api(since=parse_version("2.0.0a3"))

View file

@ -93,16 +93,7 @@ class Repository:
exit_mcode = 21
def __init__(
self,
path_or_location,
create=False,
exclusive=False,
lock_wait=1.0,
lock=True,
append_only=False,
send_log_cb=None,
):
def __init__(self, path_or_location, create=False, exclusive=False, lock_wait=1.0, lock=True, send_log_cb=None):
if isinstance(path_or_location, Location):
location = path_or_location
if location.proto == "file":
@ -139,7 +130,6 @@ class Repository:
self.created = False
self.acceptable_repo_versions = (3,)
self.opened = False
self.append_only = append_only # XXX not implemented / not implementable
self.lock = None
self.do_lock = lock
self.lock_wait = lock_wait
@ -254,7 +244,7 @@ class Repository:
"""return some infos about the repo (must be opened first)"""
# note: don't do anything expensive here or separate the lock refresh into a separate method.
self._lock_refresh() # do not remove, see do_with_lock()
info = dict(id=self.id, version=self.version, append_only=self.append_only)
info = dict(id=self.id, version=self.version)
return info
def check(self, repair=False, max_duration=0):

View file

@ -126,7 +126,7 @@ class TestCommonOptions:
formatter_class=argparse.RawDescriptionHelpFormatter,
)
subparser.set_defaults(func=1234)
subparser.add_argument("--append-only", dest="append_only", action="store_true")
subparser.add_argument("--foo-bar", dest="foo_bar", action="store_true")
def parse_vars_from_line(*line):
print(line)
@ -149,19 +149,19 @@ class TestCommonOptions:
"lock_wait": 1,
"log_level": "critical",
"progress": False,
"append_only": False,
"foo_bar": False,
"func": 1234,
}
with pytest.raises(SystemExit):
parse_vars_from_line("--append-only", "subcommand")
parse_vars_from_line("--foo-bar", "subcommand")
assert parse_vars_from_line("--append=foo", "--append", "bar", "subcommand", "--append", "baz") == {
"append": ["foo", "bar", "baz"],
"lock_wait": 1,
"log_level": "warning",
"progress": False,
"append_only": False,
"foo_bar": False,
"func": 1234,
}
@ -180,7 +180,7 @@ class TestCommonOptions:
"lock_wait": 1,
"log_level": "warning",
"progress": False,
"append_only": False,
"foo_bar": False,
"func": 1234,
args_key: args_value,
}

View file

@ -511,39 +511,6 @@ def test_shadow_index_rollback(repository):
assert repository.shadow_index[H(1)] == [] # because the deletion is considered unstable
def test_destroy_append_only(repository):
with repository:
# can't destroy append only repo (via the API)
repository.append_only = True
with pytest.raises(ValueError):
repository.destroy()
assert repository.append_only
def test_append_only(repository):
def segments_in_repository(repo):
return len(list(repo.io.segment_iterator()))
with repository:
repository.append_only = True
repository.put(H(0), fchunk(b"foo"))
repository.commit(compact=False)
repository.append_only = False
assert segments_in_repository(repository) == 2
repository.put(H(0), fchunk(b"foo"))
repository.commit(compact=True)
# normal: compact squashes the data together, only one segment
assert segments_in_repository(repository) == 2
repository.append_only = True
assert segments_in_repository(repository) == 2
repository.put(H(0), fchunk(b"foo"))
repository.commit(compact=False)
# append only: does not compact, only new segments written
assert segments_in_repository(repository) == 4
def test_additional_free_space(repository):
with repository:
add_keys(repository)
@ -680,7 +647,6 @@ def test_unknown_integrity_version(repository):
def _subtly_corrupted_hints_setup(repository):
with repository:
repository.append_only = True
assert len(repository) == 1
assert pdchunk(repository.get(H(0))) == b"foo"
repository.put(H(1), fchunk(b"bar"))
@ -703,7 +669,6 @@ def test_subtly_corrupted_hints(repository):
make_auxiliary(repository)
_subtly_corrupted_hints_setup(repository)
with repository:
repository.append_only = False
repository.put(H(3), fchunk(b"1234"))
# do a compaction run, which succeeds since the failed checksum prompted a rebuild of the index+hints.
repository.commit(compact=True)
@ -719,7 +684,6 @@ def test_subtly_corrupted_hints_without_integrity(repository):
integrity_path = os.path.join(repository.path, "integrity.5")
os.unlink(integrity_path)
with repository:
repository.append_only = False
repository.put(H(3), fchunk(b"1234"))
# do a compaction run, which fails since the corrupted refcount wasn't detected and causes an assertion failure.
with pytest.raises(AssertionError) as exc_info: