If you want fast, encrypted, and deduplicated backups without paying for a public cloud, pairing Restic with MinIO is a powerful option. Restic handles client-side encryption and incremental backups; MinIO provides an S3-compatible object store you fully control. In this hands-on guide, you will deploy MinIO using Docker Compose, initialize a Restic repository, automate backups with a retention policy, and verify restores. The steps work on modern Linux distributions (Ubuntu/Debian/RHEL) and on any host that can run Docker.
Prerequisites
- A Linux server with at least 2 CPU cores, 4 GB RAM, and storage sized to your backup needs.
- Docker and Docker Compose installed.
- A shell user with sudo rights.
- Optional but recommended: a hostname and TLS if exposing MinIO beyond localhost.
Step 1 — Create a Docker Compose file for MinIO
We will run MinIO on ports 9000 (S3 API) and 9001 (web console). Use a strong root user and password. Put the credentials into a .env file so they are not hard-coded in the Compose file.
# .env
MINIO_ROOT_USER=minioadmin_change_me_now
MINIO_ROOT_PASSWORD=SuperStrong_Passw0rd_change_me
MINIO_DATA_PATH=./minio-data
# docker-compose.yml
services:
minio:
image: minio/minio:latest
container_name: minio
command: server /data --console-address ":9001"
ports:
- "9000:9000" # S3 API
- "9001:9001" # Web Console
environment:
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
volumes:
- ${MINIO_DATA_PATH}:/data
restart: unless-stopped
Start MinIO:
docker compose up -d
Open the web console at http://<server-ip>:9001 and sign in with the root user credentials from the .env file.
Step 2 — Create a bucket and a dedicated access key
For clear separation, create a bucket named restic and generate a dedicated access key limited to that bucket.
Option A (Web Console):
- Storage → Create bucket → Name: restic.
- Identity → Service Accounts → Create access key → Scope: restrict to the restic bucket (read/write). Save the Access Key and Secret Key.
Option B (CLI, quick start):
# Uses MinIO Client without permanent install
docker run --rm --network host \
-e MC_HOST_local="http://${MINIO_ROOT_USER}:${MINIO_ROOT_PASSWORD}@127.0.0.1:9000" \
minio/mc mb local/restic
For production, prefer a limited service account rather than using the root keys in automation.
Step 3 — Initialize a Restic repository
Install Restic from your distribution or from the official releases. Then export environment variables for the repository URL and credentials. Replace placeholders with your actual keys.
export RESTIC_REPOSITORY="s3:http://127.0.0.1:9000/restic"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export RESTIC_PASSWORD="Choose_A_Strong_Repo_Password"
Initialize the repository (first time only):
restic init
Restic encrypts data with the password you set, before uploading. Keep this password safe; without it, restores are impossible.
Step 4 — Create a backup script with retention
Let’s script a daily backup with sensible retention (7 daily, 4 weekly, 6 monthly) and basic integrity checks.
sudo tee /usr/local/bin/restic-backup.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
# Environment (consider moving to /etc/restic/.env and source it)
export RESTIC_REPOSITORY="s3:http://127.0.0.1:9000/restic"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export RESTIC_PASSWORD="Choose_A_Strong_Repo_Password"
# What to back up
INCLUDE_DIRS=(
"/etc"
"/var/www"
"/var/lib/docker/volumes/project_data/_data"
"$HOME"
)
# Exclusions
EXCLUDES=(
"--exclude-file=/etc/restic-excludes.txt"
)
# Run backup
restic backup "${EXCLUDES[@]}" "${INCLUDE_DIRS[@]}"
# Retention and pruning
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
# Lightweight consistency check (5% of data)
restic check --read-data-subset=5%
EOF
sudo chmod +x /usr/local/bin/restic-backup.sh
Create a simple exclusions file to skip caches and temporary data:
sudo tee /etc/restic-excludes.txt >/dev/null <<'EOF'
/home/*/.cache
/var/cache
/var/tmp
*.iso
*.qcow2
node_modules
EOF
Schedule the backup with cron:
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/restic-backup.sh >> /var/log/restic.log 2>&1") | crontab -
Tip: For long-running servers, a systemd timer is often more reliable than cron. Also consider moving credentials into a protected file (chmod 600) and sourcing it inside the script.
Step 5 — Test listing and restoring
Verify snapshots:
restic snapshots
Restore a file or directory to a safe location:
# Find a snapshot ID from 'restic snapshots'
restic restore latest --target "$HOME/restore-test" --include /etc/hosts
Always test a restore. A backup you cannot restore is not a backup.
Step 6 — Secure access and expose safely
- Use HTTPS for MinIO. Either terminate TLS directly in MinIO (via certificates at /data/.minio/certs) or put MinIO behind a reverse proxy like Caddy or Nginx with automatic Let’s Encrypt.
- If backing up from remote machines, prefer private networks (Tailscale/WireGuard) rather than exposing port 9000 to the internet.
- Set strong passwords and rotate access keys periodically.
Step 7 — Useful maintenance and troubleshooting
- Verify integrity periodically: restic check (run monthly with full read if you can).
- Remove stale locks: restic unlock if a job was interrupted.
- Monitor logs: tail -f /var/log/restic.log for failures or timeouts.
- Storage growth: run restic prune occasionally (already included with forget --prune) and review your exclude list.
Why this stack works in 2025
Restic remains one of the most efficient open-source backup tools thanks to encryption-by-default, deduplication, and built-in S3 support. MinIO provides a modern, high-performance, and S3-compatible backend you can run on-prem or at the edge. With Docker Compose, you can upgrade easily, keep state on mapped volumes, and move the stack between servers without changing your backup commands.
With the steps above, you now have a repeatable, scriptable, and secure backup workflow: data is encrypted before it leaves the host, stored in an S3 bucket you control, and cleaned up automatically with a clear retention policy. Don’t forget to document your RESTIC_PASSWORD location and your MinIO access keys, and test restores on a schedule.
Comments
Post a Comment