Repository: borgbackup/borg

Issue:
Borg init configuring the repository as read-only when served with "--append-only"
I spent a couple of hours figuring out why my repository size wasn't shrinking despite repeated calls to `prune` before I realised what's going on.

My borg server is configured as `borg serve --append-only`, to protect against backups being deleted by a hacked client. I use a seperate repository for each backup client, so `borg init` is always ran on the client through the SSH connection. This apparently causes the repository to be "permanently" read-only, with `append_only = 1` being written to the repository config. 

This means diskspace cannot be recovered from the repository, even if `borg prune` is ran on the server itself. I would expect `borg init` to create a regular repository, even if the server is running in append-only mode (unless, of course, `-a` is used).


Discussion:
The borg serve --append-only parameter is to enforce append-only mode in a way that can not be overridden by the client (for security reasons), so I'ld say it works as designed.

What you need is maybe a separate authorized_keys entry without --apend-only and a different ssh key, that gives you more power when using it from a trusted administration client.

If you use encryption, borg prune usually can't run on the server as the untrusted server usually should not have the encryption/decryption key - but that key is needed for pruning.
If this is the intended behavior, perhaps it would be useful to describe it in the documentation at http://borgbackup.readthedocs.io/en/stable/usage.html#append-only-mode. I didn't expect it to affect the configuration for a newly created repository. (I understand the need to enforce append-only mode for the current connection regardless of the client, but setting append_only = 1 in the config doesn't only affect the current session but also all future operations) 

I could indeed `init` the repository from a separate trusted client, but deployment is much more flexible if all backup clients can init their own repository themselves when they're first launched.

(Even more awesome would be if a repository could have a separate writeonly-key and readwrite-key, so the borg server itself could automatically prune repositories without being able to read the contents)
That kinda makes sense.

1.0 -> No change, document as is. (moved to #2440)
1.1 -> Maybe change to create && append-only => create && !append-only and document.
Is this a request for a documentation change only, or do you plan to change the way future calls to `borg init` will function?

If just a documentation change, perhaps a "Note" can be added at the end of the `borg init` sub-section under Usage. This note could describe the considerations and behavior of using --append-only to init a new repository.  Also, perhaps a reference to http://borgbackup.readthedocs.io/en/latest/usage.html#drawbacks.
#2440 is about changing the docs, this one is about changing the behaviour.

Resolving patch:
diff --git a/src/borg/remote.py b/src/borg/remote.py
--- a/src/borg/remote.py
+++ b/src/borg/remote.py
@@ -180,6 +180,10 @@ class RepositoryServer:  # pragma: no cover
     def __init__(self, restrict_to_paths, append_only):
         self.repository = None
         self.restrict_to_paths = restrict_to_paths
+        # This flag is parsed from the serve command line via Archiver.do_serve,
+        # 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 = parse_version('1.0.8')  # fallback version if client is too old to send version information
 
@@ -345,8 +349,12 @@ def open(self, path, create=False, lock_wait=None, lock=True, exclusive=None, ap
                     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 = Repository(path, create, lock_wait=lock_wait, lock=lock,
-                                     append_only=self.append_only or append_only,
+                                     append_only=append_only,
                                      exclusive=exclusive)
         self.repository.__enter__()  # clean exit handled by serve() method
         return self.repository.id


Test patch: