aboutsummaryrefslogtreecommitdiffstats
path: root/playbooks
diff options
context:
space:
mode:
authorStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:23:43 -0500
committerStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:52:13 -0500
commit0261e875679f1bf63c8d689da7fc7e014597885d (patch)
tree3f19cd74a0c1070944f75437f30b098d6ef2ffcb /playbooks
downloadselfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.tar.gz
selfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.zip
initial commit
Diffstat (limited to 'playbooks')
-rw-r--r--playbooks/archiver.yml9
-rw-r--r--playbooks/asterisk.yml18
-rw-r--r--playbooks/bitwarden.yml15
-rw-r--r--playbooks/common.yml112
-rw-r--r--playbooks/cups.yml14
-rw-r--r--playbooks/dav.yml25
-rw-r--r--playbooks/dev_servers.yml9
-rw-r--r--playbooks/dns_records.yml28
-rw-r--r--playbooks/freeipa.yml24
-rw-r--r--playbooks/freeipa_bootstrap.yml10
-rw-r--r--playbooks/freeipa_replica.yml9
-rw-r--r--playbooks/git.yml54
-rw-r--r--playbooks/jellyfin.yml20
-rw-r--r--playbooks/linux_desktops.yml24
-rw-r--r--playbooks/linux_laptops.yml27
-rw-r--r--playbooks/mail.yml36
-rw-r--r--playbooks/nagios.yml15
-rw-r--r--playbooks/nameservers.yml9
-rw-r--r--playbooks/nfs.yml9
-rw-r--r--playbooks/opnsense.yml17
-rw-r--r--playbooks/photostructure.yml20
-rw-r--r--playbooks/populate_domain.yml99
-rw-r--r--playbooks/postgres.yml15
-rw-r--r--playbooks/privbrowse.yml33
-rw-r--r--playbooks/proxmox.yml21
-rw-r--r--playbooks/proxmox_instance.yml5
-rw-r--r--playbooks/radius.yml9
-rw-r--r--playbooks/site.yml37
-rw-r--r--playbooks/syncthing.yml19
-rw-r--r--playbooks/syslog.yml9
-rw-r--r--playbooks/test.yml4
-rw-r--r--playbooks/ttrss.yml21
-rw-r--r--playbooks/turn.yml10
-rw-r--r--playbooks/unifi.yml15
-rw-r--r--playbooks/util/backup.yml606
-rw-r--r--playbooks/util/client_cert.yml71
-rw-r--r--playbooks/util/decomission_host.yml56
-rw-r--r--playbooks/util/restore.yml477
-rw-r--r--playbooks/util/wireguard_config.yml49
-rw-r--r--playbooks/webserver_internal.yml46
-rw-r--r--playbooks/webserver_public.yml38
-rw-r--r--playbooks/wiki.yml25
-rw-r--r--playbooks/xmpp.yml9
-rw-r--r--playbooks/yum.yml33
-rw-r--r--playbooks/znc.yml14
45 files changed, 2225 insertions, 0 deletions
diff --git a/playbooks/archiver.yml b/playbooks/archiver.yml
new file mode 100644
index 0000000..9056db3
--- /dev/null
+++ b/playbooks/archiver.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: archive_servers
+
+- name: configure archiver
+ hosts: archive_servers
+ tags: archive,archiver
+ roles:
+ - archive_server
diff --git a/playbooks/asterisk.yml b/playbooks/asterisk.yml
new file mode 100644
index 0000000..153176a
--- /dev/null
+++ b/playbooks/asterisk.yml
@@ -0,0 +1,18 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: asterisk_servers
+
+- name: configure asterisk pbx
+ hosts: asterisk_servers
+ tags: asterisk
+ roles:
+ - role: asterisk
+
+ - role: archive_job
+ archive_name: asterisk
+ archive_user: asterisk
+ archive_shell: >-
+ TIMESTAMP=$(date +%Y%m%d%H%M%S);
+ tar czf "asterisk-${TIMESTAMP}.tar.gz"
+ --transform "s|^\.|asterisk-${TIMESTAMP}|" -C {{ asterisk_data_dir }} .
+ tags: archive
diff --git a/playbooks/bitwarden.yml b/playbooks/bitwarden.yml
new file mode 100644
index 0000000..cb9a911
--- /dev/null
+++ b/playbooks/bitwarden.yml
@@ -0,0 +1,15 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: bitwarden_servers
+
+- name: configure vaultwarden
+ hosts: bitwarden_servers
+ tags: vaultwarden,bitwarden
+ roles:
+ - role: vaultwarden
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_canonical_hostname: '{{ vaultwarden_server_name }}'
+ apache_config: '{{ vaultwarden_apache_config }}'
+ tags: apache
diff --git a/playbooks/common.yml b/playbooks/common.yml
new file mode 100644
index 0000000..e96be0b
--- /dev/null
+++ b/playbooks/common.yml
@@ -0,0 +1,112 @@
+- hosts: '{{ hostlist | default("el") }}'
+ gather_facts: no
+ tags: common
+ roles:
+ - role: proxmox_instance
+ when: '"proxmox_instances" in group_names'
+ tags: proxmox
+
+ - role: dns_records
+ when: not (bootstrap | default(false))
+ tags: dns
+
+ - role: gather_facts
+ when: not ansible_facts
+ tags: always
+
+ - role: udev
+ when: not ansible_virtualization_tech_guest
+ tags: udev
+
+ - role: root_authorized_keys
+ tags: authorized_keys
+
+ - role: root_password
+ tags: root_password
+
+ - role: polkit
+ tags: polkit
+
+ - role: grub
+ tags: grub
+
+ - role: sudo
+ tags: sudo,sudoers
+
+ - role: hostname
+ tags: hostname
+
+ - role: timezone
+ tags: timezone
+
+ - role: journald
+ tags: journald
+
+ - role: yum_disable_default_repos
+ when: '"yum_mirrors" not in group_names'
+
+ - role: yum
+ yum_repositories:
+ - rocky-baseos
+ - rocky-appstream
+ - rocky-extras
+ when:
+ - '"yum_mirrors" not in group_names'
+ - not (bootstrap | default(false))
+ tags: yum
+
+ - role: dnsmasq
+ when: '"freeipa_servers" not in group_names'
+ tags: dnsmasq
+
+ - role: locale
+ tags: locale
+
+ - role: selinux
+ tags: selinux
+
+ - role: qemu_guest_agent
+ when: '"kvm" in ansible_virtualization_tech_guest'
+ tags: qemu
+
+ - role: firewalld
+ tags: firewalld
+
+ - role: chrony
+ tags: chrony,ntp
+
+ - role: dnf_automatic
+ tags: yum
+
+ - role: ssh
+ tags: ssh
+
+ - role: tuned
+ tags: tuned
+
+ - role: motd
+ tags: motd
+
+ - role: packages
+ tags: packages
+
+ - role: postfix_client
+ when: '"mail_servers" not in group_names'
+ tags: postfix,mail
+
+ - role: freeipa_client
+ when: '"freeipa_servers" not in group_names'
+ tags: freeipa
+
+ - role: rsyslog_client
+ when:
+ - '"syslog_servers" not in group_names'
+ - not (bootstrap | default(false))
+ tags: rsyslog
+
+ - role: nagios_client
+ when:
+ - (group_names | intersect(nagios_excluded_groups) | length) == 0
+ - '"yum_mirrors" not in group_names'
+ - not (bootstrap | default(false))
+ tags: nagios
diff --git a/playbooks/cups.yml b/playbooks/cups.yml
new file mode 100644
index 0000000..20bed0b
--- /dev/null
+++ b/playbooks/cups.yml
@@ -0,0 +1,14 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: cups_servers
+
+- name: configure cups
+ hosts: cups_servers
+ tags: cups
+ roles:
+ - role: cups_server
+
+ - role: archive_job
+ archive_name: cups
+ archive_shell: '{{ cups_archive_shell }}'
+ tags: archive
diff --git a/playbooks/dav.yml b/playbooks/dav.yml
new file mode 100644
index 0000000..21c4a97
--- /dev/null
+++ b/playbooks/dav.yml
@@ -0,0 +1,25 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: dav_servers
+
+- name: configure sabredav
+ hosts: dav_servers
+ tags: sabredav,dav
+ roles:
+ - role: sabredav
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_document_root: '{{ sabredav_home }}'
+ apache_config: '{{ sabredav_apache_config }}'
+ tags: apache
+
+ - role: php
+ php_fpm_environment: '{{ sabredav_php_environment }}'
+ php_fpm_admin_flags: '{{ sabredav_php_flags }}'
+ tags: php
+
+ - role: archive_job
+ archive_name: webdav
+ archive_shell: '{{ sabredav_archive_shell }}'
+ tags: archive
diff --git a/playbooks/dev_servers.yml b/playbooks/dev_servers.yml
new file mode 100644
index 0000000..2602d6d
--- /dev/null
+++ b/playbooks/dev_servers.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: dev_servers
+
+- name: configure development environment
+ hosts: dev_servers
+ tags: dev
+ roles:
+ - dev_environment
diff --git a/playbooks/dns_records.yml b/playbooks/dns_records.yml
new file mode 100644
index 0000000..93d635e
--- /dev/null
+++ b/playbooks/dns_records.yml
@@ -0,0 +1,28 @@
+- name: add dns records for infrastructure hosts
+ hosts: proxmox_hypervisors:opnsense_firewalls:unmanaged
+ tags: dns
+ roles:
+ - dns_records
+
+- name: add reverse dns records for firewall vlan interfaces
+ hosts: freeipa_master
+ tags: dns
+ tasks:
+ - name: create reverse dns zones
+ ipadnszone:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ zone_name: '{{ item }}'
+ state: present
+ loop: "{{ vlans.values() | map(attribute='gateway') | ansible.utils.ipaddr('revdns') | map('regex_replace', '^[^.]+\\.', '') | unique }}"
+
+ - name: create ptr records
+ ipadnsrecord:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ zone_name: "{{ item | ansible.utils.ipaddr('revdns') | regex_replace('^[^.]+\\.', '') }}"
+ record_name: '{{ item | split(".") | last }}'
+ record_type: PTR
+ record_value: '{{ groups["opnsense_firewalls"] | sort | first }}.{{ domain }}.'
+ state: present
+ loop: "{{ vlans.values() | map(attribute='gateway') }}"
diff --git a/playbooks/freeipa.yml b/playbooks/freeipa.yml
new file mode 100644
index 0000000..a83aaf6
--- /dev/null
+++ b/playbooks/freeipa.yml
@@ -0,0 +1,24 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: freeipa_servers
+
+- name: configure freeipa master
+ hosts: freeipa_master
+ tags: freeipa
+ roles:
+ - role: freeipa_server
+
+ - role: archive_job
+ archive_name: ipa
+ archive_on_calendar: 'Sat *-*-* 02:00:00'
+ archive_shell: >-
+ ipa-backup &&
+ mv -v /var/lib/ipa/backup/* . &&
+ find . -mindepth 1 -type d -exec chmod -v 770 {} +
+ tags: archive
+
+- name: configure freeipa replicas
+ hosts: freeipa_servers:!freeipa_master
+ tags: freeipa
+ roles:
+ - freeipa_server
diff --git a/playbooks/freeipa_bootstrap.yml b/playbooks/freeipa_bootstrap.yml
new file mode 100644
index 0000000..38865a1
--- /dev/null
+++ b/playbooks/freeipa_bootstrap.yml
@@ -0,0 +1,10 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: freeipa_master
+ bootstrap: yes
+
+- name: configure freeipa master
+ hosts: freeipa_master
+ tags: freeipa
+ roles:
+ - freeipa_server
diff --git a/playbooks/freeipa_replica.yml b/playbooks/freeipa_replica.yml
new file mode 100644
index 0000000..adac739
--- /dev/null
+++ b/playbooks/freeipa_replica.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: freeipa_master
+
+- name: configure freeipa replicas
+ hosts: freeipa_servers:!freeipa_master
+ tags: freeipa
+ roles:
+ - freeipa_replica
diff --git a/playbooks/git.yml b/playbooks/git.yml
new file mode 100644
index 0000000..9e4c112
--- /dev/null
+++ b/playbooks/git.yml
@@ -0,0 +1,54 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: git_servers
+
+- name: configure git repository
+ hosts: git_servers
+ tags: git
+ roles:
+ - role: gitolite
+ tags: gitolite
+
+ - role: archive_job
+ archive_name: gitolite
+ archive_user: '{{ gitolite_user }}'
+ archive_shell: '{{ gitolite_archive_shell }}'
+ tags: archive
+
+ - role: cgit
+ tags: cgit
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_document_root: '{{ cgit_static_dir }}'
+ apache_config: |
+ SetEnv "GIT_PROJECT_ROOT" "{{ gitolite_home }}/repositories"
+ SetEnv "GIT_HTTP_EXPORT_ALL" "1"
+
+ <LocationMatch "{{ git_backend_regex }}">
+ AuthType GSSAPI
+ AuthName "FreeIPA Single Sign-On"
+ AuthLDAPUrl "{{ apache_ldap_url }}?krbprincipalname"
+ {{ apache_ldap_creds }}
+ <RequireAny>
+ <RequireAll>
+ Require ip {{ kerberized_cidrs | join(" ") }}
+ <RequireAny>
+ Require ldap-attribute memberof=cn={{ gitolite_access_group }},{{ freeipa_group_basedn }}
+ Require ldap-attribute memberof=cn={{ gitolite_admin_group }},{{ freeipa_group_basedn }}
+ </RequireAny>
+ </RequireAll>
+ <RequireAll>
+ Require not ip {{ kerberized_cidrs | join(" ") }}
+ Require all granted
+ </RequireAll>
+ </RequireAny>
+ </LocationMatch>
+
+ Alias /static "{{ cgit_static_dir }}"
+
+ ScriptAliasMatch "{{ git_backend_regex }}" "{{ gitolite_cgi_script }}/$1"
+ ScriptAlias "/" "{{ cgit_cgi_script }}/"
+ vars:
+ git_backend_regex: '(?x)^/(.*/(HEAD | info/refs | objects/(info/[^/]+ | [0-9a-f]{2}/[0-9a-f]{38} | pack/pack-[0-9a-f]{40}\.(pack|idx)) | git-(upload|receive)-pack))$'
+ tags: apache
diff --git a/playbooks/jellyfin.yml b/playbooks/jellyfin.yml
new file mode 100644
index 0000000..7fa6721
--- /dev/null
+++ b/playbooks/jellyfin.yml
@@ -0,0 +1,20 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: jellyfin_servers
+
+- name: configure jellyfin
+ hosts: jellyfin_servers
+ tags: jellyfin
+ roles:
+ - role: jellyfin
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_config: '{{ jellyfin_apache_config }}'
+ tags: apache
+
+ - role: archive_job
+ archive_name: jellyfin
+ archive_user: '{{ jellyfin_user }}'
+ archive_shell: '{{ jellyfin_archive_shell }}'
+ tags: archive
diff --git a/playbooks/linux_desktops.yml b/playbooks/linux_desktops.yml
new file mode 100644
index 0000000..d7c2fee
--- /dev/null
+++ b/playbooks/linux_desktops.yml
@@ -0,0 +1,24 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: linux_desktops
+
+- name: configure linux desktop environment
+ hosts: linux_desktops
+ roles:
+ - role: dev_environment
+ tags: dev
+
+ - role: linux_desktop
+ tags: desktop,linux_desktop
+
+ - role: local_homedirs
+ tags: local_homedirs,homedirs,homedir
+
+ - role: firefox
+ tags: firefox
+
+ - role: evolution
+ tags: evolution
+
+ - role: cups_client
+ tags: cups
diff --git a/playbooks/linux_laptops.yml b/playbooks/linux_laptops.yml
new file mode 100644
index 0000000..c841e95
--- /dev/null
+++ b/playbooks/linux_laptops.yml
@@ -0,0 +1,27 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: linux_laptops
+
+- name: configure linux desktop environment
+ hosts: linux_laptops
+ roles:
+ - role: dev_environment
+ tags: dev
+
+ - role: linux_desktop
+ tags: desktop,linux_desktop
+
+ - role: local_homedirs
+ tags: local_homedirs,homedirs,homedir
+
+ - role: firefox
+ tags: firefox
+
+ - role: evolution
+ tags: evolution
+
+ - role: cups_client
+ tags: cups
+
+ - role: linux_laptop
+ tags: laptop,linux_laptop
diff --git a/playbooks/mail.yml b/playbooks/mail.yml
new file mode 100644
index 0000000..6df70f3
--- /dev/null
+++ b/playbooks/mail.yml
@@ -0,0 +1,36 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: rspamd_servers,mail_servers,imap_servers
+
+- name: configure rspamd
+ hosts: rspamd_servers
+ tags: rspamd
+ roles:
+ - role: rspamd
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_config: '{{ rspamd_apache_config }}'
+ tags: apache
+
+ - role: archive_job
+ archive_name: rspamd
+ archive_shell: '{{ rspamd_archive_shell }}'
+ tags: archive
+
+- name: configure Postfix
+ hosts: mail_servers
+ tags: postfix,smtp
+ roles:
+ - postfix_server
+
+- name: configure Dovecot
+ hosts: imap_servers
+ tags: dovecot,imap
+ roles:
+ - role: dovecot
+
+ - role: archive_job
+ archive_name: dovecot
+ archive_command: '{{ dovecot_archive_script }}'
+ tags: archive
diff --git a/playbooks/nagios.yml b/playbooks/nagios.yml
new file mode 100644
index 0000000..cb13d57
--- /dev/null
+++ b/playbooks/nagios.yml
@@ -0,0 +1,15 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: nagios_servers
+
+- name: configure nagios
+ hosts: nagios_servers
+ tags: nagios
+ roles:
+ - role: nagios_server
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_document_root: '{{ nagios_html_dir }}'
+ apache_config: '{{ nagios_apache_config }}'
+ tags: apache
diff --git a/playbooks/nameservers.yml b/playbooks/nameservers.yml
new file mode 100644
index 0000000..a977744
--- /dev/null
+++ b/playbooks/nameservers.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: authoritative_nameservers
+
+- name: configure nsd
+ hosts: authoritative_nameservers
+ tags: nsd
+ roles:
+ - nsd
diff --git a/playbooks/nfs.yml b/playbooks/nfs.yml
new file mode 100644
index 0000000..a066afb
--- /dev/null
+++ b/playbooks/nfs.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: nfs_servers
+
+- name: configure nfs exports
+ hosts: nfs_servers
+ tags: nfs
+ roles:
+ - nfs_server
diff --git a/playbooks/opnsense.yml b/playbooks/opnsense.yml
new file mode 100644
index 0000000..dd23a91
--- /dev/null
+++ b/playbooks/opnsense.yml
@@ -0,0 +1,17 @@
+- name: configure opnsense firewall
+ hosts: opnsense_firewalls
+ gather_facts: yes
+ vars:
+ unbound_max_negative_cache: 5
+ roles:
+ - freebsd_loader
+ - devd
+ - pxe_server
+ tasks:
+ - name: set unbound negative ttl
+ copy:
+ content: |
+ server:
+ cache-max-negative-ttl: {{ unbound_max_negative_cache }}
+ dest: /usr/local/etc/unbound.opnsense.d/custom.conf
+ tags: unbound
diff --git a/playbooks/photostructure.yml b/playbooks/photostructure.yml
new file mode 100644
index 0000000..12ebe1f
--- /dev/null
+++ b/playbooks/photostructure.yml
@@ -0,0 +1,20 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: photostructure_servers
+
+- name: configure photostructure
+ hosts: photostructure_servers
+ tags: photostructure
+ roles:
+ - role: photostructure
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_config: '{{ photostructure_apache_config }}'
+ tags: apache
+
+ - role: archive_job
+ archive_name: photostructure
+ archive_shell: '{{ photostructure_archive_shell }}'
+ archive_on_calendar: monthly
+ tags: archive
diff --git a/playbooks/populate_domain.yml b/playbooks/populate_domain.yml
new file mode 100644
index 0000000..acb1ec7
--- /dev/null
+++ b/playbooks/populate_domain.yml
@@ -0,0 +1,99 @@
+- name: populate freeipa domain
+ hosts: freeipa_master
+ vars:
+ default_user_password: ChangeMe123!
+ tasks:
+ - name: create users
+ ipauser:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ item.name }}'
+ givenname: '{{ item.givenname }}'
+ sn: '{{ item.sn }}'
+ email: '{{ [item.mail] if item.mail is defined else omit }}'
+ loginshell: '{{ item.loginshell | default(omit) }}'
+ password: '{{ item.password | default(default_user_password) }}'
+ update_password: on_create
+ state: present
+ loop: '{{ freeipa_users | default([]) }}'
+ tags: users
+
+ - name: add custom attributes
+ ldap_attrs:
+ dn: 'uid={{ item.name }},{{ freeipa_user_basedn }}'
+ attributes:
+ mailAlternateAddress: '{{ item.mail_aliases | default([]) }}'
+ jid: '{{ item.jid | default([]) }}'
+ bind_dn: uid={{ ipa_user }},{{ freeipa_user_basedn }}
+ bind_pw: '{{ ipa_pass }}'
+ server_uri: ldaps://{{ ipa_host }}
+ state: exact
+ loop: "{{ freeipa_users | default([]) }}"
+ tags: users
+
+ - name: create groups
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ item.name }}'
+ description: '{{ item.description | default(omit) }}'
+ user: '{{ item.user | default(omit) }}'
+ group: '{{ item.group | default(omit) }}'
+ nonposix: '{{ item.nonposix | default(omit) }}'
+ action: '{{ "member" if (item.append | default(false)) else "group" }}'
+ state: present
+ loop: '{{ freeipa_groups | default([]) }}'
+ tags: groups
+
+ - name: add group email addresses
+ ldap_attrs:
+ dn: 'cn={{ item.name }},{{ freeipa_group_basedn }}'
+ attributes:
+ mail: '{{ item.mail | default([]) }}'
+ mailAlternateAddress: '{{ item.mail_aliases | default([]) }}'
+ bind_dn: uid={{ ipa_user }},{{ freeipa_user_basedn }}
+ bind_pw: '{{ ipa_pass }}'
+ server_uri: ldaps://{{ ipa_host }}
+ state: exact
+ loop: "{{ freeipa_groups | default([]) }}"
+ tags: groups
+
+ - name: create sudo rules
+ ipasudorule:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ item.name }}'
+ description: '{{ item.description | default(omit) }}'
+ allow_sudocmd: '{{ item.cmd | default(omit) }}'
+ cmdcategory: '{{ item.cmdcategory | default(omit) }}'
+ allow_sudocmdgroup: '{{ item.cmdgroup | default(omit) }}'
+ host: '{{ item.host | default(omit) }}'
+ hostcategory: '{{ item.hostcategory | default(omit) }}'
+ hostgroup: '{{ item.hostgroup | default(omit) }}'
+ runasusercategory: '{{ item.runasusercategory | default(omit) }}'
+ runasgroupcategory: '{{ item.runasgroupcategory | default(omit) }}'
+ user: '{{ item.user | default(omit) }}'
+ usercategory: '{{ item.usercategory | default(omit) }}'
+ group: '{{ item.usergroup | default(omit) }}'
+ state: present
+ loop: '{{ freeipa_sudo_rules | default([]) }}'
+ tags: sudo
+
+ - name: create hbac rules
+ ipahbacrule:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ item.name }}'
+ description: '{{ item.description | default(omit) }}'
+ host: '{{ item.host | default(omit) }}'
+ hostcategory: '{{ item.hostcategory | default(omit) }}'
+ hostgroup: '{{ item.hostgroup | default(omit) }}'
+ hbacsvc: '{{ item.service | default(omit) }}'
+ servicecategory: '{{ item.servicecategory | default(omit) }}'
+ hbacsvcgroup: '{{ item.servicegroup | default(omit) }}'
+ user: '{{ item.user | default(omit) }}'
+ usercategory: '{{ item.usercategory | default(omit) }}'
+ group: '{{ item.usergroup | default(omit) }}'
+ state: present
+ loop: '{{ freeipa_hbac_rules | default([]) }}'
+ tags: hbac
diff --git a/playbooks/postgres.yml b/playbooks/postgres.yml
new file mode 100644
index 0000000..72192ec
--- /dev/null
+++ b/playbooks/postgres.yml
@@ -0,0 +1,15 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: postgresql_servers
+
+- name: configure postgresql
+ hosts: postgresql_servers
+ tags: postgres,postgresql
+ roles:
+ - role: postgresql_server
+
+ - role: archive_job
+ archive_name: postgres
+ archive_user: '{{ postgresql_user }}'
+ archive_shell: '{{ postgresql_archive_shell }}'
+ tags: archive
diff --git a/playbooks/privbrowse.yml b/playbooks/privbrowse.yml
new file mode 100644
index 0000000..8b61d5c
--- /dev/null
+++ b/playbooks/privbrowse.yml
@@ -0,0 +1,33 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: privbrowse_servers
+
+- name: configure web service frontends
+ hosts: privbrowse_servers
+ roles:
+ - role: invidious
+ tags: invidious
+
+ - role: apache_vhost
+ apache_server_name: '{{ invidious_server_name }}'
+ apache_server_aliases: []
+ apache_config: '{{ invidious_apache_config }}'
+ tags: apache
+
+ - role: teddit
+ tags: teddit
+
+ - role: apache_vhost
+ apache_server_name: '{{ teddit_server_name }}'
+ apache_server_aliases: []
+ apache_config: '{{ teddit_apache_config }}'
+ tags: apache
+
+ - role: nitter
+ tags: nitter
+
+ - role: apache_vhost
+ apache_server_name: '{{ nitter_server_name }}'
+ apache_server_aliases: []
+ apache_config: '{{ nitter_apache_config }}'
+ tags: apache
diff --git a/playbooks/proxmox.yml b/playbooks/proxmox.yml
new file mode 100644
index 0000000..9c449a4
--- /dev/null
+++ b/playbooks/proxmox.yml
@@ -0,0 +1,21 @@
+- name: configure proxmox hypervisor
+ hosts: proxmox_hypervisors
+ gather_facts: yes
+ roles:
+ - role: root_password
+ tags: root_password
+
+ - role: root_authorized_keys
+ tags: ssh,authorized_keys
+
+ - role: journald
+ tags: journald
+
+ - role: hostname
+ tags: hostname
+
+ - role: timezone
+ tags: timezone
+
+ - role: proxmox_hypervisor
+ tags: proxmox,pve
diff --git a/playbooks/proxmox_instance.yml b/playbooks/proxmox_instance.yml
new file mode 100644
index 0000000..f326b4a
--- /dev/null
+++ b/playbooks/proxmox_instance.yml
@@ -0,0 +1,5 @@
+- name: build proxmox virtual machine
+ hosts: proxmox_instances
+ tags: proxmox
+ roles:
+ - proxmox_instance
diff --git a/playbooks/radius.yml b/playbooks/radius.yml
new file mode 100644
index 0000000..6529365
--- /dev/null
+++ b/playbooks/radius.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: radius_servers
+
+- name: configure freeradius
+ hosts: radius_servers
+ tags: freeradius,radius
+ roles:
+ - freeradius
diff --git a/playbooks/site.yml b/playbooks/site.yml
new file mode 100644
index 0000000..d4bcd11
--- /dev/null
+++ b/playbooks/site.yml
@@ -0,0 +1,37 @@
+# internal hosts
+- import_playbook: opnsense.yml
+- import_playbook: proxmox.yml
+- import_playbook: freeipa_bootstrap.yml
+- import_playbook: dns_records.yml
+- import_playbook: yum.yml
+- import_playbook: freeipa.yml
+- import_playbook: archiver.yml
+- import_playbook: syslog.yml
+- import_playbook: mail.yml
+- import_playbook: cups.yml
+- import_playbook: radius.yml
+- import_playbook: unifi.yml
+- import_playbook: postgres.yml
+- import_playbook: dav.yml
+- import_playbook: bitwarden.yml
+- import_playbook: ttrss.yml
+- import_playbook: znc.yml
+- import_playbook: git.yml
+- import_playbook: wiki.yml
+- import_playbook: jellyfin.yml
+- import_playbook: privbrowse.yml
+- import_playbook: populate_domain.yml
+- import_playbook: syncthing.yml
+- import_playbook: photostructure.yml
+- import_playbook: nfs.yml
+- import_playbook: webserver_internal.yml
+- import_playbook: dev_servers.yml
+- import_playbook: linux_desktops.yml
+- import_playbook: nagios.yml
+
+# public-facing hosts
+- import_playbook: nameservers.yml
+- import_playbook: webserver_public.yml
+- import_playbook: turn.yml
+- import_playbook: xmpp.yml
+- import_playbook: asterisk.yml
diff --git a/playbooks/syncthing.yml b/playbooks/syncthing.yml
new file mode 100644
index 0000000..3fad588
--- /dev/null
+++ b/playbooks/syncthing.yml
@@ -0,0 +1,19 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: syncthing_servers
+
+- name: configure syncthing
+ hosts: syncthing_servers
+ tags: syncthing
+ roles:
+ - role: syncthing
+
+ - role: archive_job
+ archive_name: syncthing
+ archive_shell: '{{ syncthing_archive_shell }}'
+ tags: archive
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_config: '{{ syncthing_apache_config }}'
+ tags: apache
diff --git a/playbooks/syslog.yml b/playbooks/syslog.yml
new file mode 100644
index 0000000..2891dc6
--- /dev/null
+++ b/playbooks/syslog.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: syslog_servers
+
+- name: configure rsyslog server
+ hosts: syslog_servers
+ tags: rsyslog,syslog
+ roles:
+ - rsyslog_server
diff --git a/playbooks/test.yml b/playbooks/test.yml
new file mode 100644
index 0000000..f3eaa62
--- /dev/null
+++ b/playbooks/test.yml
@@ -0,0 +1,4 @@
+- hosts: all
+ tasks:
+ - debug:
+ var: vlan
diff --git a/playbooks/ttrss.yml b/playbooks/ttrss.yml
new file mode 100644
index 0000000..befd157
--- /dev/null
+++ b/playbooks/ttrss.yml
@@ -0,0 +1,21 @@
+- import_playbook: common.yml
+ tags: common
+ vars:
+ hostlist: ttrss_servers
+
+- name: configure tinytinyrss
+ hosts: ttrss_servers
+ tags: ttrss
+ roles:
+ - role: ttrss
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_canonical_hostname: '{{ ttrss_server_name }}'
+ apache_document_root: '{{ ttrss_home }}'
+ apache_config: '{{ ttrss_apache_config }}'
+ tags: apache
+
+ - role: php
+ php_fpm_environment: '{{ ttrss_php_environment }}'
+ tags: php
diff --git a/playbooks/turn.yml b/playbooks/turn.yml
new file mode 100644
index 0000000..20b6196
--- /dev/null
+++ b/playbooks/turn.yml
@@ -0,0 +1,10 @@
+- import_playbook: common.yml
+ tags: common
+ vars:
+ hostlist: turn_servers
+
+- name: configure coturn
+ hosts: turn_servers
+ tags: coturn,turn
+ roles:
+ - role: coturn
diff --git a/playbooks/unifi.yml b/playbooks/unifi.yml
new file mode 100644
index 0000000..1b0864d
--- /dev/null
+++ b/playbooks/unifi.yml
@@ -0,0 +1,15 @@
+- import_playbook: common.yml
+ tags: common
+ vars:
+ hostlist: unifi_controllers
+
+- name: configure unifi controller
+ hosts: unifi_controllers
+ tags: unifi
+ roles:
+ - role: unifi
+
+ - role: archive_job
+ archive_name: unifi
+ archive_shell: '{{ unifi_archive_shell }}'
+ tags: archive
diff --git a/playbooks/util/backup.yml b/playbooks/util/backup.yml
new file mode 100644
index 0000000..0c99eea
--- /dev/null
+++ b/playbooks/util/backup.yml
@@ -0,0 +1,606 @@
+#################
+# Set backup name
+#################
+- hosts: localhost
+ tags: always
+ tasks:
+ - name: get current timestamp
+ setup:
+ filter: ansible_date_time
+
+ - name: create backup directory
+ file:
+ path: '{{ backup_path }}'
+ state: directory
+
+- hosts: all:localhost:!unmanaged
+ tags: always
+ tasks:
+ - name: set backup name
+ set_fact:
+ backup_name: '{{ backup_name | default(hostvars.localhost.ansible_date_time.iso8601_basic_short) }}'
+
+
+################
+# IMAP Mailboxes
+################
+- name: backup dovecot mailboxes
+ hosts: imap_servers
+ vars_files: ../../roles/dovecot/vars/main.yml
+ vars:
+ dovecot_backup_dir: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-mailboxes
+ dovecot_backup_tarball: '{{ dovecot_backup_dir }}.tar.gz'
+ dovecot_backup_sieve_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-sieve.tar.gz
+ tags: dovecot,imap
+ tasks:
+ - name: create backup directory
+ file:
+ path: '{{ dovecot_backup_dir }}'
+ owner: '{{ dovecot_vmail_user }}'
+ group: '{{ dovecot_vmail_user }}'
+ mode: 0770
+ state: directory
+
+ - name: collect dovecot users
+ command: doveadm user *
+ register: dovecot_users
+ changed_when: no
+
+ - name: export mailboxes
+ command: >-
+ doveadm -o plugin/quota= backup -n inbox -f -u {{ item | quote }}
+ mdbox:{{ dovecot_backup_dir | quote }}/{{ item | quote }}/mdbox:LAYOUT=fs
+ loop: '{{ dovecot_users.stdout_lines }}'
+
+ - name: compress backup directory
+ archive:
+ path: '{{ dovecot_backup_dir }}'
+ dest: '{{ dovecot_backup_tarball }}'
+ mode: 0400
+ remove: yes
+
+ - name: fetch mailbox tarball
+ fetch:
+ src: '{{ dovecot_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete mailbox tarball from remote host
+ file:
+ path: '{{ dovecot_backup_tarball }}'
+ state: absent
+
+ - name: compress sieve scripts
+ archive:
+ path:
+ - '{{ dovecot_vmail_dir }}/*/sieve'
+ - '{{ dovecot_vmail_dir }}/*/.dovecot.sieve'
+ dest: '{{ dovecot_backup_sieve_tarball }}'
+ mode: 0400
+
+ - name: fetch sieve tarball
+ fetch:
+ src: '{{ dovecot_backup_sieve_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete sieve tarball from remote host
+ file:
+ path: '{{ dovecot_backup_sieve_tarball }}'
+ state: absent
+
+
+##################
+# Rspamd Databases
+##################
+- name: backup rspamd databases
+ hosts: rspamd_servers
+ vars_files:
+ - ../../roles/redis/vars/main.yml
+ - ../../roles/rspamd/vars/main.yml
+ vars:
+ rspamd_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-rspamd.tar.gz
+ tags: rspamd
+ tasks:
+ - name: dump redis databases to disk
+ command:
+ cmd: redis-cli -p {{ item }}
+ stdin: save
+ loop:
+ - '{{ rspamd_redis_port }}'
+ - '{{ rspamd_redis_bayes_port }}'
+
+ - name: compress redis directory
+ archive:
+ path: '{{ redis_home }}'
+ dest: '{{ rspamd_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ rspamd_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ rspamd_backup_tarball }}'
+ state: absent
+
+
+###################
+# ZNC Configuration
+###################
+- name: backup znc configuration
+ hosts: znc_servers
+ vars_files: ../../roles/znc/vars/main.yml
+ vars:
+ znc_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-znc.tar.gz
+ tags: znc
+ tasks:
+ - name: compress znc directory
+ archive:
+ path: '{{ znc_home }}'
+ dest: '{{ znc_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ znc_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ znc_backup_tarball }}'
+ state: absent
+
+
+#########################
+# Syncthing Configuration
+#########################
+- name: backup syncthing configuration
+ hosts: syncthing_servers
+ vars_files: ../../roles/syncthing/vars/main.yml
+ vars:
+ syncthing_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-syncthing.tar.gz
+ tags: syncthing
+ tasks:
+ - name: compress syncthing directory
+ archive:
+ path: '{{ syncthing_home }}'
+ dest: '{{ syncthing_backup_tarball }}'
+ exclusion_patterns:
+ - '*/index-*.db*'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ syncthing_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ syncthing_backup_tarball }}'
+ state: absent
+
+
+##################
+# Git Repositories
+##################
+- name: backup git respositories
+ hosts: git_servers
+ vars_files: ../../roles/gitolite/vars/main.yml
+ vars:
+ git_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-git.tar.gz
+ tags: git
+ tasks:
+ - name: compress git directory
+ archive:
+ path: '{{ gitolite_home }}'
+ dest: '{{ git_backup_tarball }}'
+ exclusion_patterns:
+ - git/.ansible*
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ git_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ git_backup_tarball }}'
+ state: absent
+
+
+######################
+# PostgreSQL Databases
+######################
+- name: backup postgresql databases
+ hosts: postgresql_servers
+ vars_files: ../../roles/postgresql_server/vars/main.yml
+ vars:
+ postgresql_backup_file: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-pg_dumpall.sql
+ postgresql_backup_gzip: '{{ postgresql_backup_file }}.gz'
+ tags: postgres,postgresql
+ tasks:
+ - name: dump databases
+ command: pg_dumpall -f {{ postgresql_backup_file | quote }}
+ become: yes
+ become_user: '{{ postgresql_user }}'
+
+ - name: compress sql file
+ archive:
+ path: '{{ postgresql_backup_file }}'
+ dest: '{{ postgresql_backup_gzip }}'
+ mode: 0400
+ remove: yes
+
+ - name: fetch backup gzip
+ fetch:
+ src: '{{ postgresql_backup_gzip }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup gzip from remote
+ file:
+ path: '{{ postgresql_backup_gzip }}'
+ state: absent
+
+
+
+########################
+# Jellyfin Configuration
+########################
+- name: backup jellyfin configuration
+ hosts: jellyfin_servers
+ vars_files: ../../roles/jellyfin/vars/main.yml
+ vars:
+ jellyfin_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-jellyfin.tar.gz
+ tags: jellyfin
+ tasks:
+ - name: compress jellyfin directories
+ archive:
+ path:
+ - '{{ jellyfin_home }}/data'
+ - '{{ jellyfin_home }}/metadata'
+ - '{{ jellyfin_home }}/plugins'
+ - '{{ jellyfin_home }}/root'
+ - '{{ jellyfin_conf_dir }}'
+ dest: '{{ jellyfin_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ jellyfin_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ jellyfin_backup_tarball }}'
+ state: absent
+
+
+##################
+# Mediawiki Images
+##################
+- name: backup mediawiki images
+ hosts: wiki_servers
+ vars_files: ../../roles/mediawiki/vars/main.yml
+ vars:
+ mediawiki_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-mediawiki.tar.gz
+ tags: mediawiki,wiki
+ tasks:
+ - name: compress images directory
+ archive:
+ path: '{{ mediawiki_home }}/images'
+ dest: '{{ mediawiki_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ mediawiki_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ mediawiki_backup_tarball }}'
+ state: absent
+
+
+#########################
+# Photostructure Database
+#########################
+- name: backup photostructure database
+ hosts: photostructure_servers
+ vars_files: ../../roles/photostructure/vars/main.yml
+ vars:
+ photostructure_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-photostructure.tar
+ tags: photostructure
+ tasks:
+ - name: stop photostructure
+ systemd:
+ name: photostructure
+ state: stopped
+
+ - name: archive photostructure library
+ archive:
+ path: '{{ photostructure_library }}'
+ dest: '{{ photostructure_backup_tarball }}'
+ format: tar
+ mode: 0400
+
+ - name: start photostructure
+ systemd:
+ name: photostructure
+ state: started
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ photostructure_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+ validate_checksum: no # The tarball is way too big.
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ photostructure_backup_tarball }}'
+ state: absent
+
+
+###############
+# Asterisk Data
+###############
+- name: backup asterisk data
+ hosts: asterisk_servers
+ vars_files: ../../roles/asterisk/vars/main.yml
+ vars:
+ asterisk_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-asterisk.tar.gz
+ tags: asterisk
+ tasks:
+ - name: stop asterisk
+ systemd:
+ name: asterisk
+ state: stopped
+
+ - name: compress asterisk directory
+ archive:
+ path: '{{ asterisk_data_dir }}'
+ dest: '{{ asterisk_backup_tarball }}'
+ mode: 0400
+
+ - name: start asterisk
+ systemd:
+ name: asterisk
+ state: started
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ asterisk_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ asterisk_backup_tarball }}'
+ state: absent
+
+
+####################
+# Cups Configuration
+####################
+- name: backup cups configuration
+ hosts: cups_servers
+ vars:
+ cups_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-cups.tar.gz
+ tags: cups
+ tasks:
+ - name: compress cups configuration
+ archive:
+ path:
+ - /etc/cups/ppd
+ - /etc/cups/printers.conf
+ dest: '{{ cups_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ cups_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ cups_backup_tarball }}'
+ state: absent
+
+
+####################
+# WebDAV Directories
+####################
+- name: backup webdav directories
+ hosts: dav_servers
+ vars_files: ../../roles/sabredav/vars/main.yml
+ vars:
+ sabredav_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-webdav.tar.gz
+ tags: dav,sabredav,webdav
+ tasks:
+ - name: compress webdav directory
+ archive:
+ path: '{{ sabredav_home }}/webdav'
+ dest: '{{ sabredav_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ sabredav_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ sabredav_backup_tarball }}'
+ state: absent
+
+
+###############
+# Hastebin Data
+###############
+- name: backup hastebin data
+ hosts: pastebin_servers
+ vars_files: ../../roles/hastebin/vars/main.yml
+ vars:
+ hastebin_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-hastebin.tar.gz
+ tags: pastebin,hastebin
+ tasks:
+ - name: compress paste directory
+ archive:
+ path: '{{ hastebin_data_dir }}'
+ dest: '{{ hastebin_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ hastebin_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ hastebin_backup_tarball }}'
+ state: absent
+
+
+##################
+# Psitransfer Data
+##################
+- name: backup psitransfer data
+ hosts: filedrop_servers
+ vars_files: ../../roles/psitransfer/vars/main.yml
+ vars:
+ psitransfer_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-psitransfer.tar.gz
+ tags: psitransfer
+ tasks:
+ - name: compress files directory
+ archive:
+ path: '{{ psitransfer_data_dir }}'
+ dest: '{{ psitransfer_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ psitransfer_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ psitransfer_backup_tarball }}'
+ state: absent
+
+
+##################
+# Apache WWW files
+##################
+- name: backup public apache files
+ hosts: web_servers
+ vars_files:
+ - ../../roles/apache/vars/main.yml
+ vars:
+ apache_backup_tarball: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-www.tar.gz
+ tags: apache,www
+ tasks:
+ - when: apache_backup_dirs | default([]) | length > 0
+ block:
+ - name: compress www directory
+ archive:
+ path: "{{ apache_backup_dirs | map('regex_replace', '^', apache_public_dir~'/') }}"
+ dest: '{{ apache_backup_tarball }}'
+ mode: 0400
+
+ - name: fetch backup tarball
+ fetch:
+ src: '{{ apache_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup tarball from remote host
+ file:
+ path: '{{ apache_backup_tarball }}'
+ state: absent
+
+
+####################
+# Unifi Controllers
+####################
+- name: backup unifi controllers
+ hosts: unifi_controllers
+ vars_files: ../../roles/unifi/vars/main.yml
+ tags: unifi
+ tasks:
+ - name: collect autobackup files
+ find:
+ paths: '{{ unifi_autobackup_dir }}'
+ patterns: '*.unf'
+ file_type: file
+ register: unifi_autobackups
+
+ - name: fetch most recent autobackup file
+ fetch:
+ src: "{{ unifi_autobackups.files | sort(attribute='mtime') | map(attribute='path') | last }}"
+ dest: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-unifi.unf'
+ flat: yes
+
+
+################
+# FreeIPA Domain
+################
+- name: backup freeipa domain
+ hosts: freeipa_master
+ vars_files: ../../roles/freeipa_server/vars/main.yml
+ vars:
+ freeipa_backup_tarball: /var/tmp/{{ backup_name }}-ipa-{{ freeipa_realm }}.tar.gz
+ tags: ipa,freeipa
+ tasks:
+ - name: create full ipa backup
+ command: ipa-backup
+
+ - name: collect files in backup directory
+ find:
+ paths: '{{ freeipa_backup_dir }}'
+ patterns: ipa-full-*
+ file_type: directory
+ register: freeipa_backups
+
+ - name: compress latest backup
+ archive:
+ path: "{{ freeipa_backups.files | sort(attribute='mtime') | map(attribute='path') | last }}"
+ dest: '{{ freeipa_backup_tarball }}'
+ mode: 0400
+ remove: yes
+
+ - name: fetch backup archive
+ fetch:
+ src: '{{ freeipa_backup_tarball }}'
+ dest: '{{ backup_path }}/'
+ flat: yes
+
+ - name: delete backup archive from remote host
+ file:
+ path: '{{ freeipa_backup_tarball }}'
+ state: absent
+
+
+###############
+# Print summary
+###############
+- hosts: localhost
+ tags: always
+ tasks:
+ - debug:
+ msg: Backup {{ backup_name }} written to {{ backup_path }}.
diff --git a/playbooks/util/client_cert.yml b/playbooks/util/client_cert.yml
new file mode 100644
index 0000000..c81b298
--- /dev/null
+++ b/playbooks/util/client_cert.yml
@@ -0,0 +1,71 @@
+- name: generate client certificate
+ hosts: localhost
+ connection: local
+ become: no
+ vars_prompt:
+ - name: username
+ prompt: Enter username for the certificate subject
+ private: no
+ - name: passphrase
+ prompt: Enter password for the p12 file
+ private: yes
+ vars:
+ cert_dir: "{{ lookup('env', 'HOME') }}/pki"
+ key_size: 2048
+ key_path: '{{ cert_dir }}/{{ username }}.key'
+ csr_path: '{{ cert_dir }}/{{ username }}.csr'
+ crt_path: '{{ cert_dir }}/{{ username }}.crt'
+ p12_path: '{{ cert_dir }}/{{ username }}.p12'
+ profile_id: caIPAclientAuth
+ tasks:
+ - name: create output directory
+ file:
+ path: '{{ cert_dir }}'
+ state: directory
+
+ - name: generate private key
+ openssl_privatekey:
+ path: '{{ key_path }}'
+ size: '{{ key_size }}'
+ mode: 0600
+
+ - name: generate CSR
+ openssl_csr:
+ path: '{{ csr_path }}'
+ privatekey_path: '{{ key_path }}'
+ common_name: '{{ username }}'
+ use_common_name_for_san: no
+
+ - name: request certificate from IPA
+ shell:
+ cmd: >
+ ipa cert-request {{ csr_path }}
+ --principal {{ username }}
+ --profile-id {{ profile_id }}
+ --chain
+ --certificate-out {{ crt_path }}
+
+ # The openssl_pkcs12 ansible module seems to generate files that can't be
+ # decrypted by Android clients. The openssl CLI works fine though.
+ - name: generate PKCS#12 file
+ command:
+ cmd: >
+ openssl pkcs12 -export
+ -out {{ p12_path }}
+ -inkey {{ key_path }}
+ -in {{ crt_path }}
+ -name {{ username }}@{{ domain }}
+ -password pass:{{ passphrase | quote }}
+ creates: '{{ p12_path }}'
+
+ - name: cleanup files
+ file:
+ path: '{{ item }}'
+ state: absent
+ loop:
+ - '{{ key_path }}'
+ - '{{ csr_path }}'
+ - '{{ crt_path }}'
+
+ - debug:
+ msg: 'PKCS#12 file written to {{ p12_path }}. Passphrase: {{ passphrase }}'
diff --git a/playbooks/util/decomission_host.yml b/playbooks/util/decomission_host.yml
new file mode 100644
index 0000000..dae4b16
--- /dev/null
+++ b/playbooks/util/decomission_host.yml
@@ -0,0 +1,56 @@
+- name: decomission host
+ hosts: '{{ host }}'
+ tasks:
+ - name: delete A record
+ ipadnsrecord:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ zone_name: '{{ domain }}'
+ record_name: '{{ host }}'
+ record_type: A
+ record_value: '{{ ip }}'
+ state: absent
+ delegate_to: '{{ freeipa_master }}'
+
+ - name: delete PTR record
+ ipadnsrecord:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ zone_name: "{{ ip | ansible.utils.ipaddr('revdns') | regex_replace('^[^.]+\\.', '') }}"
+ record_name: '{{ ip.split(".") | last }}'
+ record_type: PTR
+ record_value: '{{ fqdn ~ "." }}'
+ state: absent
+ delegate_to: '{{ freeipa_master }}'
+
+ - name: delete CNAME records
+ ipadnsrecord:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ zone_name: "{{ domain }}"
+ record_name: '{{ item.split(".") | first }}'
+ record_type: CNAME
+ record_value: '{{ fqdn ~ "." }}'
+ state: absent
+ delegate_to: '{{ freeipa_master }}'
+ loop: '{{ cnames }}'
+
+ - name: delete host object
+ ipahost:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ fqdn }}'
+ state: absent
+ delegate_to: '{{ ipa_host }}'
+
+ - name: delete proxmox vm
+ proxmox_kvm:
+ node: '{{ proxmox_node }}'
+ api_host: localhost
+ api_user: '{{ proxmox_api_user }}'
+ api_password: '{{ proxmox_api_password }}'
+ name: '{{ inventory_hostname }}'
+ force: yes
+ state: absent
+ delegate_to: '{{ proxmox_api_host }}'
+ when: "'proxmox_instances' in group_names"
diff --git a/playbooks/util/restore.yml b/playbooks/util/restore.yml
new file mode 100644
index 0000000..3a0154c
--- /dev/null
+++ b/playbooks/util/restore.yml
@@ -0,0 +1,477 @@
+################
+# IMAP Mailboxes
+################
+- name: restore dovecot mailboxes
+ hosts: imap_servers
+ vars_files: ../../roles/dovecot/vars/main.yml
+ vars:
+ dovecot_temp_dir: /var/tmp/{{ backup_name }}-{{ inventory_hostname }}-mailboxes
+ dovecot_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-mailboxes.tar.gz'
+ dovecot_backup_sieve_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-sieve.tar.gz'
+ tags: dovecot,imap
+ tasks:
+ - name: create temporary directory
+ file:
+ path: '{{ dovecot_temp_dir }}'
+ owner: '{{ dovecot_vmail_user }}'
+ group: '{{ dovecot_vmail_user }}'
+ mode: 0770
+ state: directory
+
+ - name: extract mailbox tarball
+ unarchive:
+ src: '{{ dovecot_backup_tarball }}'
+ dest: '{{ dovecot_temp_dir }}'
+ extra_opts:
+ - --same-owner
+ - --strip-components=1
+
+ - name: collect dovecot users
+ command: doveadm user *
+ register: dovecot_users
+ changed_when: no
+
+ - name: import mailboxes
+ command: >-
+ doveadm -o plugin/quota= sync -u {{ item | quote }}
+ mdbox:{{ dovecot_temp_dir }}/{{ item | quote }}/mdbox
+ loop: '{{ dovecot_users.stdout_lines }}'
+
+ - name: drop FTS indexes
+ command: doveadm fts rescan -A
+
+ - name: reindex mailboxes
+ command: doveadm index -A -q *
+
+ - name: delete temporary directory
+ file:
+ path: '{{ dovecot_temp_dir }}'
+ state: absent
+
+ - name: extract sieve scripts
+ unarchive:
+ src: '{{ dovecot_backup_sieve_tarball }}'
+ dest: '{{ dovecot_vmail_dir }}'
+ extra_opts:
+ - --same-owner
+
+
+##################
+# Rspamd Databases
+##################
+- name: restore rspamd databases
+ hosts: rspamd_servers
+ vars_files:
+ - ../../roles/redis/vars/main.yml
+ - ../../roles/rspamd/vars/main.yml
+ vars:
+ rspamd_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-rspamd.tar.gz'
+ tags: rspamd
+ tasks:
+ - name: stop redis instances
+ systemd:
+ name: redis@{{ item }}
+ state: stopped
+ loop:
+ - '{{ rspamd_redis_port }}'
+ - '{{ rspamd_redis_bayes_port }}'
+
+ - name: stop rspamd
+ systemd:
+ name: rspamd
+ state: stopped
+
+ - name: extract redis tarballs
+ unarchive:
+ src: '{{ rspamd_backup_tarball }}'
+ dest: '{{ redis_home }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: start redis instances
+ systemd:
+ name: redis@{{ item }}
+ state: started
+ loop:
+ - '{{ rspamd_redis_port }}'
+ - '{{ rspamd_redis_bayes_port }}'
+
+ - name: start rspamd
+ systemd:
+ name: rspamd
+ state: started
+
+
+###################
+# ZNC Configuration
+###################
+- name: restore znc configuration
+ hosts: znc_servers
+ vars_files: ../../roles/znc/vars/main.yml
+ vars:
+ znc_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-znc.tar.gz'
+ tags: znc
+ tasks:
+ - name: stop znc
+ systemd:
+ name: znc
+ state: stopped
+
+ - name: extract config tarball
+ unarchive:
+ src: '{{ znc_backup_tarball }}'
+ dest: '{{ znc_home }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: start znc
+ systemd:
+ name: znc
+ state: started
+
+
+#########################
+# Syncthing Configuration
+#########################
+- name: restore syncthing configuration
+ hosts: syncthing_servers
+ vars_files: ../../roles/syncthing/vars/main.yml
+ vars:
+ syncthing_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-syncthing.tar.gz'
+ tags: syncthing
+ tasks:
+ - name: stop syncthing daemons
+ command: systemctl stop syncthing-user@*
+
+ - name: extract config tarball
+ unarchive:
+ src: '{{ syncthing_backup_tarball }}'
+ dest: '{{ syncthing_home }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: collect syncthing users
+ find:
+ paths: '{{ syncthing_home }}'
+ recurse: no
+ file_type: directory
+ register: syncthing_users
+
+ - name: start syncthing daemons
+ systemd:
+ name: syncthing-user@{{ item }}
+ state: started
+ loop: "{{ syncthing_users.files | map(attribute='path') | map('basename') }}"
+
+
+##################
+# Git Repositories
+##################
+- name: restore git repositories
+ hosts: git_servers
+ vars_files:
+ - ../../roles/gitolite/vars/main.yml
+ - ../../roles/cgit/vars/main.yml
+ vars:
+ git_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-git.tar.gz'
+ tags: git
+ tasks:
+ - name: extract git tarball
+ unarchive:
+ src: '{{ git_backup_tarball }}'
+ dest: '{{ gitolite_home }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: clear cgit cache
+ file:
+ path: '{{ cgit_cache_dir }}'
+ owner: apache
+ mode: 0755
+ setype: _default
+ state: '{{ item }}'
+ loop:
+ - absent
+ - directory
+
+
+######################
+# PostgreSQL Databases
+######################
+- name: restore postgresql databases
+ hosts: postgresql_servers
+ vars_files: ../../roles/postgresql_server/vars/main.yml
+ vars:
+ postgresql_backup_gzip: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-pg_dumpall.sql.gz'
+ postgresql_remote_gzip: /var/tmp/{{ postgresql_backup_gzip | basename }}
+ tags: postgres,postgresql
+ tasks:
+ - name: copy backup gzip to remote host
+ copy:
+ src: '{{ postgresql_backup_gzip }}'
+ dest: '{{ postgresql_remote_gzip }}'
+ owner: '{{ postgresql_user }}'
+ group: '{{ postgresql_user }}'
+ mode: 0400
+
+ - name: import database backup
+ shell: gunzip {{ postgresql_remote_gzip | quote }} --to-stdout | psql
+ become: yes
+ become_user: '{{ postgresql_user }}'
+
+ - name: delete gzip file from remote host
+ file:
+ path: '{{ postgresql_remote_gzip }}'
+ state: absent
+
+
+########################
+# Jellyfin Configuration
+########################
+- name: restore jellyfin configuration
+ hosts: jellyfin_servers
+ vars_files: ../../roles/jellyfin/vars/main.yml
+ vars:
+ jellyfin_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-jellyfin.tar.gz'
+ tags: jellyfin
+ tasks:
+ - name: stop jellyfin
+ systemd:
+ name: jellyfin
+ state: stopped
+
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ jellyfin_backup_tarball }}'
+ dest: /
+ extra_opts:
+ - --same-owner
+
+ - name: start jellyfin
+ systemd:
+ name: jellyfin
+ state: started
+
+
+##################
+# Mediawiki Images
+##################
+- name: restore mediawiki images
+ hosts: wiki_servers
+ vars_files: ../../roles/mediawiki/vars/main.yml
+ vars:
+ mediawiki_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-mediawiki.tar.gz'
+ tags: mediawiki,wiki
+ tasks:
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ mediawiki_backup_tarball }}'
+ dest: '{{ mediawiki_home }}/images'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+
+#########################
+# Photostructure Database
+#########################
+- name: restore photostructure database
+ hosts: photostructure_servers
+ vars_files:
+ - ../../roles/photostructure/vars/main.yml
+ vars:
+ photostructure_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-photostructure.tar'
+ tags: photostructure
+ tasks:
+ - name: stop photostructure
+ systemd:
+ name: photostructure
+ state: stopped
+
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ photostructure_backup_tarball }}'
+ dest: '{{ photostructure_library }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: start photostructure
+ systemd:
+ name: photostructure
+ state: started
+
+
+####################
+# Cups Configuration
+####################
+- name: restore cups configuration
+ hosts: cups_servers
+ vars:
+ cups_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-cups.tar.gz'
+ tags: cups
+ tasks:
+ - name: stop cups
+ systemd:
+ name: cups
+ state: stopped
+
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ cups_backup_tarball }}'
+ dest: /etc/cups
+ extra_opts:
+ - --same-owner
+
+ - name: start cups
+ systemd:
+ name: cups
+ state: started
+
+
+###############
+# Asterisk Data
+###############
+- name: restore asterisk data
+ hosts: asterisk_servers
+ vars_files: ../../roles/asterisk/vars/main.yml
+ vars:
+ asterisk_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-asterisk.tar.gz'
+ tags: asterisk
+ tasks:
+ - name: stop asterisk
+ systemd:
+ name: asterisk
+ state: stopped
+
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ asterisk_backup_tarball }}'
+ dest: '{{ asterisk_data_dir }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: start asterisk
+ systemd:
+ name: asterisk
+ state: started
+
+
+####################
+# WebDAV Directories
+####################
+- name: restore webdav directories
+ hosts: dav_servers
+ vars_files: ../../roles/sabredav/vars/main.yml
+ vars:
+ sabredav_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-webdav.tar.gz'
+ tags: sabredav,dav,webdav
+ tasks:
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ sabredav_backup_tarball }}'
+ dest: '{{ sabredav_home }}/webdav'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+
+###############
+# Hastebin Data
+###############
+- name: restore hastebin data
+ hosts: pastebin_servers
+ vars_files: ../../roles/hastebin/vars/main.yml
+ vars:
+ hastebin_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-hastebin.tar.gz'
+ tags: hastebin,pastebin
+ tasks:
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ hastebin_backup_tarball }}'
+ dest: '{{ hastebin_data_dir }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+
+##################
+# Psitransfer Data
+##################
+- name: restore psitransfer data
+ hosts: filedrop_servers
+ vars_files: ../../roles/psitransfer/vars/main.yml
+ vars:
+ psitransfer_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-psitransfer.tar.gz'
+ tags: psitransfer
+ tasks:
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ psitransfer_backup_tarball }}'
+ dest: '{{ psitransfer_data_dir }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+
+##################
+# Apache WWW Files
+##################
+- name: restore public apache files
+ hosts: web_servers
+ vars_files: ../../roles/apache/vars/main.yml
+ vars:
+ apache_backup_tarball: '{{ backup_path }}/{{ backup_name }}-{{ inventory_hostname }}-www.tar.gz'
+ tags: apache,www
+ tasks:
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ apache_backup_tarball }}'
+ dest: '{{ apache_public_dir }}'
+ extra_opts:
+ - --same-owner
+
+
+################
+# FreeIPA Domain
+################
+- name: restore freeipa domain
+ hosts: freeipa_master
+ vars_files: ../../roles/freeipa_server/vars/main.yml
+ vars:
+ freeipa_backup_tarball: '{{ backup_path }}/{{ backup_name }}-ipa-{{ freeipa_realm }}.tar.gz'
+ freeipa_remote_backup_path: '{{ freeipa_backup_dir }}/{{ backup_name }}'
+ tags: ipa,freeipa
+ tasks:
+ # Only restore FreeIPA when explicitly requested - it is quite disruptive.
+ - when: ansible_run_tags | intersect(['ipa','freeipa']) | length > 0
+ block:
+ - name: create backup directory on remote host
+ file:
+ path: '{{ freeipa_remote_backup_path }}'
+ state: directory
+ mode: 0700
+
+ - name: extract backup tarball
+ unarchive:
+ src: '{{ freeipa_backup_tarball }}'
+ dest: '{{ freeipa_remote_backup_path }}'
+ extra_opts:
+ - --strip-components=1
+ - --same-owner
+
+ - name: restore freeipa domain from backup
+ command: ipa-restore {{ backup_name | quote }} --unattended --password={{ freeipa_ds_password | quote }}
+
+ - name: clear sssd cache
+ command: sss_cache -E
+
+ - name: delete backup files from remote host
+ file:
+ path: '{{ freeipa_remote_backup_path }}'
+ state: absent
diff --git a/playbooks/util/wireguard_config.yml b/playbooks/util/wireguard_config.yml
new file mode 100644
index 0000000..fb98ca4
--- /dev/null
+++ b/playbooks/util/wireguard_config.yml
@@ -0,0 +1,49 @@
+- name: generate client certificate
+ hosts: localhost
+ connection: local
+ become: no
+ vars_prompt:
+ - name: client_ip
+ prompt: Enter client ip address
+ private: no
+ vars:
+ config_path: "{{ lookup('env', 'HOME') }}/{{ organization | replace(' ', '-') | lower }}-wg.conf"
+ server_pubkey: '{{ wireguard_pubkey }}'
+ server_port: '{{ wireguard_port | default(51820) }}'
+ server_host: '{{ wireguard_host }}'
+ gateway: '{{ vlans.vpn.gateway }}'
+ dns_server: "{{ vlans.vpn.dns_servers | join(',') }}"
+ tasks:
+ - name: generate private key
+ command:
+ cmd: wg genkey
+ register: wg_genkey
+ changed_when: no
+
+ - name: generate public key
+ command:
+ cmd: wg pubkey
+ stdin: '{{ wg_genkey.stdout }}'
+ register: wg_pubkey
+ changed_when: no
+
+ - name: generate wireguard config file
+ copy:
+ dest: '{{ config_path }}'
+ mode: 0600
+ content: |
+ [Interface]
+ Address = {{ client_ip }}/32
+ PrivateKey = {{ wg_genkey.stdout }}
+ DNS = {{ dns_server }}
+
+ [Peer]
+ PublicKey = {{ server_pubkey }}
+ AllowedIPs = 0.0.0.0/0
+ Endpoint = {{ server_host }}:{{ server_port }}
+
+ - debug:
+ msg: 'wireguard client config written to {{ config_path }}'
+
+ - debug:
+ msg: 'Add the following client to the wireguard server: {{ client_ip }}/32 {{ wg_pubkey.stdout }}'
diff --git a/playbooks/webserver_internal.yml b/playbooks/webserver_internal.yml
new file mode 100644
index 0000000..eb27c97
--- /dev/null
+++ b/playbooks/webserver_internal.yml
@@ -0,0 +1,46 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: www1
+
+- name: configure internal web servers
+ hosts: www1
+ tags: apache
+ roles:
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_config: |
+ AliasMatch "^/pub/user/([^/]+)(.*)" "/nfs/user/$1/pub$2"
+ AliasMatch "^/pub/group/([^/]+)(.*)" "/nfs/group/$1/pub$2"
+
+ <Directory "/nfs/user">
+ Options -FollowSymLinks +Indexes
+ AllowOverride None
+ Require all granted
+ </Directory>
+
+ <Directory "/nfs/group">
+ Options -FollowSymLinks +Indexes
+ AllowOverride None
+ Require all granted
+ </Directory>
+ tasks:
+ - name: generate index.html
+ tags: apache
+ copy:
+ dest: /var/www/html/index.html
+ content: |
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <title>{{ domain }} webserver</title>
+ </head>
+ <body>
+ <p>This is the {{ organization }} internal webserver. To access files in user or group
+ public directories, try paths like the following:
+ <ul>
+ <li><tt><a href="/pub/user/username/">/pub/user/username</a></tt></li>
+ <li><tt><a href="/pub/group/groupname/">/pub/group/groupname</a></tt></li>
+ </ul>
+ </body
+ </html>
diff --git a/playbooks/webserver_public.yml b/playbooks/webserver_public.yml
new file mode 100644
index 0000000..17221e6
--- /dev/null
+++ b/playbooks/webserver_public.yml
@@ -0,0 +1,38 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: dmz-www1
+
+- name: configure public web server
+ hosts: dmz-www1
+ roles:
+ - role: apache_vhost
+ apache_server_name: www.example.com
+ apache_server_aliases: [example.com]
+ apache_canonical_hostname: www.example.com
+ apache_letsencrypt: yes
+ apache_document_root: /var/www/www.example.com
+ tags: apache
+
+ - role: archive_job
+ tags: archive
+ archive_name: www
+ archive_shell: >-
+ TIMESTAMP=$(date +%Y%m%d%H%M%S);
+ tar czf "www-${TIMESTAMP}.tar.gz"
+ --transform "s|^\.|www-${TIMESTAMP}|"
+ -C "{{ apache_public_dir }}" {% for dir in apache_backup_dirs %}{{ dir | quote }} {% endfor %}
+
+ # prosody letsencrypt proxy
+ - role: prosody_letsencrypt_proxy
+ prosody_le_role: master
+ tags: prosody
+
+ tasks:
+ - name: create webroot
+ file:
+ path: /var/www/www.example.com
+ state: directory
+ owner: root
+ group: webmasters
+ mode: 02770
+ tags: apache
diff --git a/playbooks/wiki.yml b/playbooks/wiki.yml
new file mode 100644
index 0000000..794eb74
--- /dev/null
+++ b/playbooks/wiki.yml
@@ -0,0 +1,25 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: wiki_servers
+
+- name: configure mediawiki
+ hosts: wiki_servers
+ tags: wiki,mediawiki
+ roles:
+ - role: mediawiki
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_document_root: '{{ mediawiki_home }}'
+ apache_config: '{{ mediawiki_apache_config }}'
+ tags: apache
+
+ - role: php
+ php_fpm_environment: '{{ mediawiki_php_environment }}'
+ php_fpm_admin_values: '{{ mediawiki_php_admin_values }}'
+ tags: php
+
+ - role: archive_job
+ archive_name: mediawiki
+ archive_shell: '{{ mediawiki_archive_shell }}'
+ tags: archive
diff --git a/playbooks/xmpp.yml b/playbooks/xmpp.yml
new file mode 100644
index 0000000..38d0ce4
--- /dev/null
+++ b/playbooks/xmpp.yml
@@ -0,0 +1,9 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: xmpp_servers
+
+- name: configure prosody
+ hosts: xmpp_servers
+ tags: xmpp,prosody
+ roles:
+ - role: prosody
diff --git a/playbooks/yum.yml b/playbooks/yum.yml
new file mode 100644
index 0000000..e0c829f
--- /dev/null
+++ b/playbooks/yum.yml
@@ -0,0 +1,33 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: yum_mirrors
+
+- name: configure yum mirrors
+ hosts: yum_mirrors
+ tags: yum
+ roles:
+ - role: yum_mirror
+
+ - role: apache_vhost
+ apache_default_vhost: yes
+ apache_document_root: '{{ yum_mirror_webroot }}'
+ apache_autoindex: yes
+ apache_redirect_to_https: no
+ tags: apache
+
+- name: configure mirror for local packages
+ hosts: yum_mirrors
+ tags: yum
+ roles:
+ - role: yum_disable_default_repos
+
+ - role: yum
+ yum_repositories:
+ - rocky-baseos
+ - rocky-appstream
+ - rocky-extras
+ - epel
+
+ # nagios_client has to run *after* EPEL repository has been configured.
+ - role: nagios_client
+ tags: nagios
diff --git a/playbooks/znc.yml b/playbooks/znc.yml
new file mode 100644
index 0000000..79f3721
--- /dev/null
+++ b/playbooks/znc.yml
@@ -0,0 +1,14 @@
+- import_playbook: common.yml
+ vars:
+ hostlist: znc_servers
+
+- name: configure znc
+ hosts: znc_servers
+ tags: znc
+ roles:
+ - role: znc
+
+ - role: archive_job
+ archive_name: znc
+ archive_shell: '{{ znc_archive_shell }}'
+ tags: archive