initial commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
75891c3271
129 changed files with 8046 additions and 0 deletions
9
roles/restic/templates/restic-backup.service.j2
Normal file
9
roles/restic/templates/restic-backup.service.j2
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Restic Backup
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/restic-backup
|
||||
|
||||
59
roles/restic/templates/restic-backup.sh.j2
Normal file
59
roles/restic/templates/restic-backup.sh.j2
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
source /etc/restic/restic.env
|
||||
|
||||
# Metrics file for node_exporter
|
||||
METRICS_DIR="/var/lib/node_exporter/textfile_collector"
|
||||
METRICS_FILE="${METRICS_DIR}/restic_backup.prom"
|
||||
mkdir -p "${METRICS_DIR}"
|
||||
|
||||
# Temporary file for atomic writes
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
# Start backup
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
if restic backup \
|
||||
{% for path in restic_backup_paths %}
|
||||
{{ path }} \
|
||||
{% endfor %}
|
||||
{% for pattern in restic_exclude_patterns %}
|
||||
--exclude '{{ pattern }}' \
|
||||
{% endfor %}
|
||||
--host {{ ansible_facts["hostname"] }}; then
|
||||
|
||||
# Backup succeeded
|
||||
STATUS=1
|
||||
echo "# HELP restic_backup_success Whether the last backup succeeded (1=success, 0=failure)" > "${TEMP_FILE}"
|
||||
echo "# TYPE restic_backup_success gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_backup_success ${STATUS}" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_backup_timestamp_seconds Timestamp of last backup completion" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_backup_timestamp_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_backup_timestamp_seconds $(date +%s)" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_backup_duration_seconds Duration of last backup in seconds" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_backup_duration_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_backup_duration_seconds $(($(date +%s) - START_TIME))" >> "${TEMP_FILE}"
|
||||
|
||||
# Move temp file to final location atomically
|
||||
mv "${TEMP_FILE}" "${METRICS_FILE}"
|
||||
|
||||
exit 0
|
||||
else
|
||||
# Backup failed
|
||||
STATUS=0
|
||||
echo "# HELP restic_backup_success Whether the last backup succeeded (1=success, 0=failure)" > "${TEMP_FILE}"
|
||||
echo "# TYPE restic_backup_success gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_backup_success ${STATUS}" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_backup_timestamp_seconds Timestamp of last backup attempt" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_backup_timestamp_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_backup_timestamp_seconds $(date +%s)" >> "${TEMP_FILE}"
|
||||
|
||||
# Move temp file to final location atomically
|
||||
mv "${TEMP_FILE}" "${METRICS_FILE}"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
10
roles/restic/templates/restic-backup.timer.j2
Normal file
10
roles/restic/templates/restic-backup.timer.j2
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Unit]
|
||||
Description=Daily Restic Backup
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* {{ restic_backup_time }}
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
9
roles/restic/templates/restic-prune.service.j2
Normal file
9
roles/restic/templates/restic-prune.service.j2
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Restic Prune
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/restic-prune
|
||||
|
||||
56
roles/restic/templates/restic-prune.sh.j2
Normal file
56
roles/restic/templates/restic-prune.sh.j2
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
source /etc/restic/restic.env
|
||||
|
||||
# Metrics file for node_exporter
|
||||
METRICS_DIR="/var/lib/node_exporter/textfile_collector"
|
||||
METRICS_FILE="${METRICS_DIR}/restic_prune.prom"
|
||||
mkdir -p "${METRICS_DIR}"
|
||||
|
||||
# Temporary file for atomic writes
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
# Start prune
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
if restic forget \
|
||||
--keep-daily {{ restic_retention.daily }} \
|
||||
--keep-weekly {{ restic_retention.weekly }} \
|
||||
--keep-monthly {{ restic_retention.monthly }} \
|
||||
--prune; then
|
||||
|
||||
# Prune succeeded
|
||||
STATUS=1
|
||||
echo "# HELP restic_prune_success Whether the last prune succeeded (1=success, 0=failure)" > "${TEMP_FILE}"
|
||||
echo "# TYPE restic_prune_success gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_prune_success ${STATUS}" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_prune_timestamp_seconds Timestamp of last prune completion" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_prune_timestamp_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_prune_timestamp_seconds $(date +%s)" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_prune_duration_seconds Duration of last prune in seconds" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_prune_duration_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_prune_duration_seconds $(($(date +%s) - START_TIME))" >> "${TEMP_FILE}"
|
||||
|
||||
# Move temp file to final location atomically
|
||||
mv "${TEMP_FILE}" "${METRICS_FILE}"
|
||||
|
||||
exit 0
|
||||
else
|
||||
# Prune failed
|
||||
STATUS=0
|
||||
echo "# HELP restic_prune_success Whether the last prune succeeded (1=success, 0=failure)" > "${TEMP_FILE}"
|
||||
echo "# TYPE restic_prune_success gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_prune_success ${STATUS}" >> "${TEMP_FILE}"
|
||||
|
||||
echo "# HELP restic_prune_timestamp_seconds Timestamp of last prune attempt" >> "${TEMP_FILE}"
|
||||
echo "# TYPE restic_prune_timestamp_seconds gauge" >> "${TEMP_FILE}"
|
||||
echo "restic_prune_timestamp_seconds $(date +%s)" >> "${TEMP_FILE}"
|
||||
|
||||
# Move temp file to final location atomically
|
||||
mv "${TEMP_FILE}" "${METRICS_FILE}"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
10
roles/restic/templates/restic-prune.timer.j2
Normal file
10
roles/restic/templates/restic-prune.timer.j2
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Unit]
|
||||
Description=Daily Restic Prune
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* {{ restic_prune_time }}
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
4
roles/restic/templates/restic-ssh-config.j2
Normal file
4
roles/restic/templates/restic-ssh-config.j2
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Host {{ restic_host }}
|
||||
IdentityFile {{ restic_ssh_key }}
|
||||
User {{ restic_user }}
|
||||
Port {{ restic_ssh_port }}
|
||||
7
roles/restic/templates/restic.env.j2
Normal file
7
roles/restic/templates/restic.env.j2
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{% if restic_backend_type == 'sftp' %}
|
||||
export RESTIC_REPOSITORY="sftp:{{ restic_user }}@{{ restic_host }}:{{ restic_remote_path }}"
|
||||
{% else %}
|
||||
export RESTIC_REPOSITORY="{{ restic_repo }}"
|
||||
{% endif %}
|
||||
export RESTIC_PASSWORD="{{ restic_password }}"
|
||||
export RESTIC_CACHE_DIR=/var/cache/restic
|
||||
Loading…
Add table
Add a link
Reference in a new issue