Manual Backup and Restore for SparkyFitness
This document provides instructions for performing manual backup and restore operations for SparkyFitness, primarily for disaster recovery scenarios where the in-app restore might not be feasible.
1. Manual Backup
While the application provides scheduled backups, you can manually trigger a backup if needed. The in-app backup process creates a combined archive containing the PostgreSQL database dump and the uploads directory.
Important Note: This backup functionality is new and should be used with caution. While it creates a backup, it's highly recommended to create additional backups independently of this application. Always follow the 3-2-1 backup strategy (3 copies of your data, on 2 different media, with 1 copy offsite) to ensure data safety. The functionality of restore may not work properly in all scenarios, so do not rely solely on this in-app backup.
Location of Backups: All backup files are stored in a Docker volume mounted to the SparkyFitnessServer service. The default path within the container is /app/SparkyFitnessServer/backup. You will need to access this volume from your Docker host.
A backup is built in the .tmp folder inside the backup directory and only moved into the backup directory once it is complete, so a backup that fails or is cut off never shows up as a backup. If the server is killed while a backup runs, its unfinished files stay in .tmp; the next backup clears anything there that is more than a day old, and you can delete the rest while no backup is running.
Restoring from the admin page with more than one server instance:
A restore from the admin page deletes the database and the uploads folder and rebuilds them from the archive, from inside the server that received the upload. Any other server instance using the same database and uploads keeps serving during that time and would write into a half-restored database. Before you restore, scale to a single server instance:
- Helm: set
server.replicas: 1and runhelm upgrade. With one replica the chart runs no separate-jobsDeployment and does not setSPARKY_FITNESS_DISABLE_SCHEDULED_JOBS. Wait untilkubectl get podslists exactly one server pod and no server pod is stillTerminating, then restore, then set the replica count back. - Docker Compose or several containers: stop every server container but one (for example
docker compose up -d --scale sparkyfitness-server=1, and stop a separate jobs service if you added one), make sure the remaining one does not haveSPARKY_FITNESS_DISABLE_SCHEDULED_JOBS=true, restore, then start the others again.
The server refuses the restore (409, before the archive is uploaded) when it runs with SPARKY_FITNESS_DISABLE_SCHEDULED_JOBS=true, or when it sees database connections opened by another SparkyFitness server. It checks again just before it deletes anything. This check is best effort and does not replace scaling down: a server instance closes its idle database connections after about 30 seconds, so an instance that is running but has had no traffic for that long cannot be seen.
2. Manual Restore (Disaster Recovery)
This process is for situations where the SparkyFitness application or its Docker containers are not functioning correctly, or if you need to restore to a completely new environment.
WARNING: This process will permanently delete all existing data in your PostgreSQL database and uploads directory before restoring from the backup. Ensure you have chosen the correct backup file.
Prerequisites:
- Access to your Docker host machine.
- The
docker-compose.ymlfile used to deploy SparkyFitness. - The full backup archive (
sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gz) you wish to restore. dockeranddocker-compose(ordocker compose) installed on your host.psqlandtarutilities available on your host or within a temporary container.
Steps:
Stop SparkyFitness Services: Navigate to the directory containing your
docker-compose.ymlfile and stop the SparkyFitness services.bashdocker compose downIdentify and Access the Backup Volume: Find the Docker volume associated with the
SparkyFitnessServer's backup directory. You can inspect yourdocker-compose.ymlfor volume definitions or usedocker volume lsanddocker volume inspect <volume_name>. The volume will likely be mounted to a path like/var/lib/docker/volumes/<volume_name>/_dataon Linux hosts.Let's assume your backup volume is named
sparkyfitness_server_backup_dataand it's mounted to/var/lib/docker/volumes/sparkyfitness_server_backup_data/_data.Prepare the Backup File: Copy your chosen
sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gzfile into the backup volume's data directory on your host.bashcp /path/to/your/backup/sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gz /var/lib/docker/volumes/sparkyfitness_server_backup_data/_data/Replace
/path/to/your/backup/with the actual path to your backup file.Extract the Backup Archive: You'll need to extract the combined archive to get the database dump and uploads archive. You can do this directly on the host if
taris available, or use a temporary Docker container.Option A: Using host
tar(if available):bashcd /var/lib/docker/volumes/sparkyfitness_server_backup_data/_data/ tar -xzf sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gzOption B: Using a temporary Docker container:
bashdocker run --rm -v sparkyfitness_server_backup_data:/backup_volume ubuntu:latest tar -xzf /backup_volume/sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gz -C /backup_volumeThis will extract
sparkyfitness_db_backup_YYYYMMDD_HHMMSS.sql.gzandsparkyfitness_uploads_backup_YYYYMMDD_HHMMSS.tar.gzinto the backup volume.Clear Existing Database and Uploads Data:This step is destructive. Ensure you have stopped the services and are confident in your backup.
Clear
uploadsdirectory: Identify the Docker volume for yourSparkyFitnessServer'suploadsdirectory (e.g.,sparkyfitness_server_uploads_data).bash# Example: Assuming uploads volume is sparkyfitness_server_uploads_data docker run --rm -v sparkyfitness_server_uploads_data:/uploads_volume ubuntu:latest rm -rf /uploads_volume/*Clear PostgreSQL Database: You need to drop and recreate the database. You can use a temporary PostgreSQL client container. First, get the database connection details from your
docker-compose.ymlor.envfile (DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME).bash# Example: Replace with your actual DB details DB_HOST="sparkyfitness-db" # Or localhost if connecting directly to host DB DB_PORT="5432" DB_USER="sparkyfitness" DB_PASSWORD="your_db_password" DB_NAME="sparkyfitness" # Drop database docker run --rm -e PGPASSWORD=${DB_PASSWORD} postgres:latest dropdb -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} ${DB_NAME} # Create database docker run --rm -e PGPASSWORD=${DB_PASSWORD} postgres:latest createdb -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} ${DB_NAME}Note: If your
sparkyfitness-dbcontainer is not running, you might need to start it temporarily or adjustDB_HOSTtolocalhostif PostgreSQL is directly accessible on the host.
Restore Database from Dump: Use the
psqlcommand to restore the database from the extracted.sql.gzfile.bash# Example: Replace with your actual DB details and backup file name DB_HOST="sparkyfitness-db" DB_PORT="5432" DB_USER="sparkyfitness" DB_PASSWORD="your_db_password" DB_NAME="sparkyfitness" DB_DUMP_FILE="/var/lib/docker/volumes/sparkyfitness_server_backup_data/_data/sparkyfitness_db_backup_YYYYMMDD_HHMMSS.sql.gz" gunzip -c ${DB_DUMP_FILE} | docker run --rm -i -e PGPASSWORD=${DB_PASSWORD} postgres:latest psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME}Restore Uploads Directory: Extract the
uploadstar archive into theSparkyFitnessServer'suploadsvolume.bash# Example: Assuming uploads volume is sparkyfitness_server_uploads_data UPLOADS_TAR_FILE="/var/lib/docker/volumes/sparkyfitness_server_backup_data/_data/sparkyfitness_uploads_backup_YYYYMMDD_HHMMSS.tar.gz" docker run --rm -v sparkyfitness_server_uploads_data:/uploads_volume ubuntu:latest tar -xzf ${UPLOADS_TAR_FILE} -C /uploads_volumeClean Up Temporary Files: Remove the extracted database dump and uploads tar files from your backup volume.
bashcd /var/lib/docker/volumes/sparkyfitness_server_backup_data/_data/ rm sparkyfitness_db_backup_YYYYMMDD_HHMMSS.sql.gz rm sparkyfitness_uploads_backup_YYYYMMDD_HHMMSS.tar.gz rm sparkyfitness_full_backup_YYYYMMDD_HHMMSS.tar.gzStart SparkyFitness Services:
bashdocker compose up -d
Your SparkyFitness instance should now be restored to the state of your chosen backup.
