Case Study: Use a 3-2-1 Backup Strategy at Vultr

Updated on November 21, 2023
Case Study: Use a 3-2-1 Backup Strategy at Vultr header image

Introduction

With the complexity and moving pieces involved in today's applications and computing, failure is inevitable. The Cybersecurity and Infrastructure Security Agency (CISA) recommends that individuals and businesses use what is commonly referred to as a 3-2-1 strategy.

  • 3: Have one primary system backup and two copies of your data
  • 2: Store your backup two different ways or on two different sets of media
  • 1: Store one copy of the backed up data off-site

Deploy & Secure Ubuntu 20.04

This case study uses a Ubuntu 20.04 LTS server as the base operating system. Deploy a new Vultr Ubuntu 20.04 (x64) cloud server using the type of configuration that best suits the needs of the environment you support. Ensure to deploy/locate the server in any datacenter except New York (NJ). This ensures two distinctly different locations of the data and backup files. Also, ensure to check "Enable Auto Backups" in the server configuraiton. Throughout this document, the server name is apphost. After deploying apphost update the server according to the Ubuntu best practices guide.

Add a Backup User

After deploying apphost, add a user that performs the tasks of 3-2-1 backup. This document names the user beepbeep (as in backing up) because backup is often a reserved word in many operating systems and languages and, therefore, should not be used. The user beepbeep should only be performing automated tasks, so after creating it, lock the account, preventing it from logging in. To create the account and then lock it, run:

# useradd -m -s /bin/bash beepbeep
# usermod -L beepbeep

Create Supporting Directories

To perform the 3-2-1 backup, create 3 supplemental directories. These directories are for:

  • Holding the application/backup script
  • Holding the actual backup files
  • Holding the log files associated with backup

To create the application/backup directory, run:

# mkdir /usr/local/bin/backup
# chown -R beepbeep.beepbeep /usr/local/bin/backup

To create the directory to hold the backups, run:

# mkdir /opt/backups
# chown -R beepbeep.beepbeep /opt/backups

To create the directory to hold the logs, run:

# mkdir /var/log/backupauto
# chown -R beepbeep.beepbeep /var/log/backupauto

Setup AWSCLI

This guide stores the off-site data in Vultr Object Storage. Vultr Object Storage uses S3 protocols. This 3-2-1 document uses awscli to communicate and store the off-site backup.

Install AWSCLI

To install awscli run:

# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# unzip awscliv2.zip
# sudo ./aws/install
# rm -fr aws
# rm awscliv2.zip

This downloads the package and supplemental files, unzips them, installs them, and removes the original files.

Setup MySQL/MariaDB

MariaDB is one of the most common database platforms. This document uses a demonstration database running on MariaDB to highlight the 3-2-1 idea by backing up the database both locally and off-site. To install the latest version of MariaDB, update the repository by running:

# curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash

After updating the repository, install MariaDB by running:

# sudo apt install mariadb-server mariadb-client -y

After installation, enable MariaDB to start on boot by running:

# sudo systemctl enable mariadb.service

Now, secure the database. Run the built-in utility provided by MariaDB:

# sudo mysql_secure_installation

There are a series of questions. To ensure an optimal and secure database answer them as follows:

* Switch to unix_socket authentication [Y/n]: Y
* Change the root password? [Y/n]: Y
* Remove anonymous users? [Y/n]: Y
* Disallow root login remotely? [Y/n]: Y
* Remove test database and access to it? [Y/n]: Y
* Reload privilege tables now? [Y/n]: Y

After installing and configuring MariaDB, create and populate a sample database. The following steps download, extract, import, and then delete the file associated with the sample database:

# wget https://www.mysqltutorial.org/wp-content/uploads/2018/03/mysqlsampledatabase.zip
# unzip mysqlsampledatabase.zip
# mysql -u root < mysqlsampledatabase.sql
# rm mysqlsample*

Now that there is a populated database, create a restricted user to complete the 3-2-1 backup. Lock this user down, only giving permission to backup the data and not alter it. To do this, access the MariaDB console, create and then grant specific permissions to the user. Also, lock the account to only access the database from localhost. Carry out these tasks by running:

# mysql -u root
MariaDB [(none)]> GRANT SELECT, SHOW VIEW, TRIGGER on classicmodels.* to 'sqlbackuser'@'localhost' identified by 'Password123!';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit;

Note in the above, the user has a username of sqlbackuser and password of Password123!. Best practice uses a strong, random password in place of the above password. You can randomly generate a long, secure password online.

Setup Vultr Object Storage

To meet the third point of the 3-2-1 backup strategy, store files in a secondary, off-site location. To do this, create Vultr Object Storage. Label the object storage appropriately. After creating the object storage, take note of the Secret Key and Access Key.

Configure the Installation

Now all the components are in place, create the configurations to support the solution. To do this, from the root account, use the su command to log in to the beepbeep account (as it cannot log in from a command prompt, based on the account creation). From the root prompt, run:

# su - beepbeep

To confirm successful login as beepbeep the command prompt reads:

beepbeep@apphost:~$ 

AWSCLI Configuration

To configure awscli, type aws configure at the prompt (logged in as beepbeep). It asks four questions:

AWS Access Key ID []:
    * Enter the Access Key found on the Manage Object Storage page
AWS Secret Access Key []:
    * Enter the Secret Key found on the Manage Object Storage page (you will need to click the eyeball first to reveal this key)
Default region name []:
    * Enter `us-east-1`
Default output format [None]:
    * Leave this blank

After you enter these four values, awscli creates multiple configuration files used by the program and the user.

MariaDB Configuration

The database backup script needs to know the username and password to use when running. These credentials live in a file called .my.cnf, located in the root directory of the user running the backup command. To edit this file, first ensure you are in the root of the beepbeep users' home directory, logged in as the beepbeep user. You can check the directory by typing pwd and it should return /home/beepbeep/. You can check the user by typing whoami and it should return beepbeep. After confirming these two settings, create the file by typing:

$ nano ~/.my.cnf

After the editor is open, add the following lines to the file (ensuring to change the password to the one you used above):

[mysqldump]
user=sqlbackuser
password=Password123!
single-transaction
no-tablespaces

Save the file by pressing Ctrl+X and then pressing Y and Enter.

Now, secure the file by changing the permissions to only allow beepbeep to read it by running:

$ chmod 600 ~/.my.cnf

Backup Script

Creating the Backup Script

Now all the pieces are in place for the actual backup to occur, create the backup script. Store the backup script in the directory created at the beginning. Still logged in as the beepbeep user, change the working directory by typing:

$ cd /usr/local/bin/backup

After changing to this directory, create the backup script called backup.sh by typing:

# nano backup.sh

The contents of this file should contain:

#!/bin/bash

#############################################################
# Below here are variables that can be modified by the user #
# to alter the way the script behaves                       #
#############################################################
# S3 Bucket Name
BUCKET_NAME="sql-backup"
# location where the backups will be stored
DEST="/opt/backups"
# how many days to keep backups around locally
DAYS=3
# name of the database to backup
DBNAME="classicmodels"
# directory location of the log file
LOGLOC="/var/log/backupauto"
# GZip Compression Level
GZCOMP="-9"
# Vutlr S3 URL
VULTR_S3_URL="https://ewr1.vultrobjects.com"

#########################################################
# Below here are generated variables used in the script #
#########################################################
# Used as the name for the sql backup
NOW="$(date +"%d-%m-%Y_%s")"
# Used as the filename for the backup log
TODAY="$(date +"%d-%m-%Y")"
# Actual name of the SQL file that gets written
FILE="$DEST/$DBNAME.$NOW.sql.gz"
# Log file to be written to
LOG="$LOGLOC/$TODAY.log"
# LTS = Log Time Stamp. This is inserted at the front of every echo log entry
# NOTE: There is an intentional space left at the end
LTS="[`date +%Y-%m-%d\ %H:%M:%S`] "

#####################################################
# Here is where the script actually begins and runs #
#####################################################
echo $LTS began backing up >> $LOG
mysqldump $DBNAME | gzip $GZCOMP > $FILE
find $DEST -mtime +$DAYS -exec rm -f {} \;
if ! aws s3api head-bucket --bucket "$BUCKET_NAME" --endpoint-url $VULTR_S3_URL 2>/dev/null; then
    aws s3api create-bucket --bucket "$BUCKET_NAME" --endpoint-url $VULTR_S3_URL
    echo $LTS created $BUCKET_NAME >> $LOG
fi
aws s3 cp $FILE s3://$BUCKET_NAME --endpoint-url $VULTR_S3_URL >> $LOG
echo $LTS finished backup >> $LOG

The variables in the top section control the way the backup script works. Make sure to change the DBNAME to the name of the database used in production.

Allowing the Backup Script To Execute

After creating the script, it still does not have the ability to execute on behalf of the beepbeep user. Change the file to allow the user to execute the script by running:

$ chmod u+x backup.sh

After changing the execution bit on the file, you can type exit to log out of the beepbeep user session and return back to the root user's command prompt.

Automate the Backup Script

As root, create a Cron job:

# nano /etc/cron.d/beep_backup

Inside the file enter the following:

32 05 * * *     beepbeep     /usr/local/bin/backup/backup.sh > /dev/null 2>&1

The '32 05denotes the script runs daily at 05:32 (local time to the server), and the* * *denotes it runs every day of every week of every month. Thebeepbeepis the user who runs the command, and the command is at the end. The line ends with> /dev/null 2>&1` to essentially discard any extra output the file produces.

Test and Restore

The worst thing to do is create a 3-2-1 backup strategy and not actually test it. All too often, with backup strategies, it's "set it and forget it". If you do that with the backup the day you need it, the last successful backup won't contain what you need. Check the machine backup. Ensure it restores successfully. Open local archival backups. Make sure the data backed up is inside those files. Open the remote/off-site backup. Make sure the data is also in those files. The worst feeling is when you need a backup and don't have it or the files you need are missing or not there.

Summary

By deploying a virtual host with backups enabled, you carry out the easiest part of the backup. You can restore the system backup using the Vultr Console. The second part of backup is backing up files. Setting a routine job to run at set intervals accomplishes this task. Reassurance this is successful comprises opening the backup files and finding the data required. After you have the system backed up, and the files backed up as well, store another copy of the files off-site. Use a technology like Vultr Object Storage, giving you a second copy at a second location, should a catastrophic failure occur. This strategy, known as the 3-2-1 backup strategy, one day, just might come in handy.

References