From 25db56f6241ae50feb54232e25f8203c1a450c7c Mon Sep 17 00:00:00 2001 From: Matthew Fennell Date: Wed, 9 Sep 2026 21:48:42 +0100 Subject: Move bootstrap sources to their own subdirectory Since much of the setup (e.g. linter, hook, Makefile configuration) is consistent between ansible roles, instead of having a separate repo per role (as I initially planned), I'd prefer to have a single repo with all of the roles that the playbooks can then pull from. This is in preparation of adding a new munin-node role, following a similar process to bootstrap. --- Makefile | 4 +- bootstrap/defaults/main.yml | 9 ++ bootstrap/files/50-disable-password-auth.conf | 5 + bootstrap/files/50unattended-upgrades | 168 ++++++++++++++++++++++++++ bootstrap/handlers/main.yml | 11 ++ bootstrap/tasks/main.yml | 153 +++++++++++++++++++++++ bootstrap/templates/hosts.j2 | 11 ++ defaults/main.yml | 9 -- files/50-disable-password-auth.conf | 5 - files/50unattended-upgrades | 168 -------------------------- handlers/main.yml | 11 -- tasks/main.yml | 153 ----------------------- templates/hosts.j2 | 11 -- 13 files changed, 359 insertions(+), 359 deletions(-) create mode 100644 bootstrap/defaults/main.yml create mode 100644 bootstrap/files/50-disable-password-auth.conf create mode 100644 bootstrap/files/50unattended-upgrades create mode 100644 bootstrap/handlers/main.yml create mode 100644 bootstrap/tasks/main.yml create mode 100644 bootstrap/templates/hosts.j2 delete mode 100644 defaults/main.yml delete mode 100644 files/50-disable-password-auth.conf delete mode 100644 files/50unattended-upgrades delete mode 100644 handlers/main.yml delete mode 100644 tasks/main.yml delete mode 100644 templates/hosts.j2 diff --git a/Makefile b/Makefile index 6e84119..8f40589 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ .PHONY: all lint install -INSTALL_DIR = /usr/local/share/ansible/roles/bootstrap +INSTALL_DIR = /usr/local/share/ansible/roles all: make lint @@ -17,4 +17,4 @@ lint: install: rm -rf $(INSTALL_DIR) mkdir -p $(INSTALL_DIR) - cp -r defaults files handlers tasks templates $(INSTALL_DIR) + cp -r bootstrap $(INSTALL_DIR) diff --git a/bootstrap/defaults/main.yml b/bootstrap/defaults/main.yml new file mode 100644 index 0000000..85a7a6b --- /dev/null +++ b/bootstrap/defaults/main.yml @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2026 Matthew Fennell +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- + +debian_security_uri: http://security.debian.org/ +debian_uri: http://deb.debian.org/debian +debian_version: trixie diff --git a/bootstrap/files/50-disable-password-auth.conf b/bootstrap/files/50-disable-password-auth.conf new file mode 100644 index 0000000..483b8f2 --- /dev/null +++ b/bootstrap/files/50-disable-password-auth.conf @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2024 Matthew Fennell +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +PasswordAuthentication no diff --git a/bootstrap/files/50unattended-upgrades b/bootstrap/files/50unattended-upgrades new file mode 100644 index 0000000..ba218a4 --- /dev/null +++ b/bootstrap/files/50unattended-upgrades @@ -0,0 +1,168 @@ +// 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/bootstrap/handlers/main.yml b/bootstrap/handlers/main.yml new file mode 100644 index 0000000..c9aef1f --- /dev/null +++ b/bootstrap/handlers/main.yml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2026 Matthew Fennell +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- + +- name: Restart sshd + ansible.builtin.service: + name: sshd + state: restarted + become: true diff --git a/bootstrap/tasks/main.yml b/bootstrap/tasks/main.yml new file mode 100644 index 0000000..4512804 --- /dev/null +++ b/bootstrap/tasks/main.yml @@ -0,0 +1,153 @@ +# SPDX-FileCopyrightText: 2026 Matthew Fennell +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- + +- 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: hosts.j2 + dest: /etc/hosts + owner: root + group: root + mode: "0644" + become: true + +# 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 + +- name: Ensure required packages are installed + ansible.builtin.apt: + name: + - 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 + +# 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: 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: 50unattended-upgrades + dest: "/etc/apt/apt.conf.d/50unattended-upgrades" + owner: root + group: root + mode: "0644" + become: true diff --git a/bootstrap/templates/hosts.j2 b/bootstrap/templates/hosts.j2 new file mode 100644 index 0000000..9ef5300 --- /dev/null +++ b/bootstrap/templates/hosts.j2 @@ -0,0 +1,11 @@ +# 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/defaults/main.yml b/defaults/main.yml deleted file mode 100644 index 85a7a6b..0000000 --- a/defaults/main.yml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2026 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - ---- - -debian_security_uri: http://security.debian.org/ -debian_uri: http://deb.debian.org/debian -debian_version: trixie 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/handlers/main.yml b/handlers/main.yml deleted file mode 100644 index c9aef1f..0000000 --- a/handlers/main.yml +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2026 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - ---- - -- name: Restart sshd - ansible.builtin.service: - name: sshd - state: restarted - become: true diff --git a/tasks/main.yml b/tasks/main.yml deleted file mode 100644 index 4512804..0000000 --- a/tasks/main.yml +++ /dev/null @@ -1,153 +0,0 @@ -# SPDX-FileCopyrightText: 2026 Matthew Fennell -# -# SPDX-License-Identifier: AGPL-3.0-or-later - ---- - -- 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: hosts.j2 - dest: /etc/hosts - owner: root - group: root - mode: "0644" - become: true - -# 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 - -- name: Ensure required packages are installed - ansible.builtin.apt: - name: - - 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 - -# 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: 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: 50unattended-upgrades - dest: "/etc/apt/apt.conf.d/50unattended-upgrades" - owner: root - group: root - mode: "0644" - become: true diff --git a/templates/hosts.j2 b/templates/hosts.j2 deleted file mode 100644 index 9ef5300..0000000 --- a/templates/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 -- cgit v1.2.3