Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

restic: Fast Encrypted Backups

By Kokil Thapa | Last reviewed: September 2026

Production servers fail at the worst moment—disk corruption, a bad deploy, ransomware, or an operator mistake during a late-night migration. restic: Fast Encrypted Backups solves the operational half of that problem with deduplicated, encrypted snapshots you can push to cheap object storage or a second VPS. I run Linux system administration workflows on Ubuntu servers for Laravel apps, WordPress shops, and legal-tech portals, and restic is the tool I reach for when rsync alone is not enough. This guide covers install, repository setup, daily automation, restore drills, and the trade-offs against plain rsync.

What makes restic: Fast Encrypted Backups different from rsync?

rsync copies files. restic creates versioned snapshots with content-defined chunking. Changed bytes inside a large file do not force a full re-upload. Encryption happens client-side before data leaves your server.

On sister sites I maintain with Deployer 7 and GitLab CI—legal portals, translation sites, and similar Laravel stacks—off-site restic repos sit alongside rsync mirrors. rsync gives you a browsable copy on another disk. restic gives you history, deduplication, and tamper-resistant encryption at rest.

restic: Fast Encrypted Backups — Data FlowSource/var/www, DB dumpsrestic clientchunk + dedupeEncryptAES-256-GCMRepositoryS3, B2, SFTPSnapshot metadata stays separate from blob packsEach backup run = one snapshot ID (e.g. abc123de)Prune removes old snapshots; forget keeps retention policy
restic: Fast Encrypted Backups chunks files locally, encrypts packs, then uploads only new blobs to your repository.
Criteriaresticrsync
Encryption at restBuilt-in, client-sideNone unless disk or bucket encryption added
Version historyEvery snapshot retained by policyMirror only; needs separate rotation
DeduplicationContent-defined across snapshotsFile-level only
Restore granularitySingle file from any snapshotWhole tree or manual pick
Remote targetS3, B2, Azure, SFTP, REST, localSSH, local, daemon
CPU/RAM on first runHigher (hashing + packing)Lower
Best fitOff-site encrypted historyFast mirror to second server

Neither tool replaces the other. Pair them. rsync for a hot standby copy. restic for encrypted off-site retention. That pattern matches what I document in broader support and maintenance engagements for production Laravel and WordPress hosts.

How do you install and initialize a restic repository?

restic ships as a single static binary on Linux. Install from your distro package or the official release. Ubuntu 22.04 and 24.04 both carry recent builds in universe.

Install on Ubuntu

sudo apt update
sudo apt install restic
restic version

Alternatively, download the latest release from the official restic site and place the binary in /usr/local/bin.

Choose a backend and set environment variables

restic reads repository location and credentials from env vars or flags. For S3-compatible storage (AWS S3, Cloudflare R2, Wasabi, MinIO):

export RESTIC_REPOSITORY="s3:s3.amazonaws.com/my-backup-bucket/prod-web01"
export RESTIC_PASSWORD="use-a-long-random-passphrase"
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."

Generate the repository password with a proper tool—not a memorable phrase. A password generator that outputs 32+ random characters is the right starting point. Store it in your team vault. Lose the password and the backups are gone. restic cannot recover encrypted data without it.

Initialize the repository once

restic init

You should see confirmation that a new repository was created. Run init exactly once per repo. Re-running against an existing repo returns an error—that is expected.

For Backblaze B2, set B2_ACCOUNT_ID and B2_ACCOUNT_KEY and use an s3:// endpoint URL B2 documents for the S3-compatible API. For local or USB backup:

export RESTIC_REPOSITORY="/mnt/backup-drive/restic-repo"
restic init

Official backend docs live in the restic documentation. Read the section for your provider before the first production upload.

How do you run restic backup jobs on a production Linux server?

A useful backup includes application files, config outside the repo, and database dumps. On a typical Laravel stack that means /var/www, nginx or Apache vhost files, .env (handled carefully), and nightly MySQL or PostgreSQL dumps.

Nightly restic Backup Pipeline1. DB dumpmysqldump2. Stage/backup/staging3. resticbackup4. forget+ prune5. restic check --read-data-subset 1/30Weekly integrity sample; alert on non-zero exitCron + log file + email/Slack on failureNever silent failures — untested backups are fiction
Production restic: Fast Encrypted Backups should chain database dumps, file backup, retention pruning, and periodic integrity checks.

Example backup script

Save as /usr/local/bin/restic-backup.sh. Adjust paths for your stack.

#!/bin/bash
set -euo pipefail

STAGING="/backup/staging"
APP_ROOT="/var/www/myapp"
DUMP="$STAGING/db-$(date +%F).sql.gz"
LOG="/var/log/restic-backup.log"

mkdir -p "$STAGING"
mysqldump --single-transaction myapp_db | gzip > "$DUMP"

restic backup \
  "$APP_ROOT" \
  /etc/nginx/sites-available \
  "$STAGING" \
  --exclude="$APP_ROOT/node_modules" \
  --exclude="$APP_ROOT/vendor" \
  --tag nightly \
  --host prod-web01 \
  2>&1 | tee -a "$LOG"

restic forget \
  --tag nightly \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 6 \
  --prune \
  2>&1 | tee -a "$LOG"

Vendor and node_modules are reproducible from Git and Composer. Excluding them cuts repo size sharply. Rebuild them after restore from your deploy pipeline.

Schedule with cron

sudo crontab -e

Add a line that sources credentials from a root-only file:

15 2 * * * . /root/.restic-env && /usr/local/bin/restic-backup.sh

Put secrets in /root/.restic-env with mode 600:

export RESTIC_REPOSITORY="s3:s3.eu-central-1.amazonaws.com/acme-backups/web01"
export RESTIC_PASSWORD="..."
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."

A common mistake is stale cron paths after Deployer symlink swaps. Point backups at shared paths—storage/, database dumps, and config—not release-specific directories that rotate every deploy. I have seen this break restores on Notary Kathmandu-class Laravel sites that share a Deployer pipeline across multiple domains.

How do you restore files quickly from restic snapshots?

Backups you never restore are guesses. Run a restore drill quarterly. Know your snapshot IDs before an incident.

List snapshots

restic snapshots

Find a file inside a snapshot

restic find "*.env"
restic ls latest:/var/www/myapp

Restore one file or a full tree

restic restore latest --target /restore-test --include /var/www/myapp/.env
restic restore abc123de --target /restore-full --path /var/www/myapp

Verify permissions and ownership after restore. restic preserves metadata where the OS allows. On Ubuntu you may need chown -R www-data:www-data on web roots.

For database recovery, pull the gzipped dump from the snapshot staging path and import:

gunzip -c /restore-test/backup/staging/db-2026-09-10.sql.gz | mysql myapp_db

Document RTO and RPO for each tier. A brochure WordPress site and a booking portal with live payments do not share the same urgency. Platforms like Adventure Third Pole Trek need faster database recovery than a static marketing page.

Restore Options After Data Lossrestic snapshot restorePick snapshot ID or latestSingle file or full pathEncrypted off-site copyrsync mirrorCurrent files onlyFast full-tree syncNo built-in historyRecommended: both layersrsync for same-day failover to second VPSrestic for encrypted history and ransomware defense
restic: Fast Encrypted Backups excels at point-in-time recovery; rsync excels at keeping a warm secondary copy.

How do you tune performance and control backup costs?

The first backup uploads everything. Later runs upload only new chunks. That is where the "fast" label earns its keep—if you structure jobs correctly.

  • Exclude aggressively: cache dirs, vendor/, node_modules/, log files, and session temp paths.
  • Limit bandwidth on shared hosting or metered links: --limit-upload 5000 caps upload at 5 MB/s.
  • Run during off-peak hours: 02:00–04:00 NPT avoids Dashain-season traffic spikes on client sites.
  • Use nearby regions: an EC2 in Mumbai backing up to ap-south-1 beats cross-continent transfers for Nepal-hosted workloads.
  • Prune regularly: forgotten snapshots inflate storage bills. Pair forget with --prune every run.

Object storage pricing matters on tight budgets. A 40 GB web root with daily deltas might cost Rs 300–800/month (~USD 2–6) on mainstream S3 tiers before egress. Track repo stats:

restic stats --mode raw-data
restic stats latest

For application-level backups inside Laravel, Spatie Backup handles zip exports to local or cloud disks. That complements—not replaces—full-server restic jobs. Use Spatie for quick database exports; use restic for entire machine state including configs and keys. See also general guidance on testing and optimization when backup windows overlap with CI deploys.

Integrity and monitoring

Automate checks. A corrupt repo discovered during an outage is useless.

restic check
restic check --read-data-subset 10%

Send cron output to mail or a webhook. Exit code non-zero should page someone. Monthly, restore a random file to /tmp/restore-drill and record the time taken.

What backup mistakes break restic deployments in real projects?

Most failures are operational, not tool bugs. Patterns I see on production Linux hosts:

  1. Password only on one laptop. Put RESTIC_PASSWORD in a shared vault with break-glass access.
  2. Backing up symlinks blindly. Deployer release paths change. Back shared persistent dirs.
  3. Never testing restore. Schedule a drill before every major upgrade.
  4. Same credentials as production S3 app bucket. Use a dedicated IAM user limited to the backup prefix.
  5. Ignoring database consistency. Always dump with --single-transaction on InnoDB before file backup.
  6. Skipping off-site copy. Local restic on the same disk does not survive fire, theft, or ransomware.

Legal-tech portals—client uploads, signed PDFs, payment records—need stricter retention than a blog. On projects like Mijar Law Associates and Court Marriage In Nepal, document retention rules belong in the backup policy, not in ad-hoc cron edits.

Choose a restic Repository BackendNeed off-site DR?YesNoS3 / R2 / B2Best defaultSFTP VPSBudget off-siteLocal diskSpeed onlyNepal VPS + global object storage = solid 3-2-13 copies, 2 media types, 1 off-site — minimum sane bar
Pick a restic backend by recovery goal: object storage for off-site encrypted history, SFTP for budget second sites, local for speed not safety.

Hosting choice affects latency. If you manage domains and VPS together, align backup region with your primary server during domain registration and hosting planning—not after an outage.

For WooCommerce and Laravel eCommerce stacks—Quick And Easy Nepalese Grocery, gift-card platforms, multi-currency florists—add order tables to dump priority. Media uploads belong in the file backup set. Test cart checkout after every restore drill.

WordPress sites on shared cPanel rarely run restic natively. Move to a VPS you control, or use provider snapshots plus plugin exports as a bridge. Long term, WordPress development on proper Linux infrastructure makes restic automation straightforward.

Migrating from weak backup habits to restic fits under website migration projects: new server, init repo, first full backup, cut DNS, keep old host read-only for seven days.

Enterprise apps with PostgreSQL 18 or MySQL 9.7 need consistent dumps. Point-in-time recovery still wants binary logs or WAL archiving. restic captures those dump files; it is not a replacement for DB-native PITR. Layer both if RPO under one hour is contractual.

AWS documents IAM least-privilege policies for S3 backup prefixes in the AWS IAM policy guide. Scope keys to s3:PutObject, s3:GetObject, s3:ListBucket, and s3:DeleteObject on one bucket path—nothing wider.

Key Takeaways

  • Initialize one restic repo per environment, store the password in a vault, and never commit credentials to Git.
  • Chain database dumps, file backup, forget/prune, and monthly restore drills—automation without testing is theater.
  • Exclude reproducible dirs (vendor/, node_modules/) to keep deduplicated repos small and uploads fast.
  • Pair restic off-site encrypted snapshots with rsync mirrors for same-day failover on critical Laravel and WordPress hosts.
  • Use S3-compatible object storage in a nearby region for Nepal-hosted VPS workloads; budget Rs 300–800/month (~USD 2–6) for typical small sites.
  • Run restic check regularly and alert on failure—corruption found during recovery is too late.

People Also Ask

Is restic better than rsync for server backups?

restic is better for encrypted, deduplicated, versioned off-site snapshots. rsync is better for fast mirrors to a second server. Production setups should use both: rsync for hot standby, restic for history and ransomware resilience.

Can restic backup to Cloudflare R2 or Backblaze B2?

Yes. Both expose S3-compatible APIs. Point RESTIC_REPOSITORY at the provider endpoint and supply the matching access keys. R2 often saves egress fees when your origin also sits on Cloudflare.

How do you migrate restic repositories to a new bucket?

Use restic copy or restic migrate between repositories with the same password. Init the destination repo, then copy snapshots incrementally. Verify with restic check on the new repo before retiring the old one.

What happens if you lose the restic repository password?

Backups are permanently unreadable. restic uses AES-256 encryption with no vendor backdoor. Store the password in a team vault and maintain an offline break-glass copy.

Build a backup stack you will actually restore from

restic: Fast Encrypted Backups earns its place on every production Linux box I touch: one binary, strong encryption, cheap object-storage targets, and restores granular enough to pull a single .env from last Tuesday. Start tonight—init a repo, back up /var/www plus last night's database dump, and restore one file to prove the chain works. For full-stack setup on Ubuntu hosts running Laravel, WordPress, or custom apps, see the Linux system administration service or browse the portfolio of production sites that rely on disciplined ops. More backup patterns live on the blog. Ready to harden a server that still copies files to USB once a month? Contact us and we will design a 3-2-1 plan that survives real failures.

Frequently Asked Questions

restic creates deduplicated, AES-256-encrypted snapshots you push to local folders, S3-compatible buckets, SFTP, or other backends. After the first run, only new chunks upload.

restic is better for encrypted, deduplicated, versioned off-site snapshots with content-defined chunking—changed bytes inside a large file do not force a full re-upload. rsync is better for fast mirrors to a second server with a browsable copy. Neither replaces the other. Production Laravel and WordPress hosts I maintain pair rsync for same-day failover with restic for encrypted history and ransomware resilience. rsync gives a hot standby; restic gives tamper-resistant retention at rest.

Yes. Both expose S3-compatible APIs. Point RESTIC_REPOSITORY at the provider endpoint URL and set the matching access keys—AWS-style keys for R2, or B2_ACCOUNT_ID and B2_ACCOUNT_KEY for Backblaze using the S3-compatible endpoint B2 documents. Read the official restic backend docs for your provider before the first production upload. R2 often saves egress fees when your origin also sits on Cloudflare.

A 40 GB web root with daily deltas often runs Rs 300–800/month (~USD 2–6) on mainstream S3 tiers before egress. Prune snapshots regularly to avoid bill creep.

restic ships as a single static binary. On Ubuntu 22.04 or 24.04, run apt update and apt install restic from universe, then confirm with restic version. Alternatively, download the latest release from the official restic site and place the binary in /usr/local/bin. No complex dependencies—one binary is why I use it on production boxes alongside Deployer-managed Laravel stacks and WordPress shops on VPS hosts I administer.

Set RESTIC_REPOSITORY and RESTIC_PASSWORD via environment variables or flags—for S3, also export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Generate the repo password with a proper 32+ character random generator, store it in your team vault, then run restic init exactly once. Re-running against an existing repo returns an error, which is expected. For local USB backups, point RESTIC_REPOSITORY at a mounted path like /mnt/backup-drive/restic-repo before init.

Chain four steps: consistent database dumps, file backup, retention pruning, and periodic integrity checks. On a typical Laravel stack, backup /var/www, nginx or Apache vhost files, staging database dumps created with mysqldump --single-transaction piped to gzip, and handle .env carefully. Exclude vendor/ and node_modules/—rebuild those from Git and Composer after restore. Tag snapshots nightly, run restic forget with keep-daily, keep-weekly, and keep-monthly policies, and always pass --prune on the same run.

Save your script at /usr/local/bin/restic-backup.sh, put secrets in /root/.restic-env with mode 600 containing RESTIC_REPOSITORY, RESTIC_PASSWORD, and cloud keys, then add a cron line that sources that file before running the script—for example 02:15 daily. A common mistake is stale paths after Deployer symlink swaps. Point backups at shared persistent dirs—storage/, dumps, config—not release-specific directories that rotate every deploy. Send cron output to mail or a webhook and alert on non-zero exit codes.

Run restic snapshots to list IDs, restic find or restic ls to locate files, then restic restore with --target and optional --include or --path flags for single files or full trees. Verify permissions with chown after restore—www-data on web roots. For database recovery, gunzip the dump from the snapshot staging path and import into MySQL. Schedule quarterly restore drills before incidents. Document RTO and RPO per tier—a booking portal needs faster recovery than a static marketing page.

Exclude cache dirs, vendor/, node_modules/, logs, and session temp paths aggressively. Cap upload bandwidth with --limit-upload 5000 for 5 MB/s on metered links. Run jobs during off-peak hours—02:00–04:00 NPT avoids Dashain-season traffic spikes. Choose a nearby object storage region—ap-south-1 from Mumbai beats cross-continent transfers for Nepal-hosted workloads. Pair restic forget with --prune every run so forgotten snapshots do not inflate bills. Track repo size with restic stats --mode raw-data and restic stats latest.

Backups are permanently unreadable. restic uses AES-256 with no vendor backdoor. Store the password in a team vault plus an offline break-glass copy.

Use restic copy or restic migrate between repositories sharing the same password. Init the destination repo, copy snapshots incrementally, then run restic check on the new repo before retiring the old bucket. This fits website migration projects: new server, init repo, first full backup, cut DNS, keep the old host read-only for seven days. Verify integrity before decommissioning the source—corruption found during recovery is too late.

Operational failures dominate: password stored only on one laptop, backing up Deployer release symlinks instead of shared dirs, never testing restore, reusing production S3 app credentials instead of a dedicated IAM user scoped to the backup prefix, skipping --single-transaction database dumps, and keeping local-only repos on the same disk—which survives neither fire nor ransomware. Legal-tech portals need documented retention rules in policy, not ad-hoc cron edits. Schedule restore drills before major upgrades.

Automate restic check on a schedule—restic check for structure validation, and restic check --read-data-subset 10% monthly for deeper verification. Exit code non-zero should page someone. Monthly, restore a random file to /tmp/restore-drill and record time taken. A corrupt repo discovered during an outage is useless. Send cron output to mail or a webhook. Pair automated checks with quarterly full restore drills that include database import and checkout tests on eCommerce stacks.

Spatie Backup handles Laravel zip exports to local or cloud disks—use it for quick database exports. restic captures entire machine state including configs, keys, and dump files. They complement each other, not replace. restic is not a substitute for DB-native PITR—PostgreSQL WAL archiving or MySQL binary logs are still needed if RPO under one hour is contractual. restic stores the dump files; layer both approaches for strict recovery objectives on MySQL 9.7 or PostgreSQL 18 workloads.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: