Automate Home Assistant SQLite Backups to AWS S3
Published October 17, 2026 · Editorial policy

Your Home Assistant instance is tracking your power consumption, door locks, and climate automation states in a local SQLite database (home-assistant_v2.db). When your microSD card or NVMe drive inevitably corrupts after a power outage, you lose months of history and automation states. Home Assistant’s built-in snapshot tool creates local tar files, but if the underlying hardware dies, those backups die with it.
You need an automated, hands-off pipeline that dumps your SQLite database, compresses it, and ships it to an off-site AWS S3 bucket every night without interrupting your smart home automations.
The Architecture at a Glance
Instead of relying on heavy third-party Home Assistant supervisor add-ons that can fail silently, use a lean, OS-level approach. If you run Home Assistant Container or Home Assistant Core on a Linux host (such as Ubuntu Server on a Raspberry Pi or an Intel NUC), you can orchestrate this with a shell script, SQLite's online backup API, the AWS CLI, and a system cron job.
+------------------------+ +-----------------------+ +----------------+
| Home Assistant SQLite | ---> | Safe Online Backup | ---> | Compressed Tar |
| (home-assistant_v2.db) | | (sqlite3 .backup) | | (.tar.gz) |
+------------------------+ +-----------------------+ +----------------+
|
v
+----------------+
| AWS S3 Bucket |
| (Encrypted) |
+----------------+
+-------------------------------------------------------------------------------+
| Execution: Daily via Cron / Systemd Timer |
+-------------------------------------------------------------------------------+
This decoupling ensures that even if Home Assistant is writing to the database, sqlite3 safely locks and copies the file without causing database corruption or downtime.
Configuring AWS S3 and IAM
Before touching your Home Assistant host, provision a dedicated S3 bucket and limit blast radius by creating an IAM user with strictly scoped permissions.
Create the S3 Bucket
Log into the AWS Management Console, navigate to S3, and create a new bucket.
- Bucket name:
my-home-assistant-backups-2024(must be globally unique) - Region: Choose the region closest to your physical location (e.g.,
us-east-1oreu-central-1) - Block Public Access: Keep all boxes checked ("Block all public access").
- Bucket Versioning: Enable it. This protects you against accidental deletion or ransomware overwriting your backups.
Navigate to the Management tab of your new bucket, click Create lifecycle rule, and name it expire-old-backups. Set it to transition or expire current versions after 30 days to prevent runaway storage costs.
Provision an IAM User
Never use root AWS credentials or Administrator access keys for automated scripts. Create a dedicated user:
- Go to IAM -> Users -> Create user.
- Name the user
home-assistant-backup-uploader. - Select Attach policies directly and click Create policy.
- Switch to the JSON tab and paste the following least-privilege policy, substituting your actual bucket name:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListAndPutBackups",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-home-assistant-backups-2024",
"arn:aws:s3:::my-home-assistant-backups-2024/*"
]
}
]
}
- Name the policy
HomeAssistantS3BackupPolicy, finish creating the user, and generate an Access key and Secret access key under the user's Security credentials tab. Save these credentials securely.
Installing and Configuring the AWS CLI on the Host
Log into your Home Assistant host via SSH. If you are running Home Assistant OS, you cannot easily run custom cron jobs or install external binaries in the restricted root OS shell; this guide assumes you are running Home Assistant Container or Home Assistant Core on a standard Linux distribution (like Debian or Ubuntu).
Install Dependencies
Ensure sqlite3 and the AWS CLI are installed on your host system:
sudo apt update
sudo apt install -y sqlite3 awscli curl
Verify the installations:
sqlite3 --version
aws --version
Expected output:
3.37.2 2022-01-06 13:55:27 87fc9cbd447a164a66e4a643b4f620f4c0dd59d24f0c868019056d6f51cb7e5d
aws-cli/2.4.5 Python/3.8.8 Linux/5.4.0-91-generic exe/x86_64 prompt/off
Configure AWS Credentials
Configure the AWS CLI profile for the root user or a dedicated backup user. Run:
aws configure
Provide your details when prompted:
- AWS Access Key ID:
AKIAIOSFODNN7EXAMPLE - AWS Secret Access Key:
wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - Default region name:
us-east-1 - Default output format:
json
This creates a configuration directory at /root/.aws/ (or your specific user's home directory). Verify it works by listing your bucket:
aws s3 ls s3://my-home-assistant-backups-2024
If configured correctly, it will return an empty list or existing objects without throwing an error.
Writing the Backup Script
Create a dedicated directory for your maintenance scripts and place the backup script inside it.
sudo mkdir -p /opt/ha-backups
sudo nano /opt/ha-backups/s3-backup.sh
Paste the following production-ready shell script. Update HA_DIR to point to the directory where your home-assistant_v2.db file lives, and update BUCKET_NAME with your S3 bucket name.
#!/usr/bin/env bash
set -euo pipefail
# Configuration
HA_DIR="/var/lib/homeassistant"
DB_NAME="home-assistant_v2.db"
BACKUP_DIR="/tmp/ha-backup-staging"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
ARCHIVE_NAME="ha_backup_${TIMESTAMP}.tar.gz"
BUCKET_NAME="my-home-assistant-backups-2024"
LOG_FILE="/var/log/ha-s3-backup.log"
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "Starting Home Assistant backup process..."
# Create staging directory
mkdir -p "$BACKUP_DIR"
# 1. Safely backup SQLite database using the .backup command
# This prevents corruption by handling locks cleanly while HA is running.
if [ -f "$HA_DIR/$DB_NAME" ]; then
log "Backing up SQLite database..."
sqlite3 "$HA_DIR/$DB_NAME" ".backup '$BACKUP_DIR/$DB_NAME'"
else
log "ERROR: Database file not found at $HA_DIR/$DB_NAME"
exit 1
fi
# 2. Copy other critical configuration files (optional but recommended)
if [ -f "$HA_DIR/secrets.yaml" ]; then
cp "$HA_DIR/secrets.yaml" "$BACKUP_DIR/"
fi
if [ -f "$HA_DIR/configuration.yaml" ]; then
cp "$HA_DIR/configuration.yaml" "$BACKUP_DIR/"
fi
# 3. Compress the staging folder into a tarball
log "Compressing backup archive..."
tar -czf "/tmp/$ARCHIVE_NAME" -C "$BACKUP_DIR" .
# 4. Upload to AWS S3
log "Uploading archive to S3 bucket: $BUCKET_NAME..."
aws s3 cp "/tmp/$ARCHIVE_NAME" "s3://$BUCKET_NAME/$ARCHIVE_NAME" --storage-class STANDARD_IA
# 5. Cleanup local staging and temporary archive files
log "Cleaning up local temporary files..."
rm -rf "$BACKUP_DIR"
rm -f "/tmp/$ARCHIVE_NAME"
log "Backup completed successfully: $ARCHIVE_NAME"
Make the script executable:
chmod +x /opt/ha-backups/s3-backup.sh
Test the script manually to ensure it successfully pushes to S3:
sudo /opt/ha-backups/s3-backup.sh
Check your S3 bucket via the AWS CLI to confirm the archive arrived:
aws s3 ls s3://my-home-assistant-backups-2024/
Automating via Cron
To ensure your backups happen reliably without human intervention, schedule the script to run daily at 3:00 AM using a system cron job.
Open the root crontab:
sudo crontab -e
Add the following line to the bottom of the file:
0 3 * * * /bin/bash /opt/ha-backups/s3-backup.sh >> /var/log/ha-s3-backup.log 2>&1
Save and close the file. Verify that the cron job is registered by listing it:
sudo crontab -l
Troubleshooting Common Failures
Even with a bulletproof script, environmental issues can cause silent failures. If your backups stop appearing in S3, check these common failure points first:
1. SQLite Database Lock Errors (database is locked)
If your Home Assistant instance is writing heavily to the database during a massive state change or recorder purge, the sqlite3 .backup command might occasionally time out or throw a lock error.
- The Fix: Modify the script to run a PRAGMA busy timeout before backing up, or adjust your Home Assistant
recorderintegration configuration to keep fewer days of history so the database file size stays manageable (under 2GB).
2. AWS CLI Authentication Failures in Cron
When running interactively, your AWS CLI uses credentials stored in /root/.aws/credentials. Cron jobs often run with a stripped environment where $HOME or environment variables are not correctly mapped, resulting in an Unable to locate credentials error in your logs.
- The Fix: Ensure your script explicitly points to the AWS profile, or inject credentials via environment variables directly inside the cron definition or at the top of your shell script (
export AWS_ACCESS_KEY_ID="...").
3. Disk Space Exhaustion on /tmp
Tarball compression and SQLite staging require temporary disk space. If your host runs out of space in /tmp during compression, the script will crash mid-execution.
- The Fix: Change the
BACKUP_DIRvariable in the script to point to a directory on a larger data drive instead of RAM-backed or constrained temporary partitions.
Restoring from Your S3 Backup
Disaster recovery is only as good as your restore process. If your hardware dies and you need to rebuild your Home Assistant instance from your S3 backup, follow these steps to restore your data:
- Spin up a fresh installation of Home Assistant on your replacement hardware.
- Stop the Home Assistant service to prevent database writes during restoration:
sudo systemctl stop homeassistant - Download the latest backup archive from S3 to a temporary directory:
aws s3 cp s3://my-home-assistant-backups-2024/ha_backup_20241024_030000.tar.gz /tmp/restore.tar.gz - Extract the archive:
mkdir -p /tmp/ha-restore tar -xzf /tmp/restore.tar.gz -C /tmp/ha-restore - Move the SQLite database back to your Home Assistant configuration directory, ensuring correct file ownership:
cp /tmp/ha-restore/home-assistant_v2.db /var/lib/homeassistant/home-assistant_v2.db sudo chown homeassistant:homeassistant /var/lib/homeassistant/home-assistant_v2.db - Restart Home Assistant:
sudo systemctl start homeassistant
Your historical sensors, graphs, and long-term statistics are now fully restored, completely independent of local hardware failure.
Related articles

Configure Home Assistant Notifications via Webhook Server

Monitor IoT Data on Windows with Grafana & InfluxDB
