Compare commits

..

20 Commits

Author SHA1 Message Date
Tobias Müller
31286b4b71 got mounting working, added needed params to exmaple docker-compose
All checks were successful
Build And Test / build (push) Successful in 42s
2025-01-19 03:00:36 +01:00
Tobias Müller
fa3f93b1eb debug
All checks were successful
Build And Test / build (push) Successful in 40s
2025-01-19 01:12:33 +01:00
Tobias Müller
004f9b69d7 prepare for first test
All checks were successful
Build And Test / build (push) Successful in 39s
2025-01-19 01:06:54 +01:00
Tobias Müller
5ad9c1bfd9 modified: docker/src/helper_scripts/mount-backup
All checks were successful
Build And Test / build (push) Successful in 38s
2025-01-19 01:01:00 +01:00
Tobias Müller
2820fdcf44 building mount command
All checks were successful
Build And Test / build (push) Successful in 40s
2025-01-19 00:55:07 +01:00
Tobias Müller
a692543bfb implement ability to mount backups as fuse mount, first step is to get selection working 2025-01-19 00:30:22 +01:00
Tobias Müller
50164f64cd test of adding notification via ntfy
All checks were successful
Build And Test / build (push) Successful in 39s
2025-01-18 22:29:39 +01:00
Tobias Müller
64007a8e21 Customized Readme for PI
All checks were successful
Build And Test / build (push) Successful in 40s
modified:   README.md
	deleted:    docker/README.md
2025-01-17 12:27:42 +01:00
Tobias Müller
990101e8a4 still path
All checks were successful
Build And Test / build (push) Successful in 42s
2025-01-17 11:46:52 +01:00
Tobias Müller
c35198f9c2 path still wrong
Some checks failed
Build And Test / build (push) Failing after 15s
2025-01-17 11:44:48 +01:00
Tobias Müller
4dcc9a3686 typo
Some checks failed
Build And Test / build (push) Failing after 14s
2025-01-17 11:43:38 +01:00
Tobias Müller
70a220ad04 change path to upstream structure
Some checks failed
Build And Test / build (push) Failing after 16s
2025-01-17 11:40:27 +01:00
Tobias Müller
f28eac21ff update readme 2025-01-17 11:38:30 +01:00
edv-pi
a4c1bce7e4
Update README.md
Some checks failed
Build And Test / build (push) Failing after 15s
2025-01-17 11:35:02 +01:00
Tobias Müller
69ca732aaf use internal workflow 2025-01-17 11:29:58 +01:00
Tobias Müller
bd3e02aee8 pi additions 2025-01-17 11:27:59 +01:00
Tobias Müller
9cb6a3e828 add possibility to exclude files and folders 2025-01-16 07:32:09 +01:00
Tobias Müller
e94a086ead added some text 2025-01-15 12:41:10 +01:00
Tobias Müller
7b1d90ed7e modified: docker/src/s6-services/key_setup/run
modified:   docker/src/s6-services/setup_check/run_include
2025-01-15 12:39:19 +01:00
Tobias Müller
83406b84af added possiblity to turn off encryption 2025-01-15 12:18:28 +01:00
10 changed files with 205 additions and 73 deletions

View File

@ -0,0 +1,31 @@
#
# .gitea/gitea-ci.yaml
#
name: Build And Test
run-name: ${{ gitea.actor }} is runs ci pipeline
on: [ push ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: https://github.com/actions/checkout@v4
- name: Set up Docker Buildx
uses: https://github.com/docker/setup-buildx-action@v3
with:
config-inline: |
[registry."images.physi.uni-heidelberg.de"]
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: images.physi.uni-heidelberg.de/pibackup
- name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v6
with:
context: ./docker
push: true
#tags: "images.physi.uni-heidelberg.de/pibackup,images.physi.uni-heidelberg.de/pibackup:latest"
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -1,8 +1,6 @@
# Proxmox Backup Server: Client Docker # Proxmox Backup Server: Client Docker
[![Build and Publish Docker Image](https://github.com/Aterfax/pbs-client-docker/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/Aterfax/pbs-client-docker/actions/workflows/docker-publish.yml) ![Build and Publish Docker Image](https://git.physi.uni-heidelberg.de/tmueller/pbs-client-docker/actions/workflows/build_image.yaml/badge.svg)
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/aterfax/pbs-client/latest)
![Docker Pulls](https://img.shields.io/docker/pulls/aterfax/pbs-client)
## **tl;dr?** ## **tl;dr?**
@ -23,6 +21,7 @@ For more in depth instructions, see: [Using-the-DockerHub-provided-image](#Using
## Table of Contents ## Table of Contents
- [PI Customs](#PI)
- [Quickstart](#Quickstart) - [Quickstart](#Quickstart)
- [Configuration](#Configuration) - [Configuration](#Configuration)
- [FAQ](#FAQ) - [FAQ](#FAQ)
@ -30,6 +29,14 @@ For more in depth instructions, see: [Using-the-DockerHub-provided-image](#Using
- [Contributing](#Contributing) - [Contributing](#Contributing)
- [License](#License) - [License](#License)
## PI
### Changes
Encryption can be turned off.
Most of the Data is scientific related and does not contain any secrets and it would be a waste of ressources to encrypt that and loose the deduplication of it because older backups of similar data arent encrypted.
For sensible data you can and should enable the encryption with its own set of keypairs and keep them stored seperate from the backups.
## Quickstart ## Quickstart
### Prerequisites ### Prerequisites
@ -40,9 +47,6 @@ For more in depth instructions, see: [Using-the-DockerHub-provided-image](#Using
### Using the DockerHub provided image ### Using the DockerHub provided image
> [!WARNING]
> It is possible, but highly discouraged for you to make unencrypted backups by setting `UNENCRYPTED=1` in your ``.env`` file. This will bypass the automatic key generation process but **this is a bad idea** as the backed-up data will be stored in plaintext. This means that the owner of the PBS backup server you are backing up to will have full access to explore the backed-up content.
* Run the image with the provided docker-compose file after amending it and the ``.env`` file where needed. * Run the image with the provided docker-compose file after amending it and the ``.env`` file where needed.
* If allowing the container to conduct an auto setup, don't set a ``PBS_ENCRYPTION_PASSWORD`` value yet as the container first run will autogenerate one for you. * If allowing the container to conduct an auto setup, don't set a ``PBS_ENCRYPTION_PASSWORD`` value yet as the container first run will autogenerate one for you.
* Supply your desired ``master-public.pem``, ``master-private.pem`` and ``encryption-key.json`` files with a matching ``PBS_ENCRYPTION_PASSWORD`` or allow the container to automatically generate these for you on first run. * Supply your desired ``master-public.pem``, ``master-private.pem`` and ``encryption-key.json`` files with a matching ``PBS_ENCRYPTION_PASSWORD`` or allow the container to automatically generate these for you on first run.
@ -84,9 +88,17 @@ The following environment variables can be configured to customize the behavior
| Variable Name | Default Docker Compose Value | Valid Values | Description | | Variable Name | Default Docker Compose Value | Valid Values | Description |
|--------------------|------------------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------| |--------------------|------------------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------|
| Variable Name | Default Docker Compose Value | Valid Values | Description | | PBS_ENDPOINT | none | fqdn | target PBS-server |
| PBS_FINGERPRINT | none | XX:XX:XX:XX... | your fringerprint of your pbs instance |
| PBS_DATASTORE | none | string | name of your pbs datastore |
| PBS_DATASTORE_ns | none | string | name of your pbs namespace |
| CRON_SCHEDULE | none | * * * * * | cron expression to define the shedule for backups |
| CRON_BACKUP_ONLY | none | boolean | controls if first backup will be done at the first start |
| PBS_API_KEY_NAME or PBS_USER | none | string | credentials for pbs either define an api token or specify user |
| PBS_API_KEY_SECRET or PBS_PASSWORD | none | string | password or secret |
| TZ | none | IANA's time zone database long | Timezone to use for tuimestamps in backup |
| UNENCRYPTED | 0 | boolean | disables encryption if set to 1 |
| CHANGE_DETECT_MODE | metadata | metadata, data, legacy | Let you choose the desired mode for detecting file changes between backups |
## FAQ ## FAQ
@ -100,11 +112,6 @@ See also:
- https://github.com/Aterfax/pbs-client-docker/issues/8 - https://github.com/Aterfax/pbs-client-docker/issues/8
- https://forum.proxmox.com/threads/backup-client-encryption-not-working-inside-docker-container.139054/ - https://forum.proxmox.com/threads/backup-client-encryption-not-working-inside-docker-container.139054/
> [!WARNING]
> It is possible, but highly discouraged for you to bypass this issue by taking unencrypted backups. You can do this by setting `UNENCRYPTED=1` in your ``.env`` file and this will bypass the automatic key generation process.
>
>**This is a bad idea** as the backed-up data will be stored in plaintext. This means that the owner of the PBS backup server you are backing up to will have full access to explore the backed-up content.
## Troubleshooting ## Troubleshooting
If you encounter issues, check the [Troubleshooting section](TROUBLESHOOTING.md) for solutions to common problems. If you encounter issues, check the [Troubleshooting section](TROUBLESHOOTING.md) for solutions to common problems.

View File

@ -1,34 +1,32 @@
# The 4 variables below are required. # The 4 variables below are required.
PBS_ENCRYPTION_PASSWORD=123456789abcdefghijklmn PBS_ENCRYPTION_PASSWORD="123456789abcdefghijklmn"
PBS_ENDPOINT=pbs.mydomain.com PBS_ENDPOINT="pbs.mydomain.com"
PBS_DATASTORE=test-datastore PBS_DATASTORE="test-datastore"
CRON_SCHEDULE=0 */4 * * * CRON_SCHEDULE="0 */4 * * *"
# If you want to skip backup on startup, set CRON_BACKUP_ONLY=1 otherwise CRON_BACKUP_ONLY=0 # If you want to skip backup on startup, set CRON_BACKUP_ONLY=1 otherwise CRON_BACKUP_ONLY=0
CRON_BACKUP_ONLY=0 CRON_BACKUP_ONLY=0
# Set UNENCRYPTED=1 to bypass automatic encryption key generation and allow the backups to be unencrypted.
# This is a bad idea as the owner of the PBS backup server you are backing up to will have full access to
# explore the backed-up content.
UNENCRYPTED=0
# Use of the PBS_API_KEY_NAME and PBS_API_KEY_SECRET is recommended! # Use of the PBS_API_KEY_NAME and PBS_API_KEY_SECRET is recommended!
# If unset, ensure PBS_USER and PBS_PASSWORD are set. # If unset, ensure PBS_USER and PBS_PASSWORD are set.
PBS_API_KEY_NAME=username@pam!test PBS_API_KEY_NAME="username@pam!test"
PBS_API_KEY_SECRET=4054356a-f1a6-441e-86fc-e338367db185 PBS_API_KEY_SECRET="4054356a-f1a6-441e-86fc-e338367db185"
# PBS_USER is not required if PBS_API_KEY_NAME is set. # PBS_USER is not required if PBS_API_KEY_NAME is set.
# PBS_PASSWORD is not required if PBS_API_KEY_SECRET is set. # PBS_PASSWORD is not required if PBS_API_KEY_SECRET is set.
PBS_USER= PBS_USER=""
PBS_PASSWORD= PBS_PASSWORD=""
# PBS_DATASTORE_NS is optional but should be set if using namespaces. # PBS_DATASTORE_NS is optional but should be set if using namespaces.
PBS_DATASTORE_NS=test PBS_DATASTORE_NS="test"
# PBS_FINGERPRINT is required if using a self signed SSL certificate. # PBS_FINGERPRINT is required if using a self signed SSL certificate.
PBS_FINGERPRINT= PBS_FINGERPRINT=""
# Healthchecks.io details - Optional. # Healthchecks.io details - Optional.
HEALTHCHECKSUUID=aa7b0de3-2c17-4fce-b051-388a5415e656 HEALTHCHECKSUUID="aa7b0de3-2c17-4fce-b051-388a5415e656"
HEALTHCHECKSHOSTNAME=https://healthchecks.mydomain.com HEALTHCHECKSHOSTNAME="https://healthchecks.mydomain.com"
TZ=Etc/UTC TZ=Etc/UTC
# Disable Encryption
ENCRYPTION=1

View File

@ -1,7 +1,6 @@
version: '3.3'
services: services:
pbs-client: pbs-client:
image: aterfax/pbs-client image: tmueller/pbs-client
container_name: pbs-client container_name: pbs-client
hostname: pbs-client hostname: pbs-client
restart: unless-stopped restart: unless-stopped
@ -12,8 +11,17 @@ services:
- /run:exec - /run:exec
volumes: volumes:
- ./pbsconfig/:/root/.config/proxmox-backup/ - ./pbsconfig/:/root/.config/proxmox-backup/
# Note - if you want to restore backups make sure to change to read write below.
# See the 'restore-backup' command inside the container.
- ./backups/test1:/backups/test1:ro - ./backups/test1:/backups/test1:ro
- ./backups/test2:/backups/test2:ro - ./backups/test2:/backups/test2:ro
- ./backups/test3:/backups/test3:ro - ./backups/test3:/backups/test3:ro
- type: bind
source: /restore
target: /restore
bind:
propagation: rshared
cap_add:
- SYS_ADMIN
devices:
- /dev/fuse:/dev/fuse
security_opt:
- apparmor:unconfined

View File

@ -0,0 +1,73 @@
#!/usr/bin/with-contenv bash
# shellcheck shell=bash
source /etc/s6-overlay/s6-rc.d/setup_check/run_include
# We need to build this command in case namespaces are in use.
MOUNTCMD="proxmox-backup-client mount"
LISTCMD="proxmox-backup-client snapshot list"
if [ -n "$PBS_DATASTORE_NS" ]; then
LISTCMD+=" --ns ${PBS_DATASTORE_NS}"
MOUNTCMD+=" --ns ${PBS_DATASTORE_NS}"
fi
LISTCMD+=" --output-format json"
data=$(${LISTCMD})
host_name=$(hostname)
# Backups in einer nummerierten Liste ausgeben
options=$(echo "$data" | jq -r --arg host "$host_name" '
.[] |
select(.["backup-id"] == $host) |
"\(.["backup-type"])/\($host)/\(.["backup-time"] | tonumber | strftime("%Y-%m-%dT%H:%M:%SZ"))"')
# Array erstellen und anzeigen
echo "Verfügbare Backups:"
IFS=$'\n' read -d '' -r -a backups <<< "$options"
for i in "${!backups[@]}"; do
echo "$((i + 1)). ${backups[i]}"
done
# Benutzereingabe für die Auswahl
read -p "Wählen Sie ein Backup aus (Nummer eingeben): " selection
# Überprüfen, ob die Eingabe gültig ist
if [[ "$selection" -ge 1 && "$selection" -le "${#backups[@]}" ]]; then
selected_backup="${backups[$((selection - 1))]}"
MOUNTCMD+=" $selected_backup"
echo "Ausgewähltes Backup: $selected_backup"
# Dateien des ausgewählten Backups abrufen
backup_index=$((selection - 1))
files=$(echo "$data" | jq -r --argjson index "$backup_index" '
.[$index].files[].filename | select(test("\\.pxar.didx$|\\.mpxar.didx$"))')
# Dateien in einer nummerierten Liste ausgeben
echo "Verfügbare Dateien:"
IFS=$'\n' read -d '' -r -a file_list <<< "$files"
for i in "${!file_list[@]}"; do
echo "$((i + 1)). ${file_list[i]}"
done
# Benutzereingabe für die Dateiauswahl
read -p "Wählen Sie eine Datei aus (Nummer eingeben): " file_selection
# Überprüfen, ob die Eingabe gültig ist
if [[ "$file_selection" -ge 1 && "$file_selection" -le "${#file_list[@]}" ]]; then
selected_file="${file_list[$((file_selection - 1))]}"
MOUNTCMD+=" $selected_file"
echo "Ausgewählte Datei: $selected_file"
echo "DEBUG: $MOUNTCMD"
MOUNTCMD+=" /restore"
$(${MOUNTCMD})
echo "Dont forget to unmount when finished (just umount /path/on/the/host i.e. /restore)"
else
echo "Ungültige Auswahl. Abbruch."
exit 1
fi
else
echo "Ungültige Auswahl. Abbruch."
exit 1
fi

View File

@ -116,7 +116,7 @@ read -rp "Are these details correct? Press Enter to continue or Ctrl+C to cancel
#proxmox-backup-client restore host/elsa/2019-12-03T09:35:01Z root.pxar /target/path/ #proxmox-backup-client restore host/elsa/2019-12-03T09:35:01Z root.pxar /target/path/
# We need to build this command in case namespaces are in use. # We need to build this command in case namespaces are in use.
RESTORECMD="proxmox-backup-client restore ${selected_backup_type}/${selected_backup_id}/${selected_backup_time} ${selected_file} ${restore_path}" RESTORECMD="proxmox-backup-client restore ${selected_backup_type}/${selected_backup_id}/${selected_backup_time} ${selected_file} ${restore_path}"
if [ -n "$PBS_DATASTORE_NS" ]; then if [ -n "$RESTORECMD" ]; then
RESTORECMD+=" --ns ${PBS_DATASTORE_NS}" RESTORECMD+=" --ns ${PBS_DATASTORE_NS}"
fi fi
echo -e "\nRestore command:" echo -e "\nRestore command:"

View File

@ -47,6 +47,21 @@ if [ -n "$PBS_DATASTORE_NS" ]; then
BACKUPCMD+=" --ns ${PBS_DATASTORE_NS}" BACKUPCMD+=" --ns ${PBS_DATASTORE_NS}"
fi fi
# Add possibility to exlude paths
if [ -n "$EXCLUDE" ]; then
IFS=', ' read -r -a array <<< "$EXCLUDE"
for element in "${array[@]}"
do
BACKUPCMD+=" --exclude ${element}"
done
fi
if [ -n "$CHANGE_DETECT_MODE" ]; then
BACKUPCMD+=" --change-detection-mode=${CHANGE_DETECT_MODE}"
else
BACKUPCMD+=" --change-detection-mode=metadata"
fi
# Source the variables from the setup_check scripting include file. # Source the variables from the setup_check scripting include file.
source /etc/s6-overlay/s6-rc.d/setup_check/run_include source /etc/s6-overlay/s6-rc.d/setup_check/run_include
@ -60,7 +75,7 @@ fi
# to allow the first backup or we're # to allow the first backup or we're
if [ "$CRON_BACKUP_ONLY" = "0" ] || [ -e "${lastrunfile}" ]; then if [ "$CRON_BACKUP_ONLY" = "0" ] || [ -e "${lastrunfile}" ]; then
if [ -n "$HEALTHCHECKSURL" ]; then if [ -n "$HEALTHCHECKSURL" ]; then
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKSURL/start curl -fsS -m 10 --retry 5 $HEALTHCHECKSURL/start
fi fi
# Run the actual backup command. # Run the actual backup command.
@ -72,7 +87,7 @@ if [ "$CRON_BACKUP_ONLY" = "0" ] || [ -e "${lastrunfile}" ]; then
if [ -n "$HEALTHCHECKSURL" ]; then if [ -n "$HEALTHCHECKSURL" ]; then
# We pipe the exit code to healthchecks, if it isn't zero, a warning will fire. # We pipe the exit code to healthchecks, if it isn't zero, a warning will fire.
curl -fsS -m 10 --retry 5 -o /dev/null ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE} curl -fsS -m 10 --retry 5 ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE}
fi fi
elif [ "$CRON_BACKUP_ONLY" = "1" ]; then elif [ "$CRON_BACKUP_ONLY" = "1" ]; then
echo "CRON_BACKUP_ONLY=1, skipping container start up initial backup." echo "CRON_BACKUP_ONLY=1, skipping container start up initial backup."

View File

@ -32,7 +32,7 @@ fi
CRONLOG_FILE="/root/.config/proxmox-backup/cron.log" CRONLOG_FILE="/root/.config/proxmox-backup/cron.log"
CRON_FILE="/etc/cron.d/cron-backup" CRON_FILE="/etc/cron.d/cron-backup"
CRON_LINE="${CRON_SCHEDULE} root bash -c '/etc/s6-overlay/s6-rc.d/backup/run_include' >> $CRONLOG_FILE 2>&1 " CRON_LINE="${CRON_SCHEDULE} root bash -c '/etc/s6-overlay/s6-rc.d/backup/run_include' >> $CRONLOG_FILE || curl -d \"Archsync failed\" ntfy-server/pbs 2>&1"
TIMEOUT=60 TIMEOUT=60
touch "${CRONLOG_FILE}" touch "${CRONLOG_FILE}"

View File

@ -20,20 +20,15 @@ handle_error() {
} }
trap handle_error ERR trap handle_error ERR
# Check if encryption is disabled via environment variable
if [ "${UNENCRYPTED}" = "1" ]; then
echo "Encrypted backups are disabled. Skipping key setup process."
echo ""
echo "This is a bad idea as the owner of the PBS backup server you are backing up to will have full access to explore the backed-up content."
exit 0
fi
client_encryption_keyfile="/root/.config/proxmox-backup/encryption-key.json" client_encryption_keyfile="/root/.config/proxmox-backup/encryption-key.json"
master_private_keyfile="/root/.config/proxmox-backup/master-private.pem" master_private_keyfile="/root/.config/proxmox-backup/master-private.pem"
master_public_keyfile="/root/.config/proxmox-backup/master-public.pem" master_public_keyfile="/root/.config/proxmox-backup/master-public.pem"
expect="/usr/bin/expect" expect="/usr/bin/expect"
if [ "$UNENCRYPTED" = "1" ]; then
echo "Encryption set to false not gonna create any Keys."
else
# Check if client encryption keyfile exists and do stuff. # Check if client encryption keyfile exists and do stuff.
if [ -f "$client_encryption_keyfile" ]; then if [ -f "$client_encryption_keyfile" ]; then
echo "Client encryption keyfile exists. Skipping client encryption keyfile creation." echo "Client encryption keyfile exists. Skipping client encryption keyfile creation."
@ -56,3 +51,4 @@ elif [ ! -f "$master_private_keyfile" ] || [ ! -f "$master_public_keyfile" ]; th
echo "$master_oublic_keyfile \n" echo "$master_oublic_keyfile \n"
echo "To allow for automatic key recreation." echo "To allow for automatic key recreation."
fi fi
fi

View File

@ -30,11 +30,15 @@ if [ -z "$PBS_PASSWORD" ]; then
exit 1 exit 1
fi fi
# Evaluate each subvariable and replace all spaces with nothing - if not zero length set variable. if [ -n "$UNENCRYPTED" ]; then
if [[ ! -z "${HEALTHCHECKSHOSTNAME// }" ]] && [[ ! -z "${HEALTHCHECKSUUID// }" ]]; then UNENCRYPTED="${UNENCRYPTED}"
HEALTHCHECKSURL="${HEALTHCHECKSHOSTNAME}/ping/${HEALTHCHECKSUUID}" else
export HEALTHCHECKSURL="${HEALTHCHECKSURL}" UNENCRYPTED="0"
fi fi
HEALTHCHECKSURL="${HEALTHCHECKSHOSTNAME}/ping/${HEALTHCHECKSUUID}"
export UNENCRYPTED
export HEALTHCHECKSURL="${HEALTHCHECKSURL}"
export PBS_PASSWORD="${PBS_PASSWORD}" export PBS_PASSWORD="${PBS_PASSWORD}"
export PBS_REPOSITORY="${PBS_USER}@${PBS_ENDPOINT}:${PBS_DATASTORE}" export PBS_REPOSITORY="${PBS_USER}@${PBS_ENDPOINT}:${PBS_DATASTORE}"