Restic Backup: SFTP backend
Deploy a restic backup repository backed by SFTP. See Restic backup for the backend-agnostic overview, shared variables, and installation.
Ansible hosts group: restic
Variables: shared
Shared variables are documented on the Restic backup page.
Variables
| Option | Type | Description | Default |
|---|---|---|---|
cs_restic_sftp_repos_root | string | Path to SFTP repositories root | /app/{{ cs_restic_cluster_name }}-restic |
cs_restic_sftp_repos_group_name | string | Group name for SFTP repos | restic |
Server-side setup (tasks/restic_setup_repositories/sftp-main.yml, tasks/restic_setup_repositories/sftp-repo.yml)
For each repository defined in cs_restic_repos, the following steps are performed on the restic host:
- A group (
cs_restic_sftp_repos_group_name) is created. - A dedicated user
restic-<repo_name>is created in that group with the/bin/bashshell, an unlocked password state, and a home directory at/home/restic-<repo_name>. - An ed25519 SSH key pair is generated in the user's home directory and read back, and both key files are then deleted. The private key (PEM) is written to Vault; the public key is added as an authorized key for the user.
- The repository root directory (
cs_restic_sftp_repos_root) is created if absent (mode0755). - If
<cs_restic_sftp_repos_root>/<repo_name>/configdoes not exist, the repository is initialized usingrestic init --verbosewith a random 64-character password andRESTIC_REPOSITORY=<repos_root>/<repo_name>(a local path on the restic host). On failure, the partially created repository directory is removed. - After a successful init, the repository password is written to Vault. An existing repository keeps the password already in Vault.
- Ownership of
<cs_restic_sftp_repos_root>/<repo_name>is set recursively to userrestic-<repo_name>and groupcs_restic_sftp_repos_group_name. - The repository is validated: the repository password is read back from Vault and
restic snapshots --verboseis run against the repository.
Backup and restore (restic_backup_restore_sftp)
Module for performing a backup or restore operation against an SFTP-backed restic repository. The caller is responsible for reading SSH credentials and the repository password from Vault (see Vault keys below) and passing them to the module; the module writes the private key to a temporary file, runs the appropriate restic command, then runs restic snapshots and restic check to validate the repository once that command succeeds, and removes the temporary key file regardless of outcome.
Behavior
- Backup: runs
restic backup --verbose -o sftp.args="-o IdentityFile=<key_file> -o StrictHostKeyChecking=no" --host <restic_host> <local_dir>. - Restore: runs
restic restore latest --verbose --target <local_dir> -o sftp.args="-o IdentityFile=<key_file> -o StrictHostKeyChecking=no" --host <restic_host>. RESTIC_REPOSITORYis constructed assftp:<ssh_user>@<ssh_host>:<repo_path>.- The private key is written to a temp file (mode
0600) and deleted after the operation regardless of outcome. restic snapshots --verboseandrestic check --verboserun after every successful backup or restore; their output is returned insnapshots_stdout_lines/check_stdout_lines.
Example
- name: App | Restic Backup | Backup
restic_backup_restore_sftp:
ops: backup
local_dir: /var/lib/my-app
restic_host: '{{ inventory_hostname }}'
ssh_user: '{{ restic_repo_access.user }}'
ssh_host: '{{ restic_repo_access.host }}'
repo_path: '{{ restic_repo_access.path }}'
private_key: '{{ restic_repo_access.private_key }}'
repo_password: '{{ restic_repo_password.repository_password }}'
vars:
restic_repo_access: "{{ lookup('vault_kv_get',
cs_project_code + '/application-deployer/clusters/' + cs_restic_cluster_name + '/hosts/' + inventory_hostname
+ '/apps/restic/generated/sftp-repository-access-my-repo') }}"
restic_repo_password: "{{ lookup('vault_kv_get',
cs_project_code + '/application-deployer/clusters/' + cs_restic_cluster_name + '/hosts/' + inventory_hostname
+ '/apps/restic/generated/sftp-repository-password-my-repo') }}"
Vault keys
SFTP access credentials
Key: {{ cs_project_code }}/application-deployer/clusters/{{ cs_restic_cluster_name }}/hosts/{{ inventory_hostname }}/apps/restic/generated/sftp-repository-access-{{ repo_name }}
{
"private_key": "Ed25519 private key (PEM) used for SFTP authentication.",
"user": "restic-<repo_name>",
"host": "ansible_host value of the restic server.",
"hostname": "ansible_hostname value of the restic server.",
"fqdn": "ansible_fqdn value of the restic server.",
"path": "<cs_restic_sftp_repos_root>/<repo_name>"
}
Repository password
Key: {{ cs_project_code }}/application-deployer/clusters/{{ cs_restic_cluster_name }}/hosts/{{ inventory_hostname }}/apps/restic/generated/sftp-repository-password-{{ repo_name }}
{
"repository_password": "Restic repository encryption password."
}