#!/bin/bash # Mastodon Backup Script # Creates a complete backup for migration to another server # Run as root set -e BACKUP_DIR="${BACKUP_DIR:-/home/mastodon/backups}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_NAME="mastodon_backup_${TIMESTAMP}" BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}" echo "==========================================" echo "Mastodon Backup Script" echo "Backup location: ${BACKUP_PATH}" echo "==========================================" # Create backup directory mkdir -p "${BACKUP_PATH}" # 1. Backup PostgreSQL database echo "[1/5] Backing up PostgreSQL database..." sudo -u postgres pg_dump -Fc mastodon_production > "${BACKUP_PATH}/database.dump" echo " Database backup: $(du -h ${BACKUP_PATH}/database.dump | cut -f1)" # 2. Backup .env.production (contains secrets) echo "[2/5] Backing up configuration..." cp /home/mastodon/live/.env.production "${BACKUP_PATH}/.env.production" # 3. Backup user uploads (avatars, headers, media) echo "[3/5] Backing up user uploads (this may take a while)..." if [ -d /home/mastodon/live/public/system ]; then tar -czf "${BACKUP_PATH}/system.tar.gz" -C /home/mastodon/live/public system echo " System files: $(du -h ${BACKUP_PATH}/system.tar.gz | cut -f1)" else echo " No system directory found (fresh install)" fi # 4. Backup custom files (if any) echo "[4/5] Backing up custom files..." mkdir -p "${BACKUP_PATH}/custom" # Custom CSS/branding if [ -f /home/mastodon/live/app/javascript/styles/custom.scss ]; then cp /home/mastodon/live/app/javascript/styles/custom.scss "${BACKUP_PATH}/custom/" fi # Site uploads (favicon, thumbnail, etc) if [ -d /home/mastodon/live/public/site_uploads ]; then cp -r /home/mastodon/live/public/site_uploads "${BACKUP_PATH}/custom/" fi # 5. Export user data echo "[5/5] Exporting instance data..." sudo -u mastodon bash -c "cd ~/live && export PATH=\"\$HOME/.rbenv/bin:\$PATH\" && eval \"\$(rbenv init -)\" && RAILS_ENV=production bin/tootctl accounts export > /dev/null 2>&1" || true # Create restore instructions cat > "${BACKUP_PATH}/RESTORE.md" << 'RESTORE' # Mastodon Restore Instructions ## On the new server: 1. Run the install script first (without creating admin user) 2. Stop all Mastodon services: ``` systemctl stop mastodon-web mastodon-sidekiq mastodon-streaming ``` 3. Restore the database: ``` sudo -u postgres dropdb mastodon_production sudo -u postgres createdb -O mastodon mastodon_production sudo -u postgres pg_restore -d mastodon_production database.dump ``` 4. Restore .env.production: ``` cp .env.production /home/mastodon/live/.env.production chown mastodon:mastodon /home/mastodon/live/.env.production chmod 600 /home/mastodon/live/.env.production ``` 5. Restore user uploads: ``` cd /home/mastodon/live/public tar -xzf /path/to/backup/system.tar.gz chown -R mastodon:mastodon system ``` 6. Update LOCAL_DOMAIN in .env.production if domain changed 7. Run migrations (in case of version upgrade): ``` sudo -u mastodon bash -lc 'cd ~/live && RAILS_ENV=production bundle exec rails db:migrate' ``` 8. Recompile assets: ``` sudo -u mastodon bash -lc 'cd ~/live && RAILS_ENV=production bundle exec rails assets:precompile' ``` 9. Fix SELinux contexts: ``` chcon -R -t httpd_sys_content_t /home/mastodon/live/public ``` 10. Start services: ``` systemctl start mastodon-web mastodon-sidekiq mastodon-streaming ``` RESTORE # Create final archive echo "" echo "Creating final archive..." cd "${BACKUP_DIR}" tar -czf "${BACKUP_NAME}.tar.gz" "${BACKUP_NAME}" rm -rf "${BACKUP_NAME}" FINAL_SIZE=$(du -h "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" | cut -f1) echo "" echo "==========================================" echo "✅ Backup Complete!" echo "==========================================" echo "" echo "Backup file: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" echo "Size: ${FINAL_SIZE}" echo "" echo "To download: scp root@server:${BACKUP_DIR}/${BACKUP_NAME}.tar.gz ." echo ""