How to Use Restic for Encrypted Cloud Backups on Fedora

Install Restic via DNF, initialize a repository on your cloud storage, and configure environment variables for your provider's credentials before running your first backup.

You just ran a system upgrade and the boot process hangs on a black screen

Your laptop took a hard fall and the drive won't spin up. The panic is real because the only copy of your configuration files and documents lives on the hardware that just failed. Restic solves this by keeping encrypted, deduplicated backups in the cloud, ready to restore when the local system is compromised.

What's actually happening

Restic treats your backup repository like a secure vault that speaks a universal language. Instead of copying whole files every time, it breaks data into small chunks, hashes them, and only stores unique chunks. If you change one line in a config file, Restic uploads just that changed chunk, not the entire file. Encryption happens on your machine before data leaves. The cloud provider sees only encrypted blobs. You hold the key.

The repository contains data packs holding the encrypted chunks, an index mapping hashes to locations, and lock files to prevent concurrent writes. This architecture means backups are fast, storage-efficient, and secure against provider-side leaks. The deduplication works across files and snapshots, so reinstalling the same software suite does not duplicate data in the repository.

Install and initialize

Install the package from the official Fedora repositories. Restic is a single binary with no external dependencies, so the installation is straightforward.

sudo dnf install restic -y
# WHY: -y skips the confirmation prompt for a clean install script.

Initialize the repository on your cloud storage. This command creates the internal structure and sets the encryption key derived from your password.

export RESTIC_REPOSITORY="s3:s3.amazonaws.com/your-bucket-name/restic-repo"
# WHY: Sets the target location for the backup data. Restic reads this from the environment.
export RESTIC_PASSWORD="your-strong-password"
# WHY: Provides the master key for encryption. Never hardcode this in scripts.
restic init
# WHY: Creates the repository structure and locks the encryption key to the password.

Write the password down on paper and store it offline. Digital password managers can be compromised.

Run your first backup

Run your first backup. Restic scans the source directory, calculates chunk hashes, and uploads only new or changed data.

restic backup /home/youruser --exclude-caches --exclude=/tmp
# WHY: --exclude-caches skips browser caches and package manager caches to save bandwidth.
# WHY: --exclude=/tmp prevents backing up volatile temporary files that change constantly.

Exclude caches early. Backing up /var/cache wastes bandwidth and fills the repository with garbage.

Automate with systemd

Automate backups with a systemd timer. Manual backups get forgotten. A timer ensures the job runs on a schedule even if you are away from the keyboard.

Create the service file in /etc/systemd/system/. Edit files in /etc/systemd/system/. Never modify units in /usr/lib/systemd/. Package updates overwrite /usr/lib/.

# /etc/systemd/system/restic-backup.service
[Unit]
Description=Restic Backup Service
# WHY: Describes the unit for systemctl status output.

[Service]
Type=oneshot
# WHY: oneshot tells systemd the service runs a task and exits, rather than staying active.
EnvironmentFile=/etc/restic/env
# WHY: Loads credentials from a separate file to keep secrets out of the service definition.
ExecStart=/usr/bin/restic backup /home --exclude-caches
# WHY: Runs the backup command. Restic reads RESTIC_REPOSITORY from the environment file.

Create the environment file to store credentials securely.

# /etc/restic/env
RESTIC_REPOSITORY=s3:s3.amazonaws.com/your-bucket-name/restic-repo
# WHY: Defines the repository path for the service unit.
RESTIC_PASSWORD_FILE=/etc/restic/.password
# WHY: Points to a file containing the password. Restic reads this file securely.
AWS_ACCESS_KEY_ID=your-access-key
# WHY: Required for S3 authentication. Use an IAM user with minimal permissions.
AWS_SECRET_ACCESS_KEY=your-secret-key
# WHY: Required for S3 authentication. Keep this secret.

Create the timer unit.

# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run Restic Backup Daily

[Timer]
OnCalendar=daily
# WHY: Triggers the backup at midnight local time.
Persistent=true
# WHY: Runs the backup immediately if the system was off during the scheduled time.

[Install]
WantedBy=timers.target
# WHY: Ensures the timer starts on boot.

Enable the timer and verify it is active.

sudo systemctl enable --now restic-backup.timer
# WHY: Enables the timer to start on boot and starts it immediately.
systemctl list-timers | grep restic
# WHY: Verifies the timer is active and shows the next scheduled run.

Manage retention

Keeping every snapshot forever fills the repository. Define a policy to prune old snapshots and reclaim storage space.

restic forget --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --prune
# WHY: Keeps 7 daily, 5 weekly, and 12 monthly snapshots.
# WHY: --prune removes unreferenced chunks to reclaim storage space.

Add the forget command to a separate service and timer if you want retention management to run automatically after backups complete.

Restore data

Restore data when you need it. Restic allows you to extract files to a specific target directory without overwriting the live system.

restic snapshots
# WHY: Lists all saved snapshots with timestamps and IDs.
restic restore latest --target /tmp/restore-test
# WHY: Extracts the latest snapshot to /tmp/restore-test for inspection.

Verify the restored files match your expectations before copying them back to the live system.

Verify it worked

Confirm the backup completed and the data is recoverable. Trusting the backup without testing is a recipe for disaster.

restic check
# WHY: Verifies the integrity of the repository data and index.
systemctl status restic-backup.service
# WHY: Shows recent log lines AND state in one view. Always check status before restart.

Run journalctl -xeu restic-backup.service to see detailed logs with explanatory text. The x flag adds explanations and the e flag jumps to the end.

Run restic check weekly. Integrity verification catches bit rot before you need the data.

Common pitfalls and errors

Restic refuses to read password files with loose permissions. If you see open /etc/restic/.password: permission denied, the file is world-readable. Fix the permissions immediately.

sudo chmod 600 /etc/restic/.password
# WHY: Restricts access to the owner only. Restic enforces this for security.
sudo chown root:root /etc/restic/.password
# WHY: Ensures only root can read the file when used by a systemd service.

If a backup is interrupted, Restic leaves a lock file. The next run will fail with repository is locked. You must unlock it manually.

restic unlock
# WHY: Removes the stale lock file so new operations can proceed.

If the service fails with an AVC denial, SELinux is blocking access. SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux.

sudo restorecon -v /etc/restic/.password
# WHY: Resets the SELinux context to the default for that path.

Unlock the repository before retrying. A stale lock blocks all operations until cleared.

When to use this vs alternatives

Use Restic when you need encrypted backups to cloud storage with built-in deduplication and a single binary. Use BorgBackup when you are backing up to a local network share and want maximum compression control. Use Rsync when you need a simple file mirror without encryption or versioning. Use Tar when you are creating a quick archive for transfer and do not need incremental backups. Stay on Restic if you want a consistent interface across S3, B2, and local paths without changing commands.

Trust the tool that matches your threat model. Encryption matters when data leaves your control.

Where to go next