Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/python-3/.devcontainer/base.Dockerfile

# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster
ARG VARIANT=""
FROM mcr.microsoft.com/vscode/devcontainers/python:1-${VARIANT}
# https://github.com/devcontainers/images/tree/main/src/python
FROM mcr.microsoft.com/vscode/devcontainers/python:3-3.14-trixie

# Add postgresql repository
RUN set -eu; \
mkdir -p /etc/apt/keyrings; \
wget --quiet -O /etc/apt/keyrings/pgdg.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc; \
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/pgdg.asc] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/pgdg.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release --codename --short)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends mariadb-client postgresql-client-16
&& apt-get -y install --no-install-recommends mariadb-client postgresql-client-18
RUN pip install pip-tools

LABEL jan-di.database-backup.instance_id="devcontainer"
Expand Down
24 changes: 6 additions & 18 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/python-3
{
"name": "Python 3",
"runArgs": [
"--init"
],
"name": "Docker Database Backup",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"VARIANT": "3.12-bookworm",
// Options
"NODE_VERSION": "none"
}
"context": "."
},
// Set *default* container specific settings.json values on container create.
"customizations": {
Expand Down Expand Up @@ -47,13 +36,12 @@
],
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pip-sync",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"moby": "false"
}
},
// root required for pip-sync to install packages globally
"remoteUser": "root"
}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Decryption script and instructions in README

### Fixed
- No encryption key specified

### Changed

- Updated dependencies
- Switch from debian bookworm to debian trixie
- Switch from python 3.12 to python 3.14

### Removed

## [1.0.0] - 2024-06-01
### Added

Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
FROM docker.io/library/python:3.12.7-bookworm
FROM docker.io/library/python:3.14-trixie

LABEL jan-di.database-backup.instance_id="default"

# Add postgresql repository
RUN set -eu; \
mkdir -p /etc/apt/keyrings; \
wget --quiet -O /etc/apt/keyrings/pgdg.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc; \
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/pgdg.asc] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/pgdg.asc] https://apt.postgresql.org/pub/repos/apt trixie-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

ENV PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1

# Install apt packages
RUN set -eux; \
apt-get update; \
apt-get install -y mariadb-client postgresql-client-16 tzdata; \
apt-get install -y mariadb-client postgresql-client-18 tzdata; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*; \
mkdir -p /dump
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Docker Image Tags:
Supported Architectures: `amd64`, `arm64`
Supported Databases:

- Postgres (<= 16)
- Postgres (<= 18)
- MariaDB
- MySQL

Expand Down Expand Up @@ -106,6 +106,7 @@ services:
- SCHEDULE=600
- GLOBAL_PASSWORD=secret-password
volumes:
- /path/to/dump:/dump
- /var/run/docker.sock:/var/run/docker.sock

database1: # well known database image
Expand All @@ -125,6 +126,15 @@ services:
- jan-di.database-backup.password=other-password
```

## Decryption

To decrypt dump files that were encrypted with this service, you can use the following command:

```bash
docker run --rm -v /path/to/dump:/dump ghcr.io/jan-di/database-backup decrypt.py /dump/encrypted-dump.sql.aes /dump/decrypted-dump.sql your-encryption-key
```


## Credits

- Thanks to [@foorschtbar](https://github.com/foorschtbar) for many feature contributions
Expand Down
21 changes: 21 additions & 0 deletions decrypt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import sys
import pyAesCrypt


def decrypt_file(input_file, output_file, password):
try:
pyAesCrypt.decryptFile(input_file, output_file, password)
print(f"Decryption successful: {output_file}")
except Exception as e:
print(f"Decryption failed: {e}")


if __name__ == "__main__":
if len(sys.argv) != 4:
print("Usage: python decrypt.py <input_file> <output_file> <password>")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
password = sys.argv[3]

decrypt_file(input_file, output_file, password)
6 changes: 3 additions & 3 deletions requirements.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
docker~=7.1
humanize~=4.10
humanize~=4.15
requests~=2.32
pyaescrypt~=6.1
croniter~=2.0
tempora~=5.6
croniter~=6.0
tempora~=5.8
36 changes: 19 additions & 17 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# This file is autogenerated by pip-compile with Python 3.14
# by the following command:
#
# pip-compile
#
certifi==2024.2.2
certifi==2026.1.4
# via requests
cffi==1.16.0
cffi==2.0.0
# via cryptography
charset-normalizer==3.3.2
charset-normalizer==3.4.4
# via requests
croniter==2.0.7
croniter==6.0.0
# via -r requirements.in
cryptography==42.0.7
cryptography==46.0.3
# via pyaescrypt
docker==7.1.0
# via -r requirements.in
humanize==4.10.0
humanize==4.15.0
# via -r requirements.in
idna==3.7
idna==3.11
# via requests
jaraco-functools==4.0.1
jaraco-functools==4.4.0
# via tempora
more-itertools==10.2.0
more-itertools==10.8.0
# via jaraco-functools
pyaescrypt==6.1.1
# via -r requirements.in
pycparser==2.22
pycparser==2.23
# via cffi
python-dateutil==2.9.0.post0
# via
# croniter
# tempora
pytz==2025.2
# via croniter
pytz==2024.1
# via croniter
requests==2.32.3
requests==2.32.5
# via
# -r requirements.in
# docker
six==1.16.0
six==1.17.0
# via python-dateutil
tempora==5.6.0
tempora==5.8.1
# via -r requirements.in
urllib3==2.2.1
urllib3==2.6.3
# via
# docker
# requests
2 changes: 1 addition & 1 deletion src/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def run(self):
logging.debug("> Encrypting dump")
encrypted_dump_file = f"{dump_file}.aes"

if database.encryption_key is None:
if not database.encryption_key:
logging.error(
"> FAILED: No encryption key specified!")
failed = True
Expand Down