A lightweight, self-hosted web UI for restoring Docker volume backups created by offen/docker-volume-backup.
Note
This project was co-authored with Claude and Anti-Gravity.
Warning
Early-Stage Software — Functional and used in real environments, but you may encounter rough edges. This tool interacts directly with Docker volumes and container lifecycles — back up your data independently before relying on it for critical restores. Test against non-production volumes first. Bug reports welcome at Issues.
Caution
No built-in authentication. Requires direct access to the Docker socket (/var/run/docker.sock), which grants full control over the Docker daemon (effectively root on the host).
- Never expose this application to the public internet.
- Secure it behind a VPN or authenticating reverse proxy (Authelia, Authentik, Cloudflare Access, etc.).
- Features
- Screenshots
- Quick Start
- Local Development (Docker Compose)
- Local Development (No Docker)
- Security Model
- FAQ & Troubleshooting
- Flexible Project Import — Paste a
docker-compose.yml, import from a Git repository (HTTPS tokens / SSH keys), or connect to Portainer to auto-discover stacks. - Encrypted Passphrase Storage — Volume and project-wide GPG passphrases are persisted in an AES-256-GCM encrypted manifest that survives container restarts.
- Automated Volume Restore — Restore into the original volume or create a new one (e.g.
{volume}_restored_{timestamp}) for safe inspection before replacing production data. - Swarm & Compose Orchestration — Scales down Swarm services or stops Compose containers before restoring, then brings everything back up automatically.
- Real-Time Progress — Server-Sent Events stream live percentages, logs, and container state transitions to the UI.
- Multi-Backend Storage — Local directory, SMB/CIFS, AWS S3 / MinIO, WebDAV (Nextcloud), SFTP, Azure Blob, Dropbox, and Google Drive.
- Sidecar Backup Generator — A configuration wizard that generates and injects the
offen/docker-volume-backupsidecar service into your compose file, with schedule, retention, encryption, and storage settings.
Single command — no cloning required:
curl -sL https://raw.githubusercontent.com/bocklucas/dvb-made-easy/main/docker-compose.prod.yml -o docker-compose.yml && docker compose up -dOr run directly without a compose file:
docker volume create dvb-restore-staging
docker run -d -p 7331:7331 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v dvb-config:/app/config \
-v dvb-restore-staging:/staging \
ghcr.io/bocklucas/dvb-made-easy:latestThen open http://localhost:7331.
Tip
If you get a "permission denied" error for the Docker socket, add your Docker group ID:
docker run -d -p 7331:7331 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v dvb-config:/app/config \
-v dvb-restore-staging:/staging \
--group-add $(getent group docker | cut -d: -f3) \
ghcr.io/bocklucas/dvb-made-easy:latestgit clone https://github.com/bocklucas/dvb-made-easy.git
cd dvb-made-easy
export DOCKER_GID=$(getent group docker | cut -d: -f3)
docker compose up -d- Web UI: http://localhost:7331
- API Health: http://localhost:7331/api/health
- Go 1.26+
- Node.js 22+
- Access to a local Docker daemon (
/var/run/docker.sock)
go run cmd/server/main.go --port 7331 --config-dir ./config-dev --staging-dir ./staging-devcd web
npm install
npm run devOpen http://localhost:5173 — the Vite dev proxy forwards /api requests to the Go backend on port 7331.
- A 32-byte key is generated on first start and saved as
/app/config/.key(mode0600). - All credentials (SMB, Git tokens, GPG passphrases) are encrypted with AES-256-GCM and stored in
manifest.enc. - Back up your
.keyfile — without it, the manifest cannot be decrypted.
- The app needs
/var/run/docker.sockto inspect containers and run extraction helpers. Docker socket access is equivalent to root on the host. - No built-in authentication — restrict access to a trusted local network, VPN, or authenticating reverse proxy.
"permission denied" on /var/run/docker.sock
Set the DOCKER_GID environment variable before running docker compose up, or add --group-add when using docker run.
How do I restore into a different volume name?
Select New Volume Mode during the restore flow. It defaults to {volume_name}_restored_{timestamp} but can be customized to any name.
How does GPG decryption work?
The UI shows a lock icon when it detects .gpg files. You can store the passphrase in the encrypted manifest or enter it at restore time. The helper container handles decryption automatically.








