Compare commits

..

No commits in common. "main" and "miniserverupdates" have entirely different histories.

113 changed files with 2153 additions and 752 deletions

3
.envrc
View file

@ -1,3 +0,0 @@
layout python3
source_env_if_exists .envrc.local

2
.gitignore vendored
View file

@ -1,5 +1,3 @@
.secrets.cfg*
__pycache__
*.swp
.direnv
.envrc.local

View file

@ -0,0 +1,5 @@
context.exec = [
{ path = "pactl" args = "load-module module-native-protocol-tcp" }
{ path = "pactl" args = "load-module module-zeroconf-discover" }
{ path = "pactl" args = "load-module module-zeroconf-publish" }
]

View file

@ -0,0 +1,3 @@
[Autologin]
User=${user}
Session=i3.desktop

View file

@ -0,0 +1,110 @@
from os import listdir
from os.path import join
actions = {
'fc-cache_flush': {
'command': 'fc-cache -f',
'triggered': True,
'needs': {
'pkg_pacman:fontconfig',
},
},
'i3pystatus_create_virtualenv': {
'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/i3pystatus/venv/',
'unless': 'test -d /opt/i3pystatus/venv/',
'needs': {
'directory:/opt/i3pystatus/src',
'pkg_pacman:python-virtualenv',
},
},
'i3pystatus_install': {
'command': ' && '.join([
'cd /opt/i3pystatus/src',
'/opt/i3pystatus/venv/bin/pip install --upgrade pip colour netifaces basiciw pytz',
'/opt/i3pystatus/venv/bin/pip install --upgrade -e .',
]),
'needs': {
'action:i3pystatus_create_virtualenv',
},
'triggered': True,
},
}
directories = {
'/etc/sddm.conf.d': {
'purge': True,
},
'/opt/i3pystatus/src': {},
'/usr/share/fonts/bundlewrap': {
'purge': True,
'triggers': {
'action:fc-cache_flush',
},
},
}
svc_systemd = {
'avahi-daemon': {
'needs': {
'pkg_pacman:avahi',
},
},
'sddm': {
'needs': {
'pkg_pacman:sddm',
},
},
}
git_deploy = {
'/opt/i3pystatus/src': {
'repo': 'https://github.com/enkore/i3pystatus.git',
'rev': 'current',
'triggers': {
'action:i3pystatus_install',
},
},
}
files['/etc/pipewire/pipewire-pulse.conf.d/50-network.conf'] = {}
for filename in listdir(join(repo.path, 'data', 'arch-with-gui', 'files', 'fonts')):
if filename.startswith('.'):
continue
if filename.endswith('.vault'):
# XXX remove this once we have a new bundlewrap release
# https://github.com/bundlewrap/bundlewrap/commit/2429b153dd1ca6781cf3812e2dec9c2b646a546b
from os import environ
if environ.get('BW_VAULT_DUMMY_MODE', '0') == '1':
continue
font_name = filename[:-6]
attrs = {
'content': repo.vault.decrypt_file_as_base64(join('arch-with-gui', 'files', 'fonts', filename)),
'content_type': 'base64',
}
else:
font_name = filename
attrs = {
'source': join('fonts', filename),
'content_type': 'binary',
}
files[f'/usr/share/fonts/bundlewrap/{font_name}'] = {
'triggers': {
'action:fc-cache_flush',
},
**attrs,
}
if node.metadata.get('arch-with-gui/autologin_as', None):
files['/etc/sddm.conf.d/autologin.conf'] = {
'context': {
'user': node.metadata.get('arch-with-gui/autologin_as'),
},
'content_type': 'mako',
'before': {
'svc_systemd:sddm',
},
}

View file

@ -0,0 +1,124 @@
assert node.os == 'arch'
defaults = {
'backups': {
'paths': {
'/etc/netctl',
},
},
'icinga_options': {
'exclude_from_monitoring': True,
},
'nftables': {
'input': {
'50-avahi': {
'udp dport 5353 accept',
'udp sport 5353 accept',
},
},
},
'pacman': {
'packages': {
# fonts
'fontconfig': {},
'ttf-dejavu': {
'needed_by': {
'pkg_pacman:sddm',
},
},
# login management
'sddm': {},
# networking
'avahi': {},
'netctl': {},
'util-linux': {}, # provides rfkill
'wpa_supplicant': {},
'wpa_actiond': {},
# shell and other gui stuff
'dunst': {},
'fish': {},
'kitty': {},
'libnotify': {}, # provides notify-send
'light': {},
'redshift': {},
'rofi': {},
# sound
'calf': {},
'easyeffects': {},
'lsp-plugins': {},
'pavucontrol': {},
'pipewire': {},
'pipewire-jack': {},
'pipewire-pulse': {},
'pipewire-zeroconf': {},
'qpwgraph': {},
# window management
'i3-wm': {},
'i3lock': {},
'xss-lock': {},
# i3pystatus dependencies
'iw': {},
'wireless_tools': {},
# Xorg
'xf86-input-libinput': {},
'xf86-input-wacom': {},
'xorg-server': {},
'xorg-setxkbmap': {},
'xorg-xev': {},
'xorg-xinput': {},
'xorg-xset': {},
# all them apps
'browserpass': {},
'browserpass-firefox': {},
'ffmpeg': {},
'firefox': {},
'gimp': {},
'imagemagick': {},
'inkscape': {},
'kdenlive': {},
'maim': {},
'mosh': {},
'mosquitto': {},
'mpv': {},
'pass': {},
'pass-otp': {},
'pdftk': {},
'pwgen': {},
'qpdfview': {},
'samba': {},
'shotcut': {},
'sipcalc': {},
'the_silver_searcher': {},
'tlp': {},
'virt-manager': {},
'xclip': {},
'xdotool': {}, # needed for maim window selection
},
},
}
@metadata_reactor.provides(
'backups/paths',
)
def backup_every_user_home(metadata):
paths = set()
for user, config in metadata.get('users', {}).items():
if config.get('delete', False):
continue
paths.add(config.get('home', f'/home/{user}'))
return {
'backups': {
'paths': paths,
},
}

View file

@ -1,22 +0,0 @@
[server]
host-name=${node.name.split('.')[-1]}
use-ipv4=yes
use-ipv6=${'yes' if node.metadata.get('avahi-daemon/use-ipv6') else 'no'}
allow-interfaces=${','.join(sorted(node.metadata.get('interfaces', {}).keys()))}
ratelimit-interval-usec=1000000
ratelimit-burst=1000
[wide-area]
enable-wide-area=yes
[publish]
disable-publishing=no
disable-user-service-publishing=no
publish-hinfo=yes
publish-workstation=no
publish-aaaa-on-ipv4=no
publish-a-on-ipv6=no
[reflector]
[rlimits]

View file

@ -1,18 +0,0 @@
directories['/etc/avahi/services'] = {
'purge': True,
}
files['/etc/avahi/avahi-daemon.conf'] = {
'content_type': 'mako',
'triggers': {
'svc_systemd:avahi-daemon:restart',
},
}
svc_systemd['avahi-daemon'] = {
'needs': {
'file:/etc/avahi/avahi-daemon.conf',
'pkg_apt:avahi-daemon',
'pkg_apt:libnss-mdns',
},
}

View file

@ -1,11 +0,0 @@
defaults = {
'apt': {
'packages': {
'avahi-daemon': {},
'libnss-mdns': {},
},
},
'avahi-daemon': {
'use-ipv6': True,
}
}

View file

@ -24,6 +24,7 @@ files = {
'before': {
'action:',
'pkg_apt:',
'pkg_pacman:',
},
},
}

View file

@ -1,5 +1,10 @@
if node.os == 'arch':
filename = '/etc/bird.conf'
else:
filename = '/etc/bird/bird.conf'
files = {
'/etc/bird/bird.conf': {
filename: {
'content_type': 'mako',
'triggers': {
'svc_systemd:bird:reload',
@ -10,7 +15,7 @@ files = {
svc_systemd = {
'bird': {
'needs': {
f'file:/etc/bird/bird.conf',
f'file:{filename}',
},
},
}

View file

@ -13,6 +13,15 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'bird': {
'needed_by': {
'svc_systemd:bird',
},
},
},
},
'sysctl': {
'options': {
'net.ipv4.conf.all.forwarding': '1',

View file

@ -1,3 +1,10 @@
if node.os == 'arch':
service_name = 'cronie'
package_name = 'pkg_pacman:cronie'
else:
service_name = 'cron'
package_name = 'pkg_apt:cron'
files = {
'/etc/crontab': {
'content_type': 'mako',
@ -17,9 +24,9 @@ directories = {
}
svc_systemd = {
'cron': {
service_name: {
'needs': {
'pkg_apt:cron',
package_name,
},
},
}

View file

@ -4,4 +4,9 @@ defaults = {
'cron': {},
},
},
'pacman': {
'packages': {
'cronie': {},
},
},
}

View file

@ -20,7 +20,7 @@ def nodejs(metadata):
if version >= (1, 11, 71):
return {
'nodejs': {
'version': 22,
'version': 20,
},
}
else:

View file

@ -129,14 +129,11 @@ def notify_per_ntfy():
data=message_text,
headers=headers,
auth=(CONFIG['ntfy']['user'], CONFIG['ntfy']['password']),
timeout=10,
)
r.raise_for_status()
except Exception as e:
log_to_syslog('Sending a Notification failed: {}'.format(repr(e)))
return False
return True
def notify_per_mail():
@ -202,8 +199,7 @@ if __name__ == '__main__':
notify_per_mail()
if args.sms:
ntfy_worked = False
if CONFIG['ntfy']['user']:
ntfy_worked = notify_per_ntfy()
if not args.service_name or not ntfy_worked:
if not args.service_name:
notify_per_sms()
if CONFIG['ntfy']['user']:
notify_per_ntfy()

View file

@ -401,6 +401,22 @@ for rnode in sorted(repo.nodes):
DAYS_TO_STRING[day%7]: f'{hour}:{minute}-{hour}:{minute+15}',
},
})
elif (
rnode.has_bundle('pacman')
and rnode.metadata.get('pacman/unattended-upgrades/is_enabled', False)
):
day = rnode.metadata.get('pacman/unattended-upgrades/day')
hour = rnode.metadata.get('pacman/unattended-upgrades/hour')
minute = rnode.magic_number%30
downtimes.append({
'name': 'unattended-upgrades',
'host': rnode.name,
'comment': f'Downtime for upgrade-and-reboot of node {rnode.name}',
'times': {
DAYS_TO_STRING[day%7]: f'{hour}:{minute}-{hour}:{minute+15}',
},
})
files['/etc/icinga2/conf.d/groups.conf'] = {
'source': 'icinga2/groups.conf',

View file

@ -17,6 +17,7 @@ defaults = {
'icinga2': {},
'icinga2-ido-pgsql': {},
'icingaweb2': {},
'icingaweb2-module-monitoring': {},
'python3-easysnmp': {},
'python3-flask': {},
'snmp': {},

View file

@ -1,13 +1,10 @@
from datetime import datetime, timedelta, timezone
assert node.has_bundle('redis')
from datetime import datetime, timedelta
defaults = {
'infobeamer-cms': {
'config': {
'MAX_UPLOADS': 5,
'PREFERRED_URL_SCHEME': 'https',
'REDIS_HOST': '127.0.0.1',
'SESSION_COOKIE_NAME': '__Host-sess',
'STATIC_PATH': '/opt/infobeamer-cms/static',
'URL_KEY': repo.vault.password_for(f'{node.name} infobeamer-cms url key'),
@ -52,7 +49,7 @@ def nginx(metadata):
'infobeamer-cms/config/TIME_MIN',
)
def event_times(metadata):
event_start = datetime.strptime(metadata.get('infobeamer-cms/event_start_date'), '%Y-%m-%d').replace(tzinfo=timezone.utc)
event_start = datetime.strptime(metadata.get('infobeamer-cms/event_start_date'), '%Y-%m-%d')
event_duration = metadata.get('infobeamer-cms/event_duration_days', 4)
event_end = event_start + timedelta(days=event_duration)

View file

@ -1,10 +1,9 @@
#!/usr/bin/env python3
import logging
from datetime import datetime
from datetime import datetime, timezone
from json import dumps
from time import sleep
from zoneinfo import ZoneInfo
import paho.mqtt.client as mqtt
from requests import RequestException, get
@ -25,8 +24,7 @@ logging.basicConfig(
)
LOG = logging.getLogger("main")
TZ = ZoneInfo("Europe/Berlin")
DUMP_TIME = "0900"
MLOG = logging.getLogger("mqtt")
state = None
@ -40,10 +38,7 @@ def mqtt_out(message, level="INFO", device=None):
key = "infobeamer"
if device:
key += f"/{device['id']}"
if device["description"]:
message = f"[{device['description']}] {message}"
else:
message = f"[{device['serial']}] {message}"
message = f"[{device['description']}] {message}"
client.publish(
CONFIG["mqtt"]["topic"],
@ -66,14 +61,14 @@ def mqtt_dump_state(device):
out.append("Location: {}".format(device["location"]))
out.append("Setup: {} ({})".format(device["setup"]["name"], device["setup"]["id"]))
out.append("Resolution: {}".format(device["run"].get("resolution", "unknown")))
if not device["is_synced"]:
out.append("syncing ...")
mqtt_out(
" - ".join(out),
device=device,
)
def is_dump_time():
return datetime.now(TZ).strftime("%H%M") == DUMP_TIME
mqtt_out("Monitor starting up")
while True:
@ -86,14 +81,15 @@ while True:
r.raise_for_status()
ib_state = r.json()["devices"]
except RequestException as e:
LOG.exception("Could not get device data from info-beamer")
LOG.exception("Could not get data from info-beamer")
mqtt_out(
f"Could not get device data from info-beamer: {e!r}",
f"Could not get data from info-beamer: {e!r}",
level="WARN",
)
else:
new_state = {}
for device in sorted(ib_state, key=lambda x: x["id"]):
online_devices = set()
for device in ib_state:
did = str(device["id"])
if did in new_state:
@ -101,8 +97,7 @@ while True:
continue
new_state[did] = device
# force information output for every online device at 09:00 CE(S)T
must_dump_state = is_dump_time()
must_dump_state = False
if state is not None:
if did not in state:
@ -145,15 +140,16 @@ while True:
if device["is_online"]:
if device["maintenance"]:
mqtt_out(
"maintenance required: {}".format(
" ".join(sorted(device["maintenance"]))
),
"maintenance required: {}".format(' '.join(
sorted(device["maintenance"])
)),
level="WARN",
device=device,
)
if (
device["location"] != state[did]["location"]
device["is_synced"] != state[did]["is_synced"]
or device["location"] != state[did]["location"]
or device["setup"]["id"] != state[did]["setup"]["id"]
or device["run"].get("resolution")
!= state[did]["run"].get("resolution")
@ -165,52 +161,23 @@ while True:
else:
LOG.info("adding device {} to empty state".format(device["id"]))
if device["is_online"]:
online_devices.add(
"{} ({})".format(
device["id"],
device["description"],
)
)
state = new_state
try:
r = get(
"https://info-beamer.com/api/v1/account",
auth=("", CONFIG["api_key"]),
)
r.raise_for_status()
ib_account = r.json()
except RequestException as e:
LOG.exception("Could not get account data from info-beamer")
mqtt_out(
f"Could not get account data from info-beamer: {e!r}",
level="WARN",
)
else:
available_credits = ib_account["balance"]
if is_dump_time():
mqtt_out(f"Available Credits: {available_credits}")
if available_credits < 50:
mqtt_out(
f"balance has dropped below 50 credits! (available: {available_credits})",
level="ERROR",
)
elif available_credits < 100:
mqtt_out(
f"balance has dropped below 100 credits! (available: {available_credits})",
level="WARN",
)
for quota_name, quota_config in sorted(ib_account["quotas"].items()):
value = quota_config["count"]["value"]
limit = quota_config["count"]["limit"]
if value > limit * 0.9:
mqtt_out(
f"quota {quota_name} is over 90% (limit {limit}, value {value})",
level="ERROR",
)
elif value > limit * 0.8:
mqtt_out(
f"quota {quota_name} is over 80% (limit {limit}, value {value})",
level="WARN",
)
sleep(60)
if (
datetime.now(timezone.utc).strftime("%H%M") == "1312"
and online_devices
and int(datetime.now(timezone.utc).strftime("%S")) < 30
):
mqtt_out("Online Devices: {}".format(", ".join(sorted(online_devices))))
sleep(30)
except KeyboardInterrupt:
break

View file

@ -19,4 +19,9 @@ defaults = {
'/usr/bin/ipmitool *',
},
},
'pacman': {
'packages': {
'ipmitool': {},
},
},
}

View file

@ -13,6 +13,15 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'dehydrated': {
'needed_by': {
'action:letsencrypt_update_certificates',
},
},
},
},
}

View file

@ -10,4 +10,15 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'lldpd': {
'needed_by': {
'directory:/etc/lldpd.d',
'file:/etc/lldpd.conf',
'svc_systemd:lldpd',
},
},
},
},
}

View file

@ -4,6 +4,11 @@ defaults = {
'lm-sensors': {},
},
},
'pacman': {
'packages': {
'lm_sensors': {},
},
},
'telegraf': {
'input_plugins': {
'builtin': {

View file

@ -0,0 +1,40 @@
server_location: 'http://[::1]:20080'
server_name: '${server_name}'
registration_shared_secret: '${reg_secret}'
admin_api_shared_secret: '${admin_secret}'
base_url: '${base_url}'
client_redirect: '${client_redirect}'
client_logo: 'static/images/element-logo.png' # use '{cwd}' for current working directory
#db: 'sqlite:///opt/matrix-registration/data/db.sqlite3'
db: 'postgresql://${database['user']}:${database['password']}@localhost/${database['database']}'
host: 'localhost'
port: 20100
rate_limit: ["100 per day", "10 per minute"]
allow_cors: false
ip_logging: false
logging:
disable_existing_loggers: false
version: 1
root:
level: DEBUG
handlers: [console]
formatters:
brief:
format: '%(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: brief
stream: ext://sys.stdout
# password requirements
password:
min_length: 8
# username requirements
username:
validation_regex: [] #list of regexes that the selected username must match. Example: '[a-zA-Z]\.[a-zA-Z]'
invalidation_regex: #list of regexes that the selected username must NOT match. Example: '(admin|support)'
- '^abuse'
- 'admin'
- 'support'
- 'help'

View file

@ -0,0 +1,14 @@
[Unit]
Description=matrix-registration
After=network.target
[Service]
User=matrix-registration
Group=matrix-registration
WorkingDirectory=/opt/matrix-registration/src
ExecStart=/opt/matrix-registration/venv/bin/matrix-registration --config-path /opt/matrix-registration/config.yaml serve
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,65 @@
actions['matrix-registration_create_virtualenv'] = {
'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/matrix-registration/venv/',
'unless': 'test -d /opt/matrix-registration/venv/',
'needs': {
# actually /opt/matrix-registration, but we don't create that
'directory:/opt/matrix-registration/src',
},
}
actions['matrix-registration_install'] = {
'command': ' && '.join([
'cd /opt/matrix-registration/src',
'/opt/matrix-registration/venv/bin/pip install psycopg2-binary',
'/opt/matrix-registration/venv/bin/pip install -e .',
]),
'needs': {
'action:matrix-registration_create_virtualenv',
},
'triggered': True,
}
users['matrix-registration'] = {
'home': '/opt/matrix-registration',
}
directories['/opt/matrix-registration/src'] = {}
git_deploy['/opt/matrix-registration/src'] = {
'repo': 'https://github.com/zeratax/matrix-registration.git',
'rev': 'master',
'triggers': {
'action:matrix-registration_install',
'svc_systemd:matrix-registration:restart',
},
}
files['/opt/matrix-registration/config.yaml'] = {
'content_type': 'mako',
'context': {
'admin_secret': node.metadata.get('matrix-registration/admin_secret'),
'base_url': node.metadata.get('matrix-registration/base_path', ''),
'client_redirect': node.metadata.get('matrix-registration/client_redirect'),
'database': node.metadata.get('matrix-registration/database'),
'reg_secret': node.metadata.get('matrix-synapse/registration_shared_secret'),
'server_name': node.metadata.get('matrix-synapse/server_name'),
},
'triggers': {
'svc_systemd:matrix-registration:restart',
},
}
files['/usr/local/lib/systemd/system/matrix-registration.service'] = {
'triggers': {
'action:systemd-reload',
'svc_systemd:matrix-registration:restart',
},
}
svc_systemd['matrix-registration'] = {
'needs': {
'action:matrix-registration_install',
'file:/opt/matrix-registration/config.yaml',
'file:/usr/local/lib/systemd/system/matrix-registration.service',
},
}

View file

@ -0,0 +1,25 @@
defaults = {
'bash_aliases': {
'matrix-registration': '/opt/matrix-registration/venv/bin/matrix-registration --config-path /opt/matrix-registration/config.yaml',
},
'matrix-registration': {
'admin_secret': repo.vault.password_for(f'{node.name} matrix-registration admin secret'),
'database': {
'user': 'matrix-registration',
'password': repo.vault.password_for(f'{node.name} postgresql matrix-registration'),
'database': 'matrix-registration',
},
},
'postgresql': {
'roles': {
'matrix-registration': {
'password': repo.vault.password_for(f'{node.name} postgresql matrix-registration'),
},
},
'databases': {
'matrix-registration': {
'owner': 'matrix-registration',
},
},
},
}

View file

@ -1,3 +1,8 @@
if node.has_bundle('pacman'):
package = 'pkg_pacman:nfs-utils'
else:
package = 'pkg_apt:nfs-common'
for mount, data in node.metadata.get('nfs-client/mounts',{}).items():
data['mount'] = mount
data['mount_options'] = set(data.get('mount_options', set()))
@ -37,7 +42,7 @@ for mount, data in node.metadata.get('nfs-client/mounts',{}).items():
'file:/etc/systemd/system/{}.automount'.format(unitname),
'directory:{}'.format(data['mountpoint']),
'svc_systemd:systemd-networkd',
'pkg_apt:nfs-common',
package,
},
}
else:
@ -53,7 +58,7 @@ for mount, data in node.metadata.get('nfs-client/mounts',{}).items():
'file:/etc/systemd/system/{}.mount'.format(unitname),
'directory:{}'.format(data['mountpoint']),
'svc_systemd:systemd-networkd',
'pkg_apt:nfs-common',
package,
},
}

View file

@ -4,6 +4,11 @@ defaults = {
'nfs-common': {},
},
},
'pacman': {
'packages': {
'nfs-utils': {},
},
},
}
if node.has_bundle('telegraf'):

View file

@ -1,3 +1,8 @@
if node.has_bundle('pacman'):
package = 'pkg_pacman:nftables'
else:
package = 'pkg_apt:nftables'
directories = {
# used by other bundles
'/etc/nftables-rules.d': {
@ -37,7 +42,7 @@ svc_systemd = {
'nftables': {
'needs': {
'file:/etc/nftables.conf',
'pkg_apt:nftables',
package,
},
},
}

View file

@ -10,6 +10,23 @@ defaults = {
'blocked_v4': repo.libs.firewall.global_ip4_blocklist,
'blocked_v6': repo.libs.firewall.global_ip6_blocklist,
},
'pacman': {
'packages': {
'nftables': {},
# https://github.com/bundlewrap/bundlewrap/issues/688
# 'iptables': {
# 'installed': False,
# 'needed_by': {
# 'pkg_pacman:iptables-nft',
# },
# },
'iptables-nft': {
'needed_by': {
'pkg_pacman:nftables',
},
},
},
},
}
if not node.has_bundle('vmhost') and not node.has_bundle('docker-engine'):

View file

@ -0,0 +1,9 @@
[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
ExecStop=
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

View file

@ -1,4 +1,4 @@
user www-data;
user ${username};
worker_processes ${worker_processes};
pid /var/run/nginx.pid;

View file

@ -1,5 +1,12 @@
from datetime import datetime, timedelta
if node.has_bundle('pacman'):
package = 'pkg_pacman:nginx'
username = 'http'
else:
package = 'pkg_apt:nginx'
username = 'www-data'
directories = {
'/etc/nginx/sites': {
'purge': True,
@ -17,9 +24,9 @@ directories = {
},
},
'/var/log/nginx-timing': {
'owner': 'www-data',
'owner': username,
'needs': {
'pkg_apt:nginx',
package,
},
},
'/var/www': {},
@ -33,6 +40,7 @@ files = {
'/etc/nginx/nginx.conf': {
'content_type': 'mako',
'context': {
'username': username,
**node.metadata['nginx'],
},
'triggers': {
@ -61,13 +69,21 @@ files = {
'/var/www/error.html': {},
'/var/www/not_found.html': {},
}
if node.has_bundle('pacman'):
files['/etc/systemd/system/nginx.service.d/bundlewrap.conf'] = {
'source': 'arch-override.conf',
'triggers': {
'action:systemd-reload',
'svc_systemd:nginx:restart',
},
}
svc_systemd = {
'nginx': {
'needs': {
'action:generate-dhparam',
'directory:/var/log/nginx-timing',
'pkg_apt:nginx',
package,
},
},
}

View file

@ -33,6 +33,11 @@ defaults = {
'nginx': {
'worker_connections': 768,
},
'pacman': {
'packages': {
'nginx': {},
},
},
}
if node.has_bundle('telegraf'):

View file

@ -27,22 +27,29 @@ files = {
},
}
if node.has_bundle('pacman'):
package = 'pkg_pacman:openssh'
service = 'sshd'
else:
package = 'pkg_apt:openssh-server'
service = 'ssh'
actions = {
'sshd_check_config': {
'command': 'sshd -T -C user=root -C host=localhost -C addr=localhost',
'triggered': True,
'triggers': {
'svc_systemd:ssh:restart',
'svc_systemd:{}:restart'.format(service),
},
},
}
svc_systemd = {
'ssh': {
service: {
'needs': {
'file:/etc/systemd/system/ssh.service.d/bundlewrap.conf',
'file:/etc/ssh/sshd_config',
'pkg_apt:openssh-server',
package,
},
},
}

View file

@ -8,6 +8,11 @@ defaults = {
'openssh-sftp-server': {},
},
},
'pacman': {
'packages': {
'openssh': {},
},
},
}
@metadata_reactor.provides(

View file

@ -0,0 +1,38 @@
#!/bin/bash
statusfile="/var/tmp/unattended_upgrades.status"
if ! [[ -f "$statusfile" ]]
then
echo "Status file not found"
exit 3
fi
mtime=$(stat -c %Y $statusfile)
now=$(date +%s)
if (( $now - $mtime > 60*60*24*8 ))
then
echo "Status file is older than 8 days!"
exit 3
fi
exitcode=$(cat $statusfile)
case "$exitcode" in
abort_ssh)
echo "Upgrades skipped due to active SSH login"
exit 1
;;
0)
if [[ -f /var/run/reboot-required ]]
then
echo "OK, but updates require a reboot"
exit 1
else
echo "OK"
exit 0
fi
;;
*)
echo "Last exitcode was $exitcode"
exit 2
;;
esac

View file

@ -0,0 +1,18 @@
#!/bin/bash
set -xeuo pipefail
pacman -Syu --noconfirm --noprogressbar
% for affected, restarts in sorted(restart_triggers.items()):
up_since=$(systemctl show "${affected}" | sed -n 's/^ActiveEnterTimestamp=//p' || echo 0)
up_since_ts=$(date -d "$up_since" +%s || echo 0)
now=$(date +%s)
if [ $((now - up_since_ts)) -lt 3600 ]
then
% for restart in sorted(restarts):
systemctl restart "${restart}" || true
% endfor
fi
% endfor

View file

@ -0,0 +1,2 @@
# just disable faillock.
deny = 0

View file

@ -0,0 +1,52 @@
[options]
Architecture = auto
CheckSpace
Color
HoldPkg = ${' '.join(sorted(node.metadata.get('pacman/ask_before_removal')))}
ILoveCandy
IgnorePkg = ${' '.join(sorted(node.metadata.get('pacman/ignore_packages', set())))}
LocalFileSigLevel = Optional
NoExtract=${' '.join(sorted(node.metadata.get('pacman/no_extract', set())))}
ParallelDownloads = ${node.metadata.get('pacman/parallel_downloads')}
SigLevel = Required DatabaseOptional
VerbosePkgLists
% for line in sorted(node.metadata.get('pacman/additional_config', set())):
${line}
% endfor
[core]
Server = ${node.metadata.get('pacman/repository')}
Include = /etc/pacman.d/mirrorlist
[extra]
Server = ${node.metadata.get('pacman/repository')}
Include = /etc/pacman.d/mirrorlist
[community]
Server = ${node.metadata.get('pacman/repository')}
Include = /etc/pacman.d/mirrorlist
% if node.metadata.get('pacman/enable_multilib', False):
[multilib]
Server = ${node.metadata.get('pacman/repository')}
Include = /etc/pacman.d/mirrorlist
% endif
% if node.metadata.get('pacman/enable_aurto', True):
[aurto]
Server = https://aurto.kunbox.net/
SigLevel = Optional TrustAll
% endif
% if node.has_bundle('zfs'):
[archzfs]
Server = http://archzfs.com/archzfs/x86_64
% if node.metadata.get('pacman/linux-lts', False):
[zfs-linux-lts]
% else:
[zfs-linux]
% endif
Server = http://kernels.archzfs.com/$repo/
% endif

View file

@ -0,0 +1,49 @@
#!/bin/bash
# With systemd, we can force logging to the journal. This is better than
# spamming the world with cron mails. You can then view these logs using
# "journalctl -rat upgrade-and-reboot".
if which logger >/dev/null 2>&1
then
# Dump stdout and stderr to logger, which will then put everything
# into the journal.
exec 1> >(logger -t upgrade-and-reboot -p user.info)
exec 2> >(logger -t upgrade-and-reboot -p user.error)
fi
. /etc/upgrade-and-reboot.conf
echo "Starting upgrade-and-reboot for node $nodename ..."
statusfile="/var/tmp/unattended_upgrades.status"
# Workaround, because /var/tmp is usually 1777
[[ "$UID" == 0 ]] && chown root:root "$statusfile"
logins=$(ps h -C sshd -o euser | awk '$1 != "root" && $1 != "sshd" && $1 != "sshmon" && $1 != "nobody"')
if [[ -n "$logins" ]]
then
echo "Will abort now, there are active SSH logins: $logins"
echo "abort_ssh" > "$statusfile"
exit 1
fi
softlockdir=/var/lib/bundlewrap/soft-$nodename
mkdir -p "$softlockdir"
printf '{"comment": "UPDATE", "date": %s, "expiry": %s, "id": "UNATTENDED", "items": ["*"], "user": "root@localhost"}\n' \
$(date +%s) \
$(date -d 'now + 30 mins' +%s) \
>"$softlockdir"/UNATTENDED
trap 'rm -f "$softlockdir"/UNATTENDED' EXIT
do-unattended-upgrades
ret=$?
echo "$ret" > "$statusfile"
if (( $ret != 0 ))
then
exit 1
fi
systemctl reboot
echo "upgrade-and-reboot for node $nodename is DONE"

View file

@ -0,0 +1,3 @@
nodename="${node.name}"
reboot_mail_to="${node.metadata.get('apt/unattended-upgrades/reboot_mail_to', '')}"
auto_reboot_enabled="${node.metadata.get('apt/unattended-upgrades/reboot_enabled', True)}"

113
bundles/pacman/items.py Normal file
View file

@ -0,0 +1,113 @@
from bundlewrap.exceptions import BundleError
if not node.os == 'arch':
raise BundleError(f'{node.name}: bundle:pacman requires arch linux')
files = {
'/etc/pacman.conf': {
'content_type': 'mako',
},
'/etc/upgrade-and-reboot.conf': {
'content_type': 'mako',
},
'/etc/security/faillock.conf': {},
'/usr/local/sbin/upgrade-and-reboot': {
'mode': '0700',
},
'/usr/local/sbin/do-unattended-upgrades': {
'content_type': 'mako',
'mode': '0700',
'context': {
'restart_triggers': node.metadata.get('pacman/restart_triggers', {}),
}
},
'/usr/local/share/icinga/plugins/check_unattended_upgrades': {
'mode': '0755',
},
}
svc_systemd['paccache.timer'] = {
'needs': {
'pkg_pacman:pacman-contrib',
},
}
pkg_pacman = {
'at': {},
'autoconf': {},
'automake': {},
'bind': {},
'binutils': {},
'bison': {},
'bzip2': {},
'curl': {},
'dialog': {},
'diffutils': {},
'fakeroot': {},
'file': {},
'findutils': {},
'flex': {},
'fwupd': {},
'gawk': {},
'gcc': {},
'gettext': {},
'git': {},
'gnu-netcat': {},
'grep': {},
'groff': {},
'gzip': {},
'htop': {},
'jq': {},
'ldns': {},
'less': {},
'libtool': {},
'logrotate': {},
'lsof': {},
'm4': {},
'mailutils': {},
'make': {},
'man-db': {},
'man-pages': {},
'moreutils': {},
'mtr': {},
'ncdu': {},
'nmap': {},
'pacman-contrib': {},
'patch': {},
'pkgconf': {},
'python': {},
'python-setuptools': {
'needed_by': {
'pkg_pip:',
},
},
'python-pip': {
'needed_by': {
'pkg_pip:',
},
},
'python-virtualenv': {},
'rsync': {},
'run-parts': {},
'sed': {},
'tar': {},
'texinfo': {},
'tmux': {},
'tree': {},
'unzip': {},
'vim': {},
'wget': {},
'which': {},
'whois': {},
'zip': {},
}
if node.metadata.get('pacman/linux-lts', False):
pkg_pacman['linux-lts'] = {}
pkg_pacman['acpi_call-lts'] = {}
else:
pkg_pacman['linux'] = {}
pkg_pacman['acpi_call'] = {}
for pkg, config in node.metadata.get('pacman/packages', {}).items():
pkg_pacman[pkg] = config

View file

@ -0,0 +1,54 @@
defaults = {
'pacman': {
'ask_before_removal': {
'glibc',
'pacman',
},
'no_extract': {
'etc/cron.d/0hourly',
# don't install systemd-homed pam module. It produces a lot of spam in
# journal about systemd-homed not being active, so just get rid of it.
# Requires reinstall of systemd package, though
'usr/lib/security/pam_systemd_home.so',
},
'parallel_downloads': 4,
'repository': 'http://ftp.uni-kl.de/pub/linux/archlinux/$repo/os/$arch',
'unattended-upgrades': {
'day': 5,
'hour': 21,
},
},
}
@metadata_reactor.provides(
'cron/jobs/upgrade-and-reboot',
'icinga2_api/pacman/services',
)
def patchday(metadata):
if not metadata.get('pacman/unattended-upgrades/is_enabled', False):
return {}
day = metadata.get('pacman/unattended-upgrades/day')
hour = metadata.get('pacman/unattended-upgrades/hour')
return {
'cron': {
'jobs': {
'upgrade-and-reboot': '{minute} {hour} * * {day} root /usr/local/sbin/upgrade-and-reboot'.format(
minute=node.magic_number % 30,
hour=hour,
day=day,
),
},
},
'icinga2_api': {
'pacman': {
'services': {
'UNATTENDED UPGRADES': {
'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_unattended_upgrades',
},
},
},
},
}

View file

@ -34,7 +34,7 @@ defaults = {
},
},
'nodejs': {
'version': 22,
'version': 18,
},
'postgresql': {
'roles': {

View file

@ -0,0 +1,6 @@
[Service]
# arch postfix is not set up for chrooting by default
ExecStartPre=-/usr/sbin/mkdir -p /var/spool/postfix/etc
% for file in ['/etc/localtime', '/etc/nsswitch.conf', '/etc/resolv.conf', '/etc/services']:
ExecStartPre=-/usr/sbin/cp -p ${file} /var/spool/postfix${file}
% endfor

View file

@ -25,6 +25,7 @@ inet_interfaces = 127.0.0.1
% endif
<%text>
smtp_use_tls = yes
smtp_tls_loglevel = 1
smtp_tls_note_starttls_offer = yes
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

View file

@ -21,12 +21,13 @@ for identifier in node.metadata.get('postfix/mynetworks', set()):
netmask = '128'
mynetworks.add(f'[{ip6}]/{netmask}')
my_package = 'pkg_pacman:postfix' if node.os == 'arch' else 'pkg_apt:postfix'
files = {
'/etc/mailname': {
'content': node.metadata.get('postfix/myhostname'),
'before': {
'pkg_apt:postfix',
my_package,
},
'triggers': {
'svc_systemd:postfix:restart',
@ -81,7 +82,7 @@ actions = {
'command': 'newaliases',
'triggered': True,
'needs': {
'pkg_apt:postfix',
my_package,
},
'before': {
'svc_systemd:postfix',
@ -91,7 +92,7 @@ actions = {
'command': 'postmap hash:/etc/postfix/blocked_recipients',
'triggered': True,
'needs': {
'pkg_apt:postfix',
my_package,
},
'before': {
'svc_systemd:postfix',
@ -104,7 +105,17 @@ svc_systemd = {
'needs': {
'file:/etc/postfix/master.cf',
'file:/etc/postfix/main.cf',
'pkg_apt:postfix',
my_package,
},
},
}
if node.os == 'arch':
files['/etc/systemd/system/postfix.service.d/bundlewrap.conf'] = {
'source': 'arch-override.conf',
'content_type': 'mako',
'triggers': {
'action:systemd-reload',
'svc_systemd:postfix:restart',
},
}

View file

@ -14,7 +14,7 @@ defaults = {
'postfix': {
'services': {
'POSTFIX PROCESS': {
'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit postfix@-',
'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit postfix' + ('' if node.os == 'arch' else '@-'),
},
'POSTFIX QUEUE': {
'command_on_monitored_host': 'sudo /usr/local/share/icinga/plugins/check_postfix_queue -w 20 -c 40 -d 50',
@ -22,6 +22,12 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'postfix': {},
's-nail': {},
},
},
}
if node.has_bundle('postfixadmin'):

View file

@ -3,8 +3,6 @@ from os import listdir
from os.path import isfile, join
from subprocess import check_output
from bundlewrap.utils.ui import io
zone_path = join(repo.path, 'data', 'powerdns', 'files', 'bind-zones')
nameservers = set()
@ -81,10 +79,9 @@ if node.metadata.get('powerdns/features/bind', False):
continue
try:
output = check_output(['git', 'log', '-1', '--pretty=%ci']).decode('utf-8').strip()
output = check_output(['git', 'log', '-1', '--pretty=%ci', join(zone_path, zone)]).decode('utf-8').strip()
serial = datetime.strptime(output, '%Y-%m-%d %H:%M:%S %z').strftime('%y%m%d%H%M')
except Exception as e:
io.stderr(f"Error while parsing commit time for {zone} serial: {e!r}")
except:
serial = datetime.now().strftime('%y%m%d0000')
primary_zones.add(zone)

View file

@ -14,7 +14,7 @@ defaults = {
},
},
'nodejs': {
'version': 22,
'version': 18,
},
'users': {
'powerdnsadmin': {

View file

@ -7,6 +7,7 @@ from subprocess import check_output
from requests import get
UPDATE_URL = '${url}'
USERNAME = '${username}'
PASSWORD = '${password}'

View file

@ -5,6 +5,7 @@ from ipaddress import ip_address
from json import loads
from subprocess import check_output, run
DOMAIN = '${domain}'
# <%text>

View file

@ -1,5 +1,5 @@
assert node.has_bundle('redis'), f'{node.name}: pretalx needs redis'
assert node.has_bundle('nodejs'), f'{node.name}: pretalx needs nodejs for rebuild step'
assert node.has_bundle('nodejs'), f'{node.name}: pretalx needs nodejs for rebuild and regenerate_css step'
actions = {
'pretalx_create_virtualenv': {
@ -53,6 +53,17 @@ actions = {
},
'triggered': True,
},
'pretalx_regenerate-css': {
'command': 'sudo -u pretalx PRETALX_CONFIG_FILE=/opt/pretalx/pretalx.cfg /opt/pretalx/venv/bin/python -m pretalx regenerate_css',
'needs': {
'action:pretalx_migrate',
'directory:/opt/pretalx/data',
'directory:/opt/pretalx/static',
'file:/opt/pretalx/pretalx.cfg',
'bundle:nodejs',
},
'triggered': True,
},
}
users = {
@ -79,6 +90,7 @@ git_deploy = {
'action:pretalx_install',
'action:pretalx_migrate',
'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'svc_systemd:pretalx-web:restart',
'svc_systemd:pretalx-worker:restart',
},
@ -109,6 +121,7 @@ svc_systemd = {
'action:pretalx_install',
'action:pretalx_migrate',
'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'file:/etc/systemd/system/pretalx-web.service',
'file:/opt/pretalx/pretalx.cfg',
},
@ -117,7 +130,6 @@ svc_systemd = {
'needs': {
'action:pretalx_install',
'action:pretalx_migrate',
'action:pretalx_rebuild',
'file:/etc/systemd/system/pretalx-worker.service',
'file:/opt/pretalx/pretalx.cfg',
},
@ -192,6 +204,7 @@ for plugin_name, plugin_config in node.metadata.get('pretalx/plugins', {}).items
'triggers': {
'action:pretalx_migrate',
'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'svc_systemd:pretalx-web:restart',
'svc_systemd:pretalx-worker:restart',
},

View file

@ -27,7 +27,7 @@ defaults = {
},
},
'nodejs': {
'version': 22,
'version': 18,
},
'pretalx': {
'database': {

View file

@ -2,6 +2,7 @@ import re
from json import load
from os.path import join
with open(join(repo.path, 'configs', 'netbox', f'{node.name}.json')) as f:
netbox = load(f)

View file

@ -96,7 +96,7 @@ if 'dkim' in node.metadata.get('rspamd', {}):
},
}
dkim_key = repo.libs.faults.ensure_fault_or_none(node.metadata.get('rspamd/dkim'))
dkim_key = repo.libs.faults.ensure_fault_or_none(node.metadata['rspamd']['dkim'])
actions = {
'rspamd_assure_dkim_key_permissions': {

View file

@ -13,13 +13,6 @@ map to guest = bad user
load printers = no
usershare allow guests = yes
allow insecure wide links = yes
min protocol = SMB2
% if timemachine:
vfs objects = fruit
fruit:aapl = yes
fruit:copyfile = yes
fruit:model = MacSamba
% endif
% for name, opts in sorted(node.metadata.get('samba/shares', {}).items()):
[${name}]
@ -44,24 +37,3 @@ follow symlinks = yes
wide links = yes
% endif
% endfor
% for name in sorted(timemachine):
[timemachine-${name}]
comment = Time Machine backup for ${name}
available = yes
browseable = yes
guest ok = no
read only = false
valid users = timemachine-${name}
path = /srv/timemachine/${name}
durable handles = yes
vfs objects = catia fruit streams_xattr
fruit:delete_empty_adfiles = yes
fruit:metadata = stream
fruit:posix_rename = yes
fruit:time machine = yes
fruit:time machine max size = 2000G
fruit:veto_appledouble = no
fruit:wipe_intentionally_left_blank_rfork = yes
% endfor

View file

@ -1,21 +0,0 @@
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
<port>445</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=RackMac1,2</txt-record>
</service>
<service>
<type>_adisk._tcp</type>
% for idx, share_name in enumerate(sorted(shares)):
<txt-record>dk${idx}=adVN=timemachine-${share_name},adVF=0x82</txt-record>
% endfor
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
</service>
</service-group>

View file

@ -11,14 +11,9 @@ svc_systemd = {
},
}
timemachine_shares = node.metadata.get('samba/timemachine-shares', set())
files = {
'/etc/samba/smb.conf': {
'content_type': 'mako',
'context': {
'timemachine': timemachine_shares,
},
'triggers': {
'svc_systemd:nmbd:restart',
'svc_systemd:smbd:restart',
@ -62,24 +57,3 @@ for user, uconfig in node.metadata.get('users', {}).items():
last_action = {
f'action:smbpasswd_for_user_{user}',
}
if timemachine_shares:
assert node.has_bundle('avahi-daemon'), f'{node.name}: samba needs avahi-daemon to publish time machine shares'
files['/etc/avahi/services/timemachine.service'] = {
'content_type': 'mako',
'context': {
'shares': timemachine_shares,
},
}
for share_name in timemachine_shares:
users[f'timemachine-{share_name}'] = {
'home': f'/srv/timemachine/{share_name}',
}
directories[f'/srv/timemachine/{share_name}'] = {
'owner': f'timemachine-{share_name}',
'group': f'timemachine-{share_name}',
'mode': '0700',
}

View file

@ -24,30 +24,3 @@ def firewall(metadata):
},
},
}
@metadata_reactor.provides(
'zfs/datasets',
)
def timemachine_zfs(metadata):
shares = metadata.get('samba/timemachine-shares', set())
if not shares:
return {}
assert node.has_bundle('zfs'), f'{node.name}: time machine backups require zfs'
datasets = {
'tank/timemachine': {},
}
for share_name in shares:
datasets[f'tank/timemachine/{share_name}'] = {
'mountpoint': f'/srv/timemachine/{share_name}',
}
return {
'zfs': {
'datasets': datasets,
},
}

View file

@ -64,3 +64,12 @@ for check in {
files["/usr/local/share/icinga/plugins/check_{}".format(check)] = {
'mode': "0755",
}
if node.has_bundle('pacman'):
symlinks['/usr/lib/nagios/plugins'] = {
'target': '/usr/lib/monitoring-plugins',
'needs': {
'pkg_pacman:monitoring-plugins',
},
}

View file

@ -36,6 +36,14 @@ defaults = {
'sshmon',
},
},
'pacman': {
'packages': {
'gawk': {},
'perl-libwww': {},
'monitoring-plugins': {},
'python-requests': {},
},
},
}

View file

@ -4,4 +4,9 @@ defaults = {
'sudo': {},
},
},
'pacman': {
'packages': {
'sudo': {},
},
},
}

View file

@ -0,0 +1,13 @@
title ${config['title']}
% if 'linux' in config:
linux ${config['linux']}
% for line in config['initrd']:
initrd ${line}
% endfor
% if config.get('options', set()):
options ${' '.join(sorted(config['options']))}
% endif
% else:
efi ${config['efi']}
% endif

View file

@ -0,0 +1,5 @@
auto-entries no
auto-firmware yes
console-mode keep
default ${config['default']}
timeout ${config.get('timeout', 5)}

View file

@ -0,0 +1,9 @@
[Trigger]
Type = Package
Operation = Upgrade
Target = systemd
[Action]
Description = Gracefully upgrading systemd-boot...
When = PostTransaction
Exec = /usr/bin/systemctl restart systemd-boot-update.service

View file

@ -0,0 +1,32 @@
assert node.os == 'arch'
assert node.metadata.get('systemd-boot/default') in node.metadata.get('systemd-boot/entries')
files = {
'/etc/pacman.d/hooks/99-systemd-boot-update': {
'source': 'pacman_hook',
},
'/boot/loader/loader.conf': {
'content_type': 'mako',
'context': {
'config': node.metadata.get('systemd-boot'),
},
'mode': None,
},
}
directories = {
'/boot/loader/entries': {
'purge': True,
},
}
for entry, config in node.metadata.get('systemd-boot/entries').items():
files[f'/boot/loader/entries/{entry}.conf'] = {
'source': 'entry',
'content_type': 'mako',
'context': {
'entry': entry,
'config': config,
},
'mode': None,
}

View file

@ -1,4 +1,4 @@
timezone = node.metadata.get('timezone')
timezone = node.metadata.get('timezone', 'UTC')
actions['systemd-reload'] = {
'command': 'systemctl daemon-reload',

View file

@ -21,7 +21,6 @@ defaults = {
},
},
},
'timezone': 'UTC',
}
if not node.has_bundle('rsyslogd'):

View file

@ -25,4 +25,14 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'telegraf-bin': {
'needed_by': {
'svc_systemd:telegraf',
'user:telegraf',
},
},
},
},
}

View file

@ -7,6 +7,11 @@ defaults = {
'kitty-terminfo': {},
},
},
'pacman': {
'packages': {
'kitty-terminfo': {},
},
},
'users': {
'root': {
'home': '/root',

View file

@ -24,3 +24,12 @@ if node.has_bundle('nftables') and node.has_bundle('apt'):
'svc_systemd:nftables:reload',
},
}
if node.has_bundle('pacman'):
svc_systemd['libvirtd'] = {
'running': None, # triggered via .socket
}
svc_systemd['virtlogd'] = {
'running': None, # triggered via .socket
'enabled': None, # triggered via .socket
}

View file

@ -21,6 +21,12 @@ defaults = {
},
},
},
'pacman': {
'packages': {
'edk2-ovmf': {},
'libvirt': {},
},
},
}
if node.os == 'debian' and node.os_version[0] < 11:
@ -36,6 +42,9 @@ if node.has_bundle('nftables'):
},
}
if node.has_bundle('arch-with-gui'):
defaults['pacman']['packages']['virt-manager'] = {}
@metadata_reactor.provides(
'users',

View file

@ -0,0 +1,16 @@
[Unit]
Description=CRS runner for ${script}
After=network.target
[Service]
User=voc
Group=voc
EnvironmentFile=/etc/default/crs-worker
ExecStart=/opt/crs-scripts/bin/crs_run ${script}
WorkingDirectory=/opt/crs-scripts
Restart=on-failure
RestartSec=10
SyslogIdentifier=crs-${worker}
[Install]
WantedBy=crs-worker.target

View file

@ -0,0 +1,6 @@
CRS_TRACKER=${url}
CRS_TOKEN=${token}
CRS_SECRET=${secret}
% if use_vaapi:
CRS_USE_VAAPI=yes
% endif

View file

@ -0,0 +1,56 @@
paths = { # subpaths of /video
'capture',
'encoded',
'fuse',
'intros',
'repair',
'tmp',
}
directories = {
'/opt/crs-scripts': {},
}
for path in paths:
directories[f'/video/{path}'] = {
'owner': 'voc',
'group': 'voc',
}
git_deploy = {
'/opt/crs-scripts': {
'repo': 'https://github.com/crs-tools/crs-scripts.git',
'rev': 'master',
},
}
files = {
'/etc/default/crs-worker': {
'content_type': 'mako',
'source': 'environment',
'context': node.metadata.get('voc-tracker-worker'),
},
}
for worker, script in {
'recording-scheduler': 'script-A-recording-scheduler.pl',
'mount4cut': 'script-B-mount4cut.pl',
'cut-postprocessor': 'script-C-cut-postprocessor.pl',
'encoding': 'script-D-encoding.pl',
'postencoding': 'script-E-postencoding-auphonic.pl',
'postprocessing': 'script-F-postprocessing-upload.pl',
}.items():
files[f'/etc/systemd/system/crs-{worker}.service'] = {
'content_type': 'mako',
'source': 'crs-runner.service',
'context': {
'worker': worker,
'script': script,
},
'needs': {
'file:/etc/default/crs-worker',
},
'triggers': {
'action:systemd-reload',
},
}

View file

@ -0,0 +1,52 @@
defaults = {
'apt': {
'packages': {
'ffmpeg': {},
'fuse': {},
'fuse-ts': {},
'libboolean-perl': {},
'libconfig-inifiles-perl': {},
'libdatetime-perl': {},
'libfile-which-perl': {},
'libipc-run3-perl': {},
'libjson-perl': {},
'libmath-round-perl': {},
'libproc-processtable-perl': {},
'libwww-curl-perl': {},
'libxml-rpc-fast-perl': {},
'libxml-simple-perl': {},
},
},
'voc-tracker-worker': {
'use_vaapi': False,
},
'users': {
'voc': {
'home': '/opt/voc',
},
},
'pacman': {
'packages': {
'ffmpeg': {},
'fuse2': {},
'fuse3': {},
# fuse-ts missing
'perl-boolean': {}, # from aurto
'perl-config-inifiles': {},
'perl-datetime': {},
'perl-file-which': {},
'perl-ipc-run3': {},
'perl-json': {},
'perl-math-round': {},
'perl-proc-processtable': {},
'perl-www-curl': {}, # from aurto
'perl-xml-simple': {},
},
},
}
# Install manually from CPAN:
# IO::Socket::SSL
# LWP::Protocol::https
# Types::Serialiser::Error
# XML::RPC::Fast

View file

@ -283,7 +283,7 @@ def interface_ips(metadata):
'nftables/postrouting/10-wireguard',
)
def snat(metadata):
if not node.has_bundle('nftables'):
if not node.has_bundle('nftables') or node.os == 'arch':
raise DoNotRunAgain
snat_ip = metadata.get('wireguard/snat_ip', None)

View file

@ -3,4 +3,8 @@ ConditionPathExists=
[Service]
ExecStart=
% if node.os == 'arch':
ExecStart=/usr/bin/zpool import -aN -o cachefile=none
% else:
ExecStart=/usr/sbin/zpool import -aN -o cachefile=none
% endif

View file

@ -43,6 +43,18 @@ defaults = {
},
},
},
'pacman': {
'no_extract': {
'etc/sudoers.d/zfs',
},
'packages': {
'zfs-utils': {
'needed_by': {
'svc_systemd:zfs-zed',
},
},
},
},
'systemd-timers': {
'timers': {
'zfs-auto-snapshot-daily': {
@ -109,6 +121,27 @@ if node.has_bundle('telegraf'):
}
@metadata_reactor.provides(
'pacman/packages',
)
def packages(metadata):
if node.metadata.get('pacman/linux-lts', False):
pkgname = 'zfs-linux-lts'
else:
pkgname = 'zfs-linux'
return {
'pacman': {
'packages': {
pkgname: {
'needed_by': {
'zfs_dataset:',
'zfs_pool:',
},
},
},
},
}
@metadata_reactor.provides(
'apt/packages',
)

View file

@ -1,4 +1,3 @@
109.203.176.0/21
109.237.176.0/20
109.72.116.0/24
116.50.16.0/21
@ -20,6 +19,7 @@
141.77.0.0/16
143.99.213.0/24
145.225.16.0/23
146.247.58.0/24
147.161.22.0/24
147.78.17.0/24
147.79.8.0/21
@ -31,13 +31,10 @@
149.237.203.0/24
149.237.250.0/24
149.237.251.0/24
149.237.254.0/24
149.243.232.0/22
149.249.244.0/22
149.249.244.0/23
149.249.246.0/23
151.243.168.0/24
151.243.173.0/24
153.17.244.8/29
153.17.249.0/24
153.17.250.0/24
@ -49,13 +46,12 @@
153.96.218.0/24
153.96.22.0/24
153.97.32.0/24
153.97.34.0/24
158.116.231.0/24
160.211.126.0/24
163.5.156.0/24
163.5.170.0/24
163.5.186.0/24
163.5.220.0/24
163.5.47.0/24
163.5.66.0/24
164.133.10.0/24
164.133.11.0/24
@ -100,7 +96,6 @@
185.202.32.0/21
185.207.46.0/24
185.21.247.0/24
185.224.0.0/24
185.237.0.0/24
185.237.1.0/24
185.237.2.0/24
@ -113,16 +108,11 @@
185.28.208.0/22
185.39.12.0/22
185.48.0.0/22
185.57.231.0/24
185.57.24.0/24
185.82.160.0/23
185.97.227.0/24
188.208.124.0/24
188.208.125.0/24
188.209.223.0/24
188.214.136.0/24
188.214.137.0/24
188.214.138.0/24
188.214.139.0/24
192.109.121.0/24
192.109.122.0/24
192.109.124.0/24
192.109.129.0/24
@ -163,6 +153,7 @@
193.100.248.0/22
193.100.252.0/24
193.100.3.0/24
193.101.12.0/22
193.101.128.0/22
193.101.139.0/24
193.101.162.0/23
@ -294,7 +285,6 @@
194.127.242.0/23
194.127.254.0/24
194.145.252.0/24
194.147.171.0/24
194.15.194.0/24
194.15.60.0/24
194.15.61.0/24
@ -329,6 +319,7 @@
194.180.64.0/20
194.25.0.0/16
194.25.1.5/32
194.26.191.0/24
194.31.142.0/24
194.31.208.0/24
194.31.209.0/24
@ -339,11 +330,6 @@
194.33.115.0/24
194.33.120.0/24
194.33.121.0/24
194.33.50.0/24
194.38.48.0/24
194.38.49.0/24
194.38.50.0/24
194.38.51.0/24
194.39.175.0/24
194.39.189.0/24
194.39.48.0/20
@ -443,9 +429,6 @@
205.142.63.0/24
212.184.0.0/15
212.185.0.0/16
212.68.172.0/22
212.68.176.0/22
212.68.180.0/22
213.145.90.0/23
213.145.92.0/23
213.173.0.0/19
@ -454,7 +437,7 @@
213.209.156.0/24
217.0.0.0/13
217.117.96.0/24
217.177.33.0/24
217.198.189.0/24
217.224.0.0/11
217.24.32.0/20
217.24.33.0/24
@ -464,22 +447,17 @@
31.224.0.0/11
31.6.56.0/23
37.143.0.0/22
37.230.61.0/24
37.46.11.0/24
37.50.0.0/15
37.80.0.0/12
45.112.192.0/24
45.129.165.0/24
45.132.80.0/22
45.141.54.0/24
45.145.16.0/24
45.147.227.0/24
45.149.7.0/24
45.155.77.0/24
45.81.255.0/24
45.83.136.0/22
45.93.186.0/23
46.202.0.0/24
46.250.224.0/21
46.250.232.0/21
46.78.0.0/15
@ -496,7 +474,6 @@
62.224.0.0/14
62.56.208.0/21
62.68.73.0/24
62.72.172.0/24
64.137.119.0/24
64.137.125.0/24
64.137.127.0/24
@ -539,9 +516,7 @@
84.32.48.0/22
84.55.0.0/24
84.55.1.0/24
84.55.17.0/24
84.55.2.0/24
84.55.22.0/24
84.55.3.0/24
84.55.4.0/24
84.55.5.0/24
@ -552,19 +527,13 @@
85.116.30.0/24
85.116.31.0/24
85.119.160.0/23
85.133.193.0/24
85.133.208.0/24
85.133.214.0/24
85.133.254.0/24
85.204.181.0/24
85.208.248.0/24
85.208.249.0/24
85.208.250.0/24
85.208.251.0/24
86.105.211.0/24
86.105.58.0/24
86.107.164.0/24
86.110.57.0/24
86.38.248.0/21
86.38.37.0/24
87.128.0.0/10
@ -576,6 +545,7 @@
89.116.64.0/22
89.213.186.0/23
89.39.97.0/24
89.43.34.0/24
91.0.0.0/10
91.103.240.0/21
91.124.135.0/24
@ -589,6 +559,7 @@
91.124.27.0/24
91.124.28.0/24
91.124.31.0/24
91.124.32.0/24
91.124.33.0/24
91.124.34.0/24
91.124.36.0/24
@ -635,15 +606,27 @@
91.222.232.0/22
91.227.98.0/23
91.232.54.0/24
91.246.176.0/21
92.112.10.0/24
92.112.158.0/24
92.112.128.0/24
92.112.155.0/24
92.112.157.0/24
92.112.16.0/22
92.112.160.0/24
92.112.162.0/24
92.112.165.0/24
92.112.167.0/24
92.112.20.0/22
92.112.48.0/24
92.112.6.0/24
92.112.7.0/24
92.112.8.0/24
92.112.49.0/24
92.112.52.0/24
92.112.54.0/24
92.112.59.0/24
92.112.63.0/24
92.112.64.0/24
92.112.67.0/24
92.112.79.0/24
92.112.81.0/24
92.112.83.0/24
92.112.94.0/24
92.114.44.0/22
92.119.164.0/22
92.119.208.0/24
@ -652,12 +635,8 @@
92.119.211.0/24
93.113.70.0/24
93.119.201.0/24
93.119.232.0/24
93.192.0.0/10
94.126.98.0/24
94.176.72.0/24
94.176.74.0/24
94.176.79.0/24
94.26.110.0/23
94.26.64.0/23
95.178.8.0/21

View file

@ -6,7 +6,6 @@
109.250.192.0/19
109.250.224.0/19
109.250.64.0/18
109.72.113.0/24
134.101.0.0/21
14.102.90.0/24
143.58.64.0/18
@ -122,7 +121,6 @@
202.71.128.0/20
202.71.141.0/24
212.204.0.0/19
212.23.205.0/24
212.7.128.0/19
212.8.0.0/19
212.80.224.0/19
@ -154,8 +152,6 @@
46.142.96.0/19
46.142.96.0/20
46.189.0.0/17
46.203.156.0/24
46.203.227.0/24
61.8.128.0/19
61.8.128.0/22
61.8.132.0/22
@ -168,7 +164,6 @@
62.214.224.0/19
62.217.32.0/19
62.220.0.0/19
62.220.1.0/24
62.68.82.0/24
62.72.64.0/19
62.72.70.0/24
@ -229,7 +224,6 @@
88.130.0.0/16
88.130.136.0/21
88.130.144.0/20
88.130.172.0/22
88.130.176.0/21
88.130.192.0/23
88.130.194.0/23
@ -248,16 +242,14 @@
88.130.63.0/24
88.130.64.0/19
88.130.96.0/19
89.187.24.0/24
89.187.26.0/24
89.207.200.0/21
89.244.0.0/14
89.244.120.0/21
89.244.160.0/21
89.244.176.0/20
89.244.192.0/19
89.244.224.0/19
89.244.76.0/22
89.244.224.0/20
89.244.76.0/24
89.244.78.0/23
89.244.80.0/20
89.244.96.0/22
@ -274,6 +266,7 @@
89.245.64.0/19
89.245.96.0/20
89.246.0.0/19
89.246.112.0/22
89.246.122.0/24
89.246.124.0/22
89.246.160.0/21
@ -332,8 +325,6 @@
92.117.248.0/21
92.117.64.0/19
92.117.96.0/19
93.114.90.0/24
93.114.91.0/24
94.134.0.0/15
94.134.0.0/18
94.134.112.0/22
@ -359,7 +350,6 @@
2001:1438:1:a00::/56
2001:1438:2000::/36
2001:1438:3000::/36
2001:1438:300::/56
2001:1438:4000::/36
2001:1438::/32
2001:16b8:1000::/40

View file

@ -1,29 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.19 (GNU/Linux)
mQINBGZMb30BEAC6c5P5lo5cLN2wX9+jA7TEEJ/NiiOM9VxBwB/c2PFd6AjdGBbe
28VcXWmFdETg1N3Woq08yNVXdxS1tMslyl9apmmyCiSC2OPMmTOveLzZ196IljYR
DeZMF8C+rdzNKXZzn7+nEp9xRy34QUZRfx6pEnugMd0VK0d/ZKgMbcq2IvcRQwap
60+9t8ppesXhgaRBsAzvrj1twngqXP90JwzKGaR+iaGzrvvJn6cgXkw3MyXhskKY
4J0c7TV6DmTOIfL6RmBp8+SSco8xXD/O/YIpG8LWe+sbMqSaq7jFvKCINWgK4RAt
7mBRHvx81Y8IwV6B2wch/lSyYxKXTbE7uMefy3vyP9A9IFhMbFpc0EJA/4tHYEL4
qPZyR44mizsxa+1h6AXO258ERtzL+FoksXnWTcQqBKjd6SHhLwN4BLsjrlWsJ6lD
VaSKsekEwMFTLvZiLxYXBLPU04dvGNgX7nbkFMEK6RxHqfMu+m6+0jPXzQ+ejuae
xoBBT61O7v5PPTqbZFBKnVzQPf7fBIHW5/AGAc+qAI459viwcCSlJ21RCzirFYc0
/KDuSoo61yyNcq4G271lbT5SNeMZNlDxKkiHjbCpIU6iEF7uK828F1ZGKOMRztok
bzE7j1IDIfDQ3P/zfq73Rr2S9FfHlXvEmLIuj5G4PO7p0IwUlCD1a9oY+QARAQAB
tCxJY2luZ2EgR21iSCAoQnVpbGQgc2VydmVyKSA8aW5mb0BpY2luZ2EuY29tPokC
TgQTAQoAOBYhBN069hmO0AC0wLc5VswRb1WqfyOCBQJmTG99AhsDBQsJCAcCBhUK
CQgLAgQWAgMBAh4BAheAAAoJEMwRb1WqfyOCGrIP/i/4fYEkdCi4nhQGMzSP0Eyh
UhJjsUP9mEqSQRqOAplvjYa1yBbrSPLfkRE0oAL/o+4eUKcAQFeDQtDXJ/D4xl3Q
J5MehRJYzklrSs5XkEscb73HoDBUfFSgCVM2zK+JkCX0CPJ4ZLWtZGJ+8pCLpnkH
nCPonbGc6sS+m2JsPRwxyxAhdXxWSAesXd8dUSW3MOQz9JlC4/idQcCFs03fdhuZ
4jGMry08OihWVudTDK8nkwRZLzNoOivAQ3mIeaTcRMmgPJfYN4k0o90lXJWAbG+2
j8p7Pyjv71OctI8KUbS4+f2H8i6r5Pc4M4hlUQh6QAN9o1oPJrXxurdp0EXgQXSy
rVH2MeguqprFJxGjdlTCSTYgQEmEXMixRAGzteEgCf/Qk9mPXoxFTNyNg4/Lkglb
Nj6dY6or6w+IsbdrcePqDAs+j9t5B97vU7Ldquloj85myQjkWPP8kjlsOlsXBkQ/
C+mD+5iW2AiWh+yCasf6mOZwUfINZF+VDpmfIsZZbWpcMgp1f32fpRFZ3ietnsnR
+luNb19hUHKyyDDHMe/YM7H9P5vtX9BGz6O9kNpo1LAnigkSQSFBZlK3Po3Yk9eg
XPbDT5HsU3TMyS5ZnSDRRPPJwsyGPXz+0pCADae9H9hCc2C2LZIrrtwlOFPWuViA
ifY/dQmUP37n5XgMADRc
=O0zm
mQGiBFKHzk4RBACSHMIFTtfw4ZsNKAA03Gf5t7ovsKWnS7kcMYleAidypqhOmkGg
0petiYsMPYT+MOepCJFGNzwQwJhZrdLUxxMSWay4Xj0ArgpD9vbvU+gj8Tb02l+x
SqNGP8jXMV5UnK4gZsrYGLUPvx47uNNYRIRJAGOPYTvohhnFJiG402dzlwCg4u5I
1RdFplkp9JM6vNM9VBIAmcED/2jr7UQGsPs8YOiPkskGHLh/zXgO8SvcNAxCLgbp
BjGcF4Iso/A2TAI/2KGJW6kBW/Paf722ltU6s/6mutdXJppgNAz5nfpEt4uZKZyu
oSWf77179B2B/Wl1BsX/Oc3chscAgQb2pD/qPF/VYRJU+hvdQkq1zfi6cVsxyREV
k+IwA/46nXh51CQxE29ayuy1BoIOxezvuXFUXZ8rP6aCh4KaiN9AJoy7pBieCzsq
d7rPEeGIzBjI+yhEu8p92W6KWzL0xduWfYg9I7a2GTk8CaLX2OCLuwnKd7RVDyyZ
yzRjWs0T5U7SRAWspLStYxMdKert9lLyQiRHtLwmlgBPqa0gh7Q+SWNpbmdhIE9w
ZW4gU291cmNlIE1vbml0b3JpbmcgKEJ1aWxkIHNlcnZlcikgPGluZm9AaWNpbmdh
Lm9yZz6IYAQTEQIAIAUCUofOTgIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJ
EMbjGcM0QQaCgSQAnRjXdbsyqziqhmxfAKffNJYuMPwdAKCS/IRCVyQzApFBtIBQ
1xuoym/4C7kCDQRSh85OEAgAvPwjlURCi8z6+7i60no4n16dNcSzd6AT8Kizpv2r
9BmNBff/GNYGnHyob/DMtmO2esEuVG8w62rO9m1wzzXzjbtmtU7NZ1Tg+C+reU2I
GNVu3SYtEVK/UTJHAhLcgry9yD99610tYPN2Fx33Efse94mXOreBfCvDsmFGSc7j
GVNCWXpMR3jTYyGj1igYd5ztOzG63D8gPyOucTTl+RWN/G9EoGBv6sWqk5eCd1Fs
JlWyQX4BJn3YsCZx3uj1DWL0dAl2zqcn6m1M4oj1ozW47MqM/efKOcV6VvCs9SL8
F/NFvZcH4LKzeupCQ5jEONqcTlVlnLlIqId95Z4DI4AV9wADBQf/S6sKA4oH49tD
Yb5xAfUyEp5ben05TzUJbXs0Z7hfRQzy9+vQbWGamWLgg3QRUVPx1e4IT+W5vEm5
dggNTMEwlLMI7izCPDcD32B5oxNVxlfj428KGllYWCFj+edY+xKTvw/PHnn+drKs
LE65Gwx4BPHm9EqWHIBX6aPzbgbJZZ06f6jWVBi/N7e/5n8lkxXqS23DBKemapyu
S1i56sH7mQSMaRZP/iiOroAJemPNxv1IQkykxw2woWMmTLKLMCD/i+4DxejE50tK
dxaOLTc4HDCsattw/RVJO6fwE414IXHMv330z4HKWJevMQ+CmQGfswvCwgeBP9n8
PItLjBQAXIhJBBgRAgAJBQJSh85OAhsMAAoJEMbjGcM0QQaCzpAAmwUNoRyySf9p
5G3/2UD1PMueIwOtAKDVVDXEq5LJPVg4iafNu0SRMwgP0Q==
=icbY
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDsDCCAzagAwIBAgISBGjVgPFJCHOuBJul17PsmUBlMAoGCCqGSM49BAMDMDIx
MIIDsDCCAzWgAwIBAgISBIi3muU9O51f4fWWUXJHNgRHMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
NjAeFw0yNDExMzAwOTM4MzNaFw0yNTAyMjgwOTM4MzJaMBoxGDAWBgNVBAMTD2hv
bWUua3VuYm94Lm5ldDB2MBAGByqGSM49AgEGBSuBBAAiA2IABK+7B9tE5ejhYZWq
3gs8q4s6/A98pW5GGpkYl7iPsPM8ko0UvZ8tfBU+KuEavDmFoFa8W4ePEkPkypHo
gqRMhIm55/2wyTTh8/PnXp8vWCwMISmPHEqou2mphx0feLRAlqOCAiUwggIhMA4G
NjAeFw0yNDA5MDQxNjA1MThaFw0yNDEyMDMxNjA1MTdaMBoxGDAWBgNVBAMTD2hv
bWUua3VuYm94Lm5ldDB2MBAGByqGSM49AgEGBSuBBAAiA2IABA5vskMN8tWHCOsv
aUojW+t8otSpRgcU0tLsONhzQ7GhG5tC5DQ5pN7HiG14eejONQE4hRWC4rkP/e47
EVQd/rFK5m0lQesR68zogtW9KfQZUoINhlOuR4CxpBY1LrG5laOCAiQwggIgMA4G
A1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD
VR0TAQH/BAIwADAdBgNVHQ4EFgQUicTvP+5xKDeHcAhxZi7CeD5xzCUwHwYDVR0j
VR0TAQH/BAIwADAdBgNVHQ4EFgQU3iCazGKeVwzCa84zl+qckbspEmEwHwYDVR0j
BBgwFoAUkydGmAOpUWiOmNbEQkjbI79YlNIwVQYIKwYBBQUHAQEESTBHMCEGCCsG
AQUFBzABhhVodHRwOi8vZTYuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6
Ly9lNi5pLmxlbmNyLm9yZy8wLQYDVR0RBCYwJIIRKi5ob21lLmt1bmJveC5uZXSC
D2hvbWUua3VuYm94Lm5ldDATBgNVHSAEDDAKMAgGBmeBDAECATCCAQUGCisGAQQB
1nkCBAIEgfYEgfMA8QB3AM8RVu7VLnyv84db2Wkum+kacWdKsBfsrAHSW3fOzDsI
AAABk3ylPJIAAAQDAEgwRgIhAPf1V/hozFwCyj8rwHFrxslXPa77KFbbm1yrvikr
ypvZAiEAgsSapcCShSJcW21/Rig7MOjp8IjdirAzLDRnBcl4tooAdgB9WR4S4Xgq
exxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAAAZN8pURGAAAEAwBHMEUCIBF42g56
wBpQRx1aHM+tFrydhInIx+ji6o7d055uc7bAAiEA4bRrxTsQQIJ+5lY2XIYTpf5C
msc2KAHccsMqstH+ur8wCgYIKoZIzj0EAwMDaAAwZQIxAOTsntM8s/ik3N09mXq4
fVm1XQk2B2jALeTZLZevUY8jUjhKwoXTNVXQlMr1ilnC9QIwCa7zOQJQ2Y7D8xMv
uKfu7TMSLJlWMDHhIsggdPeQDYtNm85jsOXqB1SjWeCR25Mn
D2hvbWUua3VuYm94Lm5ldDATBgNVHSAEDDAKMAgGBmeBDAECATCCAQQGCisGAQQB
1nkCBAIEgfUEgfIA8AB2AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRu
AAABkb3+C2AAAAQDAEcwRQIhAMwv6NjH3Ggd1WfeSVvyToVaM15glwfSJcAW8+40
XbCKAiABUoDmQjhKi5VfwZ7e0WX5XjEmgBN2qTafK5RqlaCDJgB2AO7N0GTV2xrO
xVy3nbTNE6Iyh0Z8vOzew1FIWUZxH7WbAAABkb3+C3IAAAQDAEcwRQIgU9sxMGOG
aP3npu7vw3G9TiFRxuZRCI96My34WVSCOcsCIQDhDjS9QhJGtNT68Z0sx6DJCcco
L1AXGWwojxizcx48bTAKBggqhkjOPQQDAwNpADBmAjEA/SOZeiZrClB5EJlZFdQy
hrt2qh4HC5zvHdSLTWI4GAxDy8xRg/ANO6fp0Sb7Q7jdAjEAhiQgQfgUln08i/tv
3TGjVRIT/Y4A4QadodTROpfmFDH3QIsNwRPRhQUUSscBavK9
-----END CERTIFICATE-----

View file

@ -1 +1 @@
encrypt$gAAAAABnSurPS00unDJP1C7wyToyZOzKrEruyT6itqZG1Bbv6IZPVrkdcbgyfPrXY8ViPSRwtdVJsju-X8pvLHZGSHXvxhpNlNrNQTas2_VCMwYIihGnp7VI6ovQXd_iVHON5sXaNpKURRwCsvnYhHQfn4qPGLSN8II2QdpJ4A4nDschZwN2u-8X9omGPOcC6zeivoew4UcpossYuJDskHeJnRnR3roGwrHuPWfEKRgRJ_eTHgij00uyoJZxhWGRV9nS_MnacbGUP6KBXfaZP_23DFJPMMq734qVfcLObhYa8nam9kLHh4TaloET2pK-IVqcb_FOorWiipiGBSNCw9EQr57d8AOLEFAwMmb_1fgPCjpchVZaSKD4OhdjPt1CU3unzR-zPkrjBdL-az0ci984vJnLolr4z8nMW6oR1SyJGyccJ-lmoMf34M3oI3zIlNg2GPdGcZMFa6GhvmLYwDb7r0PHil_GRA==
encrypt$gAAAAABm2JL0vVqh3Zut-a1Gfn8iOtDZS8aBpGobV3-d3u8My0MPunYmbQ6kXUAw7U0Bu87AAPXNsmi1pxrxcu8vXvhw4uM445WwKj-UqaV5fmk-ZasHGq-O6K52YqEgK6wo-9u_sOBubbwJSwFVaHxT3gczLW_GVRHhFIFGgdnRlz4YoAz4NXcos_uNO9GMEOGhfGx9e2c2GOIg64vXkj_1LjXEDoV9HYMzy-2wLt4A6q-ZiZwCoKl8-lt8sY_rLk_yfmy3sMvzqg8JaE7T4sunmXDdf4HQlnvl_cu1uW33Rrsq4-080HKx6rKNsZQGhWD2yls016xBAYZvQbDjHd6-7bld1bs5RUF5tfEC3Kx567TBdMaf5C7-PnNB7O_MC4I6SkmUElGRdYyCHuP5HXf9dKtiGCtjHyfEzqTBrcI0xPt631_IGPWMNId7zyLqfLHpMFTPS9jgGVKoT1TXwKe4NSHaGxXO-A==

View file

@ -1,23 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDxzCCA02gAwIBAgISA1HOrGT03Yk2QXIKpt4i5P2mMAoGCCqGSM49BAMDMDIx
MIIDxjCCA0ygAwIBAgISBIbwgyWchKDri2pD+Lk46M3eMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
NjAeFw0yNDEyMTkwMTE2MTdaFw0yNTAzMTkwMTE2MTZaMCIxIDAeBgNVBAMTF2hv
bWUuc29waGllcy1raXRjaGVuLmV1MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEKI2X
YK5pxQUcBjOYQwH6OQBEaj2kVhtj1BgRXXrap/U3Zi9M1oKpDk22husbUDS4fACo
IFAsNYbFi15ayAwvkkcWEe4VkgYEdPVJes3XnkL1YOGzUpT9+eC6VbjCxjfdo4IC
NDCCAjAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRQB7GGtPhw9dPLCx28NgPOq+Wa
jjAfBgNVHSMEGDAWgBSTJ0aYA6lRaI6Y1sRCSNsjv1iU0jBVBggrBgEFBQcBAQRJ
MEcwIQYIKwYBBQUHMAGGFWh0dHA6Ly9lNi5vLmxlbmNyLm9yZzAiBggrBgEFBQcw
AoYWaHR0cDovL2U2LmkubGVuY3Iub3JnLzA9BgNVHREENjA0ghkqLmhvbWUuc29w
NTAeFw0yNDA5MTkxOTQ5NDFaFw0yNDEyMTgxOTQ5NDBaMCIxIDAeBgNVBAMTF2hv
bWUuc29waGllcy1raXRjaGVuLmV1MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4rKd
PfAtfQts90WjdnsscizZzlUF/HZBx97kT4/eWgyU/MNOFGF4WqGA92OX0ymZVJ7l
D4CnHq96odx0LqHBQ+W+MXNlsWnwBTUOPKp8XyUeDhZbkgNJDR8nGtHje9a8o4IC
MzCCAi8wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSONIAWFPI0mqJYBqnWk1J0Ea27
sDAfBgNVHSMEGDAWgBSfK1/PPCFPnQS37SssxMZwi9LXDTBVBggrBgEFBQcBAQRJ
MEcwIQYIKwYBBQUHMAGGFWh0dHA6Ly9lNS5vLmxlbmNyLm9yZzAiBggrBgEFBQcw
AoYWaHR0cDovL2U1LmkubGVuY3Iub3JnLzA9BgNVHREENjA0ghkqLmhvbWUuc29w
aGllcy1raXRjaGVuLmV1ghdob21lLnNvcGhpZXMta2l0Y2hlbi5ldTATBgNVHSAE
DDAKMAgGBmeBDAECATCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB3AKLjCuRF772t
m3447Udnd1PXgluElNcrXhssxLlQpEfnAAABk9yyNhIAAAQDAEgwRgIhAOsCeRvZ
GUN1z2lGajkrKcCtffuDhwNRPAIN2we+oXuzAiEA7XeLDROcGGcOYUMin5xKE+qr
XwitlCEyUejC5xKJm1QAdQDM+w9qhXEJZf6Vm1PO6bJ8IumFXA2XjbapflTA/kwN
sAAAAZPcsjYwAAAEAwBGMEQCIFRahCu7PZCNkSF6+oyB3MAWoLQYmjlDXxeI91E0
QfOkAiBGaToUTmM1n16nkX0hMVhNm7icCFojHkNCUzfSJ0wk8zAKBggqhkjOPQQD
AwNoADBlAjAgbshjfMt0K8pG2NzhVW1m/es3HJEtK4QGAe/BR5lgjLy1bJG/iLr9
eXPh4xACg5wCMQDx7cF2C2T06e9ogshtJGODQSM9tGHbtt2rpAbUAzWNZgu+F3XL
mwaSjFAL7mBYSMM=
DDAKMAgGBmeBDAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AEiw42vapkc0
D+VqAvqdMOscUgHLVt0sgdm7v6s52IRzAAABkgwK350AAAQDAEYwRAIga5zPs7YZ
mJqbxhinEJKKQ9XCe1w/MhBzFMzwHFGbaPgCIHeprkwET14Y3h5dmUF7szwTg1Ey
zqLM+GQL3t7EAX2cAHYAPxdLT9ciR1iUHWUchL4NEu2QN38fhWrrwb8ohez4ZG4A
AAGSDArfogAABAMARzBFAiEA0faR1cyqpmCyHo/0KCv04fkpwgzWdMY+WopJXDLD
zz8CIEBKANatmiRstc5D69jKhq2beHldLZB3jRfm1WlWqmxJMAoGCCqGSM49BAMD
A2gAMGUCMCrpe2jxoTH410jNJPOnbN4ae0Ng54JtRNcFWHlcwpk07NrByJSTPWDd
zr7AYsbbVQIxAOGboJcIxsuf+rN30iWoe5KwCY3sd5XW8bEKFQnugIVHxAQKnHNc
0InWz2sVWYKNBA==
-----END CERTIFICATE-----

View file

@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw
MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G
h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV
6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw
RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK
a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO
VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj
v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw
i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc
MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL
pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp
eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH
pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7
s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu
h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv
YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8
ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0
LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+
EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY
Ig46v9mFmBvyH04=
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C
2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+
bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG
6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV
XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO
koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq
cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI
E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e
K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX
GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL
sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd
VQD9F6Na/+zmXCc=
-----END CERTIFICATE-----

View file

@ -1 +1 @@
encrypt$gAAAAABnY4Ga6MmpudhHnOVKVh3j6R071y-Bs6es3e3hNHkZP7Tfj6IomEhTSxWb_oG9HYZmhkadw66cmVRQcxp1wGChWWLye-ykadgy0xUCxGW3YmBWp4t--Yesvbjamaa5OlvDFWQVG5Zt4fsY7BloXRdio8XUdPKBkbi2MV0quvpqsFfOqr_ZmIOOkjLlZojfw9HQ7odM9lSAm8cVS5NXimOhA1ks_gK6CzJbzwhpbekCOcx5_sGhdb8XFUxLN-VBtmQ2HGIncou66rE1P3mBg2hDSyqiXapVMkqMjNoVM71V_5lUnAF7Lxce3nG72SnOe2oITnxRNcnaavxDEgd0ffM5revuCd-XWlaUW1iQrgSyQzJyD6Ukv-mM2IRpuoq79JdTZK_LNJkAmJozrGBT0c5ZwGVNLmZEcjQ1dk8jyYslF5s7rK1lmNvcTUaHGpFToXc1p-qFY8NNWj_Iu-MLE8PNrIscDg==
encrypt$gAAAAABm7I7N50TwtCs2LUt_MArRJnLQ-xLFVhr-zDtdWUVMejViIN2O9h5d_RP45jWt5BpxIkTORarcULXprEXp7zbb-CR5CTwbsNK6HnvSHPwuwXuxJQKRJtT4wWfYEFOxY9aUR9gxvXc3arsYHwVsGyLOeWA_6YzjO5IpL1LfQrsJuUE_1p9sKRyPpslmOJtD5OihMtIfAJNzBDwOSE_gdtLa8iae3DHtSvmKbGKSvwQEZ0pkJxVTVXJY4wddQmdsuV0ky04ls_tUINH8t6IMTJCt_5_ELzpTSdcHgV6W4yh8r_LTEH38n2boYnz3fKgieHnDHDWxFW1EYA2JWjkamH7hQ8iOMl8bqQieFAENnYjF41iz6tSCjfxVyKt_OfJUAwMScVMhPsuaI_i_ZB0Ge6BLsMwkw0d3yw06CwRQ3N7PcPPJLhL_eQS3EuV7Y-7Vv64secplJJIkcFfm1t5zcGkkm4-pDw==

View file

@ -13,6 +13,7 @@ groups['raspberry'] = {
groups['linux'] = {
'subgroups': {
'arch',
'debian',
'raspberry',
},
@ -47,6 +48,13 @@ groups['linux'] = {
'pip_command': 'pip3',
}
groups['arch'] = {
'bundles': {
'pacman',
},
'os': 'arch',
}
groups['debian'] = {
'subgroup_patterns': {
'^debian-[a-z]+$',

View file

@ -25,7 +25,7 @@ def test_node(repo, node, **kwargs):
pool_name = name.split('/', 1)[0]
if pool_name not in zfs_pools:
if pool_name not in zfs_pools and node.os != 'arch':
raise BundleError('{n} zfs_dataset:{ds} wants zfs_pool:{pool}, which wasn\'t found'.format(
n=node.name,
ds=name,

View file

@ -1,6 +1,5 @@
import bwpass
def demagify(something, vault):
if isinstance(something, str):
if something.startswith('!bwpass:'):

View file

@ -4,9 +4,9 @@ from hashlib import sha3_224
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.serialization import (Encoding,
NoEncryption,
PrivateFormat,
PublicFormat)
NoEncryption,
PrivateFormat,
PublicFormat)
from bundlewrap.utils import Fault

View file

@ -5,7 +5,7 @@ from bundlewrap.utils.text import bold, red
from bundlewrap.utils.ui import io
def resolve_identifier(repo, identifier, linklocal=False, only_physical=False, allow_private=True):
def resolve_identifier(repo, identifier, linklocal=False, only_physical=False):
"""
Try to resolve an identifier (group or node). Return a set of ip
addresses valid for this identifier.
@ -62,15 +62,10 @@ def resolve_identifier(repo, identifier, linklocal=False, only_physical=False, a
'ipv6': set(),
}
has_public_ips = bool([ip for ip in found_ips if not ip.is_private])
for ip in found_ips:
if ip.is_link_local and not linklocal:
continue
if ip.is_private and not allow_private and has_public_ips:
continue
if isinstance(ip, IPv4Address):
ip_dict['ipv4'].add(ip)
else:

View file

@ -1,7 +1,6 @@
from bundlewrap.utils.scm import get_rev
from bundlewrap.utils.text import bold, red
from bundlewrap.utils.ui import io
from bundlewrap.utils.scm import get_rev
from bundlewrap.utils.text import red, bold
@node_attribute
def needs_apply(node):

View file

@ -6,6 +6,7 @@ groups = [
bundles = [
"check-mail-received",
"dovecot",
"element-web",
"forgejo",
"matrix-media-repo",
"matrix-stickerpicker",
@ -15,6 +16,7 @@ bundles = [
"miniflux",
"netbox",
"nextcloud",
"nodejs",
"ntfy",
"oidentd",
"php",
@ -36,9 +38,19 @@ email = "franzi.kunsmann@t-online.de"
imap_host = "secureimap.t-online.de"
imap_pass = "!bwpass_attr:t-online.de/franzi.kunsmann@t-online.de:imap"
[metadata.element-web]
url = "chat.franzi.business"
version = "v1.11.82"
[metadata.element-web.config]
default_server_config.'m.homeserver'.base_url = "https://matrix.franzi.business"
default_server_config.'m.homeserver'.server_name = "franzi.business"
brand = "franzi.business"
defaultCountryCode = "DE"
jitsi.preferredDomain = "meet.ffmuc.net"
[metadata.forgejo]
version = "9.0.3"
sha1 = "a04a8d5bee7321610d91da780a24e18f7407403c"
version = "9.0.1"
sha1 = "060d9f00aaf595875eaf1897cbb24e760ef54d64"
domain = "git.franzi.business"
enable_git_hooks = true
install_ssh_key = true
@ -102,8 +114,8 @@ provisioning.shared_secret = "!decrypt:encrypt$gAAAAABfVKflEMAi07C_QGP8cy97hF-4g
"'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp]
version = "v0.11.2"
sha1 = "0bd8ebef237473989c4e9658c72595e9f7c09d44"
version = "v0.11.0"
sha1 = "997c794eb246e6cc67ac050c106d54f88531f213"
permissions."'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp.homeserver]
domain = "franzi.business"
@ -114,7 +126,7 @@ domain = "rss.franzi.business"
[metadata.netbox]
domain = "netbox.franzi.business"
version = "v4.1.10"
version = "v4.1.4"
admins.kunsi = "hostmaster@kunbox.net"
[metadata.nextcloud]
@ -201,7 +213,7 @@ blocked_recipients = [
[metadata.postfixadmin]
domain = "postfixadmin.franzi.business"
setup_password = "!decrypt:encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ=="
version = "3.3.15"
version = "3.3.13"
[metadata.postgresql]
version = 15
@ -250,7 +262,7 @@ disks = [
]
[metadata.travelynx]
version = "2.9.8"
version = "2.8.40"
mail_from = "travelynx@franzi.business"
domain = "travelynx.franzi.business"

190
nodes/fkusei-locutus.py Normal file
View file

@ -0,0 +1,190 @@
nodes['fkusei-locutus'] = {
'dummy': True,
'hostname': '10.5.99.29',
'bundles': {
'arch-with-gui',
'bird',
'lldp',
'lm-sensors',
'nfs-client',
'systemd-boot',
'telegraf-battery-usage',
'wireguard',
'voc-tracker-worker',
'zfs',
},
'groups': {
'arch',
},
'metadata': {
'arch-with-gui': {
'autologin_as': 'fkunsmann',
},
'bird': {
'bgp_neighbors': {
'smedia': {
'local_as': 4200128002,
'local_ip': '10.200.128.2',
'neighbor_as': 64900,
'neighbor_ip': '10.200.128.1',
},
},
},
'firewall': {
'port_rules': {
# obs websocket thingie - just allow all RFC1918 ips here
#'4444': {
# '10.0.0.0/8',
# '172.16.0.0/12',
# '192.168.0.0/16',
#},
# For the occasional file-share using `python -m http.server`
'8000/tcp': {'*'},
},
},
'interfaces': {
'eth*': {
'dhcp': True,
},
# there is also wlan0, but that's managed by netctl
},
'location': 'home', # not actually true, but needed for static dhcp lease
'nfs-client': {
'mounts': {
'nas-storage': {
'mountpoint': '/mnt/nas',
'serverpath': '172.19.138.20:/storage/nas',
'mount_options': {
'retry=0',
'ro',
},
},
},
},
'openssh': {
'restrict-to': {
'rfc1918',
},
},
'pacman': {
'packages': {
'amd-ucode': {},
'xf86-video-amdgpu': {},
# all that other random stuff one needs
'apachedirectorystudio': {},
'direnv': {},
'freerdp': {},
'sdl_ttf': {}, # for compiling testcard
'thermald': {},
},
},
'sysctl': {
'options': {
# accept RA even though forwarding is enabled
'net.ipv4.conf.all.accept_ra': '2',
'net.ipv4.conf.wlan0.accept_ra': '2',
},
},
'systemd-boot': {
'default': 'arch',
'entries': {
'arch': {
'title': 'Arch Linux',
'linux': '/vmlinuz-linux',
'initrd': [
'/amd-ucode.img',
'/initramfs-linux.img',
],
'options': {
'net.ifnames=0',
'rw',
'zfs=zroot/system/root',
},
},
'arch-fallback': {
'title': 'Arch Linux (no ucode, fallback initramfs)',
'linux': '/vmlinuz-linux',
'initrd': [
'/initramfs-linux-fallback.img',
],
'options': {
'net.ifnames=0',
'rw',
'zfs=zroot/system/root',
},
},
},
},
'timezone': 'Europe/Berlin',
'users': {
'fkunsmann': {
'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='),
'shell': '/usr/bin/fish',
},
},
'voc-tracker-worker': {
'url': 'https://tracker.c3voc.de/rpc',
'token': vault.decrypt('encrypt$gAAAAABiYqaFl4CqOc8DTQIn49Qq0KgAJSzA19GKPNMbyHIjYg0JkvY0sK43ps8CbJWMRR6hJHVK-nP4vrWLwyoWWqt8N8aASMur4odC2s8pEHQKM0TXg4cRwobQz_lyJgrYa2VYdhcD'),
'secret': vault.decrypt('encrypt$gAAAAABiYqaYbY-3IbnRk-S25pqxrOGN7ovgPo3kBYz8ZqKDedPRzskKZefpLHxBbCOZKjg1XNT4cKbIs5cPCLdj7HdY4beAhnXl4EHZZdxU1zVC7sJCmz9XOS_Ac0UOgOlUFMiet14U'),
},
'wireguard': {
'privatekey': vault.decrypt('smedia$NotViaThisRepository'),
'peers': {
'smedia': {
'endpoint': 'wireguard.htz-cloud.kunbox.net:1194',
'their_ip': '10.200.128.1',
'my_ip': '10.200.128.2/20',
'my_port': 51820,
'endpoint': '185.122.180.82:51820',
'psk': vault.decrypt('smedia$NotViaThisRepository'),
'pubkey': vault.decrypt('smedia$NotViaThisRepository'),
},
},
},
'zfs': {
'pools': {
'zroot': {
'when_creating': {
'config': [],
},
},
},
'datasets': {
# this is not a complete list, but we can't create that
# structure using bundlewrap anyway, so there's no point
# in adding it here.
'zroot': {
'compression': 'lz4',
'relatime': 'on',
'xattr': 'sa',
'primarycache': 'metadata'
# encryption is enabled, too.
},
'zroot/system/journal': {
'mountpoint': '/var/log/journal',
'acltype': 'posix',
},
'zroot/system/root': {
'canmount': 'noauto',
'mountpoint': '/',
},
'zroot/user/fkunsmann': {
'mountpoint': '/home/fkunsmann',
},
},
'snapshots': {
'retain_per_dataset': {
'zroot/user/fkunsmann': {
# juuuuuuuust to be sure
'hourly': 100,
},
},
'snapshot_never': {
'zroot/system/journal',
},
},
},
},
'os': 'arch',
}

View file

@ -24,9 +24,15 @@ ram = 2
domain = 'hass.home.kunbox.net'
api_secret = '!decrypt:encrypt$gAAAAABm9lNg_mNhyzb4S6WRtVRDmQFBnPpoCwyqMnilRrAFUXc-EDvv-nYXPbSIbjTf7ZReTPtqr8k3WrGPqiuqhJ60LVv4A5DMqT5c6hTVr4WbhP4DPEIPgfd5aq6U9_-H9WDyQYHKjnunLJEYtEREzmhTq3XsYeQ05DyE7hfnQ-zVoBb0CsAK7GdhihRTdvhXv2N9M04_rigyBP-roRcUgCqwyHuWJc0IPAyn3R4Mr43ZqgR2fn6dNV_YUVKn9c0nWxIwRnYy6Ff_Te9NoGVmXxkiNUX-90bBLKFiCzrRAtizxrTiQb2SRipaWbgOlV6wbMy2KNux'
[metadata.nginx]
restrict-to = [
'172.19.136.0/25',
'172.19.138.0/24',
]
[metadata.pyenv]
version = 'v2.4.23'
python_versions = ["3.13.1"]
version = 'v2.3.36'
python_versions = ["3.12.2"]
[metadata.nginx.vhosts.homeassistant]
ssl = '_.home.kunbox.net'

Some files were not shown because too many files have changed in this diff Show more