Added new Feature - BORG_APPEND_ONLY & BORG_ADMIN

This commit is contained in:
Gerrit Pannek 2019-04-04 18:19:14 -05:00
parent ae2f6c90ef
commit 1b4ea9e2a0
3 changed files with 81 additions and 50 deletions

View file

@ -4,10 +4,10 @@ For every ssh-key added, a own borg-repository will be created.
**NOTE: I will assume that you know, what a ssh-key is and how to generate & use it. If not, you might want to start here: [Arch Wiki](https://wiki.archlinux.org/index.php/SSH_Keys)** **NOTE: I will assume that you know, what a ssh-key is and how to generate & use it. If not, you might want to start here: [Arch Wiki](https://wiki.archlinux.org/index.php/SSH_Keys)**
### Quick Example ## Quick Example
Here is a quick example how to configure & run this image: Here is a quick example how to configure & run this image:
#### Create persistent sshkey storage ### Create persistent sshkey storage
``` ```
$ mkdir -p borg/sshkeys/clients $ mkdir -p borg/sshkeys/clients
``` ```
@ -17,7 +17,7 @@ Make sure that the permissions are right on the sshkey folder:
$ chown 1000:1000 borg/sshkeys $ chown 1000:1000 borg/sshkeys
``` ```
#### (Generate &) Copy every client's ssh publickey into persistent storage ### (Generate &) Copy every client's ssh publickey into persistent storage
*Remember*: Filename = Borg-repository name! *Remember*: Filename = Borg-repository name!
``` ```
$ cp ~/.ssh/my_machine.pub borg/sshkeys/clients/my_machine $ cp ~/.ssh/my_machine.pub borg/sshkeys/clients/my_machine
@ -26,28 +26,51 @@ Make sure that the permissions are right on the sshkey folder:
The OpenSSH-Deamon will expose on port 22/tcp - so you will most likely want to redirect it to a different port. Like in this example: The OpenSSH-Deamon will expose on port 22/tcp - so you will most likely want to redirect it to a different port. Like in this example:
``` ```
docker run -td \ docker run -td \
-p 2222:22 \ -p 2222:22 \
--volume ./borg/sshkeys:/sshkeys \ --volume ./borg/sshkeys:/sshkeys \
--volume ./borg/backup:/backup \ --volume ./borg/backup:/backup \
nold360/borgserver:latest nold360/borgserver:latest
``` ```
## Borgserver Configuration ## Borgserver Configuration
* Place Borg-Clients SSH-PublicKeys in persistent storage * Place Borg-Clients SSH-PublicKeys in persistent storage
* Client Repositories will be named by the filename found in /sshkeys/clients/ * Client backup-directories will be named by the filename found in /sshkeys/clients/
### Environment Variables ### Environment Variables
#### BORG_SERVE_ARGS #### BORG_SERVE_ARGS
Use this variable if you want to set special options for the "borg serve"-command, which is used internally. Use this variable if you want to set special options for the "borg serve"-command, which is used internally.
See the the documentation for all available arguments: [borgbackup.readthedocs.io](https://borgbackup.readthedocs.io/en/1.0.9/usage.html#borg-serve) See the the documentation for all available arguments: [borgbackup.readthedocs.io](https://borgbackup.readthedocs.io/en/stable/usage.html#borg-serve)
##### Example ##### Example
``` ```
docker run -e BORG_SERVE_ARGS="--append-only --debug" (...) nold360/borgserver docker run --rm -e BORG_SERVE_ARGS="--progress --debug" (...) nold360/borgserver
``` ```
#### BORG_APPEND_ONLY
If you want your client to be only able to append & not prune anything from their repo, set this variable to **"yes"**.
#### BORG_ADMIN
When *BORG_APPEND_ONLY* is active, no client is able to prune it's repo.
Since you might want to cleanup the repos at some point, you can declare one client to be the borg "admin".
This client will have **full access to all repos of any client!** So he's able to add/prune/... what ever he wants.
To declare a client as admin, set this variable to the name of the client/sshkey you've added to the /sshkeys/clients directory.
##### Example
```
docker run --rm -e BORG_APPEND_ONLY="yes" -e BORG_ADMIN="nolds_notebook" (...) nold360/borgserver
```
To prune repos from another client, you have to add the path to the repository in the clients directory:
```
borg prune --keep-last 100 --keep-weekly 1 (...) borgserver:/clientA/clientA
```
### Persistent Storages & Client Configuration ### Persistent Storages & Client Configuration
We will need two persistent storage directories for our borgserver to be usefull. We will need two persistent storage directories for our borgserver to be usefull.
@ -90,10 +113,12 @@ services:
ports: ports:
- "2222:22" - "2222:22"
environment: environment:
BORG_SERVE_ARGS: "--append-only" BORG_SERVE_ARGS: ""
BORG_APPEND_ONLY: "no"
BORG_ADMIN: ""
``` ```
### ~/.ssh/config ### ~/.ssh/config for clients
With this configuration (on your borg client) you can easily connect to your borgserver. With this configuration (on your borg client) you can easily connect to your borgserver.
``` ```
Host backup Host backup

View file

@ -1,65 +1,77 @@
#!/bin/bash #!/bin/bash
# Init borg-users .ssh/authorized_keys # Start Script for docker-borgserver
BORG_DATA_DIR=/backup BORG_DATA_DIR=/backup
BORG_CMD='cd ${BORG_DATA_DIR}/${client_name}; borg serve --restrict-to-path ${BORG_DATA_DIR}/${client_name}'
SSH_KEY_DIR=/sshkeys SSH_KEY_DIR=/sshkeys
BORG_CMD='cd ${BORG_DATA_DIR}/${client_name}; borg serve --restrict-to-path ${BORG_DATA_DIR}/${client_name} ${BORG_SERVE_ARGS}'
# Parse environment # Append only mode?
if [ ! -z "${BORG_SERVE_ARGS}" ] ; then BORG_APPEND_ONLY=${BORG_APPEND_ONLY:=no}
BORG_CMD="${BORG_CMD} ${BORG_SERVE_ARGS}"
echo "########################################################"
echo -n " * Docker BorgServer powered by "
borg -V
echo "########################################################"
# Precheck if BORG_ADMIN is set
if [ "${BORG_APPEND_ONLY}" == "yes" ] && [ -z "${BORG_ADMIN}" ] ; then
echo "WARNING: BORG_APPEND_ONLY is active, but no BORG_ADMIN was specified!"
fi fi
# add all sshkeys to borg-user's authorized_keys & create repositories # Precheck directories & client ssh-keys
echo "########################################################"
for dir in BORG_DATA_DIR SSH_KEY_DIR ; do for dir in BORG_DATA_DIR SSH_KEY_DIR ; do
dirpath=$(eval echo '$'$dir) dirpath=$(eval echo '$'${dir})
echo " * Testing Volume $dir: $dirpath" echo " * Testing Volume ${dir}: ${dirpath}"
if [ ! -d "$dirpath" ] ; then if [ ! -d "${dirpath}" ] ; then
echo "ERROR: $dirpath is no directory!" echo "ERROR: ${dirpath} is no directory!"
exit 1 exit 1
fi fi
if [ $(find "${SSH_KEY_DIR}/clients" -type f | wc -l) == 0 ] ; then if [ "$(find ${SSH_KEY_DIR}/clients -type f | wc -l)" == "0" ] ; then
echo "ERROR: No SSH-Pubkey file found in $SSH_KEY_DIR" echo "ERROR: No SSH-Pubkey file found in ${SSH_KEY_DIR}"
exit 1 exit 1
fi fi
done done
# (Create &) Copy SSH-Host-Keys to persistent storage # Create SSH-Host-Keys on persistent storage, if not exist
mkdir -p ${SSH_KEY_DIR}/host 2>/dev/null mkdir -p ${SSH_KEY_DIR}/host 2>/dev/null
echo " * Checking / Preparing SSH Host-Keys..." echo " * Checking / Preparing SSH Host-Keys..."
for keytype in ed25519 rsa ; do
if [ ! -f /etc/ssh/ssh_host_rsa_key ] ; then if [ ! -f "${SSH_KEY_DIR}/host/ssh_host_${keytype}_key" ] ; then
echo " ** Creating SSH Hostkeys..." echo " ** Creating SSH Hostkey [${keytype}]..."
for keytype in ed25519 rsa ; do ssh-keygen -q -f "${SSH_KEY_DIR}/host/ssh_host_${keytype}_key" -N '' -t ${keytype}
ssh-keygen -q -f "/etc/ssh/ssh_host_${keytype}_key" -N '' -t $keytype
done
fi
for keyfile in ssh_host_rsa_key ssh_host_ed25519_key ; do
if [ ! -f "${SSH_KEY_DIR}/host/${keyfile}" ] ; then
cp /etc/ssh/${keyfile} "${SSH_KEY_DIR}/host/${keyfile}"
fi fi
done done
echo "########################################################"
echo "########################################################"
echo " * Starting SSH-Key import..." echo " * Starting SSH-Key import..."
# Add every key to borg-users authorized_keys
rm /home/borg/.ssh/authorized_keys &>/dev/null rm /home/borg/.ssh/authorized_keys &>/dev/null
for keyfile in $(find "${SSH_KEY_DIR}/clients" -type f); do for keyfile in $(find "${SSH_KEY_DIR}/clients" -type f); do
client_name=$(basename $keyfile) client_name=$(basename ${keyfile})
echo " ** Adding client ${client_name} with repo path ${BORG_DATA_DIR}/${client_name}"
mkdir ${BORG_DATA_DIR}/${client_name} 2>/dev/null mkdir ${BORG_DATA_DIR}/${client_name} 2>/dev/null
echo -n "command=\"$(eval echo -n \"${BORG_CMD}\")\" " >> /home/borg/.ssh/authorized_keys echo " ** Adding client ${client_name} with repo path ${BORG_DATA_DIR}/${client_name}"
cat $keyfile >> /home/borg/.ssh/authorized_keys
# If client is $BORG_ADMIN unset $client_name, so path restriction equals $BORG_DATA_DIR
# Otherwise add --append-only, if enabled
borg_cmd=${BORG_CMD}
if [ "${client_name}" == "${BORG_ADMIN}" ] ; then
echo " ** Client '${client_name}' is BORG_ADMIN! **"
unset client_name
elif [ "${BORG_APPEND_ONLY}" == "yes" ] ; then
borg_cmd="${BORG_CMD} --append-only"
fi
echo -n "command=\"$(eval echo -n \"${borg_cmd}\")\" " >> /home/borg/.ssh/authorized_keys
cat ${keyfile} >> /home/borg/.ssh/authorized_keys
done done
chown -R borg: /backup chown -R borg: /backup
chown borg: /home/borg/.ssh/authorized_keys chown borg: /home/borg/.ssh/authorized_keys
chmod 600 /home/borg/.ssh/authorized_keys chmod 600 /home/borg/.ssh/authorized_keys
echo " * Init done!"
echo "########################################################" echo "########################################################"
echo " * Starting SSH-Daemon" echo " * Init done! Starting SSH-Daemon..."
/usr/sbin/sshd -D -e /usr/sbin/sshd -D -e

View file

@ -14,12 +14,6 @@ PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys
LogLevel INFO LogLevel INFO
#LogLevel DEBUG
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1
PasswordAuthentication no PasswordAuthentication no
ChallengeResponseAuthentication no ChallengeResponseAuthentication no