Initial commit

This commit is contained in:
Ashten 2025-01-09 08:16:08 -08:00
commit d14d9b8fa7
4 changed files with 209 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
config
databases/

79
README.md Normal file
View 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
View 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
View 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