How to Build a Reliable Backup with Restic and S3-Compatible Storage (With Encryption and Automation)

A modern backup should be encrypted, versioned, and easy to restore under pressure. If you are still copying folders to an external disk or relying on a single cloud sync tool, you are one hardware failure or ransomware incident away from a bad day. In this tutorial, you will set up restic (a fast, encrypted backup tool) to back up a Linux server to S3-compatible object storage such as MinIO, Backblaze B2 (S3 API), Wasabi, or many private cloud providers.

The goal is to create a backup that is secure by design (client-side encryption), storage-efficient (deduplication), and maintainable (automatic scheduling and retention policies). The same approach works for a VPS, a home server, or a small business file server.

What You Need

Prerequisites: a Linux machine (Ubuntu/Debian examples here), network access to your S3-compatible endpoint, and an S3 access key/secret key with permission to read and write to a bucket. You should also have enough disk space for temporary operations and stable time synchronization (NTP) to avoid confusing logs.

Step 1: Install Restic

On Ubuntu/Debian, restic is available via the package manager. Install it and confirm the version:

Commands:

sudo apt update
sudo apt install -y restic
restic version

If your distribution ships an older build and you need a newer version (for example, due to S3 compatibility fixes), you can install from the official release packages. For many environments, the repository version is sufficient and keeps updates simple.

Step 2: Prepare S3 Credentials and Repository Settings

Restic reads S3 configuration from environment variables. Create a restricted bucket for backups (for example, server-backups) and then define the repository URL like this:

export RESTIC_REPOSITORY="s3:https://s3.example.com/server-backups/restic-repo"

Set the credentials and optional endpoint tuning variables. Replace values to match your provider:

export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"

If your provider requires a specific region value (some do, some ignore it), add:

export AWS_DEFAULT_REGION="us-east-1"

Tip: avoid leaving secrets in shell history. In production, store these in a root-only file and load them from a systemd service (shown later).

Step 3: Initialize the Backup Repository (Encryption Starts Here)

Initialize a new restic repository. You will be prompted to set a password; this password encrypts metadata and data before it leaves your server:

restic init

Choose a long passphrase and store it in a password manager. If you lose it, your backups will be unusable. That is the tradeoff of true zero-knowledge encryption.

Step 4: Run Your First Backup

Start with a simple backup of a few important paths (adjust to your system). For example, system configuration and application data:

restic backup /etc /home /var/www

Restic automatically deduplicates blocks, so subsequent backups are usually much faster and smaller. After the backup completes, list snapshots:

restic snapshots

Step 5: Add Exclusions for Noise and Speed

You typically do not want to back up caches, temporary folders, or large rebuildable directories. Create an exclusions file:

sudo nano /etc/restic-excludes.txt

Example exclusions:

/var/cache
/tmp
/var/tmp
/home/*/.cache

Run the backup using the exclude list:

restic backup / --exclude-file=/etc/restic-excludes.txt

Backing up the entire root filesystem can be useful on smaller servers, but consider carefully if you have databases or constantly changing log files. For databases, consistent dumps (or snapshots) are usually better than copying live files.

Step 6: Apply a Retention Policy (Forgetfulness Is a Feature)

Without cleanup, backups grow forever. Restic includes a clear retention mechanism via forget and prune. A common policy is “daily for 7 days, weekly for 4 weeks, monthly for 12 months”:

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

This removes old snapshots while keeping enough restore points to cover mistakes that are discovered late.

Step 7: Automate Backups with systemd (Safer Than Cron for Secrets)

Create an environment file that only root can read:

sudo nano /etc/restic.env
sudo chmod 600 /etc/restic.env

Add variables (example):

RESTIC_REPOSITORY=s3:https://s3.example.com/server-backups/restic-repo
AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
AWS_DEFAULT_REGION=us-east-1
RESTIC_PASSWORD=YOUR_LONG_REPO_PASSWORD

Now create a systemd service:

sudo nano /etc/systemd/system/restic-backup.service

Service content:

[Unit]
Description=Restic Backup to S3
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/restic.env
ExecStart=/usr/bin/restic backup /etc /home /var/www --exclude-file=/etc/restic-excludes.txt
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

Create a timer to run nightly:

sudo nano /etc/systemd/system/restic-backup.timer

Timer content:

[Unit]
Description=Run Restic Backup Nightly

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Enable and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
systemctl list-timers | grep restic

Step 8: Test Restore (The Part People Skip)

A backup is only real if it restores. Pick a small file and test a restore to a safe directory:

mkdir -p /tmp/restic-restore-test
restic snapshots
restic restore latest --target /tmp/restic-restore-test

If you only need one file, use restic ls to locate it and then restore selectively, or mount the repository for browsing (useful for investigations and audits). Build the habit of monthly restore tests, especially before major upgrades.

Common Troubleshooting Tips

403 Access Denied: confirm the bucket policy and credentials. Ensure the key has permission for list, get, put, and delete operations in the backup prefix.

Slow uploads: check MTU issues, DNS, and consider running backups during off-peak hours. For some providers, setting an explicit region or endpoint URL is required for stable performance.

Password failures in automation: verify RESTIC_PASSWORD is correctly set in /etc/restic.env and that the file permissions are restrictive.

With restic and S3-compatible storage, you get encrypted, deduplicated backups that are easy to automate and straightforward to restore. Once the basics are working, the next upgrade is adding alerting (email or webhook on failure) and keeping a second copy in another region or provider for true disaster recovery.

Set Up Incremental Backups on Linux with Restic and S3-Compatible Storage (Rclone + Encryption)

Why Restic + S3 Is a Smart Backup Combo

If you want a modern Linux backup solution that is fast, encrypted by default, and easy to automate, restic is one of the best tools available today. It creates deduplicated, incremental snapshots, so repeated backups are much smaller than full copies. Pairing restic with an S3-compatible object storage (such as MinIO, Backblaze B2 S3, Wasabi, or a private S3 gateway) gives you reliable offsite storage without managing a traditional backup server.

In this tutorial, you will set up restic on Linux, connect it to an S3-compatible destination using environment variables, run your first backup, verify it, and schedule it with systemd. The steps are designed to be practical for a workstation or a small server.

Prerequisites

You will need: a Linux machine (Ubuntu/Debian/RHEL-based are fine), access keys for an S3-compatible bucket, outbound internet access (or network access to your S3 endpoint), and a user account with permission to read the folders you plan to back up. Choose a directory to store your restic password securely (or use a password manager and a root-only file).

Step 1: Install Restic (and Rclone if Needed)

On Ubuntu/Debian, install restic with:

sudo apt update && sudo apt install -y restic

On RHEL/CentOS/Fedora, you can use your distribution repositories or install a package from your vendor. If you prefer a consistent version everywhere, you can also download the official restic release binary from the project site and place it in /usr/local/bin.

Restic can speak to S3 directly, so rclone is optional. However, rclone is useful if you want a single configuration tool for many cloud backends or if your environment already relies on it. If you want it:

sudo apt install -y rclone

Step 2: Create Your Bucket and Gather S3 Settings

Create a bucket in your S3-compatible storage, for example my-linux-backups. Collect these values: Access Key, Secret Key, Bucket name, Region (if required), and the S3 endpoint URL. For AWS S3, the endpoint is usually implicit; for MinIO or other providers, you will typically use something like https://s3.example.com.

Step 3: Set Restic Environment Variables

Restic reads credentials from environment variables. Create a root-only file to store them. This approach avoids leaving secrets in shell history and makes automation easier.

Create /etc/restic/env:

sudo mkdir -p /etc/restic
sudo nano /etc/restic/env

Add the following (adjust values to your provider):

export RESTIC_REPOSITORY="s3:https://s3.example.com/my-linux-backups"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export AWS_DEFAULT_REGION="us-east-1"

Now create a password file for the repository encryption key:

sudo nano /etc/restic/password

Put a long passphrase on a single line, then lock down permissions:

sudo chmod 600 /etc/restic/env /etc/restic/password

Step 4: Initialize the Restic Repository

Load the environment variables and initialize the repo:

source /etc/restic/env
sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic init

If everything is correct, restic will create the repository structure in the bucket and confirm initialization. If you see endpoint or TLS errors, double-check the endpoint URL and whether your provider requires a specific region.

Step 5: Run Your First Backup (Incremental by Default)

Choose what to back up. A common starting point is /home plus important configuration under /etc. You should exclude cache folders and other noise to keep snapshots clean.

Create an exclude file:

sudo nano /etc/restic/excludes

Example excludes:

*/.cache
*/Downloads
/var/tmp
/tmp

Run the backup:

source /etc/restic/env
sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic backup /home /etc --exclude-file=/etc/restic/excludes

The next time you run the same command, restic will automatically create an incremental snapshot and upload only new or changed data blocks. This is where deduplication saves both time and storage.

Step 6: Verify and Test a Restore

A backup you never tested is not a strategy. List snapshots:

source /etc/restic/env
sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic snapshots

Check repository consistency (run occasionally, not every hour):

sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic check

To restore a single file safely, restore into a temporary directory first:

sudo mkdir -p /restore-test
sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic restore latest --target /restore-test --include /etc/hosts

Confirm the file is correct, then copy it to the desired location if needed.

Step 7: Set a Retention Policy (Forget + Prune)

Backups grow over time unless you define retention. A practical policy keeps daily snapshots for a week, weekly for a month, and monthly for a year:

source /etc/restic/env
sudo RESTIC_PASSWORD_FILE=/etc/restic/password restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

The --prune step removes unneeded data blocks so your S3 storage usage stays under control.

Step 8: Automate Backups with systemd

Create a simple script so the job is repeatable. Create /usr/local/sbin/restic-backup.sh:

sudo nano /usr/local/sbin/restic-backup.sh

Add:

#!/bin/sh
set -eu
. /etc/restic/env
export RESTIC_PASSWORD_FILE=/etc/restic/password
restic backup /home /etc --exclude-file=/etc/restic/excludes
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

Make it executable:

sudo chmod 750 /usr/local/sbin/restic-backup.sh

Now create a systemd service /etc/systemd/system/restic-backup.service:

[Unit]
Description=Restic Backup

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh

And a timer /etc/systemd/system/restic-backup.timer to run daily:

[Unit]
Description=Daily Restic Backup

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Enable the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer

You can confirm runs with:

systemctl list-timers --all | grep restic

Final Tips for Reliable Offsite Backups

Keep your restic password file protected, and consider storing a sealed copy in a secure vault so you are not locked out during an emergency. If you are backing up a server with databases, add application-aware steps (such as dumping PostgreSQL or MySQL) before running restic. Most importantly, schedule a recurring restore test so you know the entire chain works—from Linux to S3 and back.

Popular Posts

Install Ollama and Open WebUI on Ubuntu 24.04 with NVIDIA GPU Acceleration (Step-by-Step)

Install Ollama + Open WebUI on Ubuntu 24.04 with NVIDIA GPU Acceleration (Step-by-Step)

Install a Local AI Chatbot on Ubuntu 24.04 with Ollama and Open WebUI (Step-by-Step)

Trending Now

Recovering from Btrfs Boot Failures Using GUI Tools on Fedora

By the end of this guide the reader will be able to identify a Btrfs‑based Fedora installation, boot from a live USB, list and restore snapshots using the graphical utilities btrfs‑assistant and snapper, and verify that the system returns to a functional state without resorting to the command line. Understanding the Btrfs Layout Used by Fedora Fedora Workstation and Fedora KDE install the root filesystem as a single Btrfs partition that contains two default sub‑volumes. One sub‑volume holds the traditional “/” hierarchy, while the second is dedicated to /var/lib/machines . The latter exists to keep container images out of snapshot operations; it remains empty on systems that do not run virtual machines. Because Btrfs stores data in sub‑volumes rather than separate partitions, a snapshot captures the state of an entire sub‑volume at a point in time. The installer (Anaconda) automatically registers these sub‑volumes with the snapper service. Snapper maintains a series of read‑only ...