You Priced AWS Glacier and Rage-Quit
You sat down, calculator open, feeling responsible. You were going to do this right. Offsite backups, encrypted, versioned, cheap. AWS Glacier Deep Archive — $0.00099 per GB per month, baby. That’s practically free.
Then you hit the restore calculator.
2TB at $0.02/GB expedited retrieval. That’s $40 just to start getting your data back. Add $0.09/GB egress out of us-east-1, and suddenly you’re looking at $220 in egress fees to restore a 2TB backup you paid $2/month to store. And that’s before the per-request charges, the retrieval tier minimums, or the 90-day minimum storage penalty for objects you deleted early.
You closed 14 tabs and poured a drink.
Here’s the thing: Backblaze B2 is not a compromise. For home lab use — and honestly, for a lot of small business use — it’s genuinely the right tool. $6/TB/month storage, $0.01/GB egress, no minimum storage duration on standard tier, and egress to Cloudflare is free. Pair it with rclone and you’ve got a backup stack that won’t surprise you with a $400 invoice when you actually need it.
Let’s build it properly.
The Cloud Storage Reality Check (2026 Edition)
Before you commit, know what you’re comparing against. Here’s what actually matters for a home lab with ~2TB of data to back up.
| Provider | Storage/TB/mo | Egress/GB | Gotchas |
|---|---|---|---|
| AWS S3 Standard | $23 | $0.09 | Everything is expensive |
| AWS S3 IA | $12.50 | $0.09 + $0.01/GB retrieval | Min 30-day per object |
| AWS Glacier Instant | $4 | $0.09 | Min 90-day, retrieval fees |
| Glacier Deep Archive | $0.99 | $0.09 | 12h retrieval, 180-day min |
| Wasabi | $6.99 | $0 | 90-day minimum storage — deleting early still costs |
| Cloudflare R2 | $15 | $0 | No egress but storage ≈ 2.5x B2 |
| Storj | $4 | $0.07 | Decentralized, performance varies |
| Backblaze B2 | $6 | $0.01 | Egress to Cloudflare is free |
Wasabi looks attractive until you realize the 90-day minimum. If you’re rotating backup snapshots more frequently than that — and you should be — you’re paying for deleted objects. The math gets ugly fast with incremental backups.
R2 is excellent if you’re already deep in the Cloudflare ecosystem and you’re serving files publicly. For pure backup cold storage, the storage cost differential stings.
B2’s real superpower: Cloudflare egress partnership. If you front your B2 bucket with Cloudflare, egress is $0. For restore operations, that’s meaningful. For 2TB in egress fees alone, you’re looking at $20 on B2 vs $180+ on S3. That’s not a rounding error.
rclone vs restic vs duplicacy on B2
You’ve got three serious options. They’re not interchangeable and the choice matters.
rclone — think of it as rsync for cloud storage. It syncs files, mirrors directories, moves data. It does not deduplicate. It doesn’t understand “this backup contains changed blocks.” It’s fast, it’s composable, and it integrates with everything. It’s the right choice for file-level syncs and when you want transparency into exactly what’s in your bucket.
restic — content-addressed deduplication, encrypted by default, designed for backups specifically. A restic repo on B2 will be significantly smaller than an rclone sync for large datasets with incremental changes. The tradeoff is that you can’t browse the bucket and see your files — the repo is opaque blobs. Restoring requires restic. For actual backup (not just offsite copy), restic wins on efficiency.
duplicacy — chunk-level dedup across multiple machines, sharable backend. Legitimately useful for multi-machine setups. More complex to operate, less community tooling.
The pragmatic answer for home lab:
- Use rclone to sync media, config exports, and large static datasets
- Use restic (targeting B2 via rclone backend or native B2 backend) for actual system/config backups
- Skip duplicacy unless you’re running backups from 5+ machines to a shared repo
For this article, we’re building the rclone layer. It handles the tiered storage movement, scheduling, and lifecycle management. restic can sit on top of it or alongside it.
B2 Setup: Application Keys Per Bucket
Don’t use your master key with rclone. Ever. Create a dedicated application key scoped to a specific bucket. This way, if your rclone config gets compromised, the blast radius is one bucket.
In the Backblaze console: Account → App Keys → Add a New Application Key
- Name:
homelab-backup-rclone - Allow access to bucket:
homelab-backups(create the bucket first) - Type of access: Read and Write
- File name prefix: leave blank (or scope further if you want)
- Duration: permanent or set an expiry if you rotate credentials
You’ll get a keyID and applicationKey. Save these — the applicationKey is only shown once.
Now configure rclone:
rclone configWalk through the interactive setup:
n) New remotename> b2-homelabStorage> b2account> your-keyID-herekey> your-applicationKey-herehard_delete> falsehard_delete = false keeps deleted files as hidden versions — critical for recovery from accidental deletes. Set lifecycle rules to expire old versions on a schedule (covered below).
Test it:
rclone lsd b2-homelab:homelab-backupsrclone ls b2-homelab:homelab-backups --max-depth 1Your config lives at ~/.config/rclone/rclone.conf. Protect it:
chmod 600 ~/.config/rclone/rclone.confIf you’re running rclone as root or a service account, move the config accordingly and reference it with --config /path/to/rclone.conf.
Encryption: Pick One and Commit
You have three options. Pick one. Using multiple in combination is how you lose data.
Option 1: B2 SSE (Server-Side Encryption) Backblaze encrypts at rest using their managed keys. You get encryption at rest without any complexity. But: Backblaze holds the keys. This is fine for “protect against storage breach” scenarios, not fine for “protect from Backblaze” scenarios. Enabled per bucket in the console.
Option 2: rclone crypt rclone wraps your B2 remote in an encryption layer. Files are encrypted client-side before upload. The bucket contains opaque encrypted blobs — not browseable without the rclone crypt config.
rclone config# Add new remoten) New remotename> b2-homelab-cryptStorage> cryptremote> b2-homelab:homelab-backups/encryptedfilename_encryption> standarddirectory_name_encryption> truepassword> [enter a strong password, store in your password manager]password2> [salt, also store this]Now use b2-homelab-crypt: as your target. Everything written goes through encryption transparently.
Option 3: restic encryption If you’re using restic on top of rclone or natively, restic handles encryption itself with a repo password. The B2 SSE or rclone crypt layer is redundant here — restic is the encryption boundary.
Recommendation: For rclone-synced files, use rclone crypt. For restic repos, let restic handle it and skip the crypt wrapper (it adds overhead for no benefit).
The Tiered Backup Strategy
Here’s the actual architecture for a 2TB home lab:
[Local: mergerfs/ZFS pool] HOT tier — instant access, no cost/GB ↓ rclone sync nightly[B2 Standard bucket] WARM tier — $6/TB/mo, $0.01/GB egress ↓ lifecycle rule (90 days old)[B2 archive/lifecycle hidden] COLD tier — old versions expired or archivedOptionally, for true cold archival (config snapshots, annual backups):
[B2 Standard] → rclone copy to Glacier Deep Archive via AWS CLIBut honestly, for most home labs, B2 Standard with versioning and lifecycle rules is your cold tier. You’re not running a compliance regime. If something catastrophic happens and you need a 90-day-old backup, B2 has it. The restore cost on 2TB would be $20 in egress — fine.
rclone Config for Real Use
Create a dedicated config file for your backup operations (keeps it separate from interactive use):
[b2-homelab]type = b2account = your-keyIDkey = your-applicationKeyhard_delete = false
[b2-homelab-crypt]type = cryptremote = b2-homelab:homelab-backups/encryptedfilename_encryption = standarddirectory_name_encryption = truepassword = your-encrypted-passwordpassword2 = your-encrypted-saltNote: rclone stores passwords in its own obfuscated format. Use rclone config to set passwords interactively — it handles the encoding. Don’t put plaintext passwords in the config file.
A typical sync command:
rclone sync \ /data/media \ b2-homelab-crypt:media \ --config /etc/rclone/backup.conf \ --transfers 8 \ --checkers 16 \ --bwlimit "08:00,512K 19:00,off" \ --stats 60s \ --log-file /var/log/rclone/backup.log \ --log-level INFO \ --exclude "*.tmp" \ --exclude ".Trash-*/**"The --bwlimit "08:00,512K 19:00,off" is gold. Saturate the uplink overnight (no limit outside the schedule), cap at 512K during work hours, and pause entirely 7pm-8am. Adjust to your ISP’s off-peak window.
--transfers 8 and --checkers 16 tune concurrency. On a 1Gbps symmetric connection with an NVMe source, you can push these higher. On a 500Mbps upload with spinning rust, stay conservative.
Lifecycle Rules: Expire Your Versions
With hard_delete = false, every deleted or overwritten file stays in B2 as a hidden version. This is great for recovery. It’s also how you accidentally accumulate 4TB of hidden junk on a 2TB dataset.
Set lifecycle rules in the Backblaze console per bucket:
Bucket → Lifecycle Rules:
- Keep only the most recent version of files
- After 30 days, delete hidden versions
In B2’s console this translates to:
daysFromHidingToDeleting: 30— hidden (deleted) versions expire after 30 daysdaysFromUploadingToHiding: 0— don’t auto-expire current versions (rclone handles that)
For a more aggressive setup (tighter version window):
{ "bucketId": "your-bucket-id", "lifecycleRules": [ { "daysFromHidingToDeleting": 14, "daysFromUploadingToHiding": null, "fileNamePrefix": "" } ]}Apply via B2 CLI if you prefer scriptable setup:
b2 update-bucket --lifecycle-rule \ '{"daysFromHidingToDeleting": 14, "fileNamePrefix": ""}' \ homelab-backupsSystemd Service + Timer
Don’t run this from cron if you’re on a modern Linux system. Systemd timers give you better logging, dependency management, and manual trigger support.
[Unit]Description=rclone B2 backup syncAfter=network-online.targetWants=network-online.target
[Service]Type=oneshotUser=backupExecStart=/usr/bin/rclone sync \ /data/media \ b2-homelab-crypt:media \ --config /etc/rclone/backup.conf \ --transfers 8 \ --checkers 16 \ --bwlimit "08:00,512K 19:00,off" \ --log-file /var/log/rclone/backup.log \ --log-level INFO \ --stats 60s \ --exclude "*.tmp" \ --exclude ".Trash-*/**"StandardOutput=journalStandardError=journal[Unit]Description=Run rclone B2 backup nightly
[Timer]OnCalendar=*-*-* 02:00:00RandomizedDelaySec=30mPersistent=true
[Install]WantedBy=timers.targetsystemctl daemon-reloadsystemctl enable --now rclone-b2-backup.timersystemctl status rclone-b2-backup.timerjournalctl -u rclone-b2-backup.service -fRandomizedDelaySec=30m staggers the start across 30 minutes — useful if you’re running this on multiple machines. Persistent=true means if the system was off at 2 AM, it runs the missed backup when it comes back up.
The Restore Test You’re Not Doing
Every quarter. Set a calendar reminder right now.
Pick a known directory from your backup. Not a tiny one. Something meaningful — a config directory, a media subfolder, a database dump. Restore it to a temp location and verify the hashes match.
# Pick a test directory from your backupRESTORE_TARGET="/tmp/restore-test-$(date +%Y%m%d)"mkdir -p "$RESTORE_TARGET"
# Restore from B2rclone copy \ b2-homelab-crypt:media/important-configs \ "$RESTORE_TARGET" \ --config /etc/rclone/backup.conf \ --transfers 4 \ --progress
# Verify hashes match the sourcerclone check \ /data/media/important-configs \ "$RESTORE_TARGET" \ --one-way
# Clean uprm -rf "$RESTORE_TARGET"rclone check compares checksums both directions. --one-way checks that everything in the source exists in the destination (not the reverse). If you get errors, you have a problem. Better to find out on a Tuesday afternoon than during an actual incident.
Log the results. Date them. Keep them somewhere outside the system you’re backing up.
Real-World Cost Math for 2TB
Let’s be honest about what this actually costs.
Storage:
- 2TB in B2 Standard: 2 × $6 = $12/month
- With versioning churn (assume 10% overhead from old versions): ~$13.20/month
Egress (normal operations):
- Nightly sync is upload-only — $0 in egress
- Monthly restore test of ~10GB: 10 × $0.01 = $0.10
- Emergency full restore (2TB): 2000 × $0.01 = $20 one-time
Compare to S3 Standard:
- 2TB storage: ~$46/month
- Full restore egress: 2000 × $0.09 = $180
Annual difference: ~$420/year saved just on storage. The restore egress gap is another $160 when you need it.
Bandwidth cost from your ISP: This is real but usually not metered for home use. If you’re on a capped plan, factor in ~60GB/month for incremental changes on a 2TB dataset (rough rule of thumb: 3% churn rate).
The Bottom Line
AWS is a great product. It is not the right product for a home lab’s backup tier. The pricing model is designed for enterprises that can negotiate volume discounts and have billing teams to manage the complexity.
B2 + rclone is straightforward: you know what you’re paying, you know what restore costs, and there are no surprises at the end of the month. $12-15/month for 2TB of offsite backup that you actually tested and can restore from is a good deal. The fact that the tooling is all open source and runs on a Raspberry Pi if necessary is a bonus.
Set up the application keys, enable encryption at the rclone layer, configure the lifecycle rules, and put the restore test on a calendar. The backup that nobody tests is a backup nobody should trust.
Your 2 AM self — the one dealing with a failed ZFS pool or a misconfigured rm -rf — will appreciate having verified this works before they needed it.