Your Raspberry Pi runs 24/7 and stores data you care about. MicroSD cards fail. What happens to your data when one does?
In this post we’ll use the AWS CLI to back up homelab data from a Pi node directly to S3. No third party tools, no agents - just the AWS CLI and a bash script running on a systemd timer.
Pre-requisites #
- AWS account with S3 access
- AWS CLI installed on your Pi node
- IAM user with S3 write permissions
- Data on your Pi you actually want to back up
Setting Up the AWS CLI on Raspberry Pi #
Install the AWS CLI on your Pi node:
sudo apt update
sudo apt install -y awscliVerify the install:
aws --versionConfigure your credentials:
aws configureYou will be prompted for:
AWS Access Key ID: <your-key>
AWS Secret Access Key: <your-secret>
Default region name: us-east-1
Default output format: jsonCreating Your S3 Bucket #
Create a dedicated bucket for homelab backups:
aws s3 mb s3://your-homelab-backups --region us-east-1Enable versioning so you can recover previous versions of files:
aws s3api put-bucket-versioning \
--bucket your-homelab-backups \
--versioning-configuration Status=EnabledCopy vs Sync #
The AWS CLI gives you two main commands for moving data to S3.
| Use Case | Command | Why |
|---|---|---|
| Initial backup | cp |
Safe, won’t delete anything |
| Regular backups | sync |
Mirrors source to destination |
| Archive old files | cp |
Preserves historical data |
| One-time transfer | cp |
Simple and safe |
aws s3 cp #
Copies a single file or directory to S3:
# Copy a single file
aws s3 cp /home/npodoba/important-file.txt s3://your-homelab-backups/
# Copy a directory recursively
aws s3 cp /home/npodoba/homelab-platform/ s3://your-homelab-backups/homelab-platform/ --recursiveaws s3 sync #
Syncs a local directory to S3, only transferring new or changed files:
aws s3 sync /home/npodoba/homelab-platform/ s3://your-homelab-backups/homelab-platform/Always test with –dryrun first:
aws s3 sync /home/npodoba/homelab-platform/ s3://your-homelab-backups/homelab-platform/ --dryrunBuilding the Backup Script #
Create a reusable backup script:
nano /home/npodoba/scripts/s3-backup.shPaste this into the script:
#!/bin/bash
BUCKET="your-homelab-backups"
SOURCE="/home/npodoba/homelab-platform"
LOG="/var/log/s3-backup.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] Starting backup..." >> $LOG
aws s3 sync $SOURCE s3://$BUCKET/homelab-platform/ \
--exclude "*.tmp" \
--exclude ".git/*" \
--delete \
>> $LOG 2>&1
if [ $? -eq 0 ]; then
echo "[$DATE] Backup completed successfully." >> $LOG
else
echo "[$DATE] Backup failed." >> $LOG
fiMake it executable:
chmod +x /home/npodoba/scripts/s3-backup.shAutomating with systemd #
Create a systemd service unit:
sudo nano /etc/systemd/system/s3-backup.servicePaste into the service file:
[Unit]
Description=S3 Homelab Backup
After=network.target
[Service]
Type=oneshot
User=npodoba
ExecStart=/home/npodoba/scripts/s3-backup.sh
[Install]
WantedBy=multi-user.targetCreate the timer:
sudo nano /etc/systemd/system/s3-backup.timerPaste into the timer file:
[Unit]
Description=Run S3 backup every 6 hours
[Timer]
OnBootSec=10min
OnUnitActiveSec=6h
[Install]
WantedBy=timers.targetEnable and start the timer:
sudo systemctl daemon-reload
sudo systemctl enable s3-backup.timer
sudo systemctl start s3-backup.timerVerify it is running:
systemctl list-timers | grep s3-backupVerifying Your Backups #
List your backed up files:
aws s3 ls s3://your-homelab-backups/homelab-platform/ --recursive --human-readableCheck the backup log:
tail -f /var/log/s3-backup.logFAQ #
Why use the AWS CLI instead of rclone? #
If you are only backing up to AWS S3, the AWS CLI is simpler - fewer dependencies, native AWS integration, and no extra configuration files. rclone makes more sense when you need to sync across multiple storage providers simultaneously.
How do I restrict the IAM permissions? #
Instead of full S3 access, create an IAM policy that only allows the specific actions your backup script needs:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::your-homelab-backups",
"arn:aws:s3:::your-homelab-backups/*"
]
}
]
}What does –delete do in sync? #
The –delete flag removes files from S3 that no longer exist locally. Use it carefully - it is powerful for keeping S3 as an exact mirror but will permanently delete files that were removed from the source.