Compare commits

...

4 Commits

Author SHA1 Message Date
unkin-agent b903c0d641 Keep wireguard keys Sensitive and generate missing private keys
ci/woodpecker/pr/ruby-validate Pipeline was successful
ci/woodpecker/pr/puppet-lint Pipeline was successful
ci/woodpecker/pr/yamllint Pipeline was successful
ci/woodpecker/pr/bolt-validate Pipeline was successful
ci/woodpecker/pr/erb-validate Pipeline was successful
ci/woodpecker/pr/epp-validate Pipeline was successful
ci/woodpecker/pr/ruby-check Pipeline was successful
ci/woodpecker/pr/puppet-validate Pipeline was successful
2026-10-03 20:57:00 +10:00
unkin-agent 0bbf797693 Add wireguard module managing wg-quick interfaces
ci/woodpecker/pr/ruby-validate Pipeline was successful
ci/woodpecker/pr/yamllint Pipeline was successful
ci/woodpecker/pr/puppet-lint Pipeline was successful
ci/woodpecker/pr/erb-validate Pipeline was successful
ci/woodpecker/pr/bolt-validate Pipeline was successful
ci/woodpecker/pr/epp-validate Pipeline was successful
ci/woodpecker/pr/ruby-check Pipeline was canceled
ci/woodpecker/pr/puppet-validate Pipeline was canceled
2026-10-03 20:54:06 +10:00
unkin-agent 410a1f13d0 Add 198.18.2.0/24 router loopback subnet (#535)
Router loopbacks in 198.18.2.0/24 (e.g. prodnxsr0020, 198.18.2.160) match no subnet entry, so they get unknown environment/region/country facts and are not autosigned.

- add 198.18.2.0/24 to subnet_facts as prod/syd1/au/common
- add 198.18.2.0/24 to puppet master autosign subnet_ranges

Reviewed-on: #535
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-03 20:46:44 +10:00
unkin-agent ec74484d89 Pin the journald ingest URL to port 443 (#533)
Estate journald ingestion has been down since 00:33Z. `systemd-journal-upload` appends `:19532/upload` to the configured URL whenever that URL carries no explicit port, so the portless k8s endpoint became `/insert/journald:19532/upload`, which vlinsert rejects as an unsupported path. The previous consul URL only worked because `:9428` was explicit.

- pin `victorialogs::client::journald::inserturl` to port 443

Requests then land on `/insert/journald/upload`, which vlinsert accepts.

Reviewed-on: #533
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 11:22:07 +10:00
6 changed files with 143 additions and 1 deletions
+3 -1
View File
@@ -178,6 +178,8 @@ lookup_options:
convert_to: Sensitive
stalwart::fallback_admin_password:
convert_to: Sensitive
wireguard::interfaces:
convert_to: Sensitive
facts_path: '/opt/puppetlabs/facter/facts.d'
@@ -401,7 +403,7 @@ networking::route_defaults:
# logging:
victorialogs::client::journald::enable: true
victorialogs::client::journald::inserturl: https://logs-ingest.k8s.syd1.au.unkin.net/insert/journald
victorialogs::client::journald::inserturl: https://logs-ingest.k8s.syd1.au.unkin.net:443/insert/journald
# FIXME these are for the proxmox ceph cluster
profiles::ceph::client::fsid: 7f7f00cb-95de-498c-8dcc-14b54e4e9ca8
+1
View File
@@ -1,5 +1,6 @@
---
profiles::puppet::autosign::subnet_ranges:
- '198.18.2.0/24'
- '198.18.13.0/24'
- '198.18.14.0/24'
- '198.18.15.0/24'
+1
View File
@@ -5,6 +5,7 @@ require 'ipaddr'
# a class that creates facts based on the subnet
class SubnetAttributes
SUBNET_TO_ATTRIBUTES = {
'198.18.2.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # router loopbacks
'198.18.13.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' },
'198.18.14.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' },
'198.18.15.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' },
+44
View File
@@ -0,0 +1,44 @@
# manage wireguard interfaces via wg-quick
class wireguard (
Boolean $manage_package = true,
String $package_name = 'wireguard-tools',
Variant[Hash, Sensitive[Hash]] $interfaces = {},
) {
if $manage_package {
package { $package_name:
ensure => installed,
before => File['/etc/wireguard'],
}
}
file { '/etc/wireguard':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0700',
}
# hiera hands eyaml secrets over as plain strings inside the (Sensitive) hash; re-wrap them per resource
$raw = $interfaces ? {
Sensitive => $interfaces.unwrap,
default => $interfaces,
}
$raw.each |String $iface, Hash $data| {
$peers = $data.get('peers', []).map |Hash $peer| {
$peer['preshared_key'] =~ String ? {
true => $peer + { 'preshared_key' => Sensitive($peer['preshared_key']) },
default => $peer,
}
}
$private_key = $data['private_key'] =~ String ? {
true => Sensitive($data['private_key']),
default => $data['private_key'],
}
wireguard::interface { $iface:
* => $data + { 'peers' => $peers, 'private_key' => $private_key },
}
}
}
+63
View File
@@ -0,0 +1,63 @@
# manage one wg-quick interface; without private_key, /etc/wireguard/<iface>.key is generated once and loaded via PostUp
define wireguard::interface (
Array[Stdlib::IP::Address] $addresses,
Optional[Stdlib::Port] $listen_port = undef,
Optional[Integer[1280, 9000]] $mtu = undef,
Optional[Sensitive[String[1]]] $private_key = undef,
Array[Struct[{
public_key => String[1],
allowed_ips => Variant[String[1], Array[String[1], 1]],
preshared_key => Optional[Sensitive[String[1]]],
endpoint => Optional[String[1]],
persistent_keepalive => Optional[Integer[0, 65535]],
}]] $peers = [],
) {
$conf = "/etc/wireguard/${name}.conf"
$key = $private_key.then |$k| { $k.unwrap }
if $private_key =~ Undef {
$keyfile = "/etc/wireguard/${name}.key"
exec { "wireguard_genkey_${name}":
command => "/bin/sh -c 'umask 077; wg genkey > ${keyfile}'",
creates => $keyfile,
path => ['/usr/bin', '/usr/sbin', '/bin', '/sbin'],
require => File['/etc/wireguard'],
}
file { $keyfile:
ensure => file,
owner => 'root',
group => 'root',
mode => '0600',
require => Exec["wireguard_genkey_${name}"],
before => [File[$conf], Service["wg-quick@${name}"]],
}
}
file { $conf:
ensure => file,
owner => 'root',
group => 'root',
mode => '0600',
content => Sensitive(template('wireguard/wg.conf.erb')),
show_diff => false,
notify => Exec["wireguard_syncconf_${name}"],
}
service { "wg-quick@${name}":
ensure => running,
enable => true,
require => File[$conf],
}
# syncconf applies peer/key changes without bouncing the tunnel; address/mtu changes need a manual restart
exec { "wireguard_syncconf_${name}":
command => "/bin/bash -c 'wg syncconf ${name} <(wg-quick strip ${name})'",
onlyif => "/usr/sbin/ip link show ${name}",
path => ['/usr/bin', '/usr/sbin', '/bin', '/sbin'],
refreshonly => true,
require => Service["wg-quick@${name}"],
}
}
+31
View File
@@ -0,0 +1,31 @@
# THIS FILE IS MANAGED BY PUPPET
[Interface]
<% @addresses.each do |addr| -%>
Address = <%= addr %>
<% end -%>
<% if @listen_port -%>
ListenPort = <%= @listen_port %>
<% end -%>
<% if @mtu -%>
MTU = <%= @mtu %>
<% end -%>
<% if @key -%>
PrivateKey = <%= @key %>
<% else -%>
PostUp = wg set %i private-key /etc/wireguard/%i.key
<% end -%>
<% @peers.each do |peer| -%>
[Peer]
PublicKey = <%= peer['public_key'] %>
<% if peer['preshared_key'] -%>
PresharedKey = <%= peer['preshared_key'].unwrap %>
<% end -%>
AllowedIPs = <%= Array(peer['allowed_ips']).join(', ') %>
<% if peer['endpoint'] -%>
Endpoint = <%= peer['endpoint'] %>
<% end -%>
<% if peer['persistent_keepalive'] -%>
PersistentKeepalive = <%= peer['persistent_keepalive'] %>
<% end -%>
<% end -%>