-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
36d6119
commit be96393
Showing
10 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
FROM mcuadros/ofelia:v3.0.8 as ofelia | ||
|
||
FROM debian:bookworm-slim | ||
ENV DEBIAN_FRONTEND noninteractive | ||
ARG DOCKERIZE_VERSION=v0.7.0 | ||
ARG POSTGRES_CLIENT_VERSION=15 | ||
|
||
LABEL authors="matthijsln" | ||
|
||
ENV TZ="Europe/Amsterdam" | ||
|
||
# musl required for Ofelia when copying from Docker image, alternative is to download binary release from GitHub like | ||
# dockerize but recent versions are not available | ||
|
||
RUN apt-get update && \ | ||
apt install -y -q --no-install-recommends bash wget ca-certificates gnupg2 lsb-release musl openssh-client sshpass pv zstd pigz bzip2 pbzip2 xz-utils && \ | ||
echo "deb [signed-by=/usr/share/keyrings/apt.postgresql.org.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \ | ||
wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor --yes -o /usr/share/keyrings/apt.postgresql.org.gpg && \ | ||
wget -qO - https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz | tar xzf - -C /usr/local/bin && \ | ||
apt-get update | ||
|
||
RUN apt-get install -y -q --no-install-recommends bash postgresql-client-${POSTGRES_CLIENT_VERSION} && \ | ||
apt-get autoremove -yqq --purge wget ca-certificates gnupg2 && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
WORKDIR /home/backup | ||
COPY *.sh . | ||
RUN chmod +x *.sh | ||
COPY include include | ||
|
||
COPY --from=ofelia /usr/bin/ofelia /usr/bin/ofelia | ||
COPY ofelia.ini.tmpl . | ||
RUN mkdir /etc/ofelia | ||
|
||
RUN mkdir -p /backup/temp /backup/ofelia /backup/uploaded | ||
|
||
ENTRYPOINT ["/home/backup/entrypoint.sh"] | ||
CMD ["/usr/bin/ofelia", "daemon", "--config", "/etc/ofelia/ofelia.ini"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Docker backup container | ||
|
||
## Introduction | ||
|
||
This container can backup a PostgreSQL cluster and directories on a schedule, compress the backup and optionally copy | ||
the backup to a SFTP server (for example a Hetzner Storage Box). | ||
|
||
This container can be run separately or it can be merged with an existing Docker Compose stack. | ||
|
||
Mainly based on https://github.com/azlux/borgbackup-docker, but also uses [dockerize](https://github.com/jwilder/dockerize). | ||
|
||
At build time the PostgreSQL client version 15 is installed. On startup and when creating a backup the major version of | ||
the PostgreSQL server to backup is checked and if this differs the corresponding PostgreSQL client packages are | ||
installed, so database dumps are created with the same major client version as the server. | ||
|
||
## Docs | ||
|
||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#!/bin/bash | ||
|
||
source ./include/msg.sh | ||
source ./include/utils.sh | ||
source ./include/postgresql.sh | ||
|
||
# Defaults | ||
|
||
[[ "$1" == "--startup" ]] && STARTUP=1 | ||
|
||
BACKUP_PG=${BACKUP_PG:-true} | ||
PGHOST=${PGHOST:-db} | ||
PGDATABASE=${PGDATABASE:-all} | ||
|
||
SFTP_PATH=${SFTP_PATH:-backup} | ||
if [[ -n "$STORAGE_BOX" ]]; then | ||
SFTP_HOST=${STORAGE_BOX}.your-storagebox.de | ||
SFTP_USER=${STORAGE_BOX} | ||
fi | ||
|
||
PG_COMPRESS=${PG_COMPRESS:-zstd} | ||
TAR_COMPRESS=${TAR_COMPRESS:-zstd} | ||
# Use all cores for compression, when this is unset the default is a single core | ||
export ZSTD_NBTHREADS=${ZSTD_NBTHREADS:-0} | ||
export XZ_DEFAULTS="-T 0" | ||
|
||
DIR_BACKUP=/backup/temp | ||
DIR_UPLOADED=/backup/uploaded | ||
|
||
echo | ||
EXITCODE=0 | ||
|
||
backup_directory | ||
backup_postgres_databases | ||
|
||
if [[ ! $STARTUP ]]; then | ||
upload_backup | ||
fi | ||
|
||
exit $EXITCODE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Merge this with a Docker Compose configuration to add it to a stack, for example | ||
# by adding it to COMPOSE_FILE in an env-file. | ||
|
||
volumes: | ||
backup: | ||
|
||
services: | ||
backup: | ||
image: ghcr.io/b3partners/backup:latest | ||
container_name: ${COMPOSE_PROJECT_NAME}-backup | ||
restart: unless-stopped | ||
build: | ||
context: . | ||
volumes: | ||
- backup:/backup | ||
environment: | ||
- "SCHEDULE" | ||
- "LOGGING" | ||
- "BACKUP_PG" | ||
- "BACKUP_DIR" | ||
- "PGHOST=${PGHOST:-db}" | ||
- "PGDATABASE" | ||
- "PGUSER=${PGUSER:-postgres}" | ||
- "PGPASSWORD=${PGPASSWORD:-postgres}" | ||
- "STORAGE_BOX" | ||
- "SFTP_HOST" | ||
- "SFTP_USER" | ||
- "SFTP_PATH=${SFTP_PATH:-.}" | ||
- "SSHPASS" | ||
- "PG_COMPRESS" | ||
- "TAR_COMPRESS" | ||
- "ZSTD_NBTHREADS" | ||
- "XZ_DEFAULTS" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Using 'docker run ghcr.io/b3partners/backup bash' you can just start a shell, to manually test whether commands/connections work | ||
if [ "$1" == "bash" ] || [ "$1" == "sh" ]; then | ||
exec "${@}" | ||
fi | ||
|
||
if [ -n "$ONESHOT" ] && [ "$ONESHOT" == "true" ]; then | ||
exec ./backup.sh | ||
else | ||
# Just test connections and install the same psql client version as the server, don't make a backup yet | ||
./backup.sh --startup | ||
# Create Ofelia config from template | ||
export LOGGING=${LOGGING:-true} | ||
export SCHEDULE=${SCHEDULE:-"@midnight"} | ||
dockerize -template ofelia.ini.tmpl:/etc/ofelia/ofelia.ini | ||
# Execute standard CMD from Dockerfile | ||
exec "$@" | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/bin/bash | ||
|
||
print_msg() { | ||
local type="INFO"; | ||
local msg="$1"; | ||
if [[ -n "$2" ]]; then | ||
type=$1 | ||
msg=$2 | ||
fi | ||
echo "$(date +"%Y-%m-%dT%H:%M:%S") [$type] $msg" | ||
} | ||
|
||
print_error() { | ||
print_msg ERROR $1 | ||
EXITCODE=1 | ||
} | ||
|
||
print_error_and_exit() { | ||
print_error $1 | ||
exit 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#!/bin/bash | ||
|
||
# Check if versions are different and install matching client if so | ||
install_matching_postgresql_client() { | ||
if [[ -n "$POSTGRES_SERVER_VERSION" && "$POSTGRES_SERVER_VERSION" -ne "$POSTGRES_CLIENT_VERSION" ]]; then | ||
print_msg "Removing the default PostgreSQL client version $POSTGRES_CLIENT_VERSION provided by Debian $(lsb_release -cs)" | ||
|
||
apt-get -qq update || print_error_and_exit "Failed to update package list" | ||
apt-get -qq remove -y postgresql-client* || print_error_and_exit "Failed to remove existing PostgreSQL client" | ||
|
||
print_msg "Installing the client for remote PostgreSQL server version $POSTGRES_SERVER_VERSION" | ||
|
||
apt-get -qq install -y "postgresql-client-$POSTGRES_SERVER_VERSION" || print_error_and_exit "Failed to install PostgreSQL client $POSTGRES_SERVER_VERSION" | ||
|
||
print_msg "PostgreSQL client installation completed successfully" | ||
fi | ||
} | ||
|
||
backup_postgres_databases() { | ||
if [[ $BACKUP_PG != "true" ]]; then | ||
return | ||
fi | ||
|
||
if [[ -z "$PGHOST" && -z "$PGPASSWORD" && -z "$PGUSER" ]]; then | ||
print_error_and_exit "PostgreSQL env vars not all set, set BACKUP_PG to false to disable PostgreSQL backup" | ||
fi | ||
|
||
[[ $STARTUP ]] && dockerize -wait tcp://$PGHOST:5432 | ||
|
||
# Extract PostgreSQL client version installed via apt | ||
POSTGRES_CLIENT_VERSION=$(dpkg -l | awk '/^ii.*postgresql-client/ {if ($2 ~ /^postgresql-client-[0-9]/) print $2}' | cut -d'-' -f3) | ||
|
||
# Extract PostgreSQL server version from the remote server | ||
POSTGRES_SERVER_VERSION=$(psql -tA -c "SELECT current_setting('server_version_num')::integer / 10000;") | ||
if [[ $? -ne 0 ]]; then | ||
print_error_and_exit "Error testing the PostgreSQL connection; please check the PG* environment variables." | ||
fi | ||
|
||
[[ $STARTUP ]] && print_msg "PostgreSQL backup configured, current client: $POSTGRES_CLIENT_VERSION, server version: $POSTGRES_SERVER_VERSION" | ||
|
||
install_matching_postgresql_client | ||
|
||
if [[ $STARTUP ]]; then | ||
return | ||
fi | ||
|
||
# Do not leave dumps from deleted databases (locally, will still remain at SFTP server) | ||
rm -f $DIR_BACKUP/*.sql.* | ||
|
||
pg_dumpall --globals-only > $DIR_BACKUP/postgres_globals.sql | ||
|
||
if [[ "$PGDATABASE" != "all" ]]; then | ||
backup_postgres_database | ||
else | ||
DBS=$(psql -tA -c "select datname from pg_database where not datistemplate and datname <> 'postgres'") | ||
print_msg "Backing up all following databases: $(echo $DBS | sed 's/ /, /g' )" | ||
for PGDATABASE in $DBS; do | ||
backup_postgres_database | ||
done | ||
fi | ||
} | ||
|
||
backup_postgres_database() { | ||
res=$(psql -tA -c "select pg_size_pretty(pg_database_size('$PGDATABASE'));") | ||
if [[ $? -ne 0 ]]; then | ||
print_error "Can't get database size for database to backup \"$PGDATABASE\"!" | ||
else | ||
print_msg "Backing up database \"$PGDATABASE\", db size $res" | ||
# Continue with other databases in case of error | ||
pg_dump --create -d "$PGDATABASE" | $PG_COMPRESS | pv -i 60 -f -F "%t %a %b" 2> /tmp/progress > $DIR_BACKUP/${PGDATABASE}.sql.$PG_COMPRESS || print_error "[ERR] Error backing up \"$PGDATABASE\"!" | ||
[[ $? -ne 0 ]] || print_msg "Elapsed time, speed and compressed size: $(cat /tmp/progress | tr '\r' '\n' | tail -2 | head -1)" | ||
fi | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/bin/bash | ||
|
||
backup_directory() { | ||
if [[ -n "$BACKUP_DIR" ]]; then | ||
print_msg "Backing up directory $BACKUP_DIR, size `du -bhs $BACKUP_DIR | awk '{print $1}'`" | ||
if [[ ! $STARTUP ]]; then | ||
rm $DIR_BACKUP/files.tar.* 2>/dev/null | ||
tar acP $BACKUP_DIR | $TAR_COMPRESS > $DIR_BACKUP/files.tar.$TAR_COMPRESS || print_error "Error backing up directory $BACKUP_DIR" | ||
fi | ||
fi | ||
} | ||
|
||
upload_backup() { | ||
if [[ -z "$SFTP_HOST" || -z "$SSHPASS" ]]; then | ||
print_msg WARN "No SFTP_HOST/SSHPASS defined, not copying backup" | ||
return | ||
fi | ||
SFTP=$SFTP_USER@$SFTP_HOST:$SFTP_PATH | ||
print_msg "Copying backup size `du -bhs $DIR_BACKUP/ | awk '{print $1}'` to SFTP $SFTP" | ||
rm $DIR_UPLOADED/* 2>/dev/null | ||
mkdir -p ~/.ssh && ssh-keyscan -H $SFTP_HOST 2> /dev/null > $HOME/.ssh/known_hosts | ||
sshpass -e scp -p $DIR_BACKUP/* $SFTP && mv $DIR_BACKUP/* $DIR_UPLOADED/ || print_error "[ERR] Error copying to SFTP server" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{{ if isTrue .Env.LOGGING }} | ||
[global] | ||
save-folder=/backup/ofelia | ||
{{ end }} | ||
|
||
[job-local "backup"] | ||
schedule={{ .Env.SCHEDULE }} | ||
command=/home/backup/backup.sh |