- Complete backup script for native Nextcloud (MySQL + files) - Systemd service and timer for daily automated backups at 2 AM - Backblaze B2 integration with secure credential storage - Incremental backup support with 30-day retention - zstd compression for 40-70% storage reduction - Comprehensive documentation and deployment guides - Successfully tested with first backup: 203MB DB + 1.3GB files - Cost-optimized: ~/bin/bash.01-0.02/month for 1.5GB data Deployment Details: - Installed B2 CLI via pipx - Created backup directories at /opt/nextcloud-backup/ - Configured systemd timer for daily execution at 2 AM - First backup verified in B2 bucket: jg-nextcloud - Automated scheduling enabled and tested Documentation includes: - Deployment report with complete setup details - Quick start guide for future deployments - Comprehensive technical reference - Troubleshooting procedures - File manifest and index
11 KiB
Nextcloud to Backblaze B2 Automated Backups
Complete guide for setting up automated periodic backups of your Nextcloud instance to Backblaze B2.
Overview
This solution provides:
- Incremental & full backups - Smart backup strategy to minimize data transfer
- Database + files - Complete Nextcloud backup including database and data
- Automated scheduling - systemd timer runs daily at 2 AM
- Retention management - Automatic cleanup of backups older than 30 days
- Compression - zstd compression to reduce storage costs
- Monitoring - Status checks and error reporting
Prerequisites
System Requirements
- Linux host with systemd
- Docker & Docker Compose (for Nextcloud)
- B2 CLI tool
- 10+ GB free disk space for temporary backups
Backblaze B2 Setup
-
Create a Backblaze B2 Account (if not already done)
- Sign up at https://www.backblaze.com/b2/cloud-storage/
-
Create a Bucket
- In B2 console: Create private bucket named
nextcloud-backups(or your preference) - Note the bucket name
- In B2 console: Create private bucket named
-
Generate API Credentials
- Go to Account → App Keys → Create Application Key
- Recommended settings:
- File names with prefix:
nextcloud-backups/ - Access: Read & Write
- Valid for: No expiration (or your preference)
- File names with prefix:
- Save the
Account IDandApplication Key
Nextcloud Setup
You need to identify:
- Nextcloud data path (usually
/srv/docker/nextcloud/dataor similar) - Database details:
- Type (MariaDB or PostgreSQL)
- Database name (usually
nextcloud) - Database user (usually
nextcloud) - Database password
Installation
Step 1: Install B2 CLI
# Install B2 command-line tool
pip3 install b2
# Verify installation
b2 version
Step 2: Create Backup Directory
sudo mkdir -p /opt/nextcloud-backup
sudo mkdir -p /etc/nextcloud-backup
sudo chmod 700 /opt/nextcloud-backup
sudo chmod 700 /etc/nextcloud-backup
Step 3: Deploy Backup Scripts
# Copy main backup script
sudo cp nextcloud-backup-to-backblaze.sh /opt/nextcloud-backup/
sudo chmod +x /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh
# Copy systemd files
sudo cp nextcloud-backup.service /etc/systemd/system/
sudo cp nextcloud-backup.timer /etc/systemd/system/
sudo chmod 644 /etc/systemd/system/nextcloud-backup.*
# Reload systemd
sudo systemctl daemon-reload
Step 4: Configure Environment
Create the configuration files:
File: /opt/nextcloud-backup/.env
# Nextcloud configuration
NEXTCLOUD_COMPOSE_DIR=/path/to/nextcloud/docker-compose
NEXTCLOUD_DATA_PATH=/srv/docker/nextcloud/data
NEXTCLOUD_DB_NAME=nextcloud
NEXTCLOUD_DB_USER=nextcloud
NEXTCLOUD_DB_PASSWORD=your_db_password_here
NEXTCLOUD_CONTAINER=nextcloud
# Backup configuration
BACKUP_RETENTION_DAYS=30
COMPRESSION=zstd
BACKUP_DIR=/opt/nextcloud-backup/.backups
File: /etc/nextcloud-backup/b2-credentials.env (root-only, no world-readable)
# Backblaze B2 credentials
B2_ACCOUNT_ID=your_account_id_here
B2_APPLICATION_KEY=your_application_key_here
B2_BUCKET_NAME=nextcloud-backups
B2_REGION=us-west-002
Set secure permissions:
sudo chmod 600 /etc/nextcloud-backup/b2-credentials.env
sudo chown root:root /etc/nextcloud-backup/b2-credentials.env
Step 5: Test the Backup
Run a test backup manually:
# Test with dry-run first
sudo DRY_RUN=true /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh
# Run actual incremental backup
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh incremental
# Or full backup
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh full
# Check backup status
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh status
Step 6: Enable Automated Backups
# Enable and start the timer
sudo systemctl enable nextcloud-backup.timer
sudo systemctl start nextcloud-backup.timer
# Verify it's active
sudo systemctl status nextcloud-backup.timer
# See next scheduled run
sudo systemctl list-timers nextcloud-backup.timer
Usage
Manual Backup Commands
# Dry-run (shows what would happen, no actual upload)
DRY_RUN=true sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh
# Incremental backup (only changed files)
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh incremental
# Full backup (all files)
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh full
# Check status
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh status
View Backup Logs
# Recent backups
sudo tail -f /opt/nextcloud-backup/.backups/logs/backup_*.log
# Latest backup status
sudo ls -lh /opt/nextcloud-backup/.backups/logs/ | tail -5
View Systemd Timer Status
# Timer status
sudo systemctl status nextcloud-backup.timer
# Last run results
sudo journalctl -u nextcloud-backup.service -n 50
# Live monitoring
sudo journalctl -u nextcloud-backup.service -f
Backup Strategy
Incremental vs Full
-
Incremental (default, runs daily):
- Only backs up files changed since last backup
- Faster, saves bandwidth and storage
- Requires full backup to restore
-
Full (recommended weekly):
- Backs up all files regardless of changes
- Slower but complete snapshot
- Standalone restore capability
Recommended Schedule
Monday-Saturday: Incremental (02:00 AM)
Sunday: Full backup (02:00 AM)
To implement this, modify the .timer file's OnCalendar line:
OnCalendar=Mon-Sat *-*-* 02:00:00
OnCalendar=Sun *-*-* 02:00:00
Monitoring and Alerts
Check Backup Status
# List recent backups
sudo b2 list-file-names nextcloud-backups nextcloud-backups/
# Get total backup size
sudo b2 list-file-names nextcloud-backups nextcloud-backups/ | \
jq '[.[] | .contentLength] | add | . / 1024 / 1024 / 1024' \
echo "Total: $size GB"
Monitor via Systemd
# Check last 10 backup runs
sudo journalctl -u nextcloud-backup.service --reverse | head -50
# Count successful vs failed backups
sudo journalctl -u nextcloud-backup.service | grep "SUCCESS\|ERROR" | wc -l
Set up Email Alerts (Optional)
Install and configure postfix or ssmtp, then add to the backup script:
# On backup failure, send email
if ! run_backup; then
echo "Nextcloud backup failed at $(date)" | \
mail -s "Nextcloud Backup Failed" admin@example.com
fi
Restoring from Backup
List Available Backups
b2 list-file-names nextcloud-backups nextcloud-backups/ | \
jq -r '.fileName + " (" + (.contentLength | . / 1024 / 1024 | floor | tostring) + " MB)"'
Restore Database
# Download database backup
b2 download-file-by-id nextcloud-backups \
<file-id> ./nextcloud-db-backup.sql.zst
# Restore to database
zstd -d nextcloud-db-backup.sql.zst -c | \
mysql -u root -p nextcloud
# Or for PostgreSQL:
zstd -d nextcloud-db-backup.sql.zst -c | \
psql -U postgres nextcloud
Restore Files
# Download file archive
b2 download-file-by-id nextcloud-backups \
<file-id> ./nextcloud-files-backup.tar.zst
# Extract to temporary location
mkdir -p /tmp/nextcloud-restore
tar --zstd -xf nextcloud-files-backup.tar.zst -C /tmp/nextcloud-restore
# Review and copy back
cp -r /tmp/nextcloud-restore/srv/docker/nextcloud/data/* \
/srv/docker/nextcloud/data/
Troubleshooting
B2 Authentication Errors
# Clear cached auth
rm ~/.b2_account_info
# Re-authenticate
b2 authorize-account YOUR_ACCOUNT_ID YOUR_APP_KEY
# Test connection
b2 account-info
Backup Size Issues
If backups are too large:
- Check for duplicate/cache files in Nextcloud data
- Enable deduplication in B2 console
- Increase
BACKUP_RETENTION_DAYSto allow fewer concurrent backups
Permission Denied Errors
Ensure the backup script runs as root and has access to:
- Docker socket (for database dumps)
- Nextcloud data directory
- Temporary directory
Database Connection Issues
Verify database credentials and that the container is running:
# Check if database container is running
docker-compose -f /path/to/nextcloud/docker-compose.yml ps
# Test database connection
docker-compose -f /path/to/nextcloud/docker-compose.yml exec -T mariadb \
mysql -u nextcloud -p${NEXTCLOUD_DB_PASSWORD} -e "SELECT 1"
Cost Optimization
Backblaze B2 Pricing
As of 2024:
- Storage: $0.006/GB/month
- Downloads: $0.003/GB (first 1GB free daily)
- API calls: $0.0004 per 1000 calls
Optimize Costs
- Compression: zstd reduces size by 40-70%
- Retention: Keep only 30 days of backups
- Incremental: Daily incremental + weekly full = smaller total size
- Deduplication: Enable in B2 for identical blocks
Example: 100GB Nextcloud → ~30-40GB compressed → $0.18-0.24/month storage
Maintenance
Monthly Checks
# Verify backup integrity
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh status
# Check logs for errors
sudo grep "ERROR" /opt/nextcloud-backup/.backups/logs/*.log
# Verify B2 credentials still valid
sudo b2 account-info
Update Schedule
- Check for B2 CLI updates monthly
- Review Backblaze pricing changes quarterly
- Test restore procedure every 6 months
Advanced Configuration
Custom Backup Schedule
Edit /etc/systemd/system/nextcloud-backup.timer:
# Run at 2 AM and 2 PM daily
OnCalendar=*-*-* 02:00:00
OnCalendar=*-*-* 14:00:00
# Or more complex: Mon-Fri 2 AM, weekends 4 AM
OnCalendar=Mon-Fri *-*-* 02:00:00
OnCalendar=Sat,Sun *-*-* 04:00:00
Then reload:
sudo systemctl daemon-reload
sudo systemctl restart nextcloud-backup.timer
Exclude Directories
Modify the get_changed_files() function in the script:
find "${NEXTCLOUD_DATA_PATH}" -type f \
! -path '*/.*' \
! -path '*/cache/*' \
! -path '*/preview/*' \
> "$manifest_file"
Pre/Post Backup Hooks
Add to the script before/after backup:
# Before backup
if [ -x /opt/nextcloud-backup/pre-backup-hook.sh ]; then
/opt/nextcloud-backup/pre-backup-hook.sh
fi
# ... backup logic ...
# After backup
if [ -x /opt/nextcloud-backup/post-backup-hook.sh ]; then
/opt/nextcloud-backup/post-backup-hook.sh
fi
References
Support
For issues:
- Check logs:
journalctl -u nextcloud-backup.service -n 100 - Verify configuration:
cat /opt/nextcloud-backup/.env - Test manually:
sudo /opt/nextcloud-backup/nextcloud-backup-to-backblaze.sh status - Check B2 credentials:
b2 account-info