Fixed Duplicity Roles
This commit is contained in:
parent
5ae3a0631c
commit
954420e9de
14 changed files with 1707 additions and 155 deletions
1556
plugins/action/gpg_key.py
Normal file
1556
plugins/action/gpg_key.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,2 +1,6 @@
|
||||||
---
|
---
|
||||||
# defaults file for duplicity-client
|
# User to run duplicity things under
|
||||||
|
duplicity_client_user: "backup-user"
|
||||||
|
|
||||||
|
# Paths to backup through duplicity
|
||||||
|
duplicity_client_backup_paths: []
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
# handlers file for duplicity-client
|
|
|
@ -1,2 +1,44 @@
|
||||||
---
|
---
|
||||||
# tasks file for duplicity-client
|
- name: "Install required software on clients"
|
||||||
|
become: true
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: "present"
|
||||||
|
with_items:
|
||||||
|
- "acl"
|
||||||
|
|
||||||
|
- name: "Create backup user on clients"
|
||||||
|
become: true
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ duplicity_client_user }}"
|
||||||
|
|
||||||
|
- name: "Deploy server ssh keys to clients"
|
||||||
|
become: true
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: "{{ duplicity_client_user }}"
|
||||||
|
state: "present"
|
||||||
|
key: "{{ item.duplicity_server_user_key }}"
|
||||||
|
with_items: "{{ groups['duplicityclient'] | flatten(levels=1) }}"
|
||||||
|
|
||||||
|
- name: "Set default ACLs on backup data"
|
||||||
|
become: true
|
||||||
|
ansible.posix.acl:
|
||||||
|
path: "{{ item }}"
|
||||||
|
entity: "{{ duplicity_client_user }}"
|
||||||
|
etype: "user"
|
||||||
|
permissions: r-X
|
||||||
|
default: true
|
||||||
|
state: present
|
||||||
|
recursive: true
|
||||||
|
with_items: "{{ duplicity_client_backup_paths }}"
|
||||||
|
|
||||||
|
- name: "Set read ACLs on existing backup data"
|
||||||
|
become: true
|
||||||
|
ansible.posix.acl:
|
||||||
|
path: "{{ item }}"
|
||||||
|
entity: "{{ duplicity_client_user }}"
|
||||||
|
etype: "user"
|
||||||
|
permissions: r-X
|
||||||
|
state: present
|
||||||
|
recursive: true
|
||||||
|
with_items: "{{ duplicity_client_backup_paths }}"
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
localhost
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
- hosts: localhost
|
|
||||||
remote_user: root
|
|
||||||
roles:
|
|
||||||
- duplicity-client
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
# vars file for duplicity-client
|
|
|
@ -1,2 +1,6 @@
|
||||||
---
|
---
|
||||||
# defaults file for duplicity-server
|
# defaults file for duplicity-server
|
||||||
|
duplicity_server_user: "backup-user"
|
||||||
|
|
||||||
|
# The GnuPG key to use for encryption
|
||||||
|
duplicity_server_gnupg_fingerprint: "C05AD49B790BAC8E3B573B697B25171F921B9E57"
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
# handlers file for duplicity-server
|
|
|
@ -1,144 +1,88 @@
|
||||||
---
|
---
|
||||||
# - name: Install required software on servers
|
### BASIC SOFTWARE
|
||||||
# become: true
|
- name: "Install required software on servers"
|
||||||
# ansible.builtin.package:
|
become: true
|
||||||
# name: "{{ item }}"
|
ansible.builtin.package:
|
||||||
# state: present
|
name: "{{ item }}"
|
||||||
# with_items:
|
state: "present"
|
||||||
# - duplicity
|
with_items:
|
||||||
# - sshfs
|
- "duplicity" # Obviously needed for backup
|
||||||
# - python3-packaging
|
- "sshfs" # TO be able to mount the remote directory
|
||||||
# - acl
|
- "python3-packaging" # ??? For something
|
||||||
|
- "acl" # To manage the access control on the backup data
|
||||||
|
|
||||||
- name: Create backup user on servers
|
### SSH ACCESS (USER/KEYS)
|
||||||
|
- name: "Create backup user on servers"
|
||||||
become: true
|
become: true
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: "{{ duplicity_server_user }}"
|
name: "{{ duplicity_server_user }}"
|
||||||
generate_ssh_key: true
|
generate_ssh_key: true # We want to generate an ssh key to be able to configure the access on the clients later
|
||||||
ssh_key_type: ed25519
|
ssh_key_type: "ed25519"
|
||||||
|
ssh_key_comment: "{{ duplicity_server_user }}@{{ ansible_hostname }} (generated by ansible)"
|
||||||
|
register: "duplicity_server_created_user" # Store the return value for the ssh key and home path
|
||||||
|
|
||||||
- name: Fetch server keys to local system
|
- name: "Store server ssh key as fact for later usage"
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
duplicity_server_user_key: "{{ duplicity_server_created_user['ssh_public_key'] }}"
|
||||||
|
|
||||||
|
- name: "Fetch sshd fingerprints from clients"
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "/etc/ssh/ssh_host_ecdsa_key.pub"
|
||||||
|
delegate_to: "{{ item }}"
|
||||||
|
with_items: "{{ groups['duplicityclient'] | flatten(levels=1) }}"
|
||||||
|
changed_when: false
|
||||||
|
register: "duplicity_client_host_key"
|
||||||
|
|
||||||
|
- name: "Register client host keys in server"
|
||||||
become: true
|
become: true
|
||||||
become_user: "{{ duplicity_server_user }}"
|
become_user: "{{ duplicity_server_user }}"
|
||||||
ansible.builtin.slurp:
|
ansible.builtin.known_hosts:
|
||||||
src: ~/.ssh/id_ed25519.pub
|
name: "{{ item.item }}"
|
||||||
register: duplicity_server_key
|
key: "{{ item.item }} {{ item.content | b64decode }}"
|
||||||
changed_when: false
|
with_items: "{{ duplicity_client_host_key.results }}"
|
||||||
|
|
||||||
# - name: "Deploy server ssh keys to clients"
|
### GNUPG ENCRYPTION
|
||||||
# when:
|
- name: "Ensure gnupg config dir"
|
||||||
# - duplicity_client
|
become: true
|
||||||
# - hostvars[item].duplicity_server is defined and hostvars[item].duplicity_server
|
become_user: "{{ duplicity_server_user }}"
|
||||||
# become: true
|
ansible.builtin.command:
|
||||||
# ansible.posix.authorized_key:
|
cmd: "gpg --list-keys"
|
||||||
# user: "{{ duplicity_client_user }}"
|
creates: "{{ duplicity_server_created_user['home'] }}/.gnupg"
|
||||||
# state: "present"
|
|
||||||
# key: "{{ lookup('file', 'buffer/{{item}}-id_ed25519.pub') }}"
|
|
||||||
# loop: "{{ groups['duplicity'] }}"
|
|
||||||
|
|
||||||
# - name: "Fetch sshd fingerprints from clients"
|
- name: "Install encryption key for backups"
|
||||||
# when: duplicity_client
|
become: true
|
||||||
# ansible.builtin.fetch:
|
become_user: "{{ duplicity_server_user }}"
|
||||||
# src: "/etc/ssh/ssh_host_ecdsa_key.pub"
|
de_enbewe.duplicity.gpg_key:
|
||||||
# dest: "buffer/{{ ansible_host }}-ssh_host_ecdsa_key.pub"
|
fpr: "{{ duplicity_server_gnupg_fingerprint }}"
|
||||||
# flat: true
|
keyserver: "hkps://keys.openpgp.org"
|
||||||
# changed_when: false
|
trust: 5
|
||||||
|
homedir: "{{ duplicity_server_created_user['home'] }}/.gnupg"
|
||||||
|
|
||||||
# - name: "Register client host keys in server"
|
### BACKUP SCRIPTS
|
||||||
# when:
|
- name: "Create backup script path"
|
||||||
# - duplicity_server
|
become: true
|
||||||
# - hostvars[item].duplicity_client is defined and hostvars[item].duplicity_client
|
ansible.builtin.file:
|
||||||
# become: true
|
path: "{{ duplicity_server_created_user['home'] }}/scripts"
|
||||||
# become_user: "{{ duplicity_server_user }}"
|
state: "directory"
|
||||||
# ansible.builtin.known_hosts:
|
owner: "{{ duplicity_server_user }}"
|
||||||
# name: "{{ item }}"
|
group: "{{ duplicity_server_user }}"
|
||||||
# key: "{{ item }} {{ lookup('file', 'buffer/{{item}}-ssh_host_ecdsa_key.pub') }}"
|
mode: "u=rwx,g=rx,o=rx"
|
||||||
# loop: "{{ groups['duplicity'] }}"
|
|
||||||
|
|
||||||
# - name: "Test ssh connection from server to client"
|
- name: "Create backup scripts for clients"
|
||||||
# when:
|
become: true
|
||||||
# - duplicity_server
|
become_user: "{{ duplicity_server_user }}"
|
||||||
# - hostvars[item].duplicity_client is defined and hostvars[item].duplicity_client
|
ansible.builtin.template:
|
||||||
# become: true
|
src: "backup-script.j2"
|
||||||
# become_user: "{{ duplicity_server_user }}"
|
dest: "{{ duplicity_server_created_user['home'] }}/scripts/backup-{{ item }}.sh"
|
||||||
# ansible.builtin.command: "ssh -o 'BatchMode yes' {{ duplicity_client_user }}@{{ item }} 'echo success'"
|
mode: "u=rwx,g=rx,o=rx"
|
||||||
# changed_when: false
|
with_items: "{{ groups['duplicityclient'] }}"
|
||||||
# loop: "{{ groups['duplicity'] }}"
|
|
||||||
|
|
||||||
# - name: "Set default ACLs on backup data"
|
- name: "Register cronjob for clients"
|
||||||
# when: duplicity_client
|
become: true
|
||||||
# become: true
|
ansible.builtin.cron:
|
||||||
# ansible.posix.acl:
|
name: "backup-{{ item }}"
|
||||||
# path: "{{ item }}"
|
user: "{{ duplicity_server_user }}"
|
||||||
# entity: "{{ duplicity_client_user }}"
|
job: "{{ duplicity_server_created_user['home'] }}/scripts/backup-{{ item }}.sh"
|
||||||
# etype: "user"
|
minute: "{{ hostvars[item].duplicity_client_backup_minute | default(12) }}"
|
||||||
# permissions: r-X
|
hour: "{{ hostvars[item].duplicity_client_backup_hour | default(1) }}"
|
||||||
# default: true
|
with_items: "{{ groups['duplicityclient'] }}"
|
||||||
# state: present
|
|
||||||
# recursive: true
|
|
||||||
# loop: "{{ duplicity_client_backup_paths }}"
|
|
||||||
|
|
||||||
# - name: "Set read ACLs on existing backup data"
|
|
||||||
# when: duplicity_client
|
|
||||||
# become: true
|
|
||||||
# ansible.posix.acl:
|
|
||||||
# path: "{{ item }}"
|
|
||||||
# entity: "{{ duplicity_client_user }}"
|
|
||||||
# etype: "user"
|
|
||||||
# permissions: r-X
|
|
||||||
# state: present
|
|
||||||
# recursive: true
|
|
||||||
# loop: "{{ duplicity_client_backup_paths }}"
|
|
||||||
|
|
||||||
# - name: "Ensure gnupg config dir"
|
|
||||||
# when: duplicity_server
|
|
||||||
# become: true
|
|
||||||
# become_user: "{{ duplicity_server_user }}"
|
|
||||||
# ansible.builtin.command:
|
|
||||||
# cmd: "gpg --list-keys"
|
|
||||||
# creates: "/home/{{ duplicity_server_user }}/.gnupg"
|
|
||||||
|
|
||||||
|
|
||||||
# - name: "Install encryption key for backups"
|
|
||||||
# when: duplicity_server
|
|
||||||
# become: true
|
|
||||||
# gpg_key:
|
|
||||||
# fpr: "C05AD49B790BAC8E3B573B697B25171F921B9E57"
|
|
||||||
# keyserver: "hkps://keys.openpgp.org"
|
|
||||||
# trust: "5"
|
|
||||||
# homedir: "/home/{{ duplicity_server_user }}/.gnupg"
|
|
||||||
|
|
||||||
# - name: "Create backup script path"
|
|
||||||
# when: duplicity_server
|
|
||||||
# become: true
|
|
||||||
# ansible.builtin.file:
|
|
||||||
# path: "{{ duplicity_server_scriptdir }}"
|
|
||||||
# state: "directory"
|
|
||||||
# owner: "{{ duplicity_server_user }}"
|
|
||||||
# group: "{{ duplicity_server_user }}"
|
|
||||||
# mode: "u=rwx,g=rx,o=rx"
|
|
||||||
|
|
||||||
# - name: "Create backup scripts for clients"
|
|
||||||
# when:
|
|
||||||
# - duplicity_server
|
|
||||||
# - hostvars[item].duplicity_client is defined and hostvars[item].duplicity_client
|
|
||||||
# become: true
|
|
||||||
# become_user: "{{ duplicity_server_user }}"
|
|
||||||
# ansible.builtin.template:
|
|
||||||
# src: "backup-script.j2"
|
|
||||||
# dest: "{{ duplicity_server_scriptdir }}/backup-{{ item }}.sh"
|
|
||||||
# mode: "u=rwx,g=rx,o=rx"
|
|
||||||
# loop: "{{ groups['duplicity'] }}"
|
|
||||||
|
|
||||||
# - name: "Register cronjob for clients"
|
|
||||||
# when:
|
|
||||||
# - duplicity_server
|
|
||||||
# - hostvars[item].duplicity_client is defined and hostvars[item].duplicity_client
|
|
||||||
# become: true
|
|
||||||
# ansible.builtin.cron:
|
|
||||||
# name: "backup-{{ item }}"
|
|
||||||
# user: "{{ duplicity_server_user }}"
|
|
||||||
# job: "{{ duplicity_server_scriptdir }}/backup-{{ item }}.sh"
|
|
||||||
# minute: "{{ hostvars[item].duplicity_client_backup_minute }}"
|
|
||||||
# hour: "{{ hostvars[item].duplicity_client_backup_hour }}"
|
|
||||||
# loop: "{{ groups['duplicity'] }}"
|
|
||||||
|
|
24
roles/duplicity_server/templates/backup-script.j2
Normal file
24
roles/duplicity_server/templates/backup-script.j2
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Cleanup old backups
|
||||||
|
duplicity remove-all-inc-of-but-n-full 2 --force file://{{ duplicity_server_storage_root }}/{{item}}
|
||||||
|
duplicity remove-all-but-n-full 3 --force file://{{ duplicity_server_storage_root }}/{{item}}
|
||||||
|
|
||||||
|
# Prepare mount directory
|
||||||
|
rm -rf {{ duplicity_server_mount_root }}/{{ item }}
|
||||||
|
mkdir -p {{ duplicity_server_mount_root }}/{{ item }}
|
||||||
|
cd {{ duplicity_server_mount_root }}/{{ item }}
|
||||||
|
|
||||||
|
# mount the client directories through sshfs
|
||||||
|
{% for path in hostvars[item].duplicity_client_backup_paths %}
|
||||||
|
mkdir -p .{{ path }}
|
||||||
|
sshfs {{ hostvars[item].duplicity_client_user | default(duplicity_client_user) }}@{{ item }}:{{path}} .{{ path }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# Perform the backup
|
||||||
|
duplicity --full-if-older-than 1W --encrypt-key C05AD49B790BAC8E3B573B697B25171F921B9E57 . file://{{ duplicity_server_storage_root }}/{{item}}
|
||||||
|
|
||||||
|
# Unmount the directories
|
||||||
|
{% for path in hostvars[item].duplicity_client_backup_paths %}
|
||||||
|
fusermount -u .{{ path }}
|
||||||
|
{% endfor %}
|
|
@ -1,2 +0,0 @@
|
||||||
localhost
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
- hosts: localhost
|
|
||||||
remote_user: root
|
|
||||||
roles:
|
|
||||||
- duplicity-server
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
# vars file for duplicity-server
|
|
Loading…
Reference in a new issue