Set up automated Redis backups with compression and GPG encryption for production environments. Create systemd timers for scheduled backups and implement secure remote storage for Redis data protection.
Prerequisites
- Redis server installed and running
- Root or sudo access
- Basic familiarity with Redis and systemd
What this solves
Redis backup automation ensures your critical data is protected with regular snapshots, compression to save storage space, and encryption for security compliance. This tutorial sets up automated Redis backups using RDB dumps, gzip compression, and GPG encryption with systemd timers for scheduling.
Install Redis backup dependencies
Update system packages
Start by updating your package manager to ensure you get the latest versions of backup tools.
sudo apt update && sudo apt upgrade -y
Install backup dependencies
Install the required tools for Redis backup automation, including compression utilities and GPG for encryption.
sudo apt install -y gzip tar gnupg2 rsync cron
Create backup directories
Set up dedicated directories for Redis backups with proper ownership and permissions for security.
sudo mkdir -p /opt/redis-backup/{scripts,data,logs}
sudo mkdir -p /var/backups/redis
sudo chown -R redis:redis /opt/redis-backup
sudo chown -R redis:redis /var/backups/redis
sudo chmod 750 /opt/redis-backup
sudo chmod 750 /var/backups/redis
Create automated backup scripts with compression
Generate GPG encryption key
Create a dedicated GPG key pair for Redis backup encryption. This ensures backup files are encrypted at rest.
sudo -u redis gpg --gen-key
Follow the prompts to create the key. Use a strong passphrase and save it securely. For automated backups, you can also create a key without a passphrase:
sudo -u redis gpg --batch --gen-key <
Create the main backup script
Create a comprehensive backup script that handles Redis data dumping, compression, and encryption.
#!/bin/bash
Redis Backup Script with Compression and Encryption
Configuration
REDIS_CLI="/usr/bin/redis-cli"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
REDIS_AUTH=""
BACKUP_DIR="/var/backups/redis"
LOG_FILE="/opt/redis-backup/logs/backup.log"
RETENTION_DAYS=30
GPG_RECIPIENT="redis-backup@example.com"
Create timestamp
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_NAME="redis_backup_${TIMESTAMP}"
Logging function
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
Check if Redis is running
check_redis() {
if ! $REDIS_CLI -h $REDIS_HOST -p $REDIS_PORT ping > /dev/null 2>&1; then
log_message "ERROR: Redis server is not responding"
exit 1
fi
}
Create Redis dump
create_dump() {
log_message "Starting Redis backup: $BACKUP_NAME"
# Force Redis to save current dataset
if [ -n "$REDIS_AUTH" ]; then
$REDIS_CLI -h $REDIS_HOST -p $REDIS_PORT -a $REDIS_AUTH BGSAVE
else
$REDIS_CLI -h $REDIS_HOST -p $REDIS_PORT BGSAVE
fi
# Wait for background save to complete
while [ $($REDIS_CLI -h $REDIS_HOST -p $REDIS_PORT LASTSAVE) -eq $($REDIS_CLI -h $REDIS_HOST -p $REDIS_PORT LASTSAVE) ]; do
sleep 1
done
log_message "Redis BGSAVE completed successfully"
}
Copy and compress dump file
backup_and_compress() {
REDIS_DATA_DIR="/var/lib/redis"
DUMP_FILE="$REDIS_DATA_DIR/dump.rdb"
if [ ! -f "$DUMP_FILE" ]; then
log_message "ERROR: Redis dump file not found at $DUMP_FILE"
exit 1
fi
# Copy dump file to backup directory
cp "$DUMP_FILE" "$BACKUP_DIR/${BACKUP_NAME}.rdb"
# Compress the backup
gzip "$BACKUP_DIR/${BACKUP_NAME}.rdb"
log_message "Backup compressed: ${BACKUP_NAME}.rdb.gz"
}
Encrypt backup file
encrypt_backup() {
cd "$BACKUP_DIR"
# Encrypt the compressed backup
gpg --trust-model always --encrypt -r "$GPG_RECIPIENT" "${BACKUP_NAME}.rdb.gz"
if [ $? -eq 0 ]; then
# Remove unencrypted file
rm "${BACKUP_NAME}.rdb.gz"
log_message "Backup encrypted successfully: ${BACKUP_NAME}.rdb.gz.gpg"
else
log_message "ERROR: Failed to encrypt backup file"
exit 1
fi
}
Clean old backups
cleanup_old_backups() {
find "$BACKUP_DIR" -name "redis_backup_*.gpg" -mtime +$RETENTION_DAYS -delete
log_message "Cleaned up backups older than $RETENTION_DAYS days"
}
Verify backup integrity
verify_backup() {
BACKUP_FILE="$BACKUP_DIR/${BACKUP_NAME}.rdb.gz.gpg"
if [ -f "$BACKUP_FILE" ]; then
BACKUP_SIZE=$(stat -c%s "$BACKUP_FILE")
if [ $BACKUP_SIZE -gt 0 ]; then
log_message "Backup verification successful: $BACKUP_SIZE bytes"
else
log_message "ERROR: Backup file is empty"
exit 1
fi
else
log_message "ERROR: Backup file not found"
exit 1
fi
}
Main execution
main() {
log_message "Starting automated Redis backup process"
check_redis
create_dump
backup_and_compress
encrypt_backup
verify_backup
cleanup_old_backups
log_message "Redis backup completed successfully: ${BACKUP_NAME}.rdb.gz.gpg"
}
Run main function
main
Create backup restore script
Create a companion script to restore Redis backups when needed.
#!/bin/bash
Redis Restore Script
Usage: ./redis-restore.sh backup_file.rdb.gz.gpg
if [ $# -ne 1 ]; then
echo "Usage: $0 "
exit 1
fi
BACKUP_FILE="$1"
REDIS_DATA_DIR="/var/lib/redis"
TEMP_DIR="/tmp/redis_restore_$$"
LOG_FILE="/opt/redis-backup/logs/restore.log"
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
if [ ! -f "$BACKUP_FILE" ]; then
echo "Error: Backup file not found: $BACKUP_FILE"
exit 1
fi
log_message "Starting restore process for: $BACKUP_FILE"
Create temporary directory
mkdir -p "$TEMP_DIR"
Decrypt backup file
echo "Decrypting backup file..."
gpg --decrypt "$BACKUP_FILE" > "$TEMP_DIR/backup.rdb.gz"
if [ $? -ne 0 ]; then
echo "Error: Failed to decrypt backup file"
rm -rf "$TEMP_DIR"
exit 1
fi
Decompress backup
echo "Decompressing backup..."
gunzip "$TEMP_DIR/backup.rdb.gz"
Stop Redis service
echo "Stopping Redis service..."
sudo systemctl stop redis-server
Backup current dump file
if [ -f "$REDIS_DATA_DIR/dump.rdb" ]; then
sudo mv "$REDIS_DATA_DIR/dump.rdb" "$REDIS_DATA_DIR/dump.rdb.backup.$(date +%s)"
fi
Restore backup file
echo "Restoring backup file..."
sudo cp "$TEMP_DIR/backup.rdb" "$REDIS_DATA_DIR/dump.rdb"
sudo chown redis:redis "$REDIS_DATA_DIR/dump.rdb"
sudo chmod 644 "$REDIS_DATA_DIR/dump.rdb"
Start Redis service
echo "Starting Redis service..."
sudo systemctl start redis-server
Clean up
rm -rf "$TEMP_DIR"
log_message "Restore completed successfully"
echo "Redis restore completed successfully"
Make scripts executable
Set proper permissions on the backup scripts to ensure they can be executed by the redis user.
sudo chmod +x /opt/redis-backup/scripts/*.sh
sudo chown redis:redis /opt/redis-backup/scripts/*.sh
Configure systemd timers for scheduled backups
Create systemd service unit
Create a systemd service that runs the Redis backup script with proper user context and error handling.
[Unit]
Description=Redis Backup Service
After=redis.service
Requires=redis.service
[Service]
Type=oneshot
User=redis
Group=redis
ExecStart=/opt/redis-backup/scripts/redis-backup.sh
StandardOutput=append:/opt/redis-backup/logs/service.log
StandardError=append:/opt/redis-backup/logs/service.log
Create systemd timer unit
Set up a timer to run Redis backups automatically at scheduled intervals.
[Unit]
Description=Redis Backup Timer
Requires=redis-backup.service
[Timer]
OnCalendar=daily
RandomizedDelaySec=30m
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the timer
Reload systemd configuration and enable the backup timer to start automatically.
sudo systemctl daemon-reload
sudo systemctl enable redis-backup.timer
sudo systemctl start redis-backup.timer
Create log rotation configuration
Set up log rotation to prevent backup logs from consuming too much disk space.
/opt/redis-backup/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 redis redis
postrotate
/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
Implement GPG encryption for backup files
Export GPG public key for backup
Export the GPG public key to enable backup restoration on other systems if needed.
sudo -u redis gpg --armor --export redis-backup@example.com > /opt/redis-backup/redis-backup-public.key
Test backup encryption
Run a test backup to ensure the encryption process works correctly.
sudo -u redis /opt/redis-backup/scripts/redis-backup.sh
Verify encrypted backup files
Check that backup files are properly encrypted and can be decrypted when needed.
ls -la /var/backups/redis/
sudo -u redis gpg --list-packets /var/backups/redis/redis_backup_*.gpg | head -10
Verify your setup
Test the complete backup and restore process to ensure everything works correctly.
# Check timer status
sudo systemctl status redis-backup.timer
sudo systemctl list-timers redis-backup.timer
Check Redis connectivity
redis-cli ping
View backup logs
sudo tail -f /opt/redis-backup/logs/backup.log
List backup files
ls -la /var/backups/redis/
Test manual backup
sudo systemctl start redis-backup.service
sudo systemctl status redis-backup.service
For more advanced Redis backup strategies, you can also refer to our guide on implementing Redis backup automation with RDB and AOF persistence.
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| GPG encryption fails | Missing or incorrect GPG key | Verify key exists: sudo -u redis gpg --list-keys |
| Permission denied errors | Incorrect file ownership | Fix ownership: sudo chown -R redis:redis /opt/redis-backup |
| Timer not running | Timer not enabled | Enable timer: sudo systemctl enable redis-backup.timer |
| Backup script fails | Redis not responding | Check Redis status: sudo systemctl status redis-server |
| Large backup files | Compression not working | Verify gzip is installed and working: gzip --version |
| Old backups not cleaned | Retention cleanup failed | Check find command syntax in cleanup function |
If you're running Redis in a cluster setup, check our tutorial on setting up Redis cluster with multiple master nodes for cluster-specific backup considerations.
Next steps
- Set up Redis monitoring with Prometheus and Grafana dashboards
- Configure Redis Sentinel with SSL/TLS encryption and authentication
- Implement Redis backup remote storage with S3-compatible services
- Configure Redis backup monitoring and failure alerts
- Set up Redis backup disaster recovery testing and validation
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Redis Backup Automation Installation Script
# Implements automated Redis backups with compression and encryption
# Colors for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m'
# Configuration
readonly REDIS_USER="redis"
readonly BACKUP_DIR="/var/backups/redis"
readonly SCRIPT_DIR="/opt/redis-backup"
readonly GPG_KEY_NAME="redis-backup@$(hostname)"
readonly RETENTION_DAYS="7"
# Error handling
cleanup() {
if [[ $? -ne 0 ]]; then
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop redis-backup.timer 2>/dev/null || true
rm -rf "$SCRIPT_DIR" "$BACKUP_DIR" /etc/systemd/system/redis-backup.* 2>/dev/null || true
fi
}
trap cleanup ERR
print_usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -r DAYS Set backup retention days (default: 7)"
echo " -h Show this help message"
exit 1
}
log() {
echo -e "${GREEN}$1${NC}"
}
warn() {
echo -e "${YELLOW}$1${NC}"
}
error() {
echo -e "${RED}$1${NC}" >&2
}
# Parse arguments
while getopts "r:h" opt; do
case $opt in
r) RETENTION_DAYS="$OPTARG" ;;
h) print_usage ;;
*) print_usage ;;
esac
done
# Check prerequisites
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
exit 1
fi
# Auto-detect distribution
if [[ -f /etc/os-release ]]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
;;
*)
error "Unsupported distribution: $ID"
exit 1
;;
esac
else
error "Cannot detect distribution"
exit 1
fi
log "[1/7] Updating system packages..."
$PKG_UPDATE
log "[2/7] Installing backup dependencies..."
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL gzip tar gnupg2 rsync redis-server redis-tools
else
$PKG_INSTALL gzip tar gnupg2 rsync redis redis-cli
systemctl enable --now redis
fi
log "[3/7] Creating backup directories..."
mkdir -p "$SCRIPT_DIR"/{scripts,logs}
mkdir -p "$BACKUP_DIR"
chown -R "$REDIS_USER":"$REDIS_USER" "$SCRIPT_DIR" "$BACKUP_DIR"
chmod 750 "$SCRIPT_DIR" "$BACKUP_DIR"
log "[4/7] Generating GPG encryption key..."
if ! sudo -u "$REDIS_USER" gpg --list-keys "$GPG_KEY_NAME" >/dev/null 2>&1; then
sudo -u "$REDIS_USER" gpg --batch --gen-key <<EOF
Key-Type: RSA
Key-Length: 2048
Name-Real: Redis Backup
Name-Email: $GPG_KEY_NAME
Expire-Date: 0
%no-protection
%commit
EOF
fi
log "[5/7] Creating backup script..."
cat > "$SCRIPT_DIR/scripts/redis-backup.sh" <<'SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail
# Configuration
REDIS_HOST="localhost"
REDIS_PORT="6379"
BACKUP_DIR="/var/backups/redis"
LOG_FILE="/opt/redis-backup/logs/backup.log"
GPG_RECIPIENT="redis-backup@$(hostname)"
RETENTION_DAYS="7"
REDIS_CLI="redis-cli"
# Logging
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Check Redis connectivity
check_redis() {
if ! $REDIS_CLI -h "$REDIS_HOST" -p "$REDIS_PORT" ping > /dev/null 2>&1; then
log_message "ERROR: Redis server is not responding"
exit 1
fi
}
# Create Redis backup
create_backup() {
local backup_name="redis_backup_$(date +%Y%m%d_%H%M%S)"
local redis_data_dir="/var/lib/redis"
local dump_file="$redis_data_dir/dump.rdb"
log_message "Starting Redis backup: $backup_name"
# Force Redis save
$REDIS_CLI -h "$REDIS_HOST" -p "$REDIS_PORT" BGSAVE
# Wait for save to complete
local last_save=$($REDIS_CLI -h "$REDIS_HOST" -p "$REDIS_PORT" LASTSAVE)
while [[ $($REDIS_CLI -h "$REDIS_HOST" -p "$REDIS_PORT" LASTSAVE) -eq $last_save ]]; do
sleep 1
done
if [[ ! -f "$dump_file" ]]; then
log_message "ERROR: Redis dump file not found"
exit 1
fi
# Copy and compress
cp "$dump_file" "$BACKUP_DIR/${backup_name}.rdb"
gzip "$BACKUP_DIR/${backup_name}.rdb"
# Encrypt
cd "$BACKUP_DIR"
gpg --trust-model always --encrypt -r "$GPG_RECIPIENT" "${backup_name}.rdb.gz"
rm "${backup_name}.rdb.gz"
# Verify
if [[ -f "${backup_name}.rdb.gz.gpg" && -s "${backup_name}.rdb.gz.gpg" ]]; then
log_message "Backup created successfully: ${backup_name}.rdb.gz.gpg"
else
log_message "ERROR: Backup verification failed"
exit 1
fi
# Cleanup old backups
find "$BACKUP_DIR" -name "redis_backup_*.gpg" -mtime +$RETENTION_DAYS -delete
log_message "Cleaned up backups older than $RETENTION_DAYS days"
}
# Main execution
main() {
check_redis
create_backup
log_message "Redis backup completed successfully"
}
main "$@"
SCRIPT_EOF
chmod 755 "$SCRIPT_DIR/scripts/redis-backup.sh"
chown "$REDIS_USER":"$REDIS_USER" "$SCRIPT_DIR/scripts/redis-backup.sh"
# Update retention days in script
sed -i "s/RETENTION_DAYS=\"7\"/RETENTION_DAYS=\"$RETENTION_DAYS\"/" "$SCRIPT_DIR/scripts/redis-backup.sh"
log "[6/7] Creating systemd service and timer..."
cat > /etc/systemd/system/redis-backup.service <<EOF
[Unit]
Description=Redis Backup Service
After=redis.service
[Service]
Type=oneshot
User=$REDIS_USER
Group=$REDIS_USER
ExecStart=$SCRIPT_DIR/scripts/redis-backup.sh
StandardOutput=journal
StandardError=journal
EOF
cat > /etc/systemd/system/redis-backup.timer <<EOF
[Unit]
Description=Redis Backup Timer
Requires=redis-backup.service
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable redis-backup.timer
systemctl start redis-backup.timer
log "[7/7] Verifying installation..."
# Test Redis connection
if systemctl is-active redis >/dev/null 2>&1 || systemctl is-active redis-server >/dev/null 2>&1; then
log "✓ Redis service is running"
else
warn "! Redis service not running - starting now"
systemctl start redis 2>/dev/null || systemctl start redis-server
fi
# Test backup script
if sudo -u "$REDIS_USER" "$SCRIPT_DIR/scripts/redis-backup.sh"; then
log "✓ Backup script executed successfully"
else
error "✗ Backup script test failed"
exit 1
fi
# Verify timer status
if systemctl is-active redis-backup.timer >/dev/null 2>&1; then
log "✓ Backup timer is active"
else
error "✗ Backup timer failed to start"
exit 1
fi
log "Redis backup automation installed successfully!"
log "Backups will run daily and retain files for $RETENTION_DAYS days"
log "Check logs: $SCRIPT_DIR/logs/backup.log"
log "Timer status: systemctl status redis-backup.timer"
Review the script before running. Execute with: bash install.sh