This project provides a Bash backup script that backs up selected files/directories and MySQL/MariaDB databases, creates an encrypted zip archive, and uploads it to S3 or an S3-compatible storage provider.
Generated archive name format:
name-yyyy-mm-dd.zip
backup.sh: backup scriptbackup.conf.example: configuration templateREADME.md: usage guide
- Back up one or more files/directories
- Back up one or more MySQL/MariaDB databases
- Create an AES-256 encrypted zip archive with
7z - Upload to AWS S3 or S3-compatible storage
- Support Gcore Object Storage
- Optionally delete remote backups older than N days
sudo apt update
sudo apt install -y awscli p7zip-fullInstall one MySQL/MariaDB dump client:
sudo apt install -y default-mysql-clientOr:
sudo apt install -y mariadb-clientVerify the required commands:
aws --version
mysqldump --version || mariadb-dump --version
7z || 7zzcp backup.conf.example backup.conf
chmod 600 backup.confEdit backup.conf.
Basic configuration example:
BACKUP_NAME="myapp"
SOURCE_DIRS=(
"/var/www/myapp/uploads"
"/etc/myapp"
)
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
MYSQL_USER="backup_user"
MYSQL_PASSWORD="change-me"
MYSQL_DATABASES=(
"myapp"
)
ZIP_PASSWORD="replace-with-a-long-random-secret"
RETENTION_DAYS=30
WORK_DIR="/tmp/backup-work"Gcore Chicago:
S3_ENDPOINT_URL="https://chicago-1.storage.gcore.dev"
S3_URI="s3://app1/backups"
AWS_DEFAULT_REGION="s-drc2"
AWS_ACCESS_KEY_ID="your-gcore-access-key"
AWS_SECRET_ACCESS_KEY="your-gcore-secret-key"
AWS_REQUEST_CHECKSUM_CALCULATION="when_required"
AWS_RESPONSE_CHECKSUM_VALIDATION="when_required"
AWS_S3_CP_EXTRA_ARGS="--no-progress"Notes:
app1is the bucket name.backupsis the path prefix inside the bucket.67116-bkupis the Object Storage resource name shown in the Gcore console. It should not be used inS3_URI.
echo "gcore upload test $(date)" > /tmp/gcore-test.txt
AWS_ACCESS_KEY_ID="your-gcore-access-key" \
AWS_SECRET_ACCESS_KEY="your-gcore-secret-key" \
AWS_DEFAULT_REGION="s-drc2" \
AWS_REQUEST_CHECKSUM_CALCULATION="when_required" \
AWS_RESPONSE_CHECKSUM_VALIDATION="when_required" \
aws --endpoint-url "https://chicago-1.storage.gcore.dev" \
s3 cp /tmp/gcore-test.txt s3://app1/backups/gcore-test.txt --no-progressList uploaded files:
AWS_ACCESS_KEY_ID="your-gcore-access-key" \
AWS_SECRET_ACCESS_KEY="your-gcore-secret-key" \
AWS_DEFAULT_REGION="s-drc2" \
aws --endpoint-url "https://chicago-1.storage.gcore.dev" \
s3 ls s3://app1/backups/./backup.sh backup.confUploaded file example:
s3://app1/backups/myapp-2026-06-05.zip
Configure:
RETENTION_DAYS=30After a successful upload, the script deletes remote backups under the same S3_URI that match this format and are older than N days:
BACKUP_NAME-yyyy-mm-dd.zip
To disable automatic cleanup:
# RETENTION_DAYS=30The access key used by the script must have list and delete permissions for the bucket.
Edit crontab:
crontab -eRun every day at 02:00:
0 2 * * * /path/to/backup.sh /path/to/backup.conf >> /var/log/myapp-backup.log 2>&1The script uses 7z to create an AES-256 encrypted zip archive. This is much stronger than traditional ZipCrypto encryption used by zip -P.
Important caveats:
7z -pPASSWORDcan briefly expose the zip password in process arguments.MYSQL_PWDis not the most secure way to pass the MySQL password.backup.confmust be protected withchmod 600.
For stronger production-grade backup encryption, consider switching to:
tar/zstd + age
Or:
tar/zstd + gpg