diff --git a/pillar/common.sls b/pillar/common.sls index d5c0e8e..d56ea7b 100644 --- a/pillar/common.sls +++ b/pillar/common.sls @@ -55,6 +55,11 @@ openssh: banner_src: salt://profile/accounts/files/ssh_banner sshd_config_mode: 0640 profile: + borgbackup: + backupserver: backup.infra.opensuse.org + # ssh_known_hosts: use ssh-keyscan 192.168.122.x,xxx.infra.opensuse.org | grep nist + ssh_known_hosts: | + 192.168.47.45,backup.infra.opensuse.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxmOY4iCa0Rd2nQX8VN09upWIcKZt9XivRWgIpc083EHpwC0aY9SC408rtrUsPjOjOp1Hi2IvY69rv935FhTWo= postfix: aliases: root: admin-auto@opensuse.org diff --git a/pillar/id/backup_infra_opensuse_org.sls b/pillar/id/backup_infra_opensuse_org.sls index 72ae4e6..f5180d1 100644 --- a/pillar/id/backup_infra_opensuse_org.sls +++ b/pillar/id/backup_infra_opensuse_org.sls @@ -3,6 +3,8 @@ grains: country: de hostusage: - general backup host + roles: + - borgbackup reboot_safe: yes salt_cluster: opensuse virt_cluster: atreju diff --git a/pillar/role/borgbackup.sls b/pillar/role/borgbackup.sls new file mode 100644 index 0000000..ef5db25 --- /dev/null +++ b/pillar/role/borgbackup.sls @@ -0,0 +1,10 @@ +profile: + borgbackup: + # pillar needed on the clients: + # backupserver: set in pillar/common.sls + # ssh_known_hosts: set in pillar/common.sls + + authorized_keys: + # format: username_on_backupserver: PUBKEY + # TODO: ssh_private_keys included from pillar/secrets/role/borgbackup/*.sls in the client pillar + cboltz: PUBKEY diff --git a/salt/profile/borgbackup/client.sls b/salt/profile/borgbackup/client.sls new file mode 100644 index 0000000..b2008fe --- /dev/null +++ b/salt/profile/borgbackup/client.sls @@ -0,0 +1,69 @@ +include: + - profile.borgbackup.packages + +# client-side user (non-privileged or root) +{% set client_user = 'cboltz' %} # TODO (use pillar - from pillar/id or pillar/role?) +{% set client_home = salt['user.info'](client_user).home %} +{% set backup_pass = 'topsecret' %} # TODO: create encrypted pillar borgbackup/{{ server_user }}.sls with backup_pass and ssh private key +{% set backup_server = pillar.get('profile:borgbackup:backupserver') %} + +# server-side +{% set server_user = 'cboltz' %} # TODO (use pillar) +{% set backupdir = '/backup/' + server_user + '/borgbackup' %} + + +# setup user and ssh stuff +borgbackup_user: + user.present: + - name: {{ client_user }} + +{{ salt['user.info'](client_user).home }}/.ssh: + file.directory: + - user: {{ client_user }} + - mode: 700 + +{{ salt['user.info'](client_user).home }}/.ssh/borgbackup_key: + file.managed: + - user: {{ client_user }} + - mode: 600 + - contents_pillar: profile.borgbackup.{{ server_user }}.privatekey + +{{ salt['user.info'](client_user).home }}/.ssh/known_hosts: + file.append: + - user: {{ client_user }} + - mode: 600 + - contents_pillar: profile.borgbackup.ssh_known_hosts + +# backup config file +{{ salt['user.info'](client_user).home }}/borg-env: + file.managed: + - user: {{ client_user }} + - mode: 600 + - contents: + - export BORG_RSH="ssh -i {{ salt['user.info'](client_user).home }}/.ssh/borgbackup_key" + - export BORG_PASSPHRASE='{{ backup_pass }}' + - "export BORG_REPO='ssh://{{ client_user }}@{{ backup_server }}{{ backupdir }}'" + - export LOG='/var/log/borg/backup.log' + # TODO: make the directory to backup configurable + # TODO: make excludes configurable + +# initialize the backup +borgbackup_init: + cmd.run: + - env: {{ backup_pass }} + - name: borg init --encryption=repokey 'ssh://{{ client_user }}@{{backup_server}}{{ backupdir }}' + - runas: {{ client_user }} + - creates: {{ salt['user.info'](client_user).home }}/.cache/borg/CACHEDIR.TAG + +{{ salt['user.info'](client_user).home }}/borg-backup-script: + file.managed: + - source: salt://profile/borgbackup/files/borg-backup-script + - user: {{ client_user }} + - mode: 600 + +/var/log/borg: + file.directory + - user: {{ client_user }} + +# create cronjob +# TODO diff --git a/salt/profile/borgbackup/files/borg-backup-cronjob b/salt/profile/borgbackup/files/borg-backup-cronjob new file mode 100755 index 0000000..31833e9 --- /dev/null +++ b/salt/profile/borgbackup/files/borg-backup-cronjob @@ -0,0 +1,57 @@ +#!/bin/bash + +. $(dirname $0)/borg-backup-env + +errorexit() { + mail -s 'BorgBackup' root < $LOG + exit $? +} + +## +## write output to logfile +## + +exec > >(tee -i ${LOG}) +exec 2>&1 + +echo "###### Backup started: $(date) ######" + +## +## You can do some tasks before starting the backup here, for example +## - create a list of installed software +## - create database dumps +## + +## +## Transfer files to repository +## + +borg create -v --stats \ + --compression zstd,18 \ + $REPOSITORY::'{now:%Y-%m-%d_%H-%M}' \ + / \ + --exclude /backup \ + --exclude /dev \ + --exclude /lost+found \ + --exclude /mnt \ + --exclude /proc \ + --exclude /run \ + --exclude /sys \ + --exclude /var/run \ +|| { echo "Error $? during backup, aborting" ; errorexit 1; } + +echo +echo +echo "Deleting old backups..." +borg prune \ + --stats \ + --list \ + --keep-hourly 12 \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 6 \ +|| { echo "Error $? while deleting old backups, aborting" ; errorexit 2; } + +echo "###### Backup finished: $(date) ######" + +errorexit 0 diff --git a/salt/profile/borgbackup/packages.sls b/salt/profile/borgbackup/packages.sls new file mode 100644 index 0000000..1292b98 --- /dev/null +++ b/salt/profile/borgbackup/packages.sls @@ -0,0 +1,6 @@ +borgbackup_server: + pkg.installed: + - pkgs: + - borgbackup + - borgbackup-bash-completion + - python3-llfuse diff --git a/salt/profile/borgbackup/server.sls b/salt/profile/borgbackup/server.sls new file mode 100644 index 0000000..f62faa3 --- /dev/null +++ b/salt/profile/borgbackup/server.sls @@ -0,0 +1,27 @@ +include: + - profile.borgbackup.packages + +# create users +# home dirs should be /backup/$user + +{% for user, key in pillar.get('profile:borgbackup:authorized_keys') %} + +user_{{ user }}: + user.present: + - name: {{ user }} + - home: /backup/{{ user }} + +/backup/{{ user }}/.ssh: + file.directory: + - user: {{ user }} + - mode: 700 + +# create */.ssh/authorized_keys (TODO: maybe with COMMAND=...?) +/backup/{{ user }}/.ssh/authorized_keys: + file.managed: + - user: {{ user }} + - mode: 600 + - contents: + - {{ key }} + +{% endfor %} diff --git a/salt/role/borgbackup.sls b/salt/role/borgbackup.sls new file mode 100644 index 0000000..18670d7 --- /dev/null +++ b/salt/role/borgbackup.sls @@ -0,0 +1,2 @@ +include: + - profile.borgbackup.server