How to make a full backup of Redmine (Linux)

Redmine Full Backup

In this article you will be learning how to create a full backup of your entire Redmine application, including files and database (MySQL). And how to do the same process unattended as well.

[Note: if your Redmine is installed on a Windows server, then this is the entry you are interested in].

Prepare the system for the backup

First we will create two directories where the database dumps and the zipped files folders will be stored after the backup action is performed. Let's assume these two directories are made in our userX's home directory and the userX has root permissions in the server:

mkdir /home/userx/backups
mkdir /home/userx/backups/database
mkdir /home/userx/backups/files

Let's also assume that the path for our Redmine application is like this one:

/opt/webapps/redmine/htdocs

Check the database credentials

We will have to check the details for the database dump. Go to the file /opt/webapps/redmine/htdocs/config/database.yml and write down:

  • database name
  • username
  • password

We also assume that the database server is localhost and the port is the standard 3306.

Create a script

Now it's time to create the script that will do everything for us with just one single command. This is the script:

#! /bin/bash
DATE=`date +"%Y-%m-%d-%H:%M"`
SQLFILE=/home/userx/backups/database/${DATE}-redmine-databasedump.sql
DATABASE=databasename1
USER=userdbY
PASSWORD=841bd86484
# do the mysql database backup (dump)
mysqldump -u ${USER} -p${PASSWORD} ${DATABASE}|gzip>${SQLFILE}.gz
FILES_DATE=`date +"%Y-%m-%d-%H:%M"`
FILE_BACKUP=/home/userx/backups/files/${FILES_DATE}-redmine-filesdump
# do the files backup
zip -r ${FILE_BACKUP}.zip /opt/webapps/redmine/htdocs/files

Let's say we will name the script file as backup-script.sh

Script explanation

In the first lines of the script we are declaring the variables that we will use in the script. Of course you will have to substitute database name, user and password by the ones you have found in the database.yml file.

This is what the script will do when launching it:

  1. Makes a database dump
  2. Compresses it into a .gz file
  3. Locates the dump in the /backups/database folder
  4. Makes a copy of the redmine /files folder
  5. Compresses it into a .zip file
  6. Locates the zip file in the /backups/files folder

To launch the script manually, just go to the SSH command line and type:

sh backup-script.sh

Click Enter and in a couple of minutes (depending on how big the database and the files folder are) the script should have created two files, like this:

2022-06-09-11:32-redmine-databasedump.sql.gz &
2022-06-09-11:34-redmine-fiesdump.zip

Just go to the backup folders and check.

Do the Redmine backup programatically and unattended

The above instructions apply for a manually created backup, but of course we don't want to do it manually every day. We can use cron jobs to perform the same action automatically.

Cron job for the Redmine backup

Let's say we want the full backup to be performed on a daily basis at 3 am. OK, you will have to open your crontab and include the cron job pointing to the script. These are the steps:

crontab -e

Now include this line in the crontab file:

00 03 * * * sh /opt/webapps/redmine/htdocs/backup-script.sh

Close the crontab with Ctrl + X and answer Y(es) so that the file is saved.

Now the backup will be done each day at 3 am.

Retention policy

“OK, Luis, this is nice, but I don't want my server to be swamped by backup files indefinitely. We should destroy old files periodically and unattended, the same way we created them with the script.”

No worries, we can add a couple of lines to the original script so that the old files are deleted automatically. In this example we will leave only the last file in each folder. All other backup files will be automatically destroyed. Check the new script:

#! /bin/bash
DATE=`date +"%Y-%m-%d-%H:%M"`
SQLFILE=/home/userx/backups/database/${DATE}-redmine-databasedump.sql
DATABASE=databasename1
USER=userdbY
PASSWORD=841bd86484
# remove the previous version of the file
find /home/userx/backups/database/* -mmin +1 -exec rm {} \;

# (3) do the mysql database backup (dump)
mysqldump -u ${USER} -p${PASSWORD} ${DATABASE}|gzip>${SQLFILE}.gz
FILES_DATE=`date +"%Y-%m-%d-%H:%M"`
FILE_BACKUP=/home/userx/backups/files/${FILES_DATE}-redmine-filesdump
# (2) in case you run this more than once a day,
# remove the previous version of the file
find /home/userx/backups/files/* -mmin +1 -exec rm {} \;

# (3) do the files backup
zip -r ${FILE_BACKUP}.zip /opt/webapps/redmine/htdocs/files

The lines in black have been added to the original script.


So we finally have a script that:

  • makes a database and files backup each day, storing a compressed version of them in the backups directory
  • deletes old backup files so that only the last one is left in the folder

In case you would want to leave the last 3 files (last 3 days), for instance, then the script would look like this:

#! /bin/bash
DATE=`date +"%Y-%m-%d-%H:%M"`
SQLFILE=/home/userx/backups/database/${DATE}-redmine-databasedump.sql
DATABASE=databasename1
USER=userdbY
PASSWORD=841bd86484
# remove the previous version of the file
find /home/userx/backups/database/* -mtime +3 -exec rm {} \;
# (3) do the mysql database backup (dump)
mysqldump -u ${USER} -p${PASSWORD} ${DATABASE}|gzip>${SQLFILE}.gz
FILES_DATE=`date +"%Y-%m-%d-%H:%M"`
FILE_BACKUP=/home/userx/backups/files/${FILES_DATE}-redmine-filesdump
# (2) in case you run this more than once a day,
# remove the previous version of the file
find /home/userx/backups/files/* -mtime +3 -exec rm {} \;
# (3) do the files backup
zip -r ${FILE_BACKUP}.zip /opt/webapps/redmine/htdocs/files
NOTE: If you encounter issues with the action of making the database dump, storing the files in their directories or deleting them, this might be caused by the fact that the user that is launching the script doesn't have the right permissions.

I hope this was a useful tip for you! Please share the post throughout your social networks if you liked it 🙂

About The Author

Leave a Comment

Your email address will not be published. Required fields are marked *