Compare commits

..

10 Commits

Author SHA1 Message Date
Aterfax
c69aa29b60
Merge pull request #14 from Aterfax/Update-run_include-to-silence-healthcheck-output
Update run_include to silence healthcheck output.
2025-03-24 14:53:38 +00:00
Aterfax
1f23e92047
Update run_include to silence healthcheck output. 2025-03-24 14:50:41 +00:00
Aterfax
4312e6db39
Merge pull request #13 from Aterfax/Update-.env.example-to-remove-double-quotes
Update .env.example to remove double quotes.
2025-03-24 14:43:09 +00:00
Aterfax
7060d5c4e0
Update run_include to only set $HEALTHCHECKSURL when both subvariables are set. 2025-03-24 14:33:17 +00:00
Aterfax
c6d06fa760
Update .env.example to remove double quotes. 2025-03-24 14:01:19 +00:00
Aterfax
6da5b7ba85
Merge pull request #9 from matt-conley/add-unencrypted-env
Add UNENCRYPTED environment variable and logic to enable users to make unencrypted backups / restorations.
2025-03-23 19:53:49 +00:00
Aterfax
92f23512e1
Add some clear warnings and discourage the use of unencrypted backups. 2025-03-23 19:47:18 +00:00
Aterfax
2fc4c03adb
Merge pull request #11 from Aterfax/Correct-faulty-variable-check
Correct faulty variable check.
2025-03-21 20:01:49 +00:00
Aterfax
a2bafd2696
Correct faulty variable check. 2025-03-21 19:57:35 +00:00
Matt Conley
cb750d4cb4 Add UNENCRYPTED environemnt variable 2025-03-20 22:17:40 -04:00
10 changed files with 73 additions and 205 deletions

View File

@ -1,31 +0,0 @@
#
# .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,6 +1,8 @@
# Proxmox Backup Server: Client Docker
![Build and Publish Docker Image](https://git.physi.uni-heidelberg.de/tmueller/pbs-client-docker/actions/workflows/build_image.yaml/badge.svg)
[![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)
![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?**
@ -21,7 +23,6 @@ For more in depth instructions, see: [Using-the-DockerHub-provided-image](#Using
## Table of Contents
- [PI Customs](#PI)
- [Quickstart](#Quickstart)
- [Configuration](#Configuration)
- [FAQ](#FAQ)
@ -29,14 +30,6 @@ For more in depth instructions, see: [Using-the-DockerHub-provided-image](#Using
- [Contributing](#Contributing)
- [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
### Prerequisites
@ -47,6 +40,9 @@ For sensible data you can and should enable the encryption with its own set of k
### 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.
* 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.
@ -88,17 +84,9 @@ The following environment variables can be configured to customize the behavior
| 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 |
| Variable Name | Default Docker Compose Value | Valid Values | Description |
## FAQ
@ -112,6 +100,11 @@ See also:
- https://github.com/Aterfax/pbs-client-docker/issues/8
- 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
If you encounter issues, check the [Troubleshooting section](TROUBLESHOOTING.md) for solutions to common problems.

View File

@ -1,32 +1,34 @@
# The 4 variables below are required.
PBS_ENCRYPTION_PASSWORD="123456789abcdefghijklmn"
PBS_ENDPOINT="pbs.mydomain.com"
PBS_DATASTORE="test-datastore"
CRON_SCHEDULE="0 */4 * * *"
PBS_ENCRYPTION_PASSWORD=123456789abcdefghijklmn
PBS_ENDPOINT=pbs.mydomain.com
PBS_DATASTORE=test-datastore
CRON_SCHEDULE=0 */4 * * *
# If you want to skip backup on startup, set CRON_BACKUP_ONLY=1 otherwise 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!
# If unset, ensure PBS_USER and PBS_PASSWORD are set.
PBS_API_KEY_NAME="username@pam!test"
PBS_API_KEY_SECRET="4054356a-f1a6-441e-86fc-e338367db185"
PBS_API_KEY_NAME=username@pam!test
PBS_API_KEY_SECRET=4054356a-f1a6-441e-86fc-e338367db185
# 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_USER=""
PBS_PASSWORD=""
PBS_USER=
PBS_PASSWORD=
# 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=""
PBS_FINGERPRINT=
# Healthchecks.io details - Optional.
HEALTHCHECKSUUID="aa7b0de3-2c17-4fce-b051-388a5415e656"
HEALTHCHECKSHOSTNAME="https://healthchecks.mydomain.com"
HEALTHCHECKSUUID=aa7b0de3-2c17-4fce-b051-388a5415e656
HEALTHCHECKSHOSTNAME=https://healthchecks.mydomain.com
TZ=Etc/UTC
# Disable Encryption
ENCRYPTION=1

View File

@ -1,6 +1,7 @@
version: '3.3'
services:
pbs-client:
image: tmueller/pbs-client
image: aterfax/pbs-client
container_name: pbs-client
hostname: pbs-client
restart: unless-stopped
@ -11,17 +12,8 @@ services:
- /run:exec
volumes:
- ./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/test2:/backups/test2: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

@ -1,73 +0,0 @@
#!/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/
# 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}"
if [ -n "$RESTORECMD" ]; then
if [ -n "$PBS_DATASTORE_NS" ]; then
RESTORECMD+=" --ns ${PBS_DATASTORE_NS}"
fi
echo -e "\nRestore command:"

View File

@ -47,21 +47,6 @@ if [ -n "$PBS_DATASTORE_NS" ]; then
BACKUPCMD+=" --ns ${PBS_DATASTORE_NS}"
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 /etc/s6-overlay/s6-rc.d/setup_check/run_include
@ -75,7 +60,7 @@ fi
# to allow the first backup or we're
if [ "$CRON_BACKUP_ONLY" = "0" ] || [ -e "${lastrunfile}" ]; then
if [ -n "$HEALTHCHECKSURL" ]; then
curl -fsS -m 10 --retry 5 $HEALTHCHECKSURL/start
curl -fsS -m 10 --retry 5 -o /dev/null $HEALTHCHECKSURL/start
fi
# Run the actual backup command.
@ -87,7 +72,7 @@ if [ "$CRON_BACKUP_ONLY" = "0" ] || [ -e "${lastrunfile}" ]; then
if [ -n "$HEALTHCHECKSURL" ]; then
# We pipe the exit code to healthchecks, if it isn't zero, a warning will fire.
curl -fsS -m 10 --retry 5 ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE}
curl -fsS -m 10 --retry 5 -o /dev/null ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE}
fi
elif [ "$CRON_BACKUP_ONLY" = "1" ]; then
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"
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 || curl -d \"Archsync failed\" ntfy-server/pbs 2>&1"
CRON_LINE="${CRON_SCHEDULE} root bash -c '/etc/s6-overlay/s6-rc.d/backup/run_include' >> $CRONLOG_FILE 2>&1 "
TIMEOUT=60
touch "${CRONLOG_FILE}"

View File

@ -20,15 +20,20 @@ handle_error() {
}
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"
master_private_keyfile="/root/.config/proxmox-backup/master-private.pem"
master_public_keyfile="/root/.config/proxmox-backup/master-public.pem"
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.
if [ -f "$client_encryption_keyfile" ]; then
echo "Client encryption keyfile exists. Skipping client encryption keyfile creation."
@ -51,4 +56,3 @@ else
echo "$master_oublic_keyfile \n"
echo "To allow for automatic key recreation."
fi
fi

View File

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