Installing Restic Backup

Restic is an open-source backup tool that focuses on providing secure, efficient, and easy-to-use backups. This guide will walk you through installing Restic on an existing Linux VM.

We also have this blog post that will show you how to automatically install and configure Restic at the time of creating an OpenStack VM using user data (cloud-init)

Prerequisites

Installation

  1. Log into your VM via SSH
  2. Switch to the root user with the following command:

sudo su -

  1. Copy the install-restic.sh script below.
#!/usr/bin/env bash
set -euo pipefail
umask 077

RESTIC_VERSION="0.17.3"
RESTIC_URL="https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_amd64.bz2"

RESTIC_DIR="/etc/restic"
SYSTEMD_DIR="/etc/systemd/system"
BIN_DIR="/usr/local/bin"

# Default directories to back up.
BACKUP_PATHS="/etc /home /root"

require_root() {
  if [[ "${EUID}" -ne 0 ]]; then
    echo "Please run this script as root." >&2
    exit 1
  fi
}

install_packages() {
  if command -v apt-get >/dev/null 2>&1; then
    apt-get update
    apt-get install -y curl bzip2 jq
  elif command -v dnf >/dev/null 2>&1; then
    dnf install -y curl bzip2 jq
  elif command -v yum >/dev/null 2>&1; then
    yum install -y curl bzip2 jq
  else
    echo "No supported package manager found." >&2
    exit 1
  fi
}

prompt_required() {
  local prompt_text="$1"
  local var_name="$2"
  local hidden="${3:-false}"
  local value=""

  while :; do
    if [[ "${hidden}" == "true" ]]; then
      read -rsp "${prompt_text}" value
      echo
    else
      read -rp "${prompt_text}" value
    fi

    if [[ -n "${value}" ]]; then
      printf -v "${var_name}" '%s' "${value}"
      return 0
    fi

    echo "Value cannot be blank. Please try again." >&2
  done
}

get_auth_url() {
  local region=""

  while :; do
    read -rp "OpenStack Region (dfw, iad, sjc): " region
    region="$(printf '%s' "${region}" | tr '[:upper:]' '[:lower:]')"

    case "${region}" in
      dfw)
        OS_AUTH_URL="https://keystone.api.dfw3.rackspacecloud.com/v3"
        return 0
        ;;
      iad)
        OS_AUTH_URL="https://keystone.api.iad3.rackspacecloud.com/v3"
        return 0
        ;;
      sjc)
        OS_AUTH_URL="https://keystone.api.sjc3.rackspacecloud.com/v3"
        return 0
        ;;
      *)
        echo "Invalid region. Please enter dfw, iad, or sjc." >&2
        ;;
    esac
  done
}

get_instance_uuid() {
  local metadata uuid
  metadata="$(curl -fsS http://169.254.169.254/openstack/latest/meta_data.json)"
  uuid="$(jq -r '.uuid // empty' <<<"${metadata}")"

  if [[ -z "${uuid}" ]]; then
    echo "Could not determine instance UUID from the metadata service." >&2
    exit 1
  fi

  printf '%s' "${uuid}"
}

write_systemd_units() {
  cat > "${SYSTEMD_DIR}/restic-backup.service" <<EOF
[Unit]
Description=Run Restic Backup
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/restic.env

# Edit the directories below if you want a different backup set.
ExecStart=/usr/local/bin/restic backup ${BACKUP_PATHS} --verbose --exclude-file=/etc/restic/restic.exclude

Nice=19
IOSchedulingClass=idle
EOF

  cat > "${SYSTEMD_DIR}/restic-backup.timer" <<'EOF'
[Unit]
Description=Run Restic backup every 12 hours

[Timer]
OnBootSec=15min
OnUnitActiveSec=12h
Unit=restic-backup.service

[Install]
WantedBy=multi-user.target
EOF
}

write_restic_files() {
  local app_cred_id="$1"
  local app_cred_secret="$2"
  local restic_password="$3"
  local instance_uuid="$4"

  cat > "${RESTIC_DIR}/restic.env" <<EOF
OS_AUTH_URL="${OS_AUTH_URL}"
OS_APPLICATION_CREDENTIAL_ID="${app_cred_id}"
OS_APPLICATION_CREDENTIAL_SECRET="${app_cred_secret}"
RESTIC_PASSWORD="${restic_password}"
RESTIC_REPOSITORY="swift:restic:/${instance_uuid}"
EOF

  cat > "${RESTIC_DIR}/restic.exclude" <<'EOF'
# Add one exclusion per line.
# Example entries:
# *.log
# /tmp
# /var/tmp
EOF

  chmod 600 "${RESTIC_DIR}/restic.env" "${RESTIC_DIR}/restic.exclude"
}

install_restic_binary() {
  curl -fsSL "${RESTIC_URL}" -o /tmp/restic.bz2
  bzip2 -d -f /tmp/restic.bz2
  mv -f /tmp/restic "${BIN_DIR}/restic"
  chmod 0755 "${BIN_DIR}/restic"

  if command -v getenforce >/dev/null 2>&1 && command -v chcon >/dev/null 2>&1; then
    if [[ "$(getenforce)" != "Disabled" ]]; then
      chcon -t bin_t "${BIN_DIR}/restic" || true
    fi
  fi
}

initialize_repository_if_needed() {
  set -a
  # shellcheck disable=SC1090
  source "${RESTIC_DIR}/restic.env"
  set +a

  if ! /usr/local/bin/restic -r "${RESTIC_REPOSITORY}" cat config >/dev/null 2>&1; then
    /usr/local/bin/restic -r "${RESTIC_REPOSITORY}" init
  fi
}

main() {
  require_root
  install_packages

  mkdir -p "${RESTIC_DIR}" "${SYSTEMD_DIR}" "${BIN_DIR}"

  get_auth_url
  prompt_required "OpenStack Application Credential ID: " APP_CRED_ID false
  prompt_required "OpenStack Application Credential Secret: " APP_CRED_SECRET true
  prompt_required "Restic Repository Password: " RESTIC_PASSWORD true

  INSTANCE_UUID="$(get_instance_uuid)"

  write_systemd_units
  write_restic_files "${APP_CRED_ID}" "${APP_CRED_SECRET}" "${RESTIC_PASSWORD}" "${INSTANCE_UUID}"
  install_restic_binary

  systemctl daemon-reload
  initialize_repository_if_needed
  systemctl enable --now restic-backup.timer
  systemctl start restic-backup.service

  echo "Restic backup setup complete."
}

main "$@"
  1. In your SSH session, create the file install-restic.sh
  2. Paste the install-restic.sh script into your new file's contents, save and exit the file.
  3. Make the script file executable with the following command:

chmod +x install-restic.sh

  1. Run the install script with the following command:

./install-restic.sh

  1. The installer will begin downloading Restic. It will then prompt you for the following:
  • Your Region (dfw, sjc, iad)
  • Your Application Credential ID
  • Your Application Credential Secret
  • Create a passphrase for the Restic repository
  1. After you enter these it will finish the installation successfully. You can confirm Restic is running by checking with this command:

restic version

Restic Commands

Configuration

Edit Backup Directories - vi /etc/systemd/system/restic-backup.service

Edit Excluded Files and Directories - vi /etc/restic/restic.exclude

Edit Backup Schedule - vi /etc/systemd/system/restic-backup.timer

Reload Systemd After Configuration Changes - systemctl daemon-reload

Restart the Backup Timer After Schedule Changes - systemctl restart restic-backup.timer

Test the Updated Configuration Immediately - systemctl start restic-backup.service

Viewing Backups

Load Restic Environment Variables - source /etc/restic/restic.env

View All Backups (Snapshots) - restic snapshots

View Files in the Latest Snapshot - restic ls latest

View Backup Logs - journalctl -u restic-backup.service

Check Backup Timer Status - systemctl status restic-backup.timer

See When the Next Backup Will Run - systemctl list-timers restic-backup.timer

Show Repository Statistics - restic stats

Check Repository Integrity - restic check

Running & Restoring Backups

Run a Backup Immediately - systemctl start restic-backup.service

Restore the Latest Snapshot - restic restore latest --target /restore

Restore a Specific Snapshot - restic restore <snapshot-id> --target /restore