Initial commit
This commit is contained in:
commit
d14d9b8fa7
4 changed files with 209 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
config
|
||||
databases/
|
79
README.md
Normal file
79
README.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
# About:
|
||||
This is a very basic backup script that:
|
||||
1. Exports databases, stores the md5sums, and then compresses them.
|
||||
2. Uploads the databases, along with specified directories to S3.
|
||||
3. Prunes old backups.
|
||||
|
||||
It will send an email to the specified email if there's an error.
|
||||
|
||||
This is the backup script in use on Woem.men's servers.
|
||||
|
||||
# Prerequisites:
|
||||
**Ubuntu Packages:**
|
||||
```bash
|
||||
sudo apt install restic postgresql-client sendemail
|
||||
```
|
||||
**External Services:**
|
||||
1. An S3 provider. (Amazon S3, Backblaze, etc)
|
||||
1. Email provider which allows SMTP. (Gmail, Fastmail, etc)
|
||||
|
||||
# Setup:
|
||||
You'll need to create the required directory, and pull the files from this repository:
|
||||
```bash
|
||||
sudo mkdir /backups/
|
||||
cd /backups/
|
||||
git clone <repository here>
|
||||
```
|
||||
Copy the `config_example` to `config`, verify permissions, and then edit using your favorite text editor:
|
||||
```bash
|
||||
sudo su
|
||||
cp config_example config
|
||||
chown root:root config
|
||||
chmod 700 config
|
||||
nano config
|
||||
```
|
||||
Next, you'll need to run initial setup on the S3 repository:
|
||||
```bash
|
||||
sudo su # if not already root
|
||||
set -a
|
||||
source config
|
||||
restic -r "$S3_BUCKET" init
|
||||
```
|
||||
And finally, set your crontab file with `sudo crontab -e`:
|
||||
```
|
||||
0 * * * * /backups/backup.sh > /backups/logfile.log
|
||||
```
|
||||
|
||||
# Restoring:
|
||||
You'll need to grab your config variables before restoring:
|
||||
```bash
|
||||
sudo su # if not already root
|
||||
cd /backups/
|
||||
|
||||
set -a
|
||||
source config
|
||||
```
|
||||
After that, fetch a list of backups available to you by running `restic -r "$S3_BUCKET" snapshots`.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
root@guilty-spark:/backups# restic -r "$S3_BUCKET" snapshots
|
||||
repository 17b028ae opened (version 2, compression level auto)
|
||||
ID Time Host Tags Paths
|
||||
---------------------------------------------------------------
|
||||
724327bb 2025-01-09 07:10:04 guilty-spark /backups
|
||||
/etc
|
||||
/home
|
||||
/root
|
||||
---------------------------------------------------------------
|
||||
```
|
||||
Select one, and run the following command, making adjustments as needed for your setup:
|
||||
Using one of the snapshots, restore the files you're missing using `restic restore`. I recommend reading the man file for `restic-restore`.
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
root@guilty-spark:/backups# restic -r "$S3_BUCKET" restore 724327bb -i /home/service/example_file.txt -t /tmp/restore/
|
||||
```
|
||||
```
|
||||
root@guilty-spark:/backups# restic -r "$S3_BUCKET" restore 724327bb -t /tmp/restore/
|
||||
```
|
93
backup.sh
Normal file
93
backup.sh
Normal file
|
@ -0,0 +1,93 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -a
|
||||
source .config
|
||||
set +a
|
||||
set -e
|
||||
|
||||
if [ "$DEBUGGING" -eq 1 ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Remove lock:
|
||||
remove_lock() {
|
||||
rm /tmp/backup.lock
|
||||
}
|
||||
|
||||
# Error Handling:
|
||||
error_handling() {
|
||||
echo "$(date) -> An error occurred!" >&2
|
||||
|
||||
if [ "$ENABLE_EMAILS" -eq 1 ]; then
|
||||
subject="Backup Error -- $SERVER_NAME"
|
||||
body="An error occurred during backup of $SERVER_NAME!\nThe current time is $(date).\nPlease check server logs!"
|
||||
if [ "$DEBUGGING" -eq 1 ]; then
|
||||
sendemail -f $SMTP_FROM -t $SMTP_RECIPIENT -u "$subject" -s $SMTP_SERVER -m "$body" -xu $SMTP_USER -xp $SMTP_PASSWORD -v -o message-charset=$CHARSET
|
||||
else
|
||||
sendemail -f $SMTP_FROM -t $SMTP_RECIPIENT -u "$subject" -s $SMTP_SERVER -m "$body" -xu $SMTP_USER -xp $SMTP_PASSWORD -q -o message-charset=$CHARSET
|
||||
fi
|
||||
echo "$(date) -> Email sent!"
|
||||
fi
|
||||
remove_lock
|
||||
exit 1
|
||||
}
|
||||
trap "error_handling" ERR
|
||||
trap "remove_lock" SIGINT
|
||||
|
||||
if [ "$TEST_ERROR_HANDLING" -eq 1 ]; then
|
||||
error_handling
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test, then create Lockfile
|
||||
if [ -e /tmp/backup.lock ]; then
|
||||
echo "Backups are already running! If in error, manually remove the lockfile!"
|
||||
fi
|
||||
touch /tmp/backup.lock
|
||||
|
||||
# Backups:
|
||||
if [ ! -z "$DATABASES" ]; then
|
||||
mkdir -p /backups/databases/
|
||||
touch /backups/databases/delete
|
||||
rm /backups/databases/*
|
||||
|
||||
echo "$(date) -> Dumping databases..."
|
||||
|
||||
for database in "${DATABASES[@]}"; do
|
||||
echo "$(date) -> $database"
|
||||
sudo -u postgres pg_dump -d "$database" -f /home/tmp/"$database".pgdump
|
||||
md5sum /home/tmp/"$database".pgdump > /backups/databases/md5sums
|
||||
zstd /home/tmp/"$database".pgdump -o /backups/databases/"$database".pgdump.zst
|
||||
rm /home/tmp/"$database".pgdump
|
||||
done
|
||||
|
||||
echo "$(date) -> Dumped!"
|
||||
else
|
||||
echo "No databases selected! Skipping DB export!"
|
||||
fi
|
||||
|
||||
echo "$(date) -> Uploading..."
|
||||
|
||||
if [ ! -z "$BACKUP_EXCLUDE" ]; then
|
||||
for exclude in "${BACKUP_EXCLUDE[@]}"; do
|
||||
exclude_parsed=$exclude_parsed' -e '$exclude
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$exclude_parsed"
|
||||
|
||||
if [ ! "$MAX_SPEED_KILOBYTES_SECOND" -eq 0 ]; then
|
||||
speed_parsed='--limit-upload '$(echo $MAX_SPEED_KILOBYTES_SECOND)
|
||||
fi
|
||||
|
||||
restic -r "$S3_BUCKET" backup $BACKUP_LIST $exclude_parsed $speed_parsed
|
||||
|
||||
echo "$(date) -> Pruning old backups..."
|
||||
|
||||
restic -r "$S3_BUCKET" forget --keep-hourly $HOURLY --keep-daily $DAILY --keep-monthly $MONTHLY --keep-yearly $YEARLY
|
||||
restic -r "$S3_BUCKET" prune
|
||||
restic -r "$S3_BUCKET" unlock
|
||||
|
||||
remove_lock
|
||||
|
||||
echo "$(date) -> Done!"
|
35
config_example
Normal file
35
config_example
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Logging:
|
||||
SERVER_NAME="Example Server"
|
||||
|
||||
# Credentials
|
||||
S3_BUCKET="s3:s3.example.com"
|
||||
AWS_ACCESS_KEY_ID="000000000000"
|
||||
AWS_SECRET_ACCESS_KEY="00000000000000"
|
||||
RESTIC_PASSWORD="Password"
|
||||
|
||||
# Backup Settings:
|
||||
BACKUP_LIST="/etc/ /backups/ /home/ /root/"
|
||||
BACKUP_EXCLUDE=(/home/bad_user/ /home/example_user/cache/)
|
||||
MAX_SPEED_KILOBYTES_SECOND=2500
|
||||
|
||||
# Database Exports:
|
||||
DATABASES=( database1 database2 )
|
||||
|
||||
# Retaining Backups:
|
||||
# For GDPR, set monthly and yearly to 0, daily to 30.
|
||||
HOURLY=48
|
||||
DAILY=30
|
||||
MONTHLY=12
|
||||
YEARLY=5
|
||||
|
||||
# SMTP Settings:
|
||||
ENABLE_EMAILS=0
|
||||
SMTP_SERVER="smtp.example.com:587"
|
||||
SMTP_USER="example@example.com"
|
||||
SMTP_FROM="noreply@example.com"
|
||||
SMTP_PASSWORD="password"
|
||||
SMTP_RECIPIENT="example@example.com"
|
||||
|
||||
# Troubleshooting:
|
||||
DEBUGGING=0
|
||||
TEST_ERROR_HANDLING=0
|
Loading…
Reference in a new issue