Compare commits

..

13 commits

Author SHA1 Message Date
Andreas Mieke 6035ca549e Merge branch 'release/1.0.0'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-13 03:20:38 +01:00
Andreas Mieke 397f800372 fix(platforms): Remove useless platforms
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-13 03:17:42 +01:00
Andreas Mieke 49b78cf10f feat(platforms): Add ARM support
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-01-13 03:14:36 +01:00
nold 45e8883cae fix(sshd_config): recommended keepalive values 2022-11-24 16:29:39 +01:00
nold ef02f845dc add(ci): woodpecker.yml 2022-11-24 16:15:37 +01:00
nold 57ed075e22 Update(drone): Image tag for bookwork v1.2 & v1.2.2 2022-09-20 09:06:17 +02:00
Nold 2c76a45aca
Update: bookworm image version 1.2.1 2022-07-20 11:01:57 +02:00
nold ea677a7da9 Add(drone): Build Bookworm 2022-05-11 18:54:55 +02:00
Gerrit Pannek 95ec06eb80 Fix(run.sh): Add new line in authorized_keys [Fixes #12] 2022-02-05 18:13:41 +01:00
Nold 0b641a8253
Upgrade: bullseye & borgbackup 1.1.16 (#13)
* Upgrade to bullseye-slim image
* Fix(run.sh): authorized_keys permissions
* Change(run.sh): Add restrict to client keys & output debian version
* Change(Dockerfile): Allow different base images
* Update(drone): Build buster & bullseye images
* Update README
2022-01-21 10:33:54 +01:00
nold 7b241c142b Update: README & docker-compose example 2022-01-21 10:02:01 +01:00
nold 7d29e33747 Fix: drone - use kaniko for building 2021-11-29 17:39:31 +01:00
nold 674b4d8757 Add: drone.yml 2021-08-13 12:56:36 +02:00
13 changed files with 197 additions and 293 deletions

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
/backup /backup
/sshkeys /sshkeys
.env

39
.woodpecker.yml Normal file
View file

@ -0,0 +1,39 @@
steps:
build:
image: woodpeckerci/plugin-docker-buildx
settings:
dry-run: true
repo: git.merp.digital/${CI_REPO_OWNER}/borgserver
platforms: linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8
registry: git.merp.digital
when:
- event: push
branch:
exclude: [develop, master]
publish-nightly:
image: woodpeckerci/plugin-docker-buildx
settings:
repo: git.merp.digital/${CI_REPO_OWNER}/borgserver
platforms: linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8
registry: git.merp.digital
tags: develop-${CI_COMMIT_SHA}
username: ${CI_REPO_OWNER}
password:
from_secret: cb_token
when:
- event: push
branch: develop
publish-release:
image: woodpeckerci/plugin-docker-buildx
settings:
repo: git.merp.digital/${CI_REPO_OWNER}/borgserver
platforms: linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8
registry: git.merp.digital
tags: ${CI_COMMIT_TAG}
username: ${CI_REPO_OWNER}
password:
from_secret: cb_token
when:
- event: tag

31
Dockerfile Normal file
View file

@ -0,0 +1,31 @@
############################################################
# Dockerfile to build borgbackup server images
# Based on Debian
############################################################
FROM debian:12.4-slim
# Volume for SSH-Keys
VOLUME /sshkeys
# Volume for borg repositories
VOLUME /backup
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get -y --no-install-recommends install \
borgbackup openssh-server && apt-get clean && \
useradd -s /bin/bash -m -U borg && \
mkdir /home/borg/.ssh && \
chmod 700 /home/borg/.ssh && \
chown borg:borg /home/borg/.ssh && \
mkdir /run/sshd && \
rm -f /etc/ssh/ssh_host*key* && \
rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*
COPY ./data/run.sh /run.sh
COPY ./data/sshd_config /etc/ssh/sshd_config
ENTRYPOINT /run.sh
# Default SSH-Port for clients
EXPOSE 22

View file

@ -29,7 +29,7 @@ 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 git.merp.digital/eranmorkon/borgserver:1.0.0
``` ```
@ -45,7 +45,7 @@ See the the documentation for all available arguments: [borgbackup.readthedocs.i
##### Example ##### Example
``` ```
docker run --rm -e BORG_SERVE_ARGS="--progress --debug" (...) nold360/borgserver docker run --rm -e BORG_SERVE_ARGS="--progress --debug" (...) git.merp.digital/eranmorkon/borgserver
``` ```
#### BORG_APPEND_ONLY #### BORG_APPEND_ONLY
@ -62,7 +62,7 @@ To declare a client as admin, set this variable to the name of the client/sshkey
##### Example ##### Example
``` ```
docker run --rm -e BORG_APPEND_ONLY="yes" -e BORG_ADMIN="nolds_notebook" (...) nold360/borgserver docker run --rm -e BORG_APPEND_ONLY="yes" -e BORG_ADMIN="nolds_notebook" (...) git.merp.digital/eranmorkon/borgserver
``` ```
To prune repos from another client, you have to add the path to the repository in the clients directory: To prune repos from another client, you have to add the path to the repository in the clients directory:
@ -112,23 +112,7 @@ In this directory will borg write all the client data to. It's best to start wit
## Example Setup ## Example Setup
### docker-compose.yml ### docker-compose.yml
Here is a quick example, how to run borgserver using docker-compose: Here is a quick example, how to run borgserver using docker-compose: [docker-compose.yml](https://github.com/Nold360/docker-borgserver/blob/master/docker-compose.yml)
```
services:
borgserver:
image: nold360/borgserver
volumes:
- /backup:/backup
- ./sshkeys:/sshkeys
ports:
- "2222:22"
environment:
BORG_SERVE_ARGS: ""
BORG_APPEND_ONLY: "no"
BORG_ADMIN: ""
PUID: 1000
PGID: 1000
```
### ~/.ssh/config for clients ### ~/.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.

View file

@ -1,2 +0,0 @@
docker build -t borg:git server
docker build -t borg:init init

99
data/run.sh Executable file
View file

@ -0,0 +1,99 @@
#!/bin/bash
# Start Script for docker-borgserver
PUID=${PUID:-1000}
PGID=${PGID:-1000}
usermod -o -u "$PUID" borg &>/dev/null
groupmod -o -g "$PGID" borg &>/dev/null
BORG_DATA_DIR=/backup
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}'
AUTHORIZED_KEYS_PATH=/home/borg/.ssh/authorized_keys
# Append only mode?
BORG_APPEND_ONLY=${BORG_APPEND_ONLY:=no}
source /etc/os-release
echo "########################################################"
echo -n " * Docker BorgServer powered by "
borg -V
echo " * Based on ${PRETTY_NAME}"
echo "########################################################"
echo " * User id: $(id -u borg)"
echo " * Group id: $(id -g borg)"
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
# Precheck directories & client ssh-keys
for dir in BORG_DATA_DIR SSH_KEY_DIR ; do
dirpath=$(eval echo '$'${dir})
echo " * Testing Volume ${dir}: ${dirpath}"
if [ ! -d "${dirpath}" ] ; then
echo "ERROR: ${dirpath} is no directory!"
exit 1
fi
if [ "$(find ${SSH_KEY_DIR}/clients ! -regex '.*/\..*' -a -type f | wc -l)" == "0" ] ; then
echo "ERROR: No SSH-Pubkey file found in ${SSH_KEY_DIR}"
exit 1
fi
done
# Create SSH-Host-Keys on persistent storage, if not exist
mkdir -p ${SSH_KEY_DIR}/host 2>/dev/null
echo " * Checking / Preparing SSH Host-Keys..."
for keytype in ed25519 rsa ; do
if [ ! -f "${SSH_KEY_DIR}/host/ssh_host_${keytype}_key" ] ; then
echo " ** Creating SSH Hostkey [${keytype}]..."
ssh-keygen -q -f "${SSH_KEY_DIR}/host/ssh_host_${keytype}_key" -N '' -t ${keytype}
fi
done
echo "########################################################"
echo " * Starting SSH-Key import..."
# Add every key to borg-users authorized_keys
rm ${AUTHORIZED_KEYS_PATH} &>/dev/null
for keyfile in $(find "${SSH_KEY_DIR}/clients" ! -regex '.*/\..*' -a -type f); do
client_name=$(basename ${keyfile})
mkdir ${BORG_DATA_DIR}/${client_name} 2>/dev/null
echo " ** Adding client ${client_name} with repo path ${BORG_DATA_DIR}/${client_name}"
# 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 "restrict,command=\"$(eval echo -n \"${borg_cmd}\")\" " >> ${AUTHORIZED_KEYS_PATH}
cat ${keyfile} >> ${AUTHORIZED_KEYS_PATH}
echo >> ${AUTHORIZED_KEYS_PATH}
done
chmod 0600 "${AUTHORIZED_KEYS_PATH}"
echo " * Validating structure of generated ${AUTHORIZED_KEYS_PATH}..."
ERROR=$(ssh-keygen -lf ${AUTHORIZED_KEYS_PATH} 2>&1 >/dev/null)
if [ $? -ne 0 ]; then
echo "ERROR: ${ERROR}"
exit 1
fi
chown -R borg:borg ${BORG_DATA_DIR}
chown borg:borg ${AUTHORIZED_KEYS_PATH}
chmod 600 ${AUTHORIZED_KEYS_PATH}
echo "########################################################"
echo " * Init done! Starting SSH-Daemon..."
/usr/sbin/sshd -D -e

View file

@ -1,19 +1,17 @@
Port 2222 Port 22
AddressFamily any AddressFamily any
ListenAddress 0.0.0.0 ListenAddress 0.0.0.0
ListenAddress :: ListenAddress ::
HostKey /sshkeys/ssh_host_rsa_key HostKey /sshkeys/host/ssh_host_rsa_key
HostKey /sshkeys/ssh_host_ed25519_key HostKey /sshkeys/host/ssh_host_ed25519_key
PidFile /tmp/sshd.pid
PermitRootLogin no PermitRootLogin no
StrictModes yes StrictModes yes
MaxSessions 20 MaxSessions 20
PubkeyAuthentication yes PubkeyAuthentication yes
AuthorizedKeysFile /home/borg/.ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys
LogLevel INFO LogLevel INFO
@ -27,3 +25,6 @@ PermitTTY no
PrintMotd no PrintMotd no
PermitTunnel no PermitTunnel no
Subsystem sftp /bin/false Subsystem sftp /bin/false
ClientAliveInterval 10
ClientAliveCountMax 30

View file

@ -1,46 +1,21 @@
version: '3' version: '3'
services: services:
init: borgserver:
image: borg:init image: git.merp.digital/eranmorkon/borgserver
env_file: .env #build: .
volumes: volumes:
- borg-home:/home/borg/.ssh:rw - ./backup:/backup
- host-keys:/sshkeys:rw - ./sshkeys:/sshkeys
ports:
- "2222:22"
environment:
# Additional Arguments, see https://borgbackup.readthedocs.io/en/stable/usage/serve.html
BORG_SERVE_ARGS: ""
# FIXME: i want to get rid of that.. # If set to "yes", only the BORG_ADMIN
- backup:/backup:rw # can delete/prune the other clients archives/repos
restart: "no" BORG_APPEND_ONLY: "no"
borgserver: # Filename of Admins SSH-Key; has full access to all repos
#image: nold360/borgserver BORG_ADMIN: ""
image: borg:git restart: unless-stopped
user: 1000:1000
volumes:
# generated authorized_keys by init
- borg-home:/home/borg/.ssh:ro
# only contains host-keys now
- host-keys:/sshkeys:ro
# Backup repository for borg
- backup:/backup:rw
ports:
- "2222:2222"
environment:
BORG_SERVE_ARGS: ""
# If set to "yes", only the BORG_ADMIN
# can delete/prune the all clients archives/repos
BORG_APPEND_ONLY: "no"
# Hostname of Admin's SSH-Key
BORG_ADMIN: ""
depends_on:
- init
restart: unless-stopped
# Shared volume to exchange authorized_keys between init & server
volumes:
borg-home:
host-keys:
backup:

View file

@ -1,2 +0,0 @@
KEY_GIT_URL=https://github.com/yourName/your-ssh-pub-keys.git
KEY_GIT_BRANCH=master

View file

@ -1,13 +0,0 @@
# Borgserver Init-Container, simply replace entrypoiny and install git
#FROM nold360/borgserver:latest
FROM borg:git
USER root
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get -y --no-install-recommends install \
git ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*
COPY ./entrypoint.sh /entrypoint.sh

View file

@ -1,107 +0,0 @@
#!/bin/bash
# Init-Start Script for docker-borgserver
# Will pull ssh-keys from git specified via KEY_GIT_URL and KEY_GIT_BRANCH [default: master]
# and merge them into a single [openssh] authorized_keys file.
PUID=${PUID:-1000}
PGID=${PGID:-1000}
usermod -o -u "$PUID" borg &>/dev/null
groupmod -o -g "$PGID" borg &>/dev/null
# FIXME: Is this changeable? guess it should be.. should move it to some kind of
# build-env file
BORG_DATA_DIR=${BORG_DATA_DIR:-/backup}
BORG_CMD='cd ${BORG_DATA_DIR}/${client_name}; borg serve --restrict-to-path ${BORG_DATA_DIR}/${client_name} ${BORG_SERVE_ARGS}'
KEY_GIT_BRANCH=${KEY_GIT_BRANCH:-master}
# This is the path where the final authorized_keys will be written:
AUTHORIZED_KEYS_PATH=${AUTHORIZED_KEYS_PATH:-/home/borg/.ssh/authorized_keys}
# This will only contain host-keys now
SSH_KEY_DIR=${SSH_KEY_DIR:-/sshkeys}
# This is no volume anymore, only temporary during init
GIT_KEY_DIR=/tmp/gitkeys
echo "########################################################"
echo " * Docker BorgServer | Git Init-Container *"
echo " * $(id)"
if [ ! -z "${KEY_GIT_URL}" ] ; then
# FIXME: Should the container die here, in case of error?
# To workaround the limitations of docker-compose we could just loop here like.. forever
# INFO: simle git clone would be enouth, but you can also use a volume for SSH_KEY_DIR if you like
echo " * Cloning '${KEY_GIT_URL}' into '${GIT_KEY_DIR}/clients'"
if [ ! -d "${GIT_KEY_DIR}/clients/.git" ] ; then
git clone -b ${KEY_GIT_BRANCH} --depth=1 "${KEY_GIT_URL}" "${GIT_KEY_DIR}/clients"
else
git -C "${GIT_KEY_DIR}/clients" pull
fi
else
echo " ! FATAL ERROR: KEY_GIT_URL is not set! Can't continue."
exit 1
fi
if [ "$(find ${GIT_KEY_DIR}/clients ! -regex '.*/\..*' -a -type f | wc -l)" == "0" ] ; then
echo " ! FATAL ERROR: No SSH-Pubkey file found in ${GIT_KEY_DIR}. Can't continue."
exit 2
fi
# Create SSH-Host-Keys on persistent storage, if not exist
# This also means that `${SSH_KEY_DIR}` has to be a shared volume
echo " * Checking / Preparing SSH Host-Keys..."
for keytype in ed25519 rsa ; do
if [ ! -f "${SSH_KEY_DIR}/ssh_host_${keytype}_key" ] ; then
echo " ** Creating SSH Hostkey [${keytype}]..."
ssh-keygen -q -f "${SSH_KEY_DIR}/ssh_host_${keytype}_key" -N '' -t ${keytype}
fi
done
echo "########################################################"
echo " * Starting SSH-Key import..."
# Add every key to borg-users authorized_keys
# FIXME: mkdir of filestructure must still be done by server-container
# since we shouldn't have access to the backup-data volume in init
rm -f ${AUTHORIZED_KEYS_PATH} &>/dev/null
for keyfile in $(find "${GIT_KEY_DIR}" ! -regex '.*/\..*' -a -type f); do
client_name=$(basename ${keyfile})
# check if file is a valid openssh public key
if ! ssh-keygen -lf $keyfile &>/dev/null ; then
echo " ! WARNING: '$keyfile' is not a valid [open]ssh-public-key. Will continue anyway."
continue
fi
# 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}\")\" " >> ${AUTHORIZED_KEYS_PATH}
cat ${keyfile} >> ${AUTHORIZED_KEYS_PATH}
done
# This will also fail if there wasn't a single valid pubkey found
echo " * Validating structure of generated ${AUTHORIZED_KEYS_PATH}..."
if ! ssh-keygen -lf ${AUTHORIZED_KEYS_PATH} >/dev/null ; then
echo " ! FATAL ERROR: ${AUTHORIZED_KEYS_PATH} is no valid authorized_keys file. Can't continue."
exit 3
fi
echo " * Correcting Permissions..."
chown borg:borg ${AUTHORIZED_KEYS_PATH}
chown -R borg:borg ${SSH_KEY_DIR}/*
chown borg:borg ${BORG_DATA_DIR}
chmod 600 ${AUTHORIZED_KEYS_PATH}
echo "########################################################"
echo " * Init done! Ready to fire up your borgserver!"
exit 0

View file

@ -1,36 +0,0 @@
############################################################
# Dockerfile to build borgbackup server images
# Based on Debian
############################################################
FROM debian:buster-slim
# Volume for SSH-Host-Keys
VOLUME /sshkeys
# Volume for borg repositories
VOLUME /backup
# Volume for authorized_keys exchange from init
VOLUME /home/borg
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get -y --no-install-recommends install \
borgbackup openssh-server iputils-ping && \
apt-get clean && \
useradd -s /bin/bash -m -U borg && \
mkdir /home/borg/.ssh && \
chmod 700 /home/borg/.ssh && \
touch /home/borg/.ssh/authorized_keys && \
chown -R borg:borg /home/borg /backup && \
mkdir /run/sshd && \
rm -f /etc/ssh/ssh_host*key* && \
rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*
COPY ./entrypoint.sh /entrypoint.sh
COPY ./sshd_config /etc/ssh/sshd_config
USER borg
EXPOSE 2222
ENTRYPOINT /entrypoint.sh

View file

@ -1,64 +0,0 @@
#!/bin/bash
# Start Script for docker-borgserver
PUID=${PUID:-1000}
PGID=${PGID:-1000}
usermod -o -u "$PUID" borg &>/dev/null
groupmod -o -g "$PGID" borg &>/dev/null
BORG_DATA_DIR=${BORG_DATA_DIR:-/backup}
SSH_KEY_DIR=${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}'
AUTHORIZED_KEYS_PATH=/home/borg/.ssh/authorized_keys
# Append only mode?
BORG_APPEND_ONLY=${BORG_APPEND_ONLY:=no}
echo "########################################################"
echo " * Docker BorgServer powered by $(borg -V)"
echo "########################################################"
echo " * $(id)"
echo "########################################################"
echo -n "Waiting for init-container to finish..."
sleep 5
while ping -c2 init >/dev/null 2>/dev/null ; do
echo .
sleep 3
done
echo " done"
# 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
# Precheck directories & client ssh-keys
for dir in BORG_DATA_DIR SSH_KEY_DIR ; do
dirpath=$(eval echo '$'${dir})
echo " * Testing Volume ${dir}: ${dirpath}"
if [ ! -d "${dirpath}" ] ; then
echo " ! ERROR: ${dirpath} is no directory!"
exit 1
fi
done
for keytype in ed25519 rsa ; do
if [ ! -f "${SSH_KEY_DIR}/ssh_host_${keytype}_key" ] ; then
echo " ! WARNING: SSH-Host-Key $keytype doesn't exist!"
continue
fi
done
echo "########################################################"
echo " * Checking authorized_keys file..."
# Check if authorzied_keys is valid
if ! ssh-keygen -lf ${AUTHORIZED_KEYS_PATH} >/dev/null; then
echo " ! ERROR: '${AUTHORIZED_KEYS_PATH}' is not a valid authorized_keys-file."
exit 1
fi
echo "########################################################"
echo " * Init done! Starting SSH-Daemon..."
/usr/sbin/sshd -D -e