Seafile backup step-by-step how-to, plus: Co-existing with NextCloud, auto-mounting seaf-fuse with Docker

As noted above, the Docker backup instructions here (Seafile CE Docker) or here (Seafile Pro Docker) are a bit simpler than what I implemented above.

So here is a script implementing that solution, but otherwise following the same general procedure as outlined above - dumping the databases and config folder using a script run by cron, then backing that up together with the Seafile data stores using Kopia (or the backup software of your choice).

This is different & simpler than the procedure above:

  • Does not require adding any new/extra volumes in the Docker Compose file
  • Requires just one shell script
  • Run that one script daily or as desired via (root) cron OR (if your backup software provides for this) as a pre-backup task just before your backup executes

Here is the step-by-step:

#1. Open the docker-compose.yml file and make a note of MYSQL_ROOT_PASSWORD found there as we will need it in Step #2.

#2. Within the directory /home/<<my-user-name>>/seafile (the same directory where I keep the Seafile Docker Compose files & other similar setup/config files), I add the new file


#Run this daily via cron (as root user OR user in the root group - seafile runs as root)

#the directory where you want to save the database dumps (inside/relative to the seafile-mysql container):
#Make sure this directory exists & has the same permissions as the other directories within the seafile_main_data_store directory

#the directory where seafile config files are found (Docker Compose files or in general any config-related things you want backed up):
configdir=/home/<<YOUR USERNAME>>/seafile

#a directory within the configdir that you wish to exclude from the backup (begin with /):
#NOTE: If you don't want/need to exclude a directory, then edit the tar statement below to remove the --exclude option
#But don't just leave the excludedir blank - that will exclude everything in the configdir from the backup


dt=`date +"%Y-%m-%d-%H-%M-%S"`

myDBpw='<<MYSQL_ROOT_PASSWORD as found in docker-compose.yml>>'

echo "****SDD: Beginning Seafile database dump and config file backup..."
echo "SDD: Adding backups and db dumps to $mydir/seafile_db_$dt.tgz ..."
mkdir $mydir/$dt
mkdir $mydir/$dt/config

docker exec seafile-mysql mysqldump -u root --password=$myDBpw --opt ccnet_db > $mydir/$dt/ccnet_db.sql
docker exec seafile-mysql mysqldump -u root --password=$myDBpw --opt seafile_db > $mydir/$dt/seafile_db.sql
docker exec seafile-mysql mysqldump -u root --password=$myDBpw --opt seahub_db > $mydir/$dt/seahub_db.sql

cp -r $configdir/* $mydir/$dt/config/
cd $mydir
tar --exclude=$dt/config$excludedir -czvf $mydir/seafile_db_$dt.tgz $dt
rm -r $mydir/$dt

echo "SDD: Removing any seafile_db_*.tgz archives older than $daystosave days..."
find $mydir/ -name 'seafile_db_*.tgz' -type f -mtime +$daystosave -exec rm -v {} +
echo "****SDD: Seafile database dump and config file backup finished."

Note that:

  • The directory you specify inmydir=/path/to/seafile_main_data_store/seafile_db_dumps must exist and should have the same permissions as the other files/directories within the Seafile data store folder. So do something like cd /path/to/seafile_main_data_store and sudo mkdir seafile_db_dumps
  • myDBpw='<<DB-password>>' - this must be the same database password you defined in the Docker Compose file as MYSQL_ROOT_PASSWORD
  • Seafile documentation suggests saving DB dumps for at least 7 days. Script above saves for just 3 days, because I run the script twice daily (thus 6 full DB backups) plus Kopia saves the daily, weekly, and monthly DB dumps along with the appropriate data stores. Obviously, change this as desired.
  • Now make the script executable: chmod +x

Make sure the Seafile containers are started and running in Docker.

Now you can test-run the script via this command:

sudo ./

(Because Seafile runs as root, various files or directories will have, or in some cases can have, root permissions - thus the need for sudo.)

You should see output similar to this, showing where the backup file is created (note that the path shown is within the seafile-mysql container file structure - to find the files outside of that container, you’ll have to translate that to the external file structure depending on how you set up the Docker Compose volumes) and which files were added to it:

****SDD: Seafile database dump starting...
SDD: Adding backups and db dumps to /mnt/seafile_db_dumps/seafile_db_2024-01-18-05-01-29.tgz ...
SDD: Removing any seafile_db_*.tgz archives older than 3 days...
****SDD: Seafile database dump and config file backup finished.

Note that, if you follow the instructions for editing crontab just below, you will find similar output in the system logs (in my system this is in /var/log/syslog, but this varies) and/or emailed to you via your cron system whenever the backup/DB dump runs.

Check that the .tgz file produced by our test run of the script is in the location expected, contains the database dumps and config directory files as expected, and that the database dump files look as expected.

#3. Add a line similar to this to your root crontab file (sudo crontab -u root -e):

55 5,17 * * * /home/<<your-username>>/seafile/ 2>&1 | logger -t seafile_db_cron
  • The above script will run at 5:55 and 17:55 daily
  • The database dump takes just a few seconds so it would probably be safe to run it even at 5:59 and 17:59 - assuming the file store backup begins at 6:00 and 18:00
  • The final portion of the line 2>&1 | logger -t seafile_db_cron adds the output of the script to the system log file (/var/log/syslog in my system - your exact log file may vary). You can use a command like tail -n 100000 /var/log/syslog | grep seafile_db_cron to find output from recent cron runs of the script.
  • Because Seafile runs as root, to access/edit/add files within the data store directory it is simplest to also run this script as root. So I suggest adding this line this to root crontab as described above.
  • If your backup program allows it, you could run the script as a pre-backup task rather than via cron.

#4. Set up your preferred backup solution, or rsync, to run just after the script (say, daily at 6:00 and 18:00) and to back up the entire Seafile library/data store directory, including the seafile_db_dumps directory that we have created within it.

#5. To be completely confident of your back up, once your backup program has backed up the data store directory with your database dumps and configs files, as well as the entire Seafile Data Store, you should end-to-end test the backup. Here is a step-by-step:

  1. Set up a different machine or VM with Docker etc

  2. Copy your config directory to the corresponding /home/<YOUR USERNAME>>/seafile folder on the new machine

  3. Build the Seafile Docker containers using those config files (docker compose up -d etc) - perhaps modifying them to use different data directories etc as necessary.

  4. Restore the databases from the DB dump files into the seafile-mysql container as described here (CE) or here (Pro). In brief that is:

docker cp /opt/seafile-backup/databases/ccnet_db.sql seafile-mysql:/tmp/ccnet_db.sql
docker cp /opt/seafile-backup/databases/seafile_db.sql seafile-mysql:/tmp/seafile_db.sql
docker cp /opt/seafile-backup/databases/seahub_db.sql seafile-mysql:/tmp/seahub_db.sql

docker exec -it seafile-mysql /bin/sh -c "mysql -uroot ccnet_db < /tmp/ccnet_db.sql"
docker exec -it seafile-mysql /bin/sh -c "mysql -uroot seafile_db < /tmp/seafile_db.sql"
docker exec -it seafile-mysql /bin/sh -c "mysql -uroot seahub_db < /tmp/seahub_db.sql"
  1. Restore the Seafile library/data stores to the expected directory as explained in the same document.

  2. Test to make sure the restored version works as expected.