Skip to content

hehljo/BackupGenie

Repository files navigation

BackupGenie

BackupGenie

Automated Multi-Source Backup Manager

License: MIT Docker Python Node.js PRs Welcome Buy Me A Coffee

Features β€’ Quick Start β€’ Documentation β€’ API Docs β€’ Contributing


A self-hosted backup manager with a modern web UI that automatically syncs 60+ source types (NAS, GitHub, Supabase, cloud services, Docker, self-hosted apps). Runs on Raspberry Pi, Synology NAS, any Linux server, or as a Docker container on any platform.

🌍 Web UI available in English and German.


πŸ§ͺ Test Status

Community-tested sources are marked βœ…. Sources marked πŸ”² are implemented but awaiting real-world validation β€” reports welcome via Discussions.

Test environment: Portainer on a Synology Diskstation (DS720+), Docker Compose stack, multi-arch image (amd64).

Source Backup Restore Notes
GitHub (mirror clone, auto-discovery) βœ… Tested β€” 77 repos, incl. private + orgs
Supabase (DB + Storage + Auth Config) βœ… Tested βœ… Tested Full + db_only mode, live logs
NAS (SMB) πŸ”² β€”
NAS (NFS) πŸ”² β€”
rsync over SSH πŸ”² β€”
GitLab πŸ”² β€”
Bitbucket πŸ”² β€”
Gitea πŸ”² β€”
MySQL πŸ”² β€”
PostgreSQL πŸ”² β€”
MongoDB πŸ”² β€”
Redis πŸ”² β€”
Google Drive (rclone) πŸ”² β€”
Dropbox (rclone) πŸ”² β€”
OneDrive (rclone) πŸ”² β€”
S3 / Backblaze B2 (rclone) πŸ”² β€”
Nextcloud πŸ”² β€”
Portainer / Docker Volumes πŸ”² β€”
Home Assistant πŸ”² β€”
Local filesystem πŸ”² β€”

If you've tested a source, please share your setup β€” it helps others a lot.


πŸ› οΈ Recent Fixes

  • Adaptive UI: The web UI now has consistent touch targets, visible focus states, responsive page shells, mobile-friendly drawers, bottom-sheet modals, and safer wrapping for backup/source lists.
  • Backup Retention: Settings now include automatic cleanup plus configurable backup versions per source. Cleanup only removes older timestamp-based artifacts after successful backups; sync/mirror targets are left alone.
  • Source Handler Compatibility: Non-GitHub/Supabase handlers now accept UI-created list fields, direct credentials, and path fallbacks more robustly across local, database, Docker, FTP/SFTP, WebDAV, rclone, rsync, self-hosted, and Proxmox sources.
  • i18n Cleanup: The language selector is always visible and common Settings/Storage/Config dialogs now use localized English/German strings.
  • Dark Mode: The web UI now follows the system theme on first load, keeps manual theme changes, and includes dark-safe colors for forms, cards, modals, badges, logs, and notifications.
  • Supabase Full Backup: Fixed full-mode backups with Storage/Auth config by resolving the service role key from the selected credential profile.
  • Restore Safety: Restore paths are now restricted to the configured backup directory and archive extraction is protected against path traversal.
  • GitHub Backups: Mirror clones no longer store access tokens in remote URLs; failed Git commands are reported as failures instead of successful backups.
  • Configuration Export: Secret-like values are redacted recursively before exporting configuration files.
  • Source Forms: UI-created sources now normalize paths, lists, repositories, Docker volumes/images, and NAS/NFS shares for the backend handlers.
  • Notifications: Notification endpoints require authentication and the UI uses the real configured channels instead of placeholder data.

✨ Features

πŸ”„ 60+ Backup Sources

  • Network Storage: NAS (SMB/NFS), rsync over SSH
  • Git Platforms: GitHub (auto-discovery), GitLab, Bitbucket, Gitea
  • BaaS/PaaS: Supabase (DB + Storage + Config)
  • Databases: MySQL, PostgreSQL, MongoDB, Redis
  • Cloud Storage: Google Drive, Dropbox, OneDrive, S3
  • Self-Hosted: Nextcloud, Plex, Home Assistant, Vaultwarden, Portainer
  • Docker: volumes, containers, images
  • Local: filesystems, home directories

πŸ“š Full source list β†’

🎯 Smart Automation

  • ⚑ USB trigger: auto-start when a drive is plugged in (Pi)
  • πŸ” Auto-discovery: detect GitHub repos automatically
  • 🌐 Modern Web UI: React-based SPA
  • πŸ” Secure: SSH key auth, SSL/TLS, RBAC
  • πŸ“Š Real-time monitoring: live dashboard & logs
  • 🐳 Docker-based: one-command deployment
  • πŸ–₯️ Universal: Raspberry Pi, Synology, Linux, Docker
  • 🌍 Multi-language: πŸ‡¬πŸ‡§ English & πŸ‡©πŸ‡ͺ German

πŸš€ Quick Start

Note

Requires Docker 20.10+ and 2 GB+ RAM. Runs on Raspberry Pi, Synology NAS, Linux servers, or any Docker host.

One-line install

curl -fsSL https://raw.githubusercontent.com/hehljo/BackupGenie/main/install.sh | bash

Manual setup

# 1. Clone the repository
git clone https://github.com/hehljo/BackupGenie.git
cd BackupGenie

# 2. Set SECRET_KEY (mandatory)
export SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")

# 3. Start the services
SECRET_KEY=$SECRET_KEY docker compose up -d

# 4. Get the admin password from logs
docker compose logs backend | grep "INIT"

# 5. Open the Web UI β†’ configure credentials and sources
open http://localhost:3000

Login: admin / password from the container logs (step 4). All credentials (tokens, passwords) are managed via the Web UI.


πŸ“‹ Table of Contents

Click to expand

πŸ”§ Requirements

Hardware

Platform RAM Architecture
Raspberry Pi 3/4/5 2 GB+ ARM/ARM64
Synology NAS 2 GB+ x86_64/ARM64
Linux Server 2 GB+ x86_64/ARM64
Docker Host 2 GB+ x86_64/ARM64/ARM

Hardware is detected automatically and resources are tuned to match.

Software

Docker:  20.10+
Compose: 2.0+

Authentication Requirements

  • πŸ”‘ NAS: SMB/NFS credentials
  • πŸ”‘ GitHub: Personal Access Token
  • πŸ”‘ Cloud: OAuth2 credentials or API keys
  • πŸ”‘ SSH: private key for rsync

πŸš€ Installation

Tip

BackupGenie detects your hardware automatically and adjusts resources (workers, RAM limits, parallel tasks) on its own.

πŸ“¦ Synology NAS / Portainer

Step-by-step guide

1. Create folders on the Diskstation (SSH)

sudo mkdir -p /volume1/docker/backupgenie/{config,data,logs,backup}

2. Generate a SECRET_KEY

python3 -c "import secrets; print(secrets.token_urlsafe(32))"

3. Create the stack in Portainer

Portainer β†’ Stacks β†’ Add Stack:

Field Value
Name backupgenie
Build method Repository
Repository URL https://github.com/hehljo/BackupGenie
Repository reference refs/heads/main
Compose path docker-compose.portainer.yml

Private repo? β†’ enable Authentication β†’ username: your GitHub user β†’ password: Personal Access Token (classic, scope: repo)

Environment variables (advanced mode):

SECRET_KEY=your_generated_key
PLATFORM_PROFILE=auto
API_PORT=5050
FRONTEND_PORT=3080

No .env file required! Just these four variables. All credentials (GitHub token, Supabase etc.) are managed through the Web UI.

β†’ Deploy the stack

4. Log in

http://diskstation-ip:3080

Password: generated randomly on first start. Find it in Portainer β†’ container backupgenie-backend β†’ Logs β†’ search for [INIT] Admin user created. Password:

Change the password immediately under Settings β†’ User.

5. Configure

  1. Settings β†’ Credentials β†’ enter GitHub token, NAS passwords etc. (stored encrypted)
  2. Sources β†’ Add Source β†’ configure backup sources
  3. Start backup β†’ Dashboard β†’ Start Backup

Updates

In Portainer β†’ stack backupgenie β†’ Update the stack β†’ Re-pull image and redeploy

Synology notes

  • Ports: DSM occupies 5000/5001 β€” use API_PORT=5050 and FRONTEND_PORT=3080
  • Autostart after reboot: handled automatically via restart: unless-stopped
  • Permissions: if you hit permission errors, run sudo chown -R 1000:1000 /volume1/docker/backupgenie/
  • Persistent data: everything under /volume1/docker/backupgenie/ survives updates

🐧 Linux Server / VPS

Step-by-step guide

1. Install Docker (if not already installed)

curl -fsSL https://get.docker.com | bash
sudo usermod -aG docker $USER
# Log in again so the group change takes effect

2. Install BackupGenie

cd /opt
sudo git clone https://github.com/hehljo/BackupGenie.git
sudo chown -R $USER:$USER BackupGenie
cd BackupGenie

cp config/example.env .env
cp config/sources-example.json config/sources.json

3. Configure

nano .env
SECRET_KEY=$(openssl rand -base64 32)
BACKUP_BASE_PATH=/mnt/backups

4. Start

docker compose up -d
docker compose ps

5. Open the Web UI

http://server-ip:3000

πŸ₯§ Raspberry Pi

Step-by-step guide

1. Prepare the system

sudo apt update && sudo apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com | bash
sudo usermod -aG docker pi

# For USB auto-trigger (optional)
sudo apt install -y usbmount

sudo reboot

2. Install BackupGenie

cd /opt
sudo git clone https://github.com/hehljo/BackupGenie.git
sudo chown -R pi:pi BackupGenie
cd BackupGenie

cp config/example.env .env
cp config/sources-example.json config/sources.json

3. Configure

nano .env
SECRET_KEY=a_long_random_string
BACKUP_BASE_PATH=/mnt/backup

# Pi 3 with limited RAM: tune the limits
# BACKEND_MEMORY_LIMIT=512M
# BACKEND_CPU_LIMIT=1.5
# FRONTEND_MEMORY_LIMIT=128M

4. Start

docker compose up -d

5. Open the Web UI

http://raspberrypi.local:3000

Set up USB auto-trigger (optional)

Plug in a USB drive β†’ backup starts automatically:

# Create the udev rule
sudo nano /etc/udev/rules.d/99-backupgenie-backup.rules
ACTION=="add", KERNEL=="sd[a-z][0-9]", TAG+="systemd", ENV{SYSTEMD_WANTS}="backupgenie-backup@%k.service"
sudo udevadm control --reload-rules

Detailed guide: USB Auto-Trigger β†’

🐳 Docker (generic)

For any platform with Docker
git clone https://github.com/hehljo/BackupGenie.git
cd BackupGenie
cp config/example.env .env
cp config/sources-example.json config/sources.json

# Adjust .env
nano .env

# Start
docker compose up -d

# Web UI: http://localhost:3000

Portainer (without Synology)

In Portainer β†’ Stacks β†’ Add Stack β†’ Repository:

  1. Repository URL: https://github.com/hehljo/BackupGenie
  2. Compose path: docker-compose.portainer.yml (uses prebuilt GHCR images, no build needed)
  3. Set environment variables (at minimum SECRET_KEY)
  4. Deploy

Environment variables for resource tuning

Variable Default Description
PLATFORM_PROFILE auto auto, raspberrypi, synology, server
BACKEND_CPU_LIMIT 2.0 CPU limit for the backend
BACKEND_MEMORY_LIMIT 1G RAM limit for the backend
FRONTEND_CPU_LIMIT 1.0 CPU limit for the frontend
FRONTEND_MEMORY_LIMIT 256M RAM limit for the frontend
MAX_PARALLEL_TASKS auto Parallel backup tasks (auto = based on RAM)

Initial Configuration

Important

SECRET_KEY is mandatory. Without it, the app refuses to start. Generate one: python3 -c "import secrets; print(secrets.token_urlsafe(32))"

Required environment variables:

Variable Required Description
SECRET_KEY Yes Random string for JWT + credential encryption
API_PORT No (5000) Port for the backend API
FRONTEND_PORT No (3000) Port for the Web UI
PLATFORM_PROFILE No (auto) auto, raspberrypi, synology, server

Credentials (GitHub token, NAS passwords, Supabase keys etc.) are not set via environment variables β€” manage them through the Web UI under Settings β†’ Credentials. They are stored AES-encrypted in the database.

Login: admin / password is generated randomly on first start β†’ docker compose logs backend | grep "INIT"

πŸ’Ύ Data Persistence (Docker Volumes)

Note

All your data survives a reinstall!

BackupGenie uses Docker volumes for persistent storage. During updates or reinstalls, the following data is preserved automatically:

Persistent directories:

./config/         # βœ… All backup sources (sources.json)
                  # βœ… rclone configuration
                  # βœ… Notification settings

./data/           # βœ… Database (users, history, settings)
                  # βœ… Backup logs
                  # βœ… Metadata

./logs/           # βœ… Application logs

/mnt/backup/      # βœ… Your backup data (configurable)

Benefits:

  • πŸ”„ Safe updates: docker compose pull && docker compose up -d
  • πŸ’Ύ Backup-friendly: just back up ./config/ and ./data/
  • πŸš€ Migration: copy folders β†’ fresh install β†’ done!
  • ⚑ Rollback: start an older container version with no data loss

Create a full backup:

# Save BackupGenie configuration
cd /opt/BackupGenie
tar -czf backupgenie-config-$(date +%Y%m%d).tar.gz config/ data/ .env

# Copy to a safe location
cp backupgenie-config-*.tar.gz /mnt/external-drive/

Restore after a fresh install:

# Fresh install
cd /opt
git clone https://github.com/hehljo/BackupGenie.git
cd BackupGenie

# Restore the backup
tar -xzf /mnt/external-drive/backupgenie-config-*.tar.gz

# Start the containers - all settings are back!
docker compose up -d

Export/Import via the Web UI:

Since v1.1 you can also export/import all settings directly from the web interface:

  1. Settings β†’ Configuration Export/Import
  2. Export β†’ downloads a JSON file with all sources & settings
  3. Import β†’ select a JSON file and restore your configuration

βš™οΈ Configuration

Backup Sources

BackupGenie supports 60+ backup sources. Configure them in config/sources.json:

πŸ“ NAS (SMB/NFS)
{
  "id": "nas-project1",
  "name": "NAS - Project 1",
  "type": "smb",
  "enabled": true,
  "priority": 1,
  "source": "//192.168.1.100/projects/project1",
  "credentials": {
    "username": "backup_user",
    "password_env": "NAS_PASSWORD"
  },
  "options": {
    "recursive": true,
    "delete": true,
    "timeout": 300
  },
  "schedule": {
    "trigger": "usb_mount",
    "max_duration": 3600
  }
}

Test connection:

smbclient -L //192.168.1.100 -U backup_user
πŸ™ GitHub Repositories (auto-discovery)
{
  "id": "github-repos",
  "name": "GitHub Repositories",
  "type": "github",
  "enabled": true,
  "priority": 2,
  "discovery_mode": "all",
  "exclude": ["user/some-unwanted-fork"],
  "repositories": [],
  "credentials": {
    "token_env": "GITHUB_TOKEN"
  },
  "options": {
    "include_wikis": true,
    "include_lfs": true
  }
}

discovery_mode: "all" automatically backs up all repos (private + public + orgs). New repos are picked up on the next backup. Use "manual" to pick repos individually via the Web UI.

Generate a token: GitHub β†’ Settings β†’ Developer settings β†’ Personal access tokens β†’ scopes: repo, gist

🟒 Supabase (DB + Storage)

Configuration is done through the Web UI:

  1. Settings β†’ Credentials β†’ Supabase β†’ create a new profile with the connection string (Session Pooler URI from the Supabase dashboard) + DB password + optional service role key
  2. Sources β†’ Add Source β†’ Supabase β†’ pick a profile + choose backup mode (db_only or full)
  3. Start backup

backup_mode: full saves DB (roles + schema + data) + storage buckets + RLS/auth config. db_only for PostgreSQL dumps only.

Storage backup: full mode with "Storage Buckets einschließen" downloads all bucket objects into storage/<bucket>/... and writes bucket/object metadata to storage_metadata/. This preserves image/file content plus common upload metadata such as content type and cache control for restore.

Restore: History β†’ backup with the restore button β†’ choose target profile β†’ start restore. Manual connection string entry is also supported.

Storage restore: enable "Storage-Objekte wiederherstellen" and provide a target Supabase profile or service role key. BackupGenie recreates missing buckets, uploads objects with upsert, and marks the restore as partial if individual Storage uploads fail. Older backups with legacy _bucket_meta.json bucket metadata remain supported.

☁️ Cloud Storage (rclone)
{
  "id": "google-drive",
  "name": "Google Drive Backup",
  "type": "rclone",
  "remote": "gdrive",
  "path": "/My_Backup",
  "enabled": true,
  "priority": 3,
  "options": {
    "transfers": 4,
    "checkers": 8
  }
}

Configure rclone:

docker exec -it backupgenie-backend rclone config

Supports: Google Drive, Dropbox, OneDrive, S3, Backblaze B2, and 40+ more!

🐳 Docker Volumes
{
  "id": "docker-volumes",
  "name": "Docker Volumes",
  "type": "docker",
  "enabled": true,
  "priority": 4,
  "volumes": ["volume1", "volume2"],
  "options": {
    "compress": true,
    "stop_containers": false
  }
}
πŸ’Ύ Local Directories
{
  "id": "local-docs",
  "name": "Local Documents",
  "type": "local",
  "enabled": true,
  "priority": 5,
  "sources": [
    "/home/pi/documents",
    "/home/pi/photos"
  ],
  "options": {
    "recursive": true,
    "delete": false,
    "compress": false
  }
}

πŸ“š View all 60+ supported sources β†’

USB Auto-Trigger

Configure automatic backup triggering when a USB drive is connected:

Set up udev + systemd

1. Create the udev rule

sudo nano /etc/udev/rules.d/99-backupgenie-backup.rules
# Trigger backup when a USB device is added
ACTION=="add", KERNEL=="sd[a-z][0-9]", TAG+="systemd", ENV{SYSTEMD_WANTS}="backupgenie-backup@%k.service"

2. Create the systemd service

sudo nano /etc/systemd/system/backupgenie-backup@.service
[Unit]
Description=BackupGenie Auto-Backup Trigger for %i
BindsTo=sys-subsystem-block-devices-%i.device
After=sys-subsystem-block-devices-%i.device
ConditionPathExists=/opt/BackupGenie/docker-compose.yml

[Service]
Type=oneshot
ExecStartPre=/bin/bash -c 'for i in {1..60}; do mountpoint -q /mnt/backup && break || sleep 1; done'
ExecStart=/opt/BackupGenie/scripts/trigger-backup.sh
StandardOutput=journal
StandardError=journal
User=pi
Group=docker
Environment="PATH=/usr/local/bin:/usr/bin:/bin"

3. Create the trigger script

sudo nano /opt/BackupGenie/scripts/trigger-backup.sh
#!/bin/bash
set -e

LOG_FILE="/var/log/backupgenie-trigger.log"
API_URL="http://localhost:5000/api/v1/backup/start"

echo "$(date '+%Y-%m-%d %H:%M:%S') - Backup triggered" >> "$LOG_FILE"

# Check if backup directory is mounted
if ! mountpoint -q "/mnt/backup"; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: /mnt/backup not mounted" >> "$LOG_FILE"
    exit 1
fi

# Start backup via API
response=$(curl -s -X POST "$API_URL" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $(cat /etc/backupgenie/api-token)" \
    -d '{"parallel": 2, "notify": true}')

if echo "$response" | grep -q '"status":"started"'; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - Backup started successfully" >> "$LOG_FILE"
else
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Backup start failed" >> "$LOG_FILE"
    exit 1
fi

4. Activate

sudo chmod +x /opt/BackupGenie/scripts/trigger-backup.sh
sudo systemctl daemon-reload
sudo udevadm control --reload-rules

Credentials Management

All credentials are managed via the Web UI:

  1. Settings β†’ Credentials
  2. Enter token / password (GitHub, NAS, Supabase, SMTP, Telegram etc.)
  3. Save Credentials

Credentials are stored AES-encrypted in the database (Fernet/PBKDF2). No plaintext passwords in files or environment variables.


πŸ’Ύ Usage

Web Interface

Access the dashboard at:

http://raspberrypi.local:3000
http://YOUR_PI_IP:3000

Features:

  • πŸ“Š Real-time backup status dashboard
  • πŸ“œ Detailed backup history with logs
  • βš™οΈ Source management (add/edit/delete)
  • πŸ” Credentials configuration
  • πŸ“ˆ Storage usage statistics
  • πŸ”” Notification settings
  • 🌍 Language switcher (EN/DE)

API Usage

Start a backup via API
# Get an API token
TOKEN=$(curl -s -X POST http://localhost:5000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "admin", "password": "your_password"}' \
  | jq -r '.access_token')

# Start a backup
curl -X POST http://localhost:5000/api/v1/backup/start \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": ["nas-project1", "github-repos"],
    "parallel": 2,
    "notify": true
  }'
Check backup status
curl -X GET http://localhost:5000/api/v1/backup/BACKUP_ID \
  -H "Authorization: Bearer $TOKEN"

CLI Commands

# Start a backup for specific sources
docker exec backupgenie-backend python -m app.backup.executor \
  --source github-repos --source nas-project1

# List all configured sources
docker exec backupgenie-backend python -m app.cli sources list

# Test a source connection
docker exec backupgenie-backend python -m app.cli sources test nas-project1

# View backup history
docker exec backupgenie-backend python -m app.cli backup history --limit 10

# Clean old backups
docker exec backupgenie-backend python -m app.cleanup --days 30

🌍 Internationalization (i18n)

BackupGenie ships with full multi-language support:

Supported languages

  • πŸ‡¬πŸ‡§ English β€” fully translated
  • πŸ‡©πŸ‡ͺ Deutsch β€” vollstΓ€ndig ΓΌbersetzt

Language selection

  • Frontend: language switcher in the sidebar header
  • Backend: auto-detection via the Accept-Language header
  • Storage: preference saved in browser localStorage

Adding a new language

See the detailed guide: i18n Documentation β†’

Quick steps:

  1. Frontend: create frontend/src/locales/{lang}/translation.json
  2. Backend: run pybabel init -d app/translations -l {lang}
  3. Translate the .po files
  4. Compile: pybabel compile -d app/translations

Technology stack:

  • Frontend: react-i18next + i18next-browser-languagedetector
  • Backend: Flask-Babel

πŸ“‘ API Documentation

Authentication

All API endpoints require Bearer token authentication.

POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "your_password"
}

Response:
{
  "access_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Endpoints

πŸ“¦ Backup management

Start a backup

POST /api/v1/backup/start
Authorization: Bearer TOKEN

{
  "sources": ["source-id-1", "source-id-2"],
  "parallel": 2,
  "notify": true
}

Response 200:
{
  "backup_id": "backup-uuid-1234",
  "status": "started",
  "started_at": "2025-11-13T19:30:00Z",
  "sources_count": 2
}

Get backup status

GET /api/v1/backup/{backup_id}
Authorization: Bearer TOKEN

Response 200:
{
  "backup_id": "backup-uuid-1234",
  "status": "running",
  "progress": 65,
  "started_at": "2025-11-13T19:30:00Z",
  "sources": [...]
}

List backup history

GET /api/v1/backup/history?limit=20&offset=0
Authorization: Bearer TOKEN

Response 200:
{
  "total": 156,
  "backups": [...]
}
πŸ”§ Source management

List sources

GET /api/v1/sources
Authorization: Bearer TOKEN

Response 200:
{
  "sources": [
    {
      "id": "nas-project1",
      "name": "NAS - Project 1",
      "type": "smb",
      "enabled": true,
      "last_backup": "2025-11-13T19:30:00Z",
      "status": "healthy"
    }
  ]
}

Add a source

POST /api/v1/sources
Authorization: Bearer TOKEN
Content-Type: application/json

{
  "name": "GitHub Org",
  "type": "github",
  "repositories": ["org/repo1"],
  "credentials": {
    "token_env": "GITHUB_TOKEN"
  },
  "enabled": true
}

Response 201:
{
  "id": "github-org-1",
  "created_at": "2025-11-13T20:00:00Z",
  "status": "pending_validation"
}

Update a source

PUT /api/v1/sources/{source_id}
Authorization: Bearer TOKEN
Content-Type: application/json

{
  "enabled": false
}

Delete a source

DELETE /api/v1/sources/{source_id}
Authorization: Bearer TOKEN

πŸ“š Complete API documentation β†’


πŸ› Troubleshooting

🚫 Docker containers won't start
# Check the logs
docker compose logs backend
docker compose logs frontend

# Rebuild the containers
docker compose down
docker compose up -d --build --force-recreate

# Check system resources
free -h
df -h
⚠️ Backup doesn't start automatically
# Reload udev rules
sudo udevadm control --reload-rules
sudo udevadm trigger

# Check systemd logs
journalctl -u backupgenie-backup@sd* -n 50 -f

# Debug USB devices
lsblk
sudo udevadm info --name=/dev/sda1 --attribute-walk
πŸ”Œ NAS connection fails
# Test SMB connection
smbclient -L //192.168.1.100 -U backup_user

# Test from inside Docker
docker exec backupgenie-backend smbclient -L //192.168.1.100 -U backup_user

# Verify credentials
cat /etc/backupgenie/credentials
πŸ”‘ GitHub token invalid
# Verify the token online
curl -H "Authorization: token YOUR_TOKEN" https://api.github.com/user

# Update the token
nano .env.secrets
docker compose restart backend
πŸ’½ Disk space full
# Check available space
df -h /mnt/backup

# Find the largest files
du -sh /mnt/backup/* | sort -rh | head -20

# Clean old backups
docker exec backupgenie-backend python -m app.cleanup --days 30

πŸ“š More troubleshooting β†’


πŸ”’ Security

Important

Follow security best practices to protect your backup data!

SSH hardening

Set up secure SSH access
# Generate an ED25519 key pair (locally)
ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/backupgenie

# Copy the public key to the Raspberry Pi
ssh-copy-id -i ~/.ssh/backupgenie.pub pi@raspberrypi.local

# Configure the SSH server
sudo nano /etc/ssh/sshd_config

Recommended sshd_config settings:

Port 2222  # Non-standard port
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
X11Forwarding no
AllowUsers pi
sudo systemctl restart ssh

Firewall configuration

# Enable UFW
sudo ufw enable

# Allow SSH (adjust port if changed)
sudo ufw allow 2222/tcp

# Allow API (local network only)
sudo ufw allow from 192.168.1.0/24 to any port 5000

# Allow Web UI (local network only)
sudo ufw allow from 192.168.1.0/24 to any port 3000

# Check status
sudo ufw status

API token management

# Generate a long-lived API token
docker exec backupgenie-backend python -c "
from app.auth import generate_token
token = generate_token('backup-automation', expires_days=365)
print(f'Token: {token}')
"

# Store it securely
sudo mkdir -p /etc/backupgenie
echo 'YOUR_TOKEN' | sudo tee /etc/backupgenie/api-token > /dev/null
sudo chmod 600 /etc/backupgenie/api-token
sudo chown pi:pi /etc/backupgenie/api-token

Encrypt credentials

# Install GPG
sudo apt install gpg -y

# Encrypt the credentials file
gpg -c /etc/backupgenie/credentials

# Securely delete the original
sudo shred -vfz /etc/backupgenie/credentials

# Decrypt in the Docker entrypoint
gpg --batch --yes --passphrase-file=/run/secrets/gpg_pass \
    -o /tmp/creds.txt \
    /etc/backupgenie/credentials.gpg

πŸ“š Security best practices β†’


πŸ‘¨β€πŸ’» Development

Project structure

BackupGenie/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ api/              # REST API endpoints
β”‚   β”‚   β”‚   β”œβ”€β”€ backup.py
β”‚   β”‚   β”‚   β”œβ”€β”€ sources.py
β”‚   β”‚   β”‚   └── auth.py
β”‚   β”‚   β”œβ”€β”€ backup/           # Backup engine
β”‚   β”‚   β”‚   β”œβ”€β”€ executor.py
β”‚   β”‚   β”‚   β”œβ”€β”€ sources/      # 60+ source implementations
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ smb.py
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ github.py
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ rclone.py
β”‚   β”‚   β”‚   β”‚   └── ...
β”‚   β”‚   β”‚   └── tasks.py      # Celery tasks
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   └── backup.py
β”‚   β”‚   β”œβ”€β”€ translations/     # i18n translations
β”‚   β”‚   └── config.py
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── Dockerfile
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ components/       # React components
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”œβ”€β”€ services/         # API client
β”‚   β”‚   └── locales/          # i18n translations
β”‚   β”œβ”€β”€ package.json
β”‚   └── Dockerfile
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ sources.json          # Backup source definitions
β”‚   β”œβ”€β”€ rclone.conf          # rclone remote configurations
β”‚   └── docker-compose.yml
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ trigger-backup.sh
β”‚   └── backup-cleanup.sh
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ BACKUP_SOURCES.md    # Complete source documentation
β”‚   β”œβ”€β”€ API.md               # API reference
β”‚   β”œβ”€β”€ i18n.md              # Internationalization guide
β”‚   └── TROUBLESHOOTING.md
└── README.md

Local development setup

# Backend
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt

# Run the backend
flask run --debug

# Frontend
cd frontend
npm install
npm run dev

Running tests

# Backend tests
cd backend
pytest tests/ -v --cov=app

# Frontend tests
cd frontend
npm test

# Integration tests
docker compose -f docker-compose.test.yml up --abort-on-container-exit

Build Docker images

# Build all services
docker compose build

# Build a specific service
docker compose build backend

# Build for ARM (Raspberry Pi)
docker buildx build --platform linux/arm/v7,linux/arm64 -t backupgenie-backend:latest .

πŸ“š Development guide β†’


🀝 Contributing

Contributions are welcome! See the Contributing Guide for details.

How to contribute

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a pull request

Development guidelines

  • Follow PEP 8 for Python code
  • Follow the Airbnb Style Guide for JavaScript
  • Write tests for new features
  • Update documentation when API behavior changes
  • Add i18n translations for any new UI strings

🎯 Roadmap

Done

  • Notifications (email, Telegram, ntfy, webhooks via Apprise)
  • Supabase backup + restore with profile-based credentials
  • Encrypted credential storage (Fernet/PBKDF2)
  • EN/DE multi-language UI
  • Configuration export/import
  • Multi-arch Docker images (amd64, arm64, armv7)

In progress / planned

  • Dark/light theme toggle
  • Advanced filtering in backup history
  • Backup scheduling (cron-style triggers)
  • Two-factor authentication (2FA)
  • Audit logging
  • Deduplication / incremental backups
  • Restore UI for additional source types (currently Supabase only)
  • Prometheus metrics export
  • OpenAPI 3.0 spec
  • Additional languages (FR, ES, IT)

πŸ“ License

This project is licensed under the MIT License β€” see the LICENSE file for details.


πŸ“ž Support & Community

Need help? Have questions?

GitHub Issues GitHub Discussions

Report Bug β€’ Request Feature β€’ Ask a Question


β˜• Support this project

If BackupGenie helps you manage your backups, consider supporting development!

Buy Me A Coffee

Your support keeps this project alive and growing! πŸ™

Resources


Made with ❀️ by the BackupGenie community

⭐ Star this repo if BackupGenie helps you! ⭐

🏠 Home β€’ πŸ“– Docs β€’ πŸ› Issues β€’ πŸ’¬ Discussions

About

Self-hosted backup manager with 60+ sources (NAS, Cloud, Git, databases, Supabase, Docker, self-hosted apps). Flask + React, runs in Docker on Pi, Synology, or any Linux server.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors