DEV Community

Roman Matkivskyy
Roman Matkivskyy

Posted on

[VPS] How to backup mongodb and postgresql dbs to S3 Object Storage

This is a simply guide with examples of how to setup a cron job to backup in efficient way both mongodb and postgresql databases.
All backups are encrypted with 7z and have an expiration time.

Prerequisites

  1. Linux based server
  2. installed p7zip-full,curl, mongodb-tools, postgresql-client
  3. Some S3 compatible storage (in this guide I've used OVH Object Storage)

MongoDB backup

With the help of mongodump tool we can easly download and compress an entire collection, then piping the stdout to 7z and encrypt the db with a password.

mongodump \ --uri="${db_host}/${db_name}?authSource=admin" \ --archive \ --gzip \ | 7z a -si -t7z -p${password} ${file_name} 
Enter fullscreen mode Exit fullscreen mode

db_host > uri to connect to mongodb
db_name > name of the collection to backup
password > password used to encrypt (but also decrypt) the 7z file
file_name > the output file (possibly with *.7z extension)

PostgreSQL backup

With the help of pg_dump tool we can easly download and compress an entire db, then piping the stdout to 7z and encrypt the db with a password.

pg_dump \ --dbname=${db_host}/${db_name} \ | 7z a -si -t7z -p${password} ${file_name} 
Enter fullscreen mode Exit fullscreen mode

db_host > uri to connect to psql
db_name > name of the db to backup
password > password used to encrypt (but also decrypt) the 7z file
file_name > the output file (possibly with *.7z extension)

Upload to S3 compatible service

Now we have the compressed and encrypted files ready to be send to an S3 storage. We can achive this with curl, this is an example of a PUT request with ${file_name} as body

curl -i ${bucket}/${file_name} \ -X PUT \ --data-binary "@${file_name}" \ -H "Content-Type: application/x-7z-compressed" \ -H "X-Auth-Token: ${token}" \ -H "X-delete-after: ${delete_after}" 
Enter fullscreen mode Exit fullscreen mode

in this example I've used OVH Object Storage

bucket > complete uri to your bucket
file_name > filename with which the uploaded file will be saved
token > with OVH we have to add the X-Auth-Token header to autenticate the request
delete_after > this is an optional header, we can decide to delete the file after a certain amount of seconds

Automation

Those 3 commands are the core of our backup script, now we can wrap them with some bash logics and put all in a file

#!/bin/bash # pass args to script if [ $# -eq 0 ]; then echo "Missing args: db_name or delete_after" exit 1 fi while [ $# -gt 0 ]; do case "$1" in --db_name=*) db_name="${1#*=}" ;; --delete_after=*) delete_after="${1#*=}" ;; *) printf "***************************\n" printf "* Error: Invalid argument.*\n" printf "***************************\n" exit 1 esac shift done if [ -z "${delete_after}" ]; then delete_after=`expr 60 \* 60 \* 24 \* 30`; # one month fi # db env db_host=mongodb://user:password@host:port #db_name=db_name file_name=${db_name}_$(date +%d-%m-%Y_%H-%M-%S).gzip.7z; #ovh env bucket=bucket_url; token=personal_token; password=password; # Create a crypted backup if mongodump \ --uri="${db_host}/${db_name}?authSource=admin" \ --archive \ --gzip \ | 7z a -si -t7z -p${password} ${file_name}; then echo 'mongodb dump created' else echo 'mongodump return non-zero code' exit 1; fi content_length=$(cat $file_name | wc -c); # send file to ovh switf  http_response=$(curl -i ${bucket}/${file_name} \ -X PUT \ --data-binary "@${file_name}" \ -H "Content-Type: application/x-7z-compressed" \ -H "Content-Length: ${content_length}" \ -H "X-Auth-Token: ${token}" \ -H "X-delete-after: ${delete_after}" \ | head -n 1 | cut -d \  -f2); if [ $http_response = 201 ] || [ $http_response = 100 ]; then echo "complete"; rm ${file_name}; else echo "error sending file to ovh"; fi 
Enter fullscreen mode Exit fullscreen mode

This file accepts two args:
db_name > mandatory, name of collection/db to backup
delete_after > optional, after how many seconds the file should be deleted

example of how to manually execute
bash script_name.sh --db_name=db_to_backup

CRON

With crontab we can schedule when to execute the backup.

add this row to crontab -e file to run the script every night at 2:00am and save the result to backup_script.logs

0 2 * * * ~/script_name.sh >> ~/backup_script.logs 2>&1 
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.