---
title: "Set Up Automated Backups with Restic"
description: "Automate encrypted off-site backups on your Arcline VPS using restic."
section: vps
order: 6
---

# Set Up Automated Backups with Restic

Restic is a fast, encrypted backup tool that supports local and remote storage backends (SFTP, S3, B2, rsync.net). This guide covers backing up your VPS to a remote repository.

---

## Prerequisites

- A VPS with sudo access
- A backup destination (SFTP server, Backblaze B2, or local storage)

---

## Step 1 — Install restic

```bash
sudo apt update
sudo apt install restic -y
```

Verify:

```bash
restic version
```

---

## Step 2 — Initialize a repository

### Option A: SFTP/SSH (recommended for Arcline customers)

If you have SSH access to a backup server:

```bash
restic init --repo sftp:backup@backup-server:/var/backups/example-vps/
```

You'll be prompted for a repository password — this encrypts your backups. Store it in a password manager — if you lose it, you cannot recover your data.

### Option B: Backblaze B2

```bash
export B2_ACCOUNT_ID="your-application-key-id"
export B2_ACCOUNT_KEY="your-application-key"
restic init --repo b2:bucket-name:/example-vps
```

### Option C: Local directory

```bash
sudo mkdir -p /backups/example-vps-repo
restic init --repo /backups/example-vps-repo
```

---

## Step 3 — Create a backup script

```bash
sudo nano /usr/local/bin/backup.sh
```

```bash
#!/bin/bash
set -e

# Repository location and password
export RESTIC_REPOSITORY="sftp:backup@backup-server:/var/backups/example-vps/"
export RESTIC_PASSWORD="your-repo-password"

# Files and directories to back up
BACKUP_PATHS=(
    /var/www
    /etc/nginx
    /etc/letsencrypt
    /opt
    /home
)

# Directories to exclude
EXCLUDE_PATTERNS=(
    --exclude "/var/www/example.com/cache"
    --exclude "*.log"
)

echo "Starting backup at $(date)"

# Create the backup
restic backup "${EXCLUDE_PATTERNS[@]}" "${BACKUP_PATHS[@]}"

# Keep last 7 daily, 4 weekly, 6 monthly snapshots
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

echo "Backup completed at $(date)"
```

Make it executable:

```bash
sudo chmod +x /usr/local/bin/backup.sh
```

---

## Step 4 — Test the backup

Run the backup manually:

```bash
sudo /usr/local/bin/backup.sh
```

List snapshots:

```bash
restic -r sftp:backup@backup-server:/var/backups/example-vps/ snapshots
```

> You'll need `RESTIC_PASSWORD` exported or passed via `--password-file` for any restic command.

---

## Step 5 — Schedule daily backups with systemd

Create a service file:

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

```ini
[Unit]
Description=Restic backup
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
```

Create a timer:

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

```ini
[Unit]
Description=Daily restic backup

[Timer]
OnCalendar=daily
RandomizedDelaySec=3600
Persistent=true

[Install]
WantedBy=timers.target
```

Enable and start the timer:

```bash
sudo systemctl daemon-reload
sudo systemctl enable restic-backup.timer
sudo systemctl start restic-backup.timer
```

Verify:

```bash
sudo systemctl status restic-backup.timer
sudo systemctl list-timers | grep restic
```

---

## Step 6 — Restoring from a backup

List available snapshots:

```bash
restic -r sftp:backup@backup-server:/var/backups/example-vps/ snapshots
```

Restore the latest snapshot:

```bash
restic -r sftp:backup@backup-server:/var/backups/example-vps/ restore latest --target /tmp/restore
```

Or restore a specific snapshot by ID:

```bash
restic -r ... restore <snapshot-id> --target /tmp/restore
```

To restore only specific paths:

```bash
restic -r ... restore <snapshot-id> --target /tmp/restore --path /var/www
```

---

## Step 7 — Database backups

For MySQL databases, add a pre-backup dump step:

```bash
#!/bin/bash
set -e

# Dump all databases
mysqldump --all-databases --single-transaction --quick | gzip > /tmp/mysql-all.sql.gz

# Include the dump in the backup
restic backup --hostname example-vps /tmp/mysql-all.sql.gz "${BACKUP_PATHS[@]}"

rm /tmp/mysql-all.sql.gz
```

---

## Monitoring backups

Add a health check notification:

```bash
# After successful backup
curl -fsS -m 10 --retry 5 https://hc-ping.com/your-uuid

# Or on failure, notify via Discord/Slack webhook
curl -fsS -m 10 -X POST -H "Content-Type: application/json" \
  -d '{"content":"Backup failed on example-vps"}' \
  https://discord.com/api/webhooks/your-webhook-url
```

---

## What's next

- [Install fail2ban](/vps/fail2ban/) for SSH brute-force protection
- [Set up a Go service](/vps/go-systemd/) with systemd

