From 4d958b4784ceda51e0dbb95f8f87d23fdbc4153a Mon Sep 17 00:00:00 2001 From: Matthew Fennell Date: Wed, 9 Sep 2026 22:22:07 +0100 Subject: Use bootstrap and munin-node roles I've moved these tasks into their own roles, which can now be used directly. --- files/50-disable-password-auth.conf | 5 - files/50unattended-upgrades | 168 ----------------------- files/hosts.j2 | 11 -- files/munin-node.conf.j2 | 69 ---------- playbook.yaml | 266 +----------------------------------- 5 files changed, 3 insertions(+), 516 deletions(-) delete mode 100644 files/50-disable-password-auth.conf delete mode 100644 files/50unattended-upgrades delete mode 100644 files/hosts.j2 delete mode 100644 files/munin-node.conf.j2 diff --git a/files/50-disable-password-auth.conf b/files/50-disable-password-auth.conf deleted file mode 100644 index 483b8f2..0000000 --- a/files/50-disable-password-auth.conf +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - -PasswordAuthentication no diff --git a/files/50unattended-upgrades b/files/50unattended-upgrades deleted file mode 100644 index ba218a4..0000000 --- a/files/50unattended-upgrades +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Matthew Fennell -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -// Unattended-Upgrade::Origins-Pattern controls which packages are -// upgraded. -// -// Lines below have the format "keyword=value,...". A -// package will be upgraded only if the values in its metadata match -// all the supplied keywords in a line. (In other words, omitted -// keywords are wild cards.) The keywords originate from the Release -// file, but several aliases are accepted. The accepted keywords are: -// a,archive,suite (eg, "stable") -// c,component (eg, "main", "contrib", "non-free") -// l,label (eg, "Debian", "Debian-Security") -// o,origin (eg, "Debian", "Unofficial Multimedia Packages") -// n,codename (eg, "jessie", "jessie-updates") -// site (eg, "http.debian.net") -// The available values on the system are printed by the command -// "apt-cache policy", and can be debugged by running -// "unattended-upgrades -d" and looking at the log file. -// -// Within lines unattended-upgrades allows 2 macros whose values are -// derived from /etc/debian_version: -// ${distro_id} Installed origin. -// ${distro_codename} Installed codename (eg, "buster") -Unattended-Upgrade::Origins-Pattern { - // Codename based matching: - // This will follow the migration of a release through different - // archives (e.g. from testing to stable and later oldstable). - // Software will be the latest available for the named release, - // but the Debian release itself will not be automatically upgraded. -// "origin=Debian,codename=${distro_codename}-updates"; -// "origin=Debian,codename=${distro_codename}-proposed-updates"; - "origin=Debian,codename=${distro_codename},label=Debian"; - "origin=Debian,codename=${distro_codename},label=Debian-Security"; - "origin=Debian,codename=${distro_codename}-security,label=Debian-Security"; - - // Archive or Suite based matching: - // Note that this will silently match a different release after - // migration to the specified archive (e.g. testing becomes the - // new stable). -// "o=Debian,a=stable"; -// "o=Debian,a=stable-updates"; -// "o=Debian,a=proposed-updates"; -// "o=Debian Backports,a=${distro_codename}-backports,l=Debian Backports"; -}; - -// Python regular expressions, matching packages to exclude from upgrading -Unattended-Upgrade::Package-Blacklist { - // The following matches all packages starting with linux- -// "linux-"; - - // Use $ to explicitely define the end of a package name. Without - // the $, "libc6" would match all of them. -// "libc6$"; -// "libc6-dev$"; -// "libc6-i686$"; - - // Special characters need escaping -// "libstdc\+\+6$"; - - // The following matches packages like xen-system-amd64, xen-utils-4.1, - // xenstore-utils and libxenstore3.0 -// "(lib)?xen(store)?"; - - // For more information about Python regular expressions, see - // https://docs.python.org/3/howto/regex.html -}; - -// This option allows you to control if on a unclean dpkg exit -// unattended-upgrades will automatically run -// dpkg --force-confold --configure -a -// The default is true, to ensure updates keep getting installed -//Unattended-Upgrade::AutoFixInterruptedDpkg "true"; - -// Split the upgrade into the smallest possible chunks so that -// they can be interrupted with SIGTERM. This makes the upgrade -// a bit slower but it has the benefit that shutdown while a upgrade -// is running is possible (with a small delay) -//Unattended-Upgrade::MinimalSteps "true"; - -// Install all updates when the machine is shutting down -// instead of doing it in the background while the machine is running. -// This will (obviously) make shutdown slower. -// Unattended-upgrades increases logind's InhibitDelayMaxSec to 30s. -// This allows more time for unattended-upgrades to shut down gracefully -// or even install a few packages in InstallOnShutdown mode, but is still a -// big step back from the 30 minutes allowed for InstallOnShutdown previously. -// Users enabling InstallOnShutdown mode are advised to increase -// InhibitDelayMaxSec even further, possibly to 30 minutes. -//Unattended-Upgrade::InstallOnShutdown "false"; - -// Send email to this address for problems or packages upgrades -// If empty or unset then no email is sent, make sure that you -// have a working mail setup on your system. A package that provides -// 'mailx' must be installed. E.g. "user@example.com" -//Unattended-Upgrade::Mail ""; - -// Set this value to one of: -// "always", "only-on-error" or "on-change" -// If this is not set, then any legacy MailOnlyOnError (boolean) value -// is used to chose between "only-on-error" and "on-change" -//Unattended-Upgrade::MailReport "on-change"; - -// Remove unused automatically installed kernel-related packages -// (kernel images, kernel headers and kernel version locked tools). -//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; - -// Do automatic removal of newly unused dependencies after the upgrade -//Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; - -// Do automatic removal of unused packages after the upgrade -// (equivalent to apt-get autoremove) -Unattended-Upgrade::Remove-Unused-Dependencies "true"; - -// Automatically reboot *WITHOUT CONFIRMATION* if -// the file /var/run/reboot-required is found after the upgrade -Unattended-Upgrade::Automatic-Reboot "true"; - -// Automatically reboot even if there are users currently logged in -// when Unattended-Upgrade::Automatic-Reboot is set to true -//Unattended-Upgrade::Automatic-Reboot-WithUsers "true"; - -// If automatic reboot is enabled and needed, reboot at the specific -// time instead of immediately -// Default: "now" -//Unattended-Upgrade::Automatic-Reboot-Time "02:00"; - -// Use apt bandwidth limit feature, this example limits the download -// speed to 70kb/sec -//Acquire::http::Dl-Limit "70"; - -// Enable logging to syslog. Default is False -// Unattended-Upgrade::SyslogEnable "false"; - -// Specify syslog facility. Default is daemon -// Unattended-Upgrade::SyslogFacility "daemon"; - -// Download and install upgrades only on AC power -// (i.e. skip or gracefully stop updates on battery) -// Unattended-Upgrade::OnlyOnACPower "true"; - -// Download and install upgrades only on non-metered connection -// (i.e. skip or gracefully stop updates on a metered connection) -// Unattended-Upgrade::Skip-Updates-On-Metered-Connections "true"; - -// Verbose logging -// Unattended-Upgrade::Verbose "false"; - -// Print debugging information both in unattended-upgrades and -// in unattended-upgrade-shutdown -// Unattended-Upgrade::Debug "false"; - -// Allow package downgrade if Pin-Priority exceeds 1000 -// Unattended-Upgrade::Allow-downgrade "false"; - -// When APT fails to mark a package to be upgraded or installed try adjusting -// candidates of related packages to help APT's resolver in finding a solution -// where the package can be upgraded or installed. -// This is a workaround until APT's resolver is fixed to always find a -// solution if it exists. (See Debian bug #711128.) -// The fallback is enabled by default, except on Debian's sid release because -// uninstallable packages are frequent there. -// Disabling the fallback speeds up unattended-upgrades when there are -// uninstallable packages at the expense of rarely keeping back packages which -// could be upgraded or installed. -// Unattended-Upgrade::Allow-APT-Mark-Fallback "true"; diff --git a/files/hosts.j2 b/files/hosts.j2 deleted file mode 100644 index 9ef5300..0000000 --- a/files/hosts.j2 +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - -127.0.1.1 {{ hostname }} -127.0.0.1 localhost - -# The following lines are desirable for IPv6 capable hosts -::1 localhost ip6-localhost ip6-loopback -ff02::1 ip6-allnodes -ff02::2 ip6-allrouters diff --git a/files/munin-node.conf.j2 b/files/munin-node.conf.j2 deleted file mode 100644 index 81400a9..0000000 --- a/files/munin-node.conf.j2 +++ /dev/null @@ -1,69 +0,0 @@ -# SPDX-FileCopyrightText: 2026 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - -# -# Example config-file for munin-node -# - -log_level 4 -log_file /var/log/munin/munin-node.log -pid_file /var/run/munin/munin-node.pid - -background 1 -setsid 1 - -user root -group root - -# This is the timeout for the whole transaction. -# Units are in sec. Default is 15 min -# -# global_timeout 900 - -# This is the timeout for each plugin. -# Units are in sec. Default is 1 min -# -# timeout 60 - -# Regexps for files to ignore -ignore_file [\#~]$ -ignore_file DEADJOE$ -ignore_file \.bak$ -ignore_file %$ -ignore_file \.dpkg-(tmp|new|old|dist)$ -ignore_file \.rpm(save|new)$ -ignore_file \.pod$ - -# Set this if the client doesn't report the correct hostname when -# telnetting to localhost, port 4949 -# -#host_name localhost.localdomain -host_name {{ hostname }} - -# A list of addresses that are allowed to connect. This must be a -# regular expression, since Net::Server does not understand CIDR-style -# network notation unless the perl module Net::CIDR is installed. You -# may repeat the allow line as many times as you'd like - -allow ^127\.0\.0\.1$ -allow ^::1$ -allow ^{{ munin_host }}$ - -# If you have installed the Net::CIDR perl module, you can use one or more -# cidr_allow and cidr_deny address/mask patterns. A connecting client must -# match any cidr_allow, and not match any cidr_deny. Note that a netmask -# *must* be provided, even if it's /32 -# -# Example: -# -# cidr_allow 127.0.0.1/32 -# cidr_allow 192.0.2.0/24 -# cidr_deny 192.0.2.42/32 - -# Which address to bind to; -host * -# host 127.0.0.1 - -# And which port -port 4949 diff --git a/playbook.yaml b/playbook.yaml index ebeefd5..7a9dc79 100644 --- a/playbook.yaml +++ b/playbook.yaml @@ -7,84 +7,11 @@ - name: Ensure XMPP server is set up gather_facts: false hosts: all + roles: + - bootstrap + - munin-node tasks: - - name: Ensure all authorized keys are copied to root account - remote_user: root - ansible.posix.authorized_key: - key: | - {% for key in authorized_key_files %} - {{ lookup('file', key) }} - {% endfor %} - user: root - exclusive: true - - # Now, we create a non-root user with sudo privileges - - name: Ensure wheel group exists - remote_user: root - ansible.builtin.group: - name: wheel - state: present - - - name: Ensure wheel group allows passwordless sudo - remote_user: root - ansible.builtin.lineinfile: - dest: /etc/sudoers - state: present - regexp: "^%wheel" - line: "%wheel ALL=(ALL) NOPASSWD: ALL" - validate: visudo -cf %s - - - name: Ensure non-root admin account is created in wheel group - remote_user: root - ansible.builtin.user: - name: admin - groups: wheel - append: true - - - name: Ensure admin ssh directory exists - remote_user: root - ansible.builtin.file: - path: /home/admin/.ssh - state: directory - owner: admin - group: admin - mode: "0700" - - - name: Copy authorised keys to admin account - remote_user: root - ansible.builtin.copy: - src: /root/.ssh/authorized_keys - dest: /home/admin/.ssh/authorized_keys - remote_src: true - owner: admin - group: admin - mode: preserve - - - name: Ensure cloud-init is disabled - ansible.builtin.copy: - content: "" - dest: /etc/cloud/cloud-init.disabled - force: false - owner: root - group: root - mode: "0644" - become: true - - - name: Ensure hostname is set - ansible.builtin.hostname: - name: "{{ hostname }}" - become: true - - - name: Ensure hostname is configured in /etc/hosts - ansible.builtin.template: - src: "{{ playbook_dir }}/files/hosts.j2" - dest: /etc/hosts - owner: root - group: root - mode: "0644" - become: true - - name: Retrieve DANE hash ansible.builtin.shell: cmd: > @@ -216,39 +143,6 @@ tags: - dns - # This is needed by ansible.builtin.deb822_repository to interact with the - # sources lists. In ansible-core 2.20 and above, there is a builtin - # install_python_debian parameter that handles that without this extra step, - # but we are currently running 2.19. - # TODO(debian-forky) use deb822_repository's install_python_debian parameter - - name: Ensure python3-debian is installed - ansible.builtin.apt: - name: - - python3-debian - state: present - update_cache: true - become: true - - - name: Ensure debian apt repositories are configured - ansible.builtin.deb822_repository: - name: debian - uris: "{{ debian_uri }}" - suites: - - "{{ debian_version }}" - - "{{ debian_version }}-updates" - components: main - signed_by: /usr/share/keyrings/debian-archive-keyring.gpg - become: true - - - name: Ensure debian-security apt repositories are configured - ansible.builtin.deb822_repository: - name: debian-security - uris: "{{ debian_security_uri }}" - suites: "{{ debian_version }}-security" - components: main - signed_by: /usr/share/keyrings/debian-archive-keyring.gpg - become: true - # We specifically use apt instead of the more general package module here, # because we want to ensure the cache is updated before we try and install # anything. This is needed because, on a freh Debian install on AWS @@ -258,18 +152,12 @@ - name: Ensure required packages are installed ansible.builtin.apt: name: - - libdbi-perl # Used by munin postgres plugins - lua-dbi-postgresql # Prosody postgres connection - lua-unbound # Prosody DNS resolution - - munin-node # Graphs and monitoring - postgresql # Database - prosody # XMPP server - prosody-modules # Extra addons - python3-psycopg2 # Used by ansible postgres role - - rsync # Backups - - systemd-timesyncd # Used to make sure the date is correct - - ufw # Firewall - - unattended-upgrades # Not every hosting provider installs by default state: present update_cache: true become: true @@ -351,7 +239,6 @@ proto: tcp state: enabled loop: - - 4949 # Munin - 5000 # XEP-0065 - 5223 # XEP-0368 - 5270 # XEP-0368 @@ -402,113 +289,6 @@ notify: Restart nginx when: not is_transport_server - - name: Ensure munin is configured - ansible.builtin.template: - src: "{{ playbook_dir }}/files/munin-node.conf.j2" - dest: /etc/munin/munin-node.conf - owner: root - group: root - mode: "0644" - become: true - notify: Restart munin-node - - - name: Ensure munin plugins are configured - ansible.builtin.file: - src: "/usr/share/munin/plugins/{{ item.src }}" - dest: "/etc/munin/plugins/{{ item.dest }}" - owner: root - group: root - state: link - become: true - with_items: - - src: apt_all - dest: apt_all - - src: cpu - dest: cpu - - src: df - dest: df - - src: df_abs - dest: df_abs - - src: df_inode - dest: df_inode - - src: diskstats - dest: diskstats - - src: entropy - dest: entropy - - src: forks - dest: forks - - src: fw_conntrack - dest: fw_conntrack - - src: fw_forwarded_local - dest: fw_forwarded_local - - src: fw_packets - dest: fw_packets - - src: if_ - dest: if_enp1s0 - - src: if_err_ - dest: if_err_enp1s0 - - src: irqstats - dest: irqstats - - src: load - dest: load - - src: memory - dest: memory - - src: netstat - dest: netstat - - src: open_files - dest: open_files - - src: open_inodes - dest: open_inodes - - src: postgres_autovacuum - dest: postgres_autovacuum - - src: postgres_bgwriter - dest: postgres_bgwriter - - src: postgres_cache_ - dest: postgres_cache_prosody - - src: postgres_checkpoints - dest: postgres_checkpoints - - src: postgres_connections_ - dest: postgres_connections_prosody - - src: postgres_connections_db - dest: postgres_connections_db - - src: postgres_locks_ - dest: postgres_locks_prosody - - src: postgres_oldest_prepared_xact_ - dest: postgres_oldest_prepared_xact_prosody - - src: postgres_prepared_xacts_ - dest: postgres_prepared_xacts_prosody - - src: postgres_querylength_ - dest: postgres_querylength_prosody - - src: postgres_scans_ - dest: postgres_scans_prosody - - src: postgres_size_ - dest: postgres_size_prosody - - src: postgres_streaming_ - dest: postgres_streaming_prosody - - src: postgres_transactions_ - dest: postgres_transactions_prosody - - src: postgres_tuples_ - dest: postgres_tuples_prosody - - src: postgres_users - dest: postgres_users - - src: postgres_xlog - dest: postgres_xlog - - src: proc_pri - dest: proc_pri - - src: processes - dest: processes - - src: swap - dest: swap - - src: threads - dest: threads - - src: uptime - dest: uptime - - src: users - dest: users - - src: vmstat - dest: vmstat - notify: Restart munin-node - - name: Ensure turn is configured ansible.builtin.template: src: "{{ playbook_dir }}/files/turnserver.conf.j2" @@ -622,34 +402,6 @@ enabled: true become: true - # Vultr adds a custom sshd_config file that enabled password authentication. - # I don't want this to be enabled, since I'm already copying the public key. - - name: Ensure password authentication is not explicitly enabled - ansible.builtin.file: - path: "/etc/ssh/sshd_config.d/50-cloud-init.conf" - state: absent - become: true - notify: Restart sshd - - - name: Ensure password based authentication is disabled - ansible.builtin.copy: - src: "{{ playbook_dir }}/files/50-disable-password-auth.conf" - dest: "/etc/ssh/sshd_config.d/50-disable-password-auth.conf" - owner: root - group: root - mode: "0644" - become: true - notify: Restart sshd - - - name: Ensure unattended upgrades config is installed - ansible.builtin.copy: - src: "{{ playbook_dir }}/files/50unattended-upgrades" - dest: "/etc/apt/apt.conf.d/50unattended-upgrades" - owner: root - group: root - mode: "0644" - become: true - handlers: - name: Restart prosody @@ -664,24 +416,12 @@ state: restarted become: true - - name: Restart sshd - ansible.builtin.service: - name: sshd - state: restarted - become: true - - name: Restart nginx ansible.builtin.service: name: nginx state: restarted become: true - - name: Restart munin-node - ansible.builtin.service: - name: munin-node - state: restarted - become: true - vars: env_prefix: >- -- cgit v1.2.3