Adds restic role to create an automatic daily backup #7
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -16,3 +16,5 @@ vars/minio.yml
|
|||
vars/woodpecker_production.yml
|
||||
|
||||
vars/woodpecker_staging.yml
|
||||
|
||||
vars/backup.yml
|
||||
|
|
|
@ -19,6 +19,8 @@ Automation to create/configure the infrastructure for all services related to [f
|
|||
- Replace the dummy values with the real ones (values are only available after the manual creation of an OAuth2 app)
|
||||
- Copy `vars/minio.yml.example` to `vars/minio.yml`
|
||||
- Replace the dummy values with the real ones
|
||||
- Copy `vars/backup.yml.example` to `vars/backup.yml`
|
||||
- Replace the dummy values with the real ones
|
||||
|
||||
|
||||
## Terraform
|
||||
|
|
8
backup.yaml
Normal file
8
backup.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: Check SSH port
|
||||
import_playbook: ssh.yaml
|
||||
- name: Deploy backup
|
||||
hosts: production
|
||||
roles:
|
||||
- restic
|
||||
become: true
|
|
@ -7,3 +7,5 @@
|
|||
import_playbook: forgejo-staging.yaml
|
||||
- name: Forgejo production
|
||||
import_playbook: forgejo-prod.yaml
|
||||
- name: Backup
|
||||
import_playbook: backup.yaml
|
||||
|
|
75
roles/restic/tasks/main.yml
Normal file
75
roles/restic/tasks/main.yml
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
- name: Include backup vars
|
||||
ansible.builtin.include_vars:
|
||||
file: backup.yml
|
||||
name: backup_config
|
||||
|
||||
- name: Install restic dependencies
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- fuse
|
||||
- bzip2
|
||||
- pigz
|
||||
state: present
|
||||
|
||||
- name: Download restic
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/restic/restic/releases/download/v{{ backup_config.restic_version }}/restic_{{ backup_config.restic_version }}_linux_amd64.bz2"
|
||||
dest: "/tmp/restic_{{ backup_config.restic_version }}_linux_amd64.bz2"
|
||||
|
||||
- name: Extract restic
|
||||
command: "bzip2 -d /tmp/restic_{{ backup_config.restic_version }}_linux_amd64.bz2"
|
||||
args:
|
||||
creates: "/tmp/restic_{{ backup_config.restic_version }}_linux_amd64"
|
||||
|
||||
- name: Create restic directory
|
||||
ansible.builtin.file:
|
||||
path: /opt/restic
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Install restic
|
||||
ansible.builtin.copy:
|
||||
remote_src: true
|
||||
src: "/tmp/restic_{{ backup_config.restic_version }}_linux_amd64"
|
||||
dest: "/opt/restic/restic"
|
||||
mode: 0755
|
||||
|
||||
- name: Remove downloaded file
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/restic_{{ backup_config.restic_version }}_linux_amd64"
|
||||
state: absent
|
||||
|
||||
- name: Copy scripts
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: /opt/restic/{{ item }}
|
||||
mode: 0755
|
||||
loop:
|
||||
- backup.sh
|
||||
- restore.sh
|
||||
|
||||
- name: Create log folder
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: 0644
|
||||
loop:
|
||||
- /var/log/restic
|
||||
|
||||
- name: Create empty log file
|
||||
ansible.builtin.copy:
|
||||
content: ""
|
||||
dest: /var/log/restic/backup.log
|
||||
force: false
|
||||
group: sys
|
||||
owner: root
|
||||
mode: 0644
|
||||
|
||||
- name: Add daily cronjob for backups
|
||||
ansible.builtin.cron:
|
||||
name: "restic backup"
|
||||
user: root
|
||||
minute: "0"
|
||||
hour: "4"
|
||||
job: "/opt/restic/backup.sh >> /var/log/restic/backup.log"
|
60
roles/restic/templates/backup.sh.j2
Normal file
60
roles/restic/templates/backup.sh.j2
Normal file
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Set crypto passphrase for encryption
|
||||
export AWS_ACCESS_KEY_ID={{ backup_config.access_key }}
|
||||
export AWS_SECRET_ACCESS_KEY={{ backup_config.secret_key }}
|
||||
export RESTIC_PASSWORD={{ backup_config.restic_key }}
|
||||
export RESTIC_REPOSITORY={{ backup_config.restic_target }}
|
||||
restic="/opt/restic/restic"
|
||||
dir_prefix="/backup/dbs"
|
||||
|
||||
# Write beginning date to backup log
|
||||
echo 'Backup date' $(date)'.'
|
||||
echo ' '
|
||||
|
||||
# Create database dump folders
|
||||
mkdir -p $dir_prefix/forgejo/postgres
|
||||
mkdir -p $dir_prefix/woodpecker/postgres
|
||||
|
||||
# Remove previous dumps
|
||||
rm -f $dir_prefix/forgejo/postgres/dump.sql
|
||||
rm -f $dir_prefix/woodpecker/postgres/dump.sql
|
||||
|
||||
# Dump databases
|
||||
docker exec -t forgejo_db_1 pg_dumpall -c -U forgejo > $dir_prefix/forgejo/postgres/dump.sql
|
||||
docker exec -t woodpecker_woodpecker-database_1 pg_dumpall -c -U postgres > $dir_prefix/woodpecker/postgres/dump.sql
|
||||
|
||||
# Check if repo must be initialized
|
||||
if $restic cat config >/dev/null 2>&1; then
|
||||
echo 'Repo was already initialized'
|
||||
else
|
||||
echo 'Repo not initialized.'
|
||||
$restic init
|
||||
fi
|
||||
|
||||
# Unlock lock of repo
|
||||
$restic unlock
|
||||
|
||||
# Do a backup
|
||||
$restic --verbose backup /var/log /var/lib/docker/volumes /srv /backup
|
||||
$restic --verbose backup /etc /opt
|
||||
$restic --verbose backup /home /root
|
||||
|
||||
# Clean up older backups
|
||||
$restic --verbose forget --keep-last 5 --keep-daily 14 --keep-weekly 4 --keep-monthly 24
|
||||
|
||||
# Data clean up
|
||||
$restic --verbose prune
|
||||
|
||||
# Write end to log file
|
||||
echo ' '
|
||||
echo '============================'
|
||||
echo ' '
|
||||
|
||||
# Unset ENVs
|
||||
unset AWS_ACCESS_KEY_ID
|
||||
unset AWS_SECRET_ACCESS_KEY
|
||||
unset RESTIC_PASSWORD
|
||||
unset RESTIC_REPOSITORY
|
39
roles/restic/templates/restore.sh.j2
Normal file
39
roles/restic/templates/restore.sh.j2
Normal file
|
@ -0,0 +1,39 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Set crypto passphrase for encryption
|
||||
export AWS_ACCESS_KEY_ID={{ backup_config.access_key }}
|
||||
export AWS_SECRET_ACCESS_KEY={{ backup_config.secret_key }}
|
||||
export RESTIC_PASSWORD={{ backup_config.restic_key }}
|
||||
export RESTIC_REPOSITORY={{ backup_config.restic_target }}
|
||||
restic="/opt/restic/restic"
|
||||
dir_prefix="/backup/dbs"
|
||||
|
||||
# Write beginning date to backup log
|
||||
echo 'Restore date' $(date)'.'
|
||||
echo ' '
|
||||
|
||||
# Unlock lock of repo
|
||||
$restic unlock
|
||||
|
||||
# Show snapshots
|
||||
$restic snapshots
|
||||
|
||||
# Restore the latest backup to /tmp/restic/restore
|
||||
mkdir -p /tmp/restic/restore
|
||||
# One of each paths is enough to match filter
|
||||
$restic --verbose restore latest --target /tmp/restic/restore --path "/var/log" --host "{{prod_url}}"
|
||||
$restic --verbose restore latest --target /tmp/restic/restore --path "/etc" --host "{{prod_url}}"
|
||||
$restic --verbose restore latest --target /tmp/restic/restore --path "/root" --host "{{prod_url}}"
|
||||
|
||||
# Write end to log file
|
||||
echo ' '
|
||||
echo '============================'
|
||||
echo ' '
|
||||
|
||||
# Unset ENVs
|
||||
unset AWS_ACCESS_KEY_ID
|
||||
unset AWS_SECRET_ACCESS_KEY
|
||||
unset RESTIC_PASSWORD
|
||||
unset RESTIC_REPOSITORY
|
11
vars/backup.yml.example
Normal file
11
vars/backup.yml.example
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
|
||||
#
|
||||
# Backup configuration
|
||||
#
|
||||
|
||||
restic_version: "0.15.1"
|
||||
restic_target: "s3:https://s3.TODO.com/BUCKET"
|
||||
restic_key: "TODO"
|
||||
access_key: "TODO"
|
||||
secret_key: "TODO"
|
Loading…
Reference in a new issue