aboutsummaryrefslogtreecommitdiff
path: root/ansible/roles
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2019-05-15 13:58:42 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2019-08-08 09:03:00 +0200
commit030305fc22b16851935de4dc52f912c550bdbd09 (patch)
tree3153888a7d1b63468194f0e8334ffbf4ef63dbea /ansible/roles
parent4bd33c6a46f57f8a830042795cfaa68ef91963a9 (diff)
downloadinfra-030305fc22b16851935de4dc52f912c550bdbd09.tar.gz
infra-030305fc22b16851935de4dc52f912c550bdbd09.tar.bz2
infra-030305fc22b16851935de4dc52f912c550bdbd09.tar.xz
infra-030305fc22b16851935de4dc52f912c550bdbd09.zip
o New borg.
Diffstat (limited to 'ansible/roles')
-rw-r--r--ansible/roles/borg-client/defaults/main.yml2
-rw-r--r--ansible/roles/borg-client/handlers/main.yml3
-rw-r--r--ansible/roles/borg-client/tasks/main.yml59
-rw-r--r--ansible/roles/borg-client/templates/bin/tergum24
-rw-r--r--ansible/roles/borg-client/templates/bin/tergum-post18
-rw-r--r--ansible/roles/borg-job/defaults/main.yml6
-rw-r--r--ansible/roles/borg-job/handlers/main.yml8
-rw-r--r--ansible/roles/borg-job/tasks/main.yml60
-rw-r--r--ansible/roles/borg-target/defaults/main.yml6
-rw-r--r--ansible/roles/borg-target/tasks/borg-init.yml47
-rw-r--r--ansible/roles/borg-target/tasks/main.yml62
11 files changed, 295 insertions, 0 deletions
diff --git a/ansible/roles/borg-client/defaults/main.yml b/ansible/roles/borg-client/defaults/main.yml
new file mode 100644
index 0000000..ff82ed3
--- /dev/null
+++ b/ansible/roles/borg-client/defaults/main.yml
@@ -0,0 +1,2 @@
+borg_client__ssh_key: "borg/{{ ansible_hostname }}/ssh-key"
+
diff --git a/ansible/roles/borg-client/handlers/main.yml b/ansible/roles/borg-client/handlers/main.yml
new file mode 100644
index 0000000..970492f
--- /dev/null
+++ b/ansible/roles/borg-client/handlers/main.yml
@@ -0,0 +1,3 @@
+- name: systemctl daemon-reload
+ systemd:
+ daemon_reload: true
diff --git a/ansible/roles/borg-client/tasks/main.yml b/ansible/roles/borg-client/tasks/main.yml
new file mode 100644
index 0000000..d5767cd
--- /dev/null
+++ b/ansible/roles/borg-client/tasks/main.yml
@@ -0,0 +1,59 @@
+- tags: packages
+ apt:
+ name:
+ - borgbackup
+ install_recommends: no
+
+- name: "mkdir /etc/tergum"
+ file:
+ path: "/etc/tergum"
+ state: directory
+ mode: u=rwx,go=
+ owner: root
+ group: root
+
+- copy:
+ dest: /etc/tergum/ssh-key
+ src: "{{ borg_client__ssh_key }}"
+ mode: u=rwx,go=
+ owner: root
+ group: root
+
+- name: "/etc/systemd/system/tergum@.service"
+ copy:
+ dest: "/etc/systemd/system/tergum@.service"
+ content: |
+ [Unit]
+ Description=Borg backup
+
+ [Service]
+ Type=oneshot
+ WorkingDirectory=/
+ ExecStart=-/usr/bin/tergum %i
+ #ExecStartPost=-/usr/bin/tergum-post foo@example.org
+ SuccessExitStatus=0 1
+ EnvironmentFile=/etc/tergum/jobs/%i/env
+ notify:
+ - systemctl daemon-reload
+
+- name: "/etc/systemd/system/tergum@.timer"
+ copy:
+ dest: "/etc/systemd/system/tergum@.timer"
+ content: |
+ [Unit]
+ Description=Borg
+
+ [Install]
+ WantedBy=timers.target
+ notify:
+ - systemctl daemon-reload
+
+- template:
+ dest: "/usr/bin/{{ item }}"
+ src: "bin/{{ item }}"
+ mode: u=rwx,go=rx
+ owner: root
+ group: root
+ with_items:
+ - tergum
+ - tergum-post
diff --git a/ansible/roles/borg-client/templates/bin/tergum b/ansible/roles/borg-client/templates/bin/tergum
new file mode 100644
index 0000000..eaab95c
--- /dev/null
+++ b/ansible/roles/borg-client/templates/bin/tergum
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cd /
+
+instance=$1; shift
+
+echo BORG_RSH="$BORG_RSH"
+echo BORG_REPO="$BORG_REPO"
+
+echo "Doing backup for instance $instance"
+
+cmd=()
+cmd+=(borg create)
+cmd+=("--stats")
+cmd+=("--exclude-from=/etc/tergum/jobs/$instance/excludes")
+cmd+=("--patterns-from=/etc/tergum/jobs/$instance/patterns")
+cmd+=("::{hostname}-{now:%Y-%m-%dT%H:%M:%S}")
+
+set -x
+time "${cmd[@]}"
+
+borg info --last 1
diff --git a/ansible/roles/borg-client/templates/bin/tergum-post b/ansible/roles/borg-client/templates/bin/tergum-post
new file mode 100644
index 0000000..647bf5b
--- /dev/null
+++ b/ansible/roles/borg-client/templates/bin/tergum-post
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cd /
+
+instance=$1; shift
+
+/usr/sbin/sendmail -t <<ERRMAIL
+To: $1
+From: systemd <root@$HOSTNAME>
+Subject: Backup @ $HOSTNAME
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain; charset=UTF-8
+
+$(systemctl status --full 2>&1)
+$(journalctl --since today --unit tergum@$instance 2>&1)
+ERRMAIL
diff --git a/ansible/roles/borg-job/defaults/main.yml b/ansible/roles/borg-job/defaults/main.yml
new file mode 100644
index 0000000..b5f3cbc
--- /dev/null
+++ b/ansible/roles/borg-job/defaults/main.yml
@@ -0,0 +1,6 @@
+borg_job__on_calendar: daily
+borg_job__default_excludes:
+ - /proc
+ - /dev
+ - /sys
+ - /run
diff --git a/ansible/roles/borg-job/handlers/main.yml b/ansible/roles/borg-job/handlers/main.yml
new file mode 100644
index 0000000..76e08ab
--- /dev/null
+++ b/ansible/roles/borg-job/handlers/main.yml
@@ -0,0 +1,8 @@
+- name: systemctl daemon-reload
+ systemd:
+ daemon_reload: true
+
+- name: "service start tergum@{{ borg_job__name }}.timer"
+ service:
+ name: "tergum@{{ borg_job__name }}.timer"
+ state: restarted
diff --git a/ansible/roles/borg-job/tasks/main.yml b/ansible/roles/borg-job/tasks/main.yml
new file mode 100644
index 0000000..10076d6
--- /dev/null
+++ b/ansible/roles/borg-job/tasks/main.yml
@@ -0,0 +1,60 @@
+- name: Install packages
+ tags: packages
+ apt:
+ name:
+ - borgbackup
+ install_recommends: no
+
+- name: "mkdir /etc/tergum/jobs/{{ borg_job__name }}"
+ file:
+ path: "/etc/tergum/jobs/{{ borg_job__name }}"
+ state: directory
+
+- name: "/etc/tergum/jobs/{{ borg_job__name }}/env"
+ copy:
+ dest: "/etc/tergum/jobs/{{ borg_job__name }}/env"
+ content: |
+ BORG_REPO={{ borg_job__username }}@{{ borg_job__target }}:{{ ansible_hostname }}/{{ borg_job__name }}
+ BORG_RSH=ssh -i /etc/tergum/ssh-key
+ BORG_PASSPHRASE={{ borg__passphrases[ansible_hostname][borg_job__name] }}
+
+# BORG_KEYS_DIR
+# BORG_SECURITY_DIR
+# BORG_CACHE_DIR
+
+- name: "/etc/tergum/jobs/{{ borg_job__name }}/patterns"
+ copy:
+ dest: "/etc/tergum/jobs/{{ borg_job__name }}/patterns"
+ content: "{{ borg_job__settings.patterns }}"
+
+- name: "/etc/tergum/jobs/{{ borg_job__name }}/excludes"
+ vars:
+ excludes: "{{ borg_job__settings.excludes if borg_job__settings.excludes is defined else [] }}"
+ copy:
+ dest: "/etc/tergum/jobs/{{ borg_job__name }}/excludes"
+ content: |
+ {% for item in excludes %}
+ {{ item }}
+ {% endfor %}
+ {% for item in borg_job__default_excludes %}
+ {{ item }}
+ {% endfor %}
+
+- file:
+ path: "/etc/systemd/system/tergum@{{ borg_job__name }}.timer.d"
+ state: directory
+
+- copy:
+ dest: "/etc/systemd/system/tergum@{{ borg_job__name }}.timer.d/override.conf"
+ content: |
+ [Timer]
+ OnCalendar={{ borg_job__settings.on_calendar if borg_job__settings.on_calendar is defined else borg_job__on_calendar }}
+ notify:
+ - systemctl daemon-reload
+
+- meta: flush_handlers
+
+- systemd:
+ name: "tergum@{{ borg_job__name }}.timer"
+ enabled: yes
+ state: started
diff --git a/ansible/roles/borg-target/defaults/main.yml b/ansible/roles/borg-target/defaults/main.yml
new file mode 100644
index 0000000..734434a
--- /dev/null
+++ b/ansible/roles/borg-target/defaults/main.yml
@@ -0,0 +1,6 @@
+borg_target__user: borg
+borg_target__group: borg
+borg_target__shell: /bin/bash
+borg_target__home: /opt/borg
+
+borg_target__repos:
diff --git a/ansible/roles/borg-target/tasks/borg-init.yml b/ansible/roles/borg-target/tasks/borg-init.yml
new file mode 100644
index 0000000..21b86d6
--- /dev/null
+++ b/ansible/roles/borg-target/tasks/borg-init.yml
@@ -0,0 +1,47 @@
+- with_items: "{{ client.value.repos }}"
+ assert:
+ that:
+ - "item in borg_target__passphrases[client.key]"
+ fail_msg: "{{ item }} is missing from borg-secrets.yml"
+ success_msg: ""
+
+- set_fact:
+ ssh_key: "{{ client.value.ssh_key_path if client.value.ssh_key_path is defined else ('files/borg/' + client.key + '/ssh-key') }}"
+- debug: var=ssh_key
+
+- with_items: "{{ client.value.repos }}"
+ name: mkdir client dir
+ file:
+ path: "{{ path | dirname }}"
+ state: directory
+ owner: "{{ borg_target__user }}"
+ group: "{{ borg_target__group }}"
+ vars:
+ path: "{{ borg_target__home }}/repos/{{ client.key }}/{{ item }}"
+
+- with_items: "{{ client.value.repos }}"
+ name: borg init
+ become_user: "{{ borg_target__user }}"
+ command: "borg init --encryption repokey {{ path }}"
+ args:
+ creates: "{{ path }}"
+ environment:
+ BORG_PASSPHRASE: "{{ borg_target__passphrases[client.key][item] }}"
+ vars:
+ path: "{{ borg_target__home }}/repos/{{ client.key }}/{{ item }}"
+
+- local_action:
+ module: stat
+ path: "{{ ssh_key }}"
+ register: ssh_key_stat
+
+- local_action:
+ module: file
+ path: "{{ (playbook_dir + '/' + ssh_key) | dirname }}"
+ state: directory
+ become: no
+
+- name: Generating SSH key
+ local_action: command ssh-keygen -t ed25519 -N "" -f "{{ ssh_key }}" -C "borg@{{ client.key }}"
+ when: not ssh_key_stat.stat.exists
+ become: no
diff --git a/ansible/roles/borg-target/tasks/main.yml b/ansible/roles/borg-target/tasks/main.yml
new file mode 100644
index 0000000..c3b8693
--- /dev/null
+++ b/ansible/roles/borg-target/tasks/main.yml
@@ -0,0 +1,62 @@
+- name: Install packages
+ tags: packages
+ apt:
+ name:
+ - borgbackup
+ install_recommends: no
+
+- name: Create unix group
+ become: yes
+ group:
+ name: "{{ borg_target__group }}"
+ system: yes
+
+- name: Create unix user
+ become: yes
+ user:
+ name: "{{ borg_target__user }}"
+ group: "{{ borg_target__group }}"
+ shell: "{{ borg_target__shell }}"
+ home: "{{ borg_target__home }}"
+ system: yes
+
+- name: mkdir repos
+ file:
+ path: "{{ borg_target__home }}/repos"
+ state: directory
+ mode: u=rwx,go=
+ owner: "{{ borg_target__user }}"
+ group: "{{ borg_target__group }}"
+
+- with_dict: "{{ borg_target__clients }}"
+ file:
+ path: "{{ borg_target__home }}/repos/{{ item.key }}"
+ state: directory
+
+- include_tasks: borg-init.yml
+ with_dict: "{{ borg_target__clients }}"
+ loop_control:
+ loop_var: client
+
+- file:
+ path: "{{ borg_target__home }}/.ssh"
+ state: directory
+ mode: u=rx,go=
+ owner: "{{ borg_target__user }}"
+ group: "{{ borg_target__group }}"
+
+- name: authorized_keys
+ tags: xxx
+ copy:
+ dest: "{{ borg_target__home }}/.ssh/authorized_keys"
+ content: |
+ tilde={{ '~borg' | expanduser }}
+ {% for client, config in borg_target__clients.items() %}
+ {% set state=config.state | default('present') %}
+ # Client: {{ client }}, state={{state}}
+ {% if state == 'present' %}
+ {% set key=lookup('file', 'borg/' + client + '/ssh-key.pub') %}
+ command="cd {{ borg_target__home }}/repos && borg serve --append-only{% for r in config.repos %} --restrict-to-repository {{ client }}/{{ r }}{% endfor %}",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc {{ key }}
+ {% endif %}
+ {% endfor %}
+# "