changeset 480:2c3e745be8d2

Update server defs and own modules to match * $osver and $fqdn and others are now all in $facts * Firewall swapped action for jump and has new way to do IPv6 * SSH server setup changed * Resolve warnings from fileserver.conf * has_key() no longer exists because Puppet can do "key in array" * Some variables are now more strictly typed Also: * Try to configure full IPv6 DNS resolver * Clean up old config - unused servers and some CentOS complexity
author IBBoard <dev@ibboard.co.uk>
date Thu, 29 Aug 2024 18:58:49 +0100
parents 162dc4376331
children 36eacac6bf5e
files common/unbound.conf-ibbpi fileserver.conf hiera.yaml manifests/nodes.pp manifests/templates.pp modules/dovecot/manifests/init.pp modules/fail2ban/manifests/init.pp modules/my_fw/manifests/init.pp modules/my_fw/manifests/post.pp modules/my_fw/manifests/pre.pp modules/postfix/manifests/init.pp modules/vcs/manifests/init.pp modules/website/manifests/https.pp modules/website/manifests/https/redir.pp modules/website/manifests/init.pp modules/website/manifests/mysql.pp modules/website/manifests/php.pp
diffstat 17 files changed, 130 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/common/unbound.conf-ibbpi	Thu Aug 29 18:48:03 2024 +0100
+++ b/common/unbound.conf-ibbpi	Thu Aug 29 18:58:49 2024 +0100
@@ -1,14 +1,12 @@
 # Based on https://www.nlnetlabs.nl/documentation/unbound/howto-setup/
-# Note: If the upstream DNS stops synthesising IPv6 records for IPv4-only
-# domains due to honouring DNSSEC then we need to go back to doing DNS64 here
+# and https://www.nlnetlabs.nl/news/2023/Aug/30/unbound-1.18.0-released/
 server:
 	interface: 127.0.0.1
 	interface: ::1
 	access-control: 127.0.0.0/24 allow
 	access-control: ::1 allow
         verbosity: 1
-
-forward-zone:
-        name: "."
-        forward-addr: 2a00:1098:0:80:1000:3b:0:1
-        forward-addr: 2a00:1098:0:82:1000:3b:0:1
\ No newline at end of file
+        do-nat64: yes
+        module-config: "dns64 validator iterator"
+        dns64-prefix: 64:ff9b::/96
+        qname-minimisation: yes 
--- a/fileserver.conf	Thu Aug 29 18:48:03 2024 +0100
+++ b/fileserver.conf	Thu Aug 29 18:58:49 2024 +0100
@@ -1,30 +1,9 @@
 # This file consists of arbitrarily named sections/modules
 # defining where files are served from and to whom
 
-# Define a section 'files'
-# Adapt the allow/deny settings to your needs. Order
-# for allow/deny does not matter, allow always takes precedence
-# over deny
-# [files]
-#  path /var/lib/puppet/files
-#  allow *.example.com
-#  deny *.evil.example.com
-#  allow 192.168.0.0/24
-#[files]
-#path    /etc/puppet/files
-#allow *.ibboard.co.uk
-#allow 127.0.0.1
-#allow localhost
-
 [private]
 path	/etc/puppet/private
-allow *.ibboard.co.uk
-allow 127.0.0.1
-allow localhost
 
 [common]
 path	/etc/puppet/common
-allow *.ibboard.co.uk
-allow 127.0.0.1
-allow localhost
 
--- a/hiera.yaml	Thu Aug 29 18:48:03 2024 +0100
+++ b/hiera.yaml	Thu Aug 29 18:58:49 2024 +0100
@@ -1,3 +1,11 @@
+---
+# Hiera 5 Global configuration file
 
-# Let the system set defaults
 version: 5
+
+# defaults:
+#   data_hash: yaml_data
+# hierarchy:
+#  - name: Common
+#    data_hash: yaml_data
+hierarchy: []
--- a/manifests/nodes.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/manifests/nodes.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -23,25 +23,9 @@
 		action => 'accept',
 	}
 }
-node 'vpsarm.home' {
-	class { 'ibboardvpsnode':
-		primary_ip => '2a00:23c8:a480:3701:5054:ff:fe42:65f9',
-		mailserver => 'mail.ibboard.co.uk',
-		imapserver => 'imap.ibboard.co.uk',
-		firewall_cmd => 'iptables',
-	}
-}
-node 'vps-arm-2204.test.ibboard.co.uk' {
-	class { 'ibboardvpsnode':
-		primary_ip => 'fd21:d7cd:fe52:0:5054:ff:fee4:9b6e',
-		mailserver => 'mail.ibboard.co.uk',
-		imapserver => 'imap.ibboard.co.uk',
-		firewall_cmd => 'iptables',
-	}
-}
 node 'vps-2204.test.ibboard.co.uk' {
 	class { 'ibboardvpsnode':
-		primary_ip => 'fd21:d7cd:fe52:0:5054:ff:fec7:76c3',
+		primary_ip => '2a10:8702:8:5200:5054:ff:fec7:76c3',
 		mailserver => 'mail.ibboard.co.uk',
 		imapserver => 'imap.ibboard.co.uk',
 		firewall_cmd => 'iptables',
--- a/manifests/templates.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/manifests/templates.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -13,8 +13,8 @@
 -> Service<| |>
 
 # Set some shortcut variables
-#$os = $operatingsystem
-$osver = $operatingsystemmajrelease
+$osname = $facts["os"]["name"]
+$osver = $facts["os"]["release"]["major"]
 $server = ''
 
 
@@ -35,7 +35,7 @@
 		ensure => stopped,
 		enable => false,
 	}
-	if $operatingsystem == 'Ubuntu' {
+	if $osname == 'Ubuntu' {
 		package { 'locales':
 			ensure => present
 		} ->
@@ -89,14 +89,14 @@
 	}
 	file { '/etc/hosts':
 		ensure => present,
-		content => "${lo_ip}   localhost\n${primary_ip} ${fqdn}",
+		content => "${lo_ip}   localhost\n${primary_ip} ${facts['networking']['fqdn']}",
 	}
 
 	if $proxy_4to6_ip_prefix != undef {
 		# …:1 to …:9 for websites, …:10 for mail
 		# Note: IPv6 is hexadecimal and so 0x10 is not in a /124 netblock with 0x01 to 0x09!
 		$ipv6_addresses = Integer[1, 10].map |$octet| { "$proxy_4to6_ip_prefix:$octet" }
-		if $operatingsystem == 'Ubuntu' {
+		if $osname == 'Ubuntu' {
 			# Ubuntu can't parse the existing file, so we need to brute-force it with a template
 			file { "/etc/network/interfaces.d/eth0":
 				content => epp('privat/eth0.epp',
@@ -143,8 +143,25 @@
 	include privat
 	include dnsresolver
 	include ::privat::params
-	class { '::ssh':
-		sshd_config_port => $::privat::params::ssh_port[$::fqdn]
+
+	if $osname == "Ubuntu" and versioncmp($osver, '24.04') >= 0 {
+		$sshd_service = "ssh"
+	}
+	else {
+		$sshd_service = "sshd"
+	}
+	
+	class { 'ssh::server':
+		service_name => $sshd_service,
+		include => '/etc/ssh/sshd_config.d/*.conf',
+		subsystem => "sftp /usr/lib/openssh/sftp-server",
+	}
+	
+	$::privat::params::ssh_port[$facts["networking"]["fqdn"]].map |$port| {
+		ssh::config_file_server {
+			"99-port-${port}":
+				lines=>{"Port" => $port}
+		}
 	}
 	include vcs::server
 	include vcs::client
@@ -191,25 +208,25 @@
 			],
 	}
 	include privat::params
-	$ssh_ports = $::privat::params::ssh_port[$::fqdn]
+	$ssh_ports = $::privat::params::ssh_port[$facts["networking"]["fqdn"]]
 	firewall { '090 Allow SSH':
 		dport => $ssh_ports - 22,
 		proto => 'tcp',
-		action => 'accept',
+		jump => 'accept',
 	}
 	if ($fw_protocol != "IPv6") {
 		firewall { '010 Whitelist Googlebot':
 			source => '66.249.64.0/19',
 			dport => [80,443],
 			proto => tcp,
-			action => accept,
+			jump => accept,
 		}
 		# Block a spammer hitting our contact forms (also on StopForumSpam list A LOT)
 		firewall { '099 Blacklist spammers 1':
 			source => '107.181.78.172',
 			dport => [80, 443],
 			proto => tcp,
-			action => 'reject',
+			jump => 'reject',
 		}
 		firewall { '099 Blacklist IODC bot':
 			# IODC bot makes too many bad requests, and contact form is broken
@@ -217,7 +234,7 @@
 			source => '86.153.145.149',
 			dport => [ 80, 443 ],
 			proto => tcp,
-			action => 'reject',
+			jump => 'reject',
 		}
 		firewall { '099 Blacklist Baidu Brazil':
 			#Baidu got a Brazilian netblock and are hitting us hard
@@ -226,7 +243,7 @@
 			source => '131.161.8.0/22',
 			dport => [ 80, 443 ],
 			proto => tcp,
-			action => 'reject',
+			jump => 'reject',
 		}
 	}
 	firewallchain { "GREATFIREWALLOFCHINA:filter:$fw_protocol":
@@ -268,7 +285,7 @@
 	file { '/etc/unbound/unbound.conf':
 		ensure => present,
 		source => [
-                        "puppet:///common/unbound.conf-${::hostname}",
+                        "puppet:///common/unbound.conf-${facts['networking']['hostname']}",
                         "puppet:///common/unbound.conf",
                 ],
 		require => Package['unbound'],
@@ -288,8 +305,7 @@
 	}
 	file { '/etc/resolv.conf':
 		ensure => file,
-		# "ipaddress" key only exists for machines with IPv4 addresses
-		content => has_key($facts, 'ipaddress') ? { true => "nameserver 127.0.0.1", default => "nameserver ::1" },
+		content => "nameserver ::1",
 		require => Service['unbound'],
 		tag => 'post-service',
 	}
@@ -297,47 +313,9 @@
 
 class repos {
 	include ::python::params
-	if $operatingsystem == 'CentOS' {
-		yumrepo { 'epel':
-			mirrorlist => 'https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch',
-			descr => "Extra Packages for Enterprise Linux",
-			enabled => 1,
-			failovermethod => absent,
-			gpgcheck => 1,
-			gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver",
-		}
-		file { "/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver":
-			ensure => present,
-			source => "puppet:///common/RPM-GPG-KEY-EPEL-$osver",
-			tag => 'repo-config',
-		}
-		yumrepo { 'ibboard':
-			baseurl => 'https://download.opensuse.org/repositories/home:/IBBoard:/server/CentOS_$releasever/',
-			descr => 'Extra packages from IBBoard',
-			enabled => 1,
-			gpgcheck => 1,
-			gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard',
-		}
-		file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard':
-			ensure => present,
-			source => 'puppet:///common/RPM-GPG-KEY-ibboard',
-			tag => 'repo-config',
-		}
-		yumrepo { 'webtatic':
-			ensure => absent,
-		}
-		file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-andy':
-			ensure => absent,
-		}
-		file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-el7':
-			ensure => absent,
-		}
-		# Python requires the `devel` package on CentOS, but by default the module tries to uninstall it
-		$dev = 'present'
-	}
-	else {
-		# Other distros can take the default devel status
-		$dev = $::python::params::dev
+	if $facts["os"]["name"] == "Ubuntu" {
+		# Other distros don't need the devel package
+		$dev = 'absent'
 		# CentOS-like distros have PKI by default. Others need it creating.
 		file { '/etc/pki/':
 			ensure => directory,
@@ -350,26 +328,14 @@
 
 		apt::source {
 			'ibboard':
-				location => 'http://download.opensuse.org/repositories/home:/IBBoard:/server/xUbuntu_22.04/',
+				location => "http://download.opensuse.org/repositories/home:/IBBoard:/server/xUbuntu_${osver}",
 				release => '/',
 				repos => '',
 				keyring => '/etc/apt/trusted.gpg.d/home_IBBoard_server.gpg',
 		}
 	}
-
-	if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 {
-		# The following may possibly work to ensure a CentOS Streams install.
-		# Or it might fail for inexplicable reasons.
-		# FIXME: Should be "centos-release-stream" to migrate (provides repos), but then that gets replaced by centos-stream-release,
-		# which Puppet doesn't recognise as the same and so keeps trying to re-install. May need an "unless" or maybe "allow_virtual"
-		package { 'centos-stream-release':
-			ensure => installed,
-			notify => Exec['migrate to streams'];
-		}
-		exec { 'migrate to streams':
-			command => '/usr/bin/dnf swap centos-linux-repos centos-stream-repos; /usr/bin/dnf distro-sync -y',
-			refreshonly => true
-		}
+	else {
+		fail("Unsupported OS: ${facts['os']['name']}")
 	}
 
 	class { 'python':
@@ -386,12 +352,12 @@
 	package { $packages:
 		ensure => installed;
 	}
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		package { 'yum-utils':
 			ensure => installed
 		}
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		package { 'dnsutils':
 			ensure => installed
 		}
@@ -490,73 +456,8 @@
 		default_extra_tlds => [ 'com' ],
 	}
 
-	if $operatingsystem == 'CentOS' {
-		$php_suffix = ''
-		$ini_prefix_20 = '20-'
-		$ini_prefix_30 = '30-'
-		$ini_prefix_40 = '40-'
-		$variant_prefix = 'php-'
-		$extra_prefix = 'pecl-'
-		$extra_extras = {
-			'posix' => {
-			        ini_prefix => '20-',
-			},
-			# Sodium has been bundled since 7.2, but CentOS packages it separately
-			'sodium' => {
-			        ini_prefix => '20-',
-			},
-			# JSON is integrated into PHP 8+ and so it's only a plugin in CentOS
-			'json' => {
-			        ini_prefix => '20-',
-			},
-		}
-		if versioncmp($operatingsystemrelease, '8') >= 0 {
-			yumrepo { 'remirepo-safe':
-				mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/$basearch/mirror',
-				descr => "Extra CentOS packages from Remi",
-				enabled => 1,
-				failovermethod => absent,
-				gpgcheck => 1,
-				gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi',
-			}
-			yumrepo { 'remirepo-php':
-				mirrorlist => 'http://cdn.remirepo.net/enterprise/8/modular/$basearch/mirror',
-				descr => 'Remi\'s Modular repository for Enterprise Linux 8 - $basearch',
-				enabled => 1,
-				failovermethod => absent,
-				gpgcheck => 1,
-				gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi',
-			}
-			file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi':
-				ensure => present,
-				source => 'puppet:///common/RPM-GPG-KEY-remi.el8',
-				tag => 'repo-config',
-			}
-		} else {
-			yumrepo { 'remirepo-safe':
-				mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/mirror',
-				descr => "Extra CentOS packages from Remi",
-				enabled => 1,
-				failovermethod => absent,
-				gpgcheck => 1,
-				gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi',
-			}
-			yumrepo { 'remirepo-php':
-				mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/php74/mirror',
-				descr => "PHP7.4 for CentOS from Remi",
-				enabled => 1,
-				failovermethod => absent,
-				gpgcheck => 1,
-				gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi',
-			}
-			file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi':
-				ensure => present,
-				source => 'puppet:///common/RPM-GPG-KEY-remi',
-				tag => 'repo-config',
-			}
-		}
-	}
-	elsif $operatingsystem == 'Ubuntu' {
+	if $facts["os"]["name"] == 'Ubuntu' {
+		$php_module = undef
 		$php_suffix = ''
 		$ini_prefix_20 = ''
 		$ini_prefix_30 = ''
@@ -580,11 +481,14 @@
 			}
 		}
 	}
+	else {
+		fail("Unsupported OS: ${facts['os']['name']}")
+	}
 
 	#Configure the PHP version to use
 	class { 'website::php':
 		suffix => $php_suffix,
-		module => ($operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0) ? { true => 'remi-7.4', default => undef },
+		module => $php_module,
 		extras => {
 			'bcmath' => {
 			        ini_prefix => $ini_prefix_20,
@@ -653,44 +557,13 @@
 	}
 
 	#Setup MySQL, using (private) templates to make sure that we set non-std passwords and a default user
-	if $operatingsystem == 'CentOS' {
-		if versioncmp($operatingsystemrelease, '7') >= 0 {
-			$mysqlpackage = 'mariadb'
-			$mysqlsuffix = ''
-
-			# Required for SELinux rule setting/status checks
-			if versioncmp($operatingsystemrelease, '8') >= 0 {
-				$semanage_package_name = 'policycoreutils-python-utils'
-			} else {
-				$semanage_package_name = 'policycoreutils-python'
-			}
-
-			package { 'policycoreutils-python':
-				name => $semanage_package_name,
-				ensure => present,
-			}
-
-			$extra_packages = [
-				'perl-Sys-Syslog', #Required for Perl SPF checking
-			]
-
-			package { $extra_packages:
-				 ensure => installed
-			}
-		}
-		else {
-			$mysqlpackage = 'mysql'
-			$mysqlsuffix = '55w'
-		}
-		$phpmysqlsuffix = 'nd'
-	}
-	elsif $operatingsystem == 'Ubuntu' {
+	if $facts["os"]["name"] == 'Ubuntu' {
 		$mysqlpackage = 'mariadb'
 		$mysqlsuffix = ''
 		$phpmysqlsuffix = ''
 	}
 	else {
-		fail("No MySQL support for ${operatingsystem}")
+		fail("Unsupported OS: ${facts['os']['name']}")
 	}
 	include ::defaultusers::params
 	class { 'website::mysql':
@@ -744,7 +617,7 @@
 	# Debian doesn't handle sensible depends like module names because of the underscore
 	# So we need to use the package name
 	package { "mod_cspnonce":
-		name => $osfamily == 'Debian' ? { true => "libapache2-mod-cspnonce", default => "mod_cspnonce" },
+		name => $facts["os"]["family"] == 'Debian' ? { true => "libapache2-mod-cspnonce", default => "mod_cspnonce" },
 		ensure => installed,
 	}
 
@@ -831,10 +704,10 @@
 		},
 		custom_fragment => template("privat/apache/admin.fragment"),
 	}
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		$cron_user = 'apache'
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		$cron_user = 'www-data'
 	}
 	cron { 'loadavg':
@@ -909,13 +782,10 @@
 	}
 }
 class devsite ($proxy_4to6_ip) {
-	if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 {
-		$package_name = 'python3-mod_wsgi'
-		$mod_path = 'mod_wsgi_python3.so'
-	} else {
-		$package_name = undef
-		$mod_path = undef
-	}
+	# CentOS used to require special values
+	$package_name = undef
+	$mod_path = undef
+
 	class { 'apache::mod::wsgi':
 		  package_name => $package_name,
 		  mod_path => $mod_path,
@@ -986,7 +856,7 @@
 	}
 	# Unspecified SpamAssassin config dependencies that started
 	# showing up as errors in our logs
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		$spamassassin_deps = ['perl-File-MimeInfo']
 		$spamassassin_dir = '/etc/mail/spamassassin/'
 		$amavis_config = '/etc/amavisd/amavisd.conf'
@@ -1000,7 +870,7 @@
 			enable=> 'mask',
 		}
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		$spamassassin_deps = ['libfile-mimeinfo-perl']
 		$spamassassin_dir = '/etc/spamassassin/'
 		$amavis_config = '/etc/amavis/conf.d/60-puppeted'
@@ -1024,7 +894,7 @@
 		ensure => present,
 		content => epp('privat/postfix/amavis.conf.epp',
 			{
-				fqdn => $::fqdn,
+				fqdn => $facts["networking"]["fqdn"],
 				rundir => $amavis_rundir,
 				spooldir => $amavis_spooldir,
 				quarantinedir => $amavis_quarantinedir,
@@ -1063,7 +933,7 @@
 class cronjobs {
 	package { 'cron':
 		ensure => installed,
-		name => $operatingsystem == 'Ubuntu' ? { true => 'cron', default => 'cronie' }
+		name => $osname == 'Ubuntu' ? { true => 'cron', default => 'cronie' }
 	}
 	# Add Mutt for scripts that send emails, but stop it clogging the disk by keeping copies of emails
 	package { 'mutt':
@@ -1082,14 +952,6 @@
 		hour => "4",
 		minute => "9"
 	}
-	# Only run the Great Firewall Against China on IPv4 (since we don't have an IPv6 list
-	# and the PROXY forwards the IPs to services, but not at the network level)
-	cron { 'greatfirewallofchina':
-		command => '/usr/local/bin/update-great-firewall-of-china',
-		ensure => has_key($facts, 'ipaddress') ? { true => "present", default => "absent" },
-		hour => 3,
-		minute => 30
-	}
 	cron { 'permissions':
 		command => '/usr/local/bin/set-permissions',
 		hour => 3,
--- a/modules/dovecot/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/dovecot/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -4,10 +4,10 @@
 	$imapserver_proxy = undef,
 	$proxy_upstream = [],
 	) {
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		$dovecot_package = 'dovecot'
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		$dovecot_package = 'dovecot-imapd'
 	}
 	
@@ -79,7 +79,7 @@
 		destination => $imapserver_ip,
 		dport => 993,
 		proto => tcp,
-		action => accept,
+		jump => accept,
 	}
 	if $imapserver_proxy != undef {
 		$proxy_upstream.each |Stdlib::IP::Address::V6 $upstream_addr| {
@@ -88,7 +88,7 @@
 				destination => $imapserver_proxy,
 				dport => 993,
 				proto => tcp,
-				action => accept,
+				jump => accept,
 			}
 		}
 	}
--- a/modules/fail2ban/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/fail2ban/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -16,13 +16,13 @@
 	file { '/etc/fail2ban/fail2ban.local':
 		source => 'puppet:///modules/fail2ban/fail2ban.local',
 	}
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		$ssh_log = '/var/log/secure'
 		$mail_log = '/var/log/maillog'
 		$log_group = 'root'
 		$log_mode = '0600'
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		$ssh_log = '/var/log/auth.log'
 		$mail_log = '/var/log/mail.log'
 		$log_group = 'adm'
@@ -41,10 +41,10 @@
 		$firewall_ban_cmd = $firewall_cmd
 	}
 
-	if $osfamily == 'RedHat' {
+	if $facts["os"]["family"] == 'RedHat' {
 		$apache_conf_custom = '/etc/httpd/conf.custom/'
 	}
-	elsif $osfamily == 'Debian' {
+	elsif $facts["os"]["family"] == 'Debian' {
 		$apache_conf_custom = '/etc/apache2/conf.custom/'
 	}
 	
@@ -70,7 +70,7 @@
 		ensure => present,
 		seltype => 'httpd_config_t',
 	}
-	if $operatingsystem == 'CentOS' {
+	if $facts["os"]["name"] == 'CentOS' {
 		# And let the httxt2dbm process work the rest of the time
 		file { '/etc/selinux/apache-ip-banlist.pp':
 			source => 'puppet:///modules/fail2ban/apache-ip-banlist.pp',
--- a/modules/my_fw/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/my_fw/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -1,7 +1,7 @@
 class my_fw ($ip_version) {
   $real_ensure_v4 = $ip_version == "IPv6" ? { true => 'stopped', default => 'running'}
   $real_ensure_v6 = $ip_version == "IPv6" ? { true => 'running', default => 'stopped'}
-  case $::operatingsystem {
+  case $facts["os"]["name"] {
     'CentOS': {
       $ensure_v4 = $real_ensure_v4
       $ensure_v6 = $real_ensure_v6
@@ -13,7 +13,7 @@
     }
   }
   Firewall <| |> {
-    provider => $ip_version == "IPv6" ? { true => 'ip6tables', default => 'iptables'},
+    protocol => $ip_version == "IPv6" ? { true => 'ip6tables', default => 'iptables'},
   }
   class { ['my_fw::pre', 'my_fw::post']: }
   class { 'firewall':
--- a/modules/my_fw/manifests/post.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/my_fw/manifests/post.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -1,7 +1,7 @@
 class my_fw::post {
   firewall { '999 drop all':
-    proto   => 'all',
-    action  => 'drop',
-    before  => undef,
+    proto  => 'all',
+    jump   => 'drop',
+    before => undef,
   }
 }
\ No newline at end of file
--- a/modules/my_fw/manifests/pre.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/my_fw/manifests/pre.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -8,23 +8,23 @@
 
    # Default firewall rules
   firewall { '000 accept all icmp':
-    proto   => $icmp_proto,
-    action  => 'accept',
+    proto => $icmp_proto,
+    jump  => 'accept',
   } ->
   firewall { '001 accept all to lo interface':
     proto   => 'all',
     iniface => 'lo',
-    action  => 'accept',
+    jump    => 'accept',
   } ->
   firewall { "002 reject local traffic not on loopback interface":
     iniface     => '! lo',
     proto       => 'all',
     destination => $localhost,
-    action      => 'reject',
+    jump        => 'reject',
   } ->
   firewall { '005 accept related established rules':
-    proto   => 'all',
+    proto => 'all',
     state => ['RELATED', 'ESTABLISHED'],
-    action  => 'accept',
+    jump  => 'accept',
   }
 }
--- a/modules/postfix/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/postfix/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -38,7 +38,7 @@
     destination => $mailserver_ip,
     dport => [25, 465, 587],
     proto => tcp,
-    action => accept,
+    jump => accept,
   }
   if $mailserver_proxy != undef {
     $proxy_upstream.each |Stdlib::IP::Address::V6 $upstream_addr| {
@@ -47,7 +47,7 @@
         destination => $mailserver_proxy,
         dport => [25, 465, 587],
         proto => tcp,
-        action => accept,
+        jump => accept,
       }
     }
   }
@@ -59,7 +59,7 @@
       destination => $nat64_range,
       dport => [25, 265, 587],
       proto => tcp,
-      action => 'reject',
+      jump => 'reject',
       chain => 'OUTPUT',
     }
   }
@@ -76,10 +76,10 @@
     notify  => Exec['postmap-files'],
     require => Package['postfix'],
   }
-  if $osfamily == 'RedHat' {
+  if $facts["os"]["family"] == 'RedHat' {
     $policyd_script = '/usr/libexec/postfix/policyd-spf'
   }
-  elsif $osfamily == 'Debian' {
+  elsif $facts["os"]["family"] == 'Debian' {
     $policyd_script = '/usr/bin/policyd-spf'
   }
   file { '/etc/postfix/main.cf':
@@ -179,11 +179,11 @@
   } 
 
   #SPF checking
-  if $osfamily == 'RedHat' {
+  if $facts["os"]["family"] == 'RedHat' {
     $pypolicyd_package = 'pypolicyd-spf'
     $pypolicyd_config = '/etc/python-policyd-spf/policyd-spf.conf'
   }
-  elsif $osfamily == 'Debian' {
+  elsif $facts["os"]["family"] == 'Debian' {
     $pypolicyd_package = 'postfix-policyd-spf-python'
     $pypolicyd_config = '/etc/postfix-policyd-spf-python/policyd-spf.conf'
   }
--- a/modules/vcs/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/vcs/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -8,6 +8,7 @@
     python::pip { 'mercurial-keyring':
         ensure => 'present',
         pip_provider => 'pip3',
+        install_args => '--break-system-packages',
     }
     # Alt keyrings are insecure, but a) we're on a limited access server and
     # b) I share the Mecurial config with the desktop, which uses the system
@@ -18,8 +19,9 @@
     python::pip { 'keyrings.alt':
         ensure => 'present',
         pip_provider => 'pip3',
+        install_args => '--break-system-packages',
     }
-    if $operatingsystem == 'Ubuntu' {
+    if $facts["os"]["name"] == 'Ubuntu' {
         $gitprompt = '/etc/bash_completion.d/git-prompt'
     }
     else {
--- a/modules/website/manifests/https.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/website/manifests/https.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -106,8 +106,8 @@
     $sslcert = "/etc/letsencrypt/live/${letsencrypt_name}/cert.pem"
     $sslkey = "/etc/letsencrypt/live/${letsencrypt_name}/privkey.pem"
   } else {
-    $sslcert = "/etc/letsencrypt/live/${::fqdn}/cert.pem"
-    $sslkey = "/etc/letsencrypt/live/${::fqdn}/privkey.pem"
+    $sslcert = "/etc/letsencrypt/live/${facts['networking']['fqdn']}/cert.pem"
+    $sslkey = "/etc/letsencrypt/live/${facts['networking']['fqdn']}/privkey.pem"
   }
 
   if $ssl_ca_chain == '' and '' in [$ssl_ca_chain] {
--- a/modules/website/manifests/https/redir.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/website/manifests/https/redir.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -64,8 +64,8 @@
     $sslcert = "/etc/letsencrypt/live/${letsencrypt_name}/cert.pem"
     $sslkey = "/etc/letsencrypt/live/${letsencrypt_name}/privkey.pem"
   } else {
-    $sslcert = "/etc/letsencrypt/live/${::fqdn}/cert.pem"
-    $sslkey = "/etc/letsencrypt/live/${::fqdn}/privkey.pem"
+    $sslcert = "/etc/letsencrypt/live/${facts['networking']['fqdn']}/cert.pem"
+    $sslkey = "/etc/letsencrypt/live/${facts['networking']['fqdn']}/privkey.pem"
   }
 
   if $ssl_ca_chain == '' and '' in [$ssl_ca_chain] {
--- a/modules/website/manifests/init.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/website/manifests/init.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -15,7 +15,7 @@
   $certdir = $cert_dir
   $docroot_owner = $default_owner
   $docroot_group = $default_group
-  $ca_chain = "/etc/letsencrypt/live/${::fqdn}/chain.pem"
+  $ca_chain = "/etc/letsencrypt/live/${facts['networking']['fqdn']}/chain.pem"
   $tld = $default_tld
   $extra_tlds = $default_extra_tlds
   $htmlphpfragment = "Include conf.extra/html-php.conf"
@@ -35,14 +35,14 @@
     "font-src" => "'self' 'nonce-%{CSP_NONCE}e'"
   }
 
-  if $osfamily == 'RedHat' {
+  if $facts["os"]["family"] == 'RedHat' {
     $apache_base_dir = "/etc/httpd/"
     $vhost_dir = "/etc/httpd/conf.d/vhosts"
     $apache_user = 'apache'
     $apache_group = $apache_user
     $apache_log_group = $apache_user
   }
-  elsif $osfamily == 'Debian' {
+  elsif $facts["os"]["family"] == 'Debian' {
     $apache_base_dir = "/etc/apache2/"
     $vhost_dir = "/etc/apache2/sites-available"
     $apache_user = 'www-data'
@@ -60,7 +60,7 @@
   }
   class { 'apache::mod::dir': indexes => [ 'index.html' ] }
   class { 'apache::mod::event': }
-  class { 'apache::mod::http2': }
+#  class { 'apache::mod::http2': }
   class { 'apache::mod::mime': mime_types_config => "${apache_base_dir}mime.types" }
   apache::mod {
     'rewrite':;
@@ -70,12 +70,6 @@
     'headers':;
     'allowmethods':;
   }
-  if $osfamily == 'RedHat' {
-    # Ubuntu builds the "version" module in, but CentOS doesn't
-    apache::mod {
-      'version':;
-    }
-  }
 
   # Updating the httpd package puts back some configs that we
   # don't load the relevant modules for, so we'll try to make
@@ -137,7 +131,7 @@
     destination => $primary_ip,
     dport => [80, 443],
     proto => tcp,
-    action => accept,
+    jump => accept,
   }
   if ($proxy_4to6_ip_prefix != undef) and ($proxy_upstream != undef) {
     apache::mod { "remoteip": }
@@ -149,31 +143,21 @@
         destination => $proxy_4to6_ip,
         dport => [80, 443],
         proto => tcp,
-        action => accept,
+        jump => accept,
       }
     }
     firewall { "101 block all other PROXY protocol access":
       destination => $proxy_4to6_ip,
       dport => [80, 443],
       proto => tcp,
-      action => reject,
+      jump => reject,
     }
   }
-  if $operatingsystem == 'CentOS' {
-    exec { 'set_apache_defaults':
-      command => 'semanage fcontext -a -t httpd_sys_content_t "/srv/sites(/.*)?"',
-      path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
-      require => Package['policycoreutils-python'],
-      unless  => 'semanage fcontext --list | grep "/srv/sites\\(/\\.\\*\\)\\?"',
-    }
-    if versioncmp($operatingsystemrelease, '8') < 0 {
-        $certbot_pkg = 'python2-certbot-apache'
-    } else {
-        $certbot_pkg = 'python3-certbot-apache'
-    }
+  if $facts["os"]["name"] == 'Ubuntu' {
+    $certbot_pkg = 'python3-certbot-apache'
   }
-  elsif $operatingsystem == 'Ubuntu' {
-    $certbot_pkg = 'python3-certbot-apache'
+  else {
+    fail("Unsupported OS: ${facts['os']['name']}")
   }
   cron { 'letsencrypt-renewal':
     command => '/usr/bin/certbot renew --quiet',
--- a/modules/website/manifests/mysql.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/website/manifests/mysql.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -6,10 +6,10 @@
   $phpmysqlsuffix = '',
   $mysqlprefix    = 'mysql')
   {
-  if $osfamily == 'RedHat' {
+  if $facts["os"]["family"] == 'RedHat' {
     $client_package_suffix = ''
   }
-  elsif $osfamily == 'Debian' {
+  elsif $facts["os"]["family"] == 'Debian' {
     $client_package_suffix = '-client'
   }
   
@@ -35,15 +35,7 @@
     'innodb_file_per_table' => '1',
   }
 
-  if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') < 0 {
-    $mysqld_settings = $mysqld_base_settings + {
-      'innodb_file_format' => 'barracuda',
-      'innodb_large_prefix' => 'true',
-    }
-  }
-  else {
-    $mysqld_settings = $mysqld_base_settings
-  }
+  $mysqld_settings = $mysqld_base_settings
 
 
   class { 'mysql::server':
--- a/modules/website/manifests/php.pp	Thu Aug 29 18:48:03 2024 +0100
+++ b/modules/website/manifests/php.pp	Thu Aug 29 18:58:49 2024 +0100
@@ -4,24 +4,17 @@
     $extras = [],
     ) {
   include ::apache::params
-  if $osfamily == 'RedHat' {
-    # Work around SELinux "denied execmem" warnings from preg_match JITing
-    $pcre_jit = 0
-  }
-  else {
-    $pcre_jit = 1
-  }
+  $pcre_jit = 1
 
-  if $operatingsystem == 'CentOS' {
-    $ini_prefix_10 = '10-'
-    $ini_prefix_20 = '20-'
-  }
-  elsif $operatingsystem == 'Ubuntu' {
+  if $facts["os"]["name"] == 'Ubuntu' {
     # Ubuntu doesn't prefix its ini files as created here
     # and has a different way of handling ordering
     $ini_prefix_10 = ''
     $ini_prefix_20 = ''
   }
+  else {
+    fail("Unsupported OS: ${facts['os']['name']}")
+  }
 
   file { '/run/php/':
     ensure => directory,
@@ -57,8 +50,9 @@
       'PHP/default_charset' => 'UTF-8',
       'PHP/pcre.jit' => $pcre_jit,
       # Space isn't scarce these days - increase default sizes
-      'PHP/upload_max_filesize' => "16M",
-      'PHP/post_max_size' => "16M",
+      # The new module is typed, so we need ints instead of "16M"
+      'PHP/upload_max_filesize' => 16777216,
+      'PHP/post_max_size' => 16777216,
       'Data/date.timezone' => 'UTC',
     },
     cli_settings => {