Backup & Restore

Protect your Nexo Share data with proper backup strategies.

What to Backup

Nexo Share has three critical components:

  1. PostgreSQL Database - Users, shares, settings, metadata
  2. Upload Files - The actual files users have shared
  3. Docker Compose Configuration - Your environment setup

Manual Backup

Database Backup

Create SQL dump:

docker compose exec postgres pg_dump -U nexoshare nexoshare > backup_$(date +%Y%m%d).sql

Compressed backup (recommended):

docker compose exec postgres pg_dump -U nexoshare nexoshare | gzip > backup_$(date +%Y%m%d).sql.gz

Files Backup

Simple copy (for small installations):

cp -r ./uploads ./uploads_backup_$(date +%Y%m%d)

Efficient rsync (for large installations):

rsync -a ./uploads/ /backup/Nexoshare/uploads_$(date +%Y%m%d)/

Compressed archive:

tar -czf uploads_backup_$(date +%Y%m%d).tar.gz ./uploads

Configuration Backup

cp docker-compose.yml docker-compose.yml.backup

Save .env file if using environment variables:

cp .env .env.backup

Automated Backup Script

Create /usr/local/bin/backup-Nexoshare.sh:

#!/bin/bash

# Configuration
BACKUP_DIR="/backup/Nexoshare"
Nexoshare_DIR="/home/user/Nexoshare"
RETENTION_DAYS=30

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Timestamp for backup
DATE=$(date +%Y%m%d_%H%M%S)

# Log file
LOG="$BACKUP_DIR/backup_$DATE.log"
echo "Nexo Share Backup Started: $(date)" > "$LOG"

# Navigate to Nexo Share directory
cd "$Nexoshare_DIR" || exit 1

# Backup database
echo "Backing up database..." | tee -a "$LOG"
docker compose exec -T postgres pg_dump -U nexoshare nexoshare | gzip > "$BACKUP_DIR/db_$DATE.sql.gz"

if [ $? -eq 0 ]; then
    echo "Database backup successful: db_$DATE.sql.gz" | tee -a "$LOG"
else
    echo "ERROR: Database backup failed!" | tee -a "$LOG"
    exit 1
fi

# Backup files
echo "Backing up files..." | tee -a "$LOG"
rsync -a --info=progress2 ./uploads/ "$BACKUP_DIR/uploads_$DATE/"

if [ $? -eq 0 ]; then
    echo "Files backup successful: uploads_$DATE/" | tee -a "$LOG"
else
    echo "ERROR: Files backup failed!" | tee -a "$LOG"
    exit 1
fi

# Backup configuration
echo "Backing up configuration..." | tee -a "$LOG"
cp docker-compose.yml "$BACKUP_DIR/docker-compose_$DATE.yml"

# Calculate backup size
DB_SIZE=$(du -sh "$BACKUP_DIR/db_$DATE.sql.gz" | cut -f1)
FILES_SIZE=$(du -sh "$BACKUP_DIR/uploads_$DATE" | cut -f1)

echo "Backup sizes: Database=$DB_SIZE, Files=$FILES_SIZE" | tee -a "$LOG"

# Cleanup old backups
echo "Cleaning up old backups (older than $RETENTION_DAYS days)..." | tee -a "$LOG"
find "$BACKUP_DIR" -name "db_*.sql.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "uploads_*" -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +
find "$BACKUP_DIR" -name "docker-compose_*.yml" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "backup_*.log" -mtime +$RETENTION_DAYS -delete

echo "Nexo Share Backup Completed: $(date)" | tee -a "$LOG"

Make executable:

sudo chmod +x /usr/local/bin/backup-Nexoshare.sh

Test the script:

sudo /usr/local/bin/backup-Nexoshare.sh

Schedule with Cron

Daily backup at 2 AM:

sudo crontab -e

Add:

0 2 * * * /usr/local/bin/backup-Nexoshare.sh

Weekly backup on Sunday at 3 AM:

0 3 * * 0 /usr/local/bin/backup-Nexoshare.sh

View cron logs:

grep CRON /var/log/syslog

Remote Backup

Backup to Remote Server (rsync)

#!/bin/bash
BACKUP_DIR="/backup/Nexoshare"
REMOTE_USER="backup"
REMOTE_HOST="backup.company.com"
REMOTE_DIR="/backups/Nexoshare"

# After local backup completes
rsync -avz --delete "$BACKUP_DIR/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"

Setup SSH keys for passwordless transfer:

ssh-keygen -t ed25519 -C "Nexoshare-backup"
ssh-copy-id [email protected]

Backup to Cloud Storage (rclone)

Install rclone:

curl https://rclone.org/install.sh | sudo bash

Configure (example: AWS S3):

rclone config
# Follow prompts to add S3 remote named "s3backup"

Add to backup script:

# Upload to S3
rclone sync "$BACKUP_DIR" s3backup:Nexoshare-backups \
  --transfers 4 \
  --checkers 8 \
  --progress

Restore Procedures

Full Restore

Prerequisites: Fresh Nexo Share installation with same version.

Step 1: Stop Services

cd /path/to/Nexoshare
docker compose down

Step 2: Restore Files

# Remove current files
rm -rf ./uploads/*

# Restore from backup
rsync -a /backup/Nexoshare/uploads_YYYYMMDD_HHMMSS/ ./uploads/

# Or from tar.gz
tar -xzf uploads_backup_YYYYMMDD.tar.gz

Step 3: Restore Database

# Start only PostgreSQL
docker compose up -d postgres

# Wait for database to be ready
sleep 10

# Restore from backup
zcat /backup/Nexoshare/db_YYYYMMDD_HHMMSS.sql.gz | \
  docker compose exec -T postgres psql -U nexoshare nexoshare

# Or from uncompressed backup
docker compose exec -T postgres psql -U nexoshare nexoshare < backup_YYYYMMDD.sql

Step 4: Start All Services

docker compose up -d

Step 5: Verify

docker compose logs -f

Check for:

  • ✅ DB Ready & Up-to-date
  • No error messages
  • Login works
  • Files are accessible

Partial Restore

Restore Only Database

Useful for recovering from database corruption while keeping files.

# Stop Nexo Share (keep postgres running)
docker compose stop nexoshare

# Backup current database (just in case)
docker compose exec postgres pg_dump -U nexoshare nexoshare > current_db_backup.sql

# Drop and recreate database
docker compose exec postgres psql -U nexoshare -c "DROP DATABASE IF EXISTS nexoshare;"
docker compose exec postgres psql -U nexoshare -c "CREATE DATABASE nexoshare;"

# Restore from backup
zcat db_backup.sql.gz | docker compose exec -T postgres psql -U nexoshare nexoshare

# Restart Nexo Share
docker compose start nexoshare

Restore Only Files

Useful for recovering deleted shares while keeping user accounts.

# Identify share ID from database
docker compose exec postgres psql -U nexoshare nexoshare -c \
  "SELECT id, name FROM shares WHERE name LIKE '%important%';"

# Restore specific share
SHARE_ID="abc123def456"
rsync -a /backup/Nexoshare/uploads_YYYYMMDD/$SHARE_ID/ ./uploads/$SHARE_ID/

Restore Single User

# Export user from backup database
zcat db_backup.sql.gz | grep "INSERT INTO users" | grep "[email protected]" > user_restore.sql

# Import to current database
docker compose exec -T postgres psql -U nexoshare nexoshare < user_restore.sql

Disaster Recovery

Scenario 1: Complete Server Loss

Requirements:

  • Recent backups on external storage
  • New server with Docker installed

Recovery Steps:

  1. Install Docker and Docker Compose on new server
  2. Clone/download Nexo Share:
mkdir Nexo Share && cd Nexo Share
# Copy your docker-compose.yml backup
  1. Restore files:
# Download from remote backup
rsync -avz [email protected]:/backups/Nexoshare/uploads_LATEST/ ./uploads/
  1. Start PostgreSQL only:
docker compose up -d postgres
sleep 10
  1. Restore database:
# Download and restore
scp [email protected]:/backups/Nexoshare/db_LATEST.sql.gz .
zcat db_LATEST.sql.gz | docker compose exec -T postgres psql -U nexoshare nexoshare
  1. Start all services:
docker compose up -d
  1. Update DNS to point to new server IP

RTO (Recovery Time Objective): 30-60 minutes depending on data size.

Scenario 2: Database Corruption

Symptoms: Errors, missing data, application crashes.

Recovery:

docker compose down
docker compose up -d postgres
sleep 10

# Restore from most recent backup
zcat /backup/Nexoshare/db_LATEST.sql.gz | \
  docker compose exec -T postgres psql -U nexoshare nexoshare

docker compose up -d

Data Loss: Changes since last backup.

Scenario 3: Ransomware/File Deletion

Symptoms: Files missing, encrypted, or corrupted.

Recovery:

# Stop Nexo Share immediately
docker compose down

# Restore files from clean backup
rm -rf ./uploads/*
rsync -a /backup/Nexoshare/uploads_BEFORE_INCIDENT/ ./uploads/

docker compose up -d

Prevention:

  • Immutable backups (write-once storage)
  • Air-gapped backup rotation
  • Regular restore testing

Backup Verification

Test Database Restore

# Create test container
docker run -d --name test-postgres \
  -e POSTGRES_PASSWORD=test \
  -e POSTGRES_USER=nexoshare \
  -e POSTGRES_DB=nexoshare \
  postgres:17-alpine

# Restore backup to test container
zcat db_backup.sql.gz | docker exec -i test-postgres psql -U nexoshare nexoshare

# Verify data
docker exec test-postgres psql -U nexoshare nexoshare -c "SELECT COUNT(*) FROM users;"
docker exec test-postgres psql -U nexoshare nexoshare -c "SELECT COUNT(*) FROM shares;"

# Cleanup
docker stop test-postgres
docker rm test-postgres

Test Files Restore

# Create test directory
mkdir /tmp/restore-test

# Restore to test location
rsync -a ./uploads/ /tmp/restore-test/

# Verify file count and size
find ./uploads -type f | wc -l
find /tmp/restore-test -type f | wc -l

du -sh ./uploads
du -sh /tmp/restore-test

# Cleanup
rm -rf /tmp/restore-test

Backup Best Practices

3-2-1 Rule

  • 3 copies of data (original + 2 backups)
  • 2 different media (local disk + cloud/remote server)
  • 1 offsite backup (different location)

Encryption

Encrypt sensitive backups:

# Encrypt database backup
gpg --symmetric --cipher-algo AES256 db_backup.sql.gz

# Decrypt when needed
gpg --decrypt db_backup.sql.gz.gpg | zcat | docker compose exec -T postgres psql ...

Retention Policy

Example retention schedule:

  • Daily: Last 7 days
  • Weekly: Last 4 weeks
  • Monthly: Last 12 months
  • Yearly: Last 3 years

Monitoring

Add backup monitoring:

#!/bin/bash
# Check if backup ran today
BACKUP_DIR="/backup/Nexoshare"
TODAY=$(date +%Y%m%d)

if ls $BACKUP_DIR/db_${TODAY}*.sql.gz 1> /dev/null 2>&1; then
    echo "Backup OK: Found backup from $TODAY"
    exit 0
else
    echo "Backup FAILED: No backup from $TODAY found!"
    # Send alert email
    echo "Nexo Share backup failed on $(hostname)" | mail -s "BACKUP ALERT" [email protected]
    exit 1
fi

Add to crontab (runs at 6 AM):

0 6 * * * /usr/local/bin/check-backup.sh

Storage Requirements

Estimate backup space needed:

Database: Usually small (< 100 MB for typical installations) Files: Depends on usage

  • 100 users, 10 GB quota each = 1 TB
  • With 30-day retention = 30 TB (if all data changes daily)

Realistic: Most shares are temporary, actual backup size is much smaller.

Monitoring Backup Size:

du -sh /backup/Nexoshare

Recovery Testing

Test quarterly:

  1. Restore to test server
  2. Verify login works
  3. Test file download
  4. Check database integrity
  5. Document any issues

Untested backups = No backups

Keep documentation updated with:

  • Backup locations
  • Restore procedures
  • Access credentials
  • Contact information
  • Last successful test date