diff --git a/.envrc b/.envrc deleted file mode 100644 index 5fd603a..0000000 --- a/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -layout python3 - -source_env_if_exists .envrc.local diff --git a/.gitignore b/.gitignore index 8c736ec..bbb5845 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ .secrets.cfg* __pycache__ *.swp -.direnv -.envrc.local -.bw_debug_history diff --git a/Jenkinsfile b/Jenkinsfile index 8b0af2d..f371f82 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -25,6 +25,15 @@ pipeline { """ } } + stage('syntax checking using isort') { + steps { + sh """ + . venv/bin/activate + + isort --check . + """ + } + } stage('config and metadata determinism') { steps { sh """ diff --git a/PORT_MAP.md b/PORT_MAP.md index 908b747..a1725cb 100644 --- a/PORT_MAP.md +++ b/PORT_MAP.md @@ -30,13 +30,13 @@ Rule of thumb: keep ports below 10000 free for stuff that reserves ports. | 20010 | mautrix-telegram | Bridge | | 20020 | mautrix-whatsapp | Bridge | | 20030 | matrix-dimension | Matrix Integrations Manager| -| 20070 | matrix-synapse | sliding-sync | | 20080 | matrix-synapse | client, federation | | 20081 | matrix-synapse | prometheus metrics | | 20090 | matrix-media-repo | media_repo | | 20090 | matrix-media-repo | prometheus metrics | +| 21000 | pleroma | pleroma | | 21010 | grafana | grafana | -| 22000 | forgejo | forgejo | +| 22000 | gitea | forgejo | | 22010 | jenkins-ci | Jenkins CI | | 22020 | travelynx | Travelynx Web | | 22030 | octoprint | OctoPrint Web Interface | @@ -45,9 +45,6 @@ Rule of thumb: keep ports below 10000 free for stuff that reserves ports. | 22060 | pretalx | gunicorn | | 22070 | paperless-ng | gunicorn | | 22080 | netbox | gunicorn | -| 22090 | jugendhackt_tools | gunicorn | -| 22100 | powerdnsadmin | gunicorn | -| 22110 | icinga2-statuspage | gunicorn | | 22999 | nginx | stub_status | | 22100 | ntfy | http | diff --git a/README.md b/README.md index 6663cd4..c102b84 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,3 @@ onto shared webhosting. `bw test` runs according to Jenkinsfile after every commit. [![Build Status](https://jenkins.franzi.business/buildStatus/icon?job=kunsi%2Fbundlewrap%2Fmain)](https://jenkins.franzi.business/job/kunsi/job/bundlewrap/job/main/) - -## automatix - -Ensure you set `bundlewrap: true` in your `~/.automatix.cfg.yaml`. - -## system naming - -All systems should be named after their location and use. - -For example, influxdb hosted at hetzner cloud will be `htz-cloud.influxdb`. - -The only exception to this are name servers, they are named after [demons -in fiction](https://en.wikipedia.org/wiki/List_of_demons_in_fiction). diff --git a/automatix/upgrade_debian_bullseye.yaml b/automatix/upgrade_debian_bullseye.yaml deleted file mode 100644 index 3eaee06..0000000 --- a/automatix/upgrade_debian_bullseye.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: Upgrade to debian bullseye -systems: - node: foonode - -always: - - has_zfs=python: NODES.node.has_bundle('zfs') - -pipeline: - - manual: "set icinga2 downtime: https://icinga.franzi.business/monitoring/host/schedule-downtime?host={SYSTEMS.node}" - - # apply first so we only see the upgrade changes later - - local: bw apply {SYSTEMS.node} - - manual: update debian version in node groups - - local: "bw apply -o bundle:apt -s symlink:/usr/bin/python pkg_apt: -- {SYSTEMS.node}" - - # double time! - - remote@node: DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold dist-upgrade - - remote@node: DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold dist-upgrade - - # reboot into bullseye - - remote@node: systemctl reboot - - local: | - exit=1 - while [[ $exit -ne 0 ]]; - do - sleep 1 - ssh {SYSTEMS.node} true - exit=$? - done - - # fix zfs and reboot again - - has_zfs?remote@node: zpool import tank -f - - has_zfs?remote@node: zpool upgrade -a - - has_zfs?remote@node: systemctl reboot - - has_zfs?local: | - exit=1 - while [[ $exit -ne 0 ]]; - do - sleep 1 - ssh {SYSTEMS.node} true - exit=$? - done - - # final apply - - local: bw apply {SYSTEMS.node} diff --git a/bundles/apt/files/deb822-sources b/bundles/apt/files/deb822-sources deleted file mode 100644 index c1b8202..0000000 --- a/bundles/apt/files/deb822-sources +++ /dev/null @@ -1,9 +0,0 @@ -% for uri in sorted(uris): -Types: ${' '.join(sorted(data.get('types', {'deb'})))} -URIs: ${uri} -Suites: ${os_release} -Components: ${' '.join(sorted(data.get('components', {'main'})))} -Architectures: ${' '.join(sorted(data.get('architectures', {'amd64'})))} -Signed-By: /etc/apt/trusted.gpg.d/${name}.list.asc - -% endfor diff --git a/bundles/apt/files/do-unattended-upgrades b/bundles/apt/files/do-unattended-upgrades index 3ed0166..5eb8adf 100644 --- a/bundles/apt/files/do-unattended-upgrades +++ b/bundles/apt/files/do-unattended-upgrades @@ -6,9 +6,9 @@ apt-get update DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold dist-upgrade -DEBIAN_FRONTEND=noninteractive apt-get -y -q autoremove +DEBIAN_FRONTEND=noninteractive apt-get -y -q autoclean -DEBIAN_FRONTEND=noninteractive apt-get -y -q clean +DEBIAN_FRONTEND=noninteractive apt-get -y -q autoremove % if clean_old_kernels: existing=$(dpkg --get-selections | grep -E '^linux-(image|headers)-[0-9]' || true) diff --git a/bundles/apt/files/sources.list-debian-bookworm b/bundles/apt/files/sources.list-debian-bookworm deleted file mode 100644 index 852554d..0000000 --- a/bundles/apt/files/sources.list-debian-bookworm +++ /dev/null @@ -1,3 +0,0 @@ -deb http://deb.debian.org/debian/ bookworm main non-free contrib non-free-firmware -deb http://security.debian.org/debian-security bookworm-security main contrib non-free -deb http://deb.debian.org/debian/ bookworm-updates main contrib non-free diff --git a/bundles/apt/files/sources.list-debian-trixie b/bundles/apt/files/sources.list-debian-trixie deleted file mode 100644 index 6ac79f3..0000000 --- a/bundles/apt/files/sources.list-debian-trixie +++ /dev/null @@ -1,3 +0,0 @@ -deb http://deb.debian.org/debian/ trixie main non-free contrib non-free-firmware -deb http://security.debian.org/debian-security trixie-security main contrib non-free -deb http://deb.debian.org/debian/ trixie-updates main contrib non-free diff --git a/bundles/apt/files/sources.list-raspbian-buster b/bundles/apt/files/sources.list-raspbian-buster new file mode 100644 index 0000000..d52d1f9 --- /dev/null +++ b/bundles/apt/files/sources.list-raspbian-buster @@ -0,0 +1 @@ +deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi diff --git a/bundles/apt/files/upgrade-and-reboot b/bundles/apt/files/upgrade-and-reboot index 81516e2..1a0ff36 100644 --- a/bundles/apt/files/upgrade-and-reboot +++ b/bundles/apt/files/upgrade-and-reboot @@ -46,6 +46,10 @@ fi if [[ -f /var/run/reboot-required ]] && [[ "$auto_reboot_enabled" == "True" ]] then + if [[ -n "$reboot_mail_to" ]] + then + date | mail -s "SYSREBOOTNOW $nodename" "$reboot_mail_to" + fi systemctl reboot fi diff --git a/bundles/apt/files/upgrade-and-reboot.conf b/bundles/apt/files/upgrade-and-reboot.conf index 8eff278..ca71dce 100644 --- a/bundles/apt/files/upgrade-and-reboot.conf +++ b/bundles/apt/files/upgrade-and-reboot.conf @@ -1,2 +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)}" diff --git a/bundles/apt/items.py b/bundles/apt/items.py index 12578fa..639417d 100644 --- a/bundles/apt/items.py +++ b/bundles/apt/items.py @@ -4,10 +4,11 @@ supported_os = { 'debian': { 10: 'buster', 11: 'bullseye', - 12: 'bookworm', - 13: 'trixie', 99: 'unstable', }, + 'raspbian': { + 10: 'buster', + }, } try: @@ -25,10 +26,6 @@ actions = { 'triggered': True, 'cascade_skip': False, }, - 'apt_execute_update_commands': { - 'command': ' && '.join(sorted(node.metadata.get('apt/additional_update_commands', {'true'}))), - 'triggered': True, - }, } files = { @@ -116,7 +113,7 @@ pkg_apt = { 'mtr': {}, 'ncdu': {}, 'ncurses-term': {}, - 'netcat-openbsd': {}, + 'netcat': {}, 'nmap': {}, 'python3': {}, 'python3-dev': {}, @@ -138,7 +135,6 @@ pkg_apt = { 'tmux': {}, 'tree': {}, 'unzip': {}, - 'util-linux': {}, 'vim': {}, 'wget': {}, 'whois': {}, @@ -156,9 +152,6 @@ pkg_apt = { 'popularity-contest': { 'installed': False, }, - 'python3-packaging': { - 'installed': False, - }, 'unattended-upgrades': { 'installed': False, }, @@ -175,44 +168,21 @@ if node.os_version[0] >= 11: } for name, data in node.metadata.get('apt/repos', {}).items(): - if 'items' in data: - files['/etc/apt/sources.list.d/{}.list'.format(name)] = { - 'content_type': 'mako', - 'content': ("\n".join(sorted(data['items']))).format( - os=node.os, - os_release=supported_os[node.os][node.os_version[0]], - ), - 'triggers': { - 'action:apt_update', - }, - } - elif 'uris' in data: - uris = { - x.format( - os=node.os, - os_release=supported_os[node.os][node.os_version[0]], - ) for x in data['uris'] - } - - files['/etc/apt/sources.list.d/{}.sources'.format(name)] = { - 'source': 'deb822-sources', - 'content_type': 'mako', - 'context': { - 'data': data, - 'name': name, - 'os_release': supported_os[node.os][node.os_version[0]], - 'uris': uris, - }, - 'triggers': { - 'action:apt_update', - }, - } + files['/etc/apt/sources.list.d/{}.list'.format(name)] = { + 'content_type': 'mako', + 'content': ("\n".join(sorted(data['items']))).format( + os=node.os, + os_release=supported_os[node.os][node.os_version[0]], + ), + 'triggers': { + 'action:apt_update', + }, + } if data.get('install_gpg_key', True): - if 'items' in data: - files['/etc/apt/sources.list.d/{}.list'.format(name)]['needs'] = { - 'file:/etc/apt/trusted.gpg.d/{}.list.asc'.format(name), - } + files['/etc/apt/sources.list.d/{}.list'.format(name)]['needs'] = { + 'file:/etc/apt/trusted.gpg.d/{}.list.asc'.format(name), + } files['/etc/apt/trusted.gpg.d/{}.list.asc'.format(name)] = { 'source': 'gpg-keys/{}.asc'.format(name), diff --git a/bundles/apt/metadata.py b/bundles/apt/metadata.py index 526f318..141d89a 100644 --- a/bundles/apt/metadata.py +++ b/bundles/apt/metadata.py @@ -21,24 +21,16 @@ defaults = { 'cron/jobs/upgrade-and-reboot' ) def patchday(metadata): - if not node.metadata.get('apt/unattended-upgrades/enabled', True): - return {} - day = metadata.get('apt/unattended-upgrades/day') hour = metadata.get('apt/unattended-upgrades/hour') - spread = metadata.get('apt/unattended-upgrades/spread_in_group', None) - if spread is not None: - spread_nodes = sorted(repo.nodes_in_group(spread)) - day += spread_nodes.index(node) - 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%7, + day=day, ), }, }, diff --git a/bundles/arch-with-gui/files/autologin.conf b/bundles/arch-with-gui/files/autologin.conf new file mode 100644 index 0000000..9398062 --- /dev/null +++ b/bundles/arch-with-gui/files/autologin.conf @@ -0,0 +1,3 @@ +[Autologin] +User=${user} +Session=i3.desktop diff --git a/bundles/arch-with-gui/items.py b/bundles/arch-with-gui/items.py new file mode 100644 index 0000000..9d3d911 --- /dev/null +++ b/bundles/arch-with-gui/items.py @@ -0,0 +1,103 @@ +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 = { + 'sddm': { + 'needs': { + 'pkg_pacman:sddm', + }, + }, +} + +git_deploy = { + '/opt/i3pystatus/src': { + 'repo': 'https://github.com/enkore/i3pystatus.git', + 'rev': 'current', + 'triggers': { + 'action:i3pystatus_install', + }, + }, +} + +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', + }, + } diff --git a/bundles/arch-with-gui/metadata.py b/bundles/arch-with-gui/metadata.py new file mode 100644 index 0000000..4666cca --- /dev/null +++ b/bundles/arch-with-gui/metadata.py @@ -0,0 +1,114 @@ +assert node.os == 'arch' + +defaults = { + 'backups': { + 'paths': { + '/etc/netctl', + }, + }, + 'icinga_options': { + 'exclude_from_monitoring': True, + }, + 'pacman': { + 'packages': { + # fonts + 'fontconfig': {}, + 'ttf-dejavu': { + 'needed_by': { + 'pkg_pacman:sddm', + }, + }, + + # login management + 'sddm': {}, + + # networking + 'netctl': {}, + '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': {}, + '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, + }, + } diff --git a/bundles/avahi-daemon/files/avahi-daemon.conf b/bundles/avahi-daemon/files/avahi-daemon.conf deleted file mode 100644 index 0ad1412..0000000 --- a/bundles/avahi-daemon/files/avahi-daemon.conf +++ /dev/null @@ -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] diff --git a/bundles/avahi-daemon/items.py b/bundles/avahi-daemon/items.py deleted file mode 100644 index 0a0f1aa..0000000 --- a/bundles/avahi-daemon/items.py +++ /dev/null @@ -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', - }, -} diff --git a/bundles/avahi-daemon/metadata.py b/bundles/avahi-daemon/metadata.py deleted file mode 100644 index f6c3ef5..0000000 --- a/bundles/avahi-daemon/metadata.py +++ /dev/null @@ -1,11 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'avahi-daemon': {}, - 'libnss-mdns': {}, - }, - }, - 'avahi-daemon': { - 'use-ipv6': True, - } -} diff --git a/bundles/backup-client/files/generate-backup b/bundles/backup-client/files/generate-backup index 3fd9d7d..28ef49d 100644 --- a/bundles/backup-client/files/generate-backup +++ b/bundles/backup-client/files/generate-backup @@ -62,13 +62,10 @@ trap "on_exit" EXIT # redirect stdout and stderr to logfile prepare_and_cleanup_logdir -if [[ -z "$DEBUG" ]] -then - logfile="$logdir/backup--$(date '+%F--%H-%M-%S')--$$.log.gz" - echo "All log output will go to $logfile" | logger -it backup-client - exec > >(gzip >"$logfile") - exec 2>&1 -fi +logfile="$logdir/backup--$(date '+%F--%H-%M-%S')--$$.log.gz" +echo "All log output will go to $logfile" | logger -it backup-client +exec > >(gzip >"$logfile") +exec 2>&1 # this is where the real work starts ts_begin=$(date +%s) diff --git a/bundles/backup-server/files/check_backup_for_node b/bundles/backup-server/files/check_backup_for_node index bf57012..b7866f8 100644 --- a/bundles/backup-server/files/check_backup_for_node +++ b/bundles/backup-server/files/check_backup_for_node @@ -2,6 +2,7 @@ from datetime import datetime from json import load +from subprocess import check_output from sys import argv, exit from time import time @@ -17,17 +18,29 @@ try: with open(f'/etc/backup-server/config.json', 'r') as f: server_settings = load(f) - with open(f'/etc/backup-server/backups.json', 'r') as f: - backups = load(f) + # get all existing snapshots for NODE + for line in check_output('LC_ALL=C zfs list -H -t snapshot -o name', shell=True).splitlines(): + line = line.decode('UTF-8') - if NODE not in backups: + if line.startswith('{}/{}@'.format(server_settings['zfs-base'], NODE)): + _, snapname = line.split('@', 1) + + if 'zfs-auto-snap' in snapname: + # migration from auto-snapshots, ignore + continue + + ts, bucket = snapname.split('-', 1) + snaps.add(int(ts)) + + if not snaps: print('No backups found!') exit(2) - delta = NOW - backups[NODE] + last_snap = sorted(snaps)[-1] + delta = NOW - last_snap print('Last backup was on {} UTC'.format( - datetime.fromtimestamp(backups[NODE]).strftime('%Y-%m-%d %H:%M:%S'), + datetime.fromtimestamp(last_snap).strftime('%Y-%m-%d %H:%M:%S'), )) # One day without backups is still okay. There may be fluctuations diff --git a/bundles/backup-server/files/check_backup_for_node-cron b/bundles/backup-server/files/check_backup_for_node-cron deleted file mode 100644 index ff1a368..0000000 --- a/bundles/backup-server/files/check_backup_for_node-cron +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -from json import load, dump -from subprocess import check_output -from shutil import move -from os import remove -from collections import defaultdict - -with open('/etc/backup-server/config.json', 'r') as f: - server_settings = load(f) - -snapshots = defaultdict(set) - -for line in check_output('LC_ALL=C zfs list -H -t snapshot -o name', shell=True).splitlines(): - line = line.decode('UTF-8') - - if line.startswith('{}/'.format(server_settings['zfs-base'])): - try: - dataset, snapname = line.split('@', 1) - - dataset = dataset.split('/')[-1] - ts, bucket = snapname.split('-', 1) - - snapshots[dataset].add(int(ts)) - except Exception as e: - print(f"Exception while parsing snapshot name {line!r}: {e!r}") - -backups = {} -for dataset, snaps in snapshots.items(): - backups[dataset] = sorted(snaps)[-1] - -with open('/etc/backup-server/backups.tmp.json', 'w') as f: - dump(backups, f) - -move( - '/etc/backup-server/backups.tmp.json', - '/etc/backup-server/backups.json', -) diff --git a/bundles/backup-server/files/rotate-single-backup-client b/bundles/backup-server/files/rotate-single-backup-client index c76c6b5..ee49e26 100644 --- a/bundles/backup-server/files/rotate-single-backup-client +++ b/bundles/backup-server/files/rotate-single-backup-client @@ -33,11 +33,12 @@ for line in check_output('LC_ALL=C zfs list -H -t snapshot -o name', shell=True) if line.startswith('{}/{}@'.format(server_settings['zfs-base'], NODE)): _, snapname = line.split('@', 1) - ts, bucket = snapname.split('-', 1) - if not ts.isdigit(): + if 'zfs-auto-snap' in snapname: + # migration from auto-snapshots, ignore continue + ts, bucket = snapname.split('-', 1) buckets.setdefault(bucket, set()).add(int(ts)) syslog(f'classified {line} as {bucket} from {ts}') diff --git a/bundles/backup-server/items.py b/bundles/backup-server/items.py index e872231..bd4d12f 100644 --- a/bundles/backup-server/items.py +++ b/bundles/backup-server/items.py @@ -18,9 +18,6 @@ files = { '/usr/local/share/icinga/plugins/check_backup_for_node': { 'mode': '0755', }, - '/usr/local/share/icinga/plugins/check_backup_for_node-cron': { - 'mode': '0755', - }, } directories['/etc/backup-server/clients'] = { diff --git a/bundles/backup-server/metadata.py b/bundles/backup-server/metadata.py index 6714288..098e264 100644 --- a/bundles/backup-server/metadata.py +++ b/bundles/backup-server/metadata.py @@ -1,5 +1,3 @@ -from bundlewrap.exceptions import BundleError - defaults = { 'backup-server': { 'my_ssh_port': 22, @@ -10,14 +8,6 @@ defaults = { 'c-*', }, }, - 'systemd-timers': { - 'timers': { - 'check_backup_for_node-cron': { - 'command': '/usr/local/share/icinga/plugins/check_backup_for_node-cron', - 'when': '*-*-* *:00/5:00', # every five minutes - } - }, - }, 'zfs': { # The whole point of doing backups is to keep them for a long # time, which eliminates the need for this check. @@ -45,15 +35,8 @@ def get_my_clients(metadata): continue my_clients[rnode.name] = { - 'exclude_from_monitoring': rnode.metadata.get( - 'backup-client/exclude_from_monitoring', - rnode.metadata.get( - 'icinga_options/exclude_from_monitoring', - False, - ), - ), - 'one_backup_every_hours': rnode.metadata.get('backup-client/one_backup_every_hours', 24), 'user': rnode.metadata.get('backup-client/user-name'), + 'one_backup_every_hours': rnode.metadata.get('backup-client/one_backup_every_hours', 24), 'retain': { 'daily': rnode.metadata.get('backups/retain/daily', retain_defaults['daily']), 'weekly': rnode.metadata.get('backups/retain/weekly', retain_defaults['weekly']), @@ -79,28 +62,25 @@ def zfs_pool(metadata): return {} crypt_devices = {} + pool_devices = set() unlock_actions = set() - devices = metadata.get('backup-server/encrypted-devices') - - pool_devices = set() - - for device, dconfig in devices.items(): - crypt_devices[dconfig['device']] = { - 'dm-name': f'backup-{device}', - 'passphrase': dconfig['passphrase'], + for number, (device, passphrase) in enumerate(sorted(metadata.get('backup-server/encrypted-devices', {}).items())): + crypt_devices[device] = { + 'dm-name': f'backup{number}', + 'passphrase': passphrase, } - pool_devices.add(f'/dev/mapper/backup-{device}') - unlock_actions.add(f'action:dm-crypt_open_backup-{device}') + pool_devices.add(f'/dev/mapper/backup{number}') + unlock_actions.add(f'action:dm-crypt_open_backup{number}') - pool_config = [{ + pool_opts = { 'devices': pool_devices, - }] + } if len(pool_devices) > 2: - pool_config[0]['type'] = 'raidz' + pool_opts['type'] = 'raidz' elif len(pool_devices) > 1: - pool_config[0]['type'] = 'mirror' + pool_opts['type'] = 'mirror' return { 'backup-server': { @@ -113,8 +93,9 @@ def zfs_pool(metadata): 'pools': { 'backups': { 'when_creating': { - 'config': pool_config, - **metadata.get('backup-server/zpool_create_options', {}), + 'config': [ + pool_opts, + ], }, 'needs': unlock_actions, # That's a bit hacky. We do it this way to auto-import @@ -168,11 +149,11 @@ def monitoring(metadata): continue services[f'BACKUPS FOR NODE {client}'] = { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_backup_for_node {} {}'.format( + 'command_on_monitored_host': 'sudo /usr/local/share/icinga/plugins/check_backup_for_node {} {}'.format( client, config['one_backup_every_hours'], ), - 'vars.sshmon_timeout': 40, + 'vars.sshmon_timeout': 20, } return { diff --git a/bundles/basic/files/htoprc b/bundles/basic/files/htoprc index f9dfd53..68ef687 100644 --- a/bundles/basic/files/htoprc +++ b/bundles/basic/files/htoprc @@ -32,8 +32,8 @@ account_guest_in_cpu_meter=0 color_scheme=0 enable_mouse=0 delay=10 -left_meters=Tasks LoadAverage Uptime Memory CPU LeftCPUs2 CPU +left_meters=Tasks LoadAverage Uptime Memory CPU LeftCPUs CPU left_meter_modes=2 2 2 1 1 1 2 -right_meters=Hostname CPU RightCPUs2 +right_meters=Hostname CPU RightCPUs right_meter_modes=2 3 1 hide_function_bar=0 diff --git a/bundles/basic/items.py b/bundles/basic/items.py index c2cdd49..d25d4c7 100644 --- a/bundles/basic/items.py +++ b/bundles/basic/items.py @@ -24,23 +24,13 @@ files = { 'before': { 'action:', 'pkg_apt:', + 'pkg_pacman:', }, }, } -if node.has_any_bundle([ - 'dovecot', - 'nginx', - 'postfix', -]): - actions['generate-dhparam'] = { - 'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048', - 'unless': 'test -f /etc/ssl/certs/dhparam.pem', - } - - locale_needs = set() -for locale in sorted(node.metadata.get('locale/installed')): +for locale in sorted(node.metadata['locale']['installed']): actions[f'ensure_locale_{locale}_is_enabled'] = { 'command': f"sed -i '/{locale}/s/^# *//g' /etc/locale.gen", 'unless': f"grep -e '^{locale}' /etc/locale.gen", @@ -51,15 +41,17 @@ for locale in sorted(node.metadata.get('locale/installed')): } locale_needs = {f'action:ensure_locale_{locale}_is_enabled'} -actions['locale-gen'] = { - 'triggered': True, - 'command': 'locale-gen', +actions = { + 'locale-gen': { + 'triggered': True, + 'command': 'locale-gen', + }, } description = [] if not node.metadata.get('icinga_options/exclude_from_monitoring', False): - description.append('icingaweb2: https://icinga.franzi.business/monitoring/host/show?host={}'.format(node.name)) + description.append('icingaweb2: https://icinga.kunsmann.eu/monitoring/host/show?host={}'.format(node.name)) if node.has_bundle('telegraf'): description.append('Grafana: https://grafana.kunsmann.eu/d/{}'.format(UUID(int=node.magic_number).hex[:10])) diff --git a/bundles/bird/files/bird.conf b/bundles/bird/files/bird.conf index b3ebbc9..0e6e876 100644 --- a/bundles/bird/files/bird.conf +++ b/bundles/bird/files/bird.conf @@ -19,9 +19,7 @@ protocol static { ipv4; % for route in sorted(node.metadata.get('bird/static_routes', set())): -% for name, config in sorted(node.metadata.get('bird/bgp_neighbors', {}).items()): - route ${route} via ${config['local_ip']}; -% endfor + route ${route} via ${node.metadata.get('bird/my_ip')}; % endfor } % endif diff --git a/bundles/bird/items.py b/bundles/bird/items.py index 4c4b51c..38a1549 100644 --- a/bundles/bird/items.py +++ b/bundles/bird/items.py @@ -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}', }, }, } diff --git a/bundles/bird/metadata.py b/bundles/bird/metadata.py index f6096a7..a5547d4 100644 --- a/bundles/bird/metadata.py +++ b/bundles/bird/metadata.py @@ -13,9 +13,18 @@ defaults = { }, }, }, + 'pacman': { + 'packages': { + 'bird': { + 'needed_by': { + 'svc_systemd:bird', + }, + }, + }, + }, 'sysctl': { 'options': { - 'net.ipv4.conf.all.forwarding': '1', + 'net.ipv4.ip_forward': '1', 'net.ipv6.conf.all.forwarding': '1', }, }, @@ -34,9 +43,6 @@ def neighbor_info_from_wireguard(metadata): except NoSuchNode: continue - if not rnode.has_bundle('bird'): - continue - neighbors[name] = { 'local_ip': config['my_ip'], 'local_as': my_as, @@ -56,10 +62,7 @@ def neighbor_info_from_wireguard(metadata): ) def my_ip(metadata): if node.has_bundle('wireguard'): - wg_ifaces = sorted({iface for iface in metadata.get('interfaces').keys() if iface.startswith('wg_')}) - if not wg_ifaces: - return {} - my_ip = sorted(metadata.get(f'interfaces/{wg_ifaces[0]}/ips'))[0].split('/')[0] + my_ip = sorted(metadata.get('interfaces/wg0/ips'))[0].split('/')[0] else: my_ip = str(sorted(repo.libs.tools.resolve_identifier(repo, node.name))[0]) @@ -81,7 +84,7 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '179/tcp': atomic(sources), + '179': atomic(sources), }, }, } diff --git a/bundles/c3voc-addons/items.py b/bundles/c3voc-addons/items.py index cd7612b..a8116a2 100644 --- a/bundles/c3voc-addons/items.py +++ b/bundles/c3voc-addons/items.py @@ -1,19 +1,5 @@ from bundlewrap.exceptions import BundleError -supported_os = { - 'debian': { - 10: 'buster', - 11: 'bullseye', - 12: 'bookworm', - 99: 'unstable', - }, -} - -try: - supported_os[node.os][node.os_version[0]] -except (KeyError, IndexError): - raise BundleError(f'{node.name}: OS {node.os} {node.os_version} is not supported by bundle:apt') - CONFLICTING_BUNDLES = { 'apt', 'nginx', @@ -71,18 +57,6 @@ actions = { 'svc_systemd:', }, }, - 'apt_update': { - 'command': 'apt-get update', - 'needed_by': { - 'pkg_apt:', - }, - 'triggered': True, - 'cascade_skip': False, - }, - 'apt_execute_update_commands': { - 'command': ' && '.join(sorted(node.metadata.get('apt/additional_update_commands', {'true'}))), - 'triggered': True, - }, } directories = { @@ -118,30 +92,6 @@ files = { }, } -for name, data in node.metadata.get('apt/repos', {}).items(): - files['/etc/apt/sources.list.d/{}.list'.format(name)] = { - 'content_type': 'mako', - 'content': ("\n".join(sorted(data['items']))).format( - os=node.os, - os_release=supported_os[node.os][node.os_version[0]], - ), - 'triggers': { - 'action:apt_update', - }, - } - - if data.get('install_gpg_key', True): - files['/etc/apt/sources.list.d/{}.list'.format(name)]['needs'] = { - 'file:/etc/apt/trusted.gpg.d/{}.list.asc'.format(name), - } - - files['/etc/apt/trusted.gpg.d/{}.list.asc'.format(name)] = { - 'source': 'gpg-keys/{}.asc'.format(name), - 'triggers': { - 'action:apt_update', - }, - } - for crontab, content in node.metadata.get('cron/jobs', {}).items(): files['/etc/cron.d/{}'.format(crontab)] = { 'source': 'cron_template', diff --git a/bundles/cron/items.py b/bundles/cron/items.py index 577bb59..81409b8 100644 --- a/bundles/cron/items.py +++ b/bundles/cron/items.py @@ -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', @@ -10,16 +17,16 @@ files = { directories = { '/etc/cron.d': { 'purge': True, - 'after': { + 'needs': { 'pkg_apt:', }, }, } svc_systemd = { - 'cron': { + service_name: { 'needs': { - 'pkg_apt:cron', + package_name, }, }, } diff --git a/bundles/cron/metadata.py b/bundles/cron/metadata.py index 67b2b22..66d612a 100644 --- a/bundles/cron/metadata.py +++ b/bundles/cron/metadata.py @@ -4,4 +4,9 @@ defaults = { 'cron': {}, }, }, + 'pacman': { + 'packages': { + 'cronie': {}, + }, + }, } diff --git a/bundles/dhcpd/files/dhcpd.conf b/bundles/dhcpd/files/dhcpd.conf new file mode 100644 index 0000000..97e734b --- /dev/null +++ b/bundles/dhcpd/files/dhcpd.conf @@ -0,0 +1,36 @@ +<% + import re + from ipaddress import ip_network +%> +ddns-update-style none; + +authoritative; + +% for interface, subnet in sorted(dhcp_config.get('subnets', {}).items()): +<% + network = ip_network(subnet['subnet']) +%> +# interface ${interface} provides ${subnet['subnet']} +subnet ${network.network_address} netmask ${network.netmask} { +% if subnet.get('range_lower', None) and subnet.get('range_higher', None): + range ${subnet['range_lower']} ${subnet['range_higher']}; +% endif + interface "${interface}"; + default-lease-time ${subnet.get('default-lease-time', 600)}; + max-lease-time ${subnet.get('max-lease-time', 3600)}; +% for option, value in sorted(subnet.get('options', {}).items()): +% if re.match('([^0-9\.,\ ])', value): + option ${option} "${value}"; +% else: + option ${option} ${value}; +% endif +% endfor +} +% endfor + +% for identifier, allocation in dhcp_config.get('fixed_allocations', {}).items(): +host ${identifier} { + hardware ethernet ${allocation['mac']}; + fixed-address ${allocation['ipv4']}; +} +% endfor diff --git a/bundles/dhcpd/files/isc-dhcp-server b/bundles/dhcpd/files/isc-dhcp-server new file mode 100644 index 0000000..4b0120d --- /dev/null +++ b/bundles/dhcpd/files/isc-dhcp-server @@ -0,0 +1,18 @@ +# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server) + +# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf). +#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf +#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf + +# Path to dhcpd's PID file (default: /var/run/dhcpd.pid). +#DHCPDv4_PID=/var/run/dhcpd.pid +#DHCPDv6_PID=/var/run/dhcpd6.pid + +# Additional options to start dhcpd with. +# Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead +#OPTIONS="" + +# On what interfaces should the DHCP server (dhcpd) serve DHCP requests? +# Separate multiple interfaces with spaces, e.g. "eth0 eth1". +INTERFACESv4="${' '.join(sorted(node.metadata.get('dhcpd/subnets', {})))}" +INTERFACESv6="" diff --git a/bundles/dhcpd/items.py b/bundles/dhcpd/items.py new file mode 100644 index 0000000..bdf9944 --- /dev/null +++ b/bundles/dhcpd/items.py @@ -0,0 +1,41 @@ +files = { + '/etc/dhcp/dhcpd.conf': { + 'content_type': 'mako', + 'context': { + 'dhcp_config': node.metadata['dhcpd'], + }, + 'needs': { + 'pkg_apt:isc-dhcp-server' + }, + 'triggers': { + 'svc_systemd:isc-dhcp-server:restart', + }, + }, + '/etc/default/isc-dhcp-server': { + 'content_type': 'mako', + 'needs': { + 'pkg_apt:isc-dhcp-server' + }, + 'triggers': { + 'svc_systemd:isc-dhcp-server:restart', + }, + }, +} + +actions = { + # needed for dhcp-lease-list + 'dhcpd_download_oui.txt': { + 'command': 'wget http://standards-oui.ieee.org/oui.txt -O /usr/local/etc/oui.txt', + 'unless': 'test -f /usr/local/etc/oui.txt', + }, +} + +svc_systemd = { + 'isc-dhcp-server': { + 'needs': { + 'pkg_apt:isc-dhcp-server', + 'file:/etc/dhcp/dhcpd.conf', + 'file:/etc/default/isc-dhcp-server', + }, + }, +} diff --git a/bundles/dhcpd/metadata.py b/bundles/dhcpd/metadata.py new file mode 100644 index 0000000..cc091af --- /dev/null +++ b/bundles/dhcpd/metadata.py @@ -0,0 +1,54 @@ +defaults = { + 'apt': { + 'packages': { + 'isc-dhcp-server': {}, + }, + }, + 'bash_aliases': { + 'leases': 'sudo dhcp-lease-list | tail -n +4 | sort -k 2,2', + }, +} + + +@metadata_reactor.provides( + 'dhcpd/fixed_allocations', +) +def get_static_allocations(metadata): + allocations = {} + for rnode in repo.nodes: + if rnode.metadata.get('location', '') != metadata.get('location', ''): + continue + + for iface_name, iface_config in rnode.metadata.get('interfaces', {}).items(): + if iface_config.get('dhcp', False): + try: + allocations[f'{rnode.name}_{iface_name}'] = { + 'ipv4': sorted(iface_config['ips'])[0], + 'mac': iface_config['mac'], + } + except KeyError: + pass + + return { + 'dhcpd': { + 'fixed_allocations': allocations, + } + } + + +@metadata_reactor.provides( + 'nftables/rules/10-dhcpd', +) +def nftables(metadata): + rules = set() + for iface in node.metadata.get('dhcpd/subnets', {}): + rules.add(f'inet filter input udp dport {{ 67, 68 }} iif {iface} accept') + + return { + 'nftables': { + 'rules': { + # can't use port_rules here, because we're generating interface based rules. + '10-dhcpd': sorted(rules), + }, + } + } diff --git a/bundles/docker-engine/files/check_docker_container b/bundles/docker-engine/files/check_docker_container deleted file mode 100644 index ea94173..0000000 --- a/bundles/docker-engine/files/check_docker_container +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -from json import loads -from subprocess import check_output -from sys import argv - -try: - container_name = argv[1] - - docker_ps = check_output([ - 'docker', - 'container', - 'ls', - '--all', - '--format', - 'json', - '--filter', - f'name={container_name}' - ]) - - docker_json = loads(f"[{','.join([l for l in docker_ps.decode().splitlines() if l])}]") - - containers = [ - container - for container in docker_json - if container['Names'] == container_name - ] - - if not containers: - print(f'CRITICAL: container {container_name} not found!') - exit(2) - - if len(containers) > 1: - print(f'Found more than one container matching {container_name}!') - print(docker_ps) - exit(3) - - if containers[0]['State'] != 'running': - print(f'WARNING: container {container_name} not "running"') - exit(2) - - print(f"OK: {containers[0]['Status']}") -except Exception as e: - print(repr(e)) - exit(2) diff --git a/bundles/docker-engine/files/docker-wrapper b/bundles/docker-engine/files/docker-wrapper deleted file mode 100644 index 2821d29..0000000 --- a/bundles/docker-engine/files/docker-wrapper +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -[[ -n "$DEBUG" ]] && set -x - -ACTION="$1" - -set -euo pipefail - -if [[ -z "$ACTION" ]] -then - echo "Usage: $0 start|stop" - exit 1 -fi - -PUID="$(id -u "${user}")" -PGID="$(id -g "${user}")" - -if [ "$ACTION" == "start" ] -then - # just exit if the container is actually running already. - set +e - /usr/local/share/icinga/plugins/check_docker_container "${name}" && exit 0 - set -e - - docker rm "${name}" || true - - docker pull "${image}" - - docker run -d \ - --name "${name}" \ - --env "PUID=$PUID" \ - --env "PGID=$PGID" \ - --env "TZ=${timezone}" \ -% for k, v in sorted(environment.items()): - --env "${k}=${v}" \ -% endfor - --network aaarghhh \ -% for host_port, container_port in sorted(ports.items()): - --publish "127.0.0.1:${host_port}:${container_port}" \ -% endfor -% for host_path, container_path in sorted(volumes.items()): -% if host_path.startswith('/'): - --volume "${host_path}:${container_path}" \ -% else: - --volume "/var/opt/docker-engine/${name}/${host_path}:${container_path}" \ -% endif -% endfor - --restart unless-stopped \ -% if command: - "${image}" \ - "${command}" -% else: - "${image}" -% endif - -elif [ "$ACTION" == "stop" ] -then - docker stop "${name}" - -else - echo "Unknown action $ACTION" - exit 1 -fi - -% if node.has_bundle('nftables'): -systemctl reload nftables -% endif diff --git a/bundles/docker-engine/files/docker-wrapper.service b/bundles/docker-engine/files/docker-wrapper.service deleted file mode 100644 index a908c86..0000000 --- a/bundles/docker-engine/files/docker-wrapper.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=docker-engine app ${name} -After=network.target -Requires=${' '.join(sorted(requires))} - -[Service] -WorkingDirectory=/var/opt/docker-engine/${name}/ -ExecStart=/opt/docker-engine/${name} start -ExecStop=/opt/docker-engine/${name} stop -Type=simple -RemainAfterExit=true - -[Install] -WantedBy=multi-user.target diff --git a/bundles/docker-engine/items.py b/bundles/docker-engine/items.py deleted file mode 100644 index 253daff..0000000 --- a/bundles/docker-engine/items.py +++ /dev/null @@ -1,126 +0,0 @@ -from bundlewrap.metadata import metadata_to_json - -deps = { - 'pkg_apt:docker-ce', - 'pkg_apt:docker-ce-cli', -} - -directories['/opt/docker-engine'] = { - 'purge': True, -} -directories['/var/opt/docker-engine'] = {} - -files['/etc/docker/daemon.json'] = { - 'content': metadata_to_json(node.metadata.get('docker-engine/config')), - 'triggers': { - 'svc_systemd:docker:restart', - }, - # install config before installing packages to ensure the config is - # applied to the first start as well - 'before': deps, -} - -svc_systemd['docker'] = { - 'needs': deps, -} - -files['/usr/local/share/icinga/plugins/check_docker_container'] = { - 'mode': '0755', -} - -actions['docker_create_nondefault_network'] = { - # - # By default, containers inherit the DNS settings as defined in the - # /etc/resolv.conf configuration file. Containers that attach to the - # default bridge network receive a copy of this file. Containers that - # attach to a custom network use Docker's embedded DNS server. The embedded - # DNS server forwards external DNS lookups to the DNS servers configured on - # the host. - 'command': 'docker network create aaarghhh', - 'unless': 'docker network ls | grep -q -F aaarghhh', - 'needs': { - 'svc_systemd:docker', - }, -} - -for app, config in node.metadata.get('docker-engine/containers', {}).items(): - volumes = config.get('volumes', {}) - user = config.get('user', f'docker-{app}') - directories[f'/var/opt/docker-engine/{app}'] = { - 'owner': user, - 'group': user, - } - - files[f'/opt/docker-engine/{app}'] = { - 'source': 'docker-wrapper', - 'content_type': 'mako', - 'context': { - 'command': config.get('command'), - 'environment': config.get('environment', {}), - 'image': config['image'], - 'name': app, - 'ports': config.get('ports', {}), - 'timezone': node.metadata.get('timezone'), - 'user': user, - 'volumes': volumes, - }, - 'mode': '0755', - 'triggers': { - f'svc_systemd:docker-{app}:restart', - }, - } - - users[user] = { - 'groups': { - 'docker', - }, - 'after': { - 'action:docker_create_nondefault_network', - 'svc_systemd:docker', - }, - } - if user == f'docker-{app}': - users[user]['home'] = f'/var/opt/docker-engine/{app}' - - files[f'/usr/local/lib/systemd/system/docker-{app}.service'] = { - 'source': 'docker-wrapper.service', - 'content_type': 'mako', - 'context': { - 'name': app, - 'requires': { - *set(config.get('requires', set())), - 'docker.service', - } - }, - 'triggers': { - 'action:systemd-reload', - f'svc_systemd:docker-{app}:restart', - }, - } - - svc_systemd[f'docker-{app}'] = { - 'needs': { - *deps, - f'directory:/var/opt/docker-engine/{app}', - f'file:/opt/docker-engine/{app}', - f'file:/usr/local/lib/systemd/system/docker-{app}.service', - f'user:{user}', - 'svc_systemd:docker', - *set(config.get('needs', set())), - }, - } - - for volume in volumes: - if not volume.startswith('/'): - volume = f'/var/opt/docker-engine/{app}/{volume}' - - directories[volume] = { - 'owner': user, - 'group': user, - 'needed_by': { - f'svc_systemd:docker-{app}', - }, - # don't do anything if the directory exists, docker images - # mangle owners - 'unless': f'test -d {volume}', - } diff --git a/bundles/docker-engine/metadata.py b/bundles/docker-engine/metadata.py deleted file mode 100644 index 4600233..0000000 --- a/bundles/docker-engine/metadata.py +++ /dev/null @@ -1,92 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'docker-ce': {}, - 'docker-ce-cli': {}, - 'docker-compose-plugin': {}, - }, - 'repos': { - 'docker': { - 'items': { - 'deb https://download.docker.com/linux/debian {os_release} stable', - }, - }, - }, - }, - 'nftables': { - 'forward': { - 'docker-engine': [ - 'ct state { related, established } accept', - 'ip saddr 172.16.0.0/12 accept', - ], - }, - 'postrouting': { - 'docker-engine': [ - 'ip saddr 172.16.0.0/12 masquerade', - ], - }, - }, - 'docker-engine': { - 'config': { - 'iptables': False, - 'no-new-privileges': True, - }, - }, - 'zfs': { - 'datasets': { - 'tank/docker-data': {}, - }, - }, -} - - -@metadata_reactor.provides( - 'icinga2_api/docker-engine/services', -) -def monitoring(metadata): - services = { - 'DOCKER PROCESS': { - 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_procs -C dockerd -c 1:', - }, - } - - for app in metadata.get('docker-engine/containers', {}): - services[f'DOCKER CONTAINER {app}'] = { - 'command_on_monitored_host': f'sudo /usr/local/share/icinga/plugins/check_docker_container {app}' - } - - return { - 'icinga2_api': { - 'docker-engine': { - 'services': services, - }, - }, - } - - -@metadata_reactor.provides( - 'backups/paths', - 'zfs/datasets', -) -def zfs(metadata): - datasets = {} - - for app in metadata.get('docker-engine/containers', {}): - datasets[f'tank/docker-data/{app}'] = { - 'mountpoint': f'/var/opt/docker-engine/{app}', - 'needed_by': { - f'directory:/var/opt/docker-engine/{app}', - }, - } - - return { - 'backups': { - 'paths': { - v['mountpoint'] - for v in datasets.values() - }, - }, - 'zfs': { - 'datasets': datasets, - }, - } diff --git a/bundles/docker-goauthentik/metadata.py b/bundles/docker-goauthentik/metadata.py deleted file mode 100644 index 9d742fa..0000000 --- a/bundles/docker-goauthentik/metadata.py +++ /dev/null @@ -1,89 +0,0 @@ -assert node.has_bundle('docker-engine') - -defaults = { - 'docker-engine': { - 'containers': { - 'goauthentik-server': { - 'image': 'ghcr.io/goauthentik/server:latest', - 'command': 'server', - 'environment': { - 'AUTHENTIK_POSTGRESQL__HOST': 'goauthentik-postgresql', - 'AUTHENTIK_POSTGRESQL__NAME': 'goauthentik', - 'AUTHENTIK_POSTGRESQL__PASSWORD': repo.vault.password_for(f'{node.name} postgresql goauthentik'), - 'AUTHENTIK_POSTGRESQL__USER': 'goauthentik', - 'AUTHENTIK_REDIS__HOST': 'goauthentik-redis', - 'AUTHENTIK_SECRET_KEY': repo.vault.password_for(f'{node.name} goauthentik secret key'), - }, - 'volumes': { - 'media': '/media', - 'templates': '/templates', - }, - 'ports': { - '9000': '9000', - '9443': '9443', - }, - 'needs': { - 'svc_systemd:docker-goauthentik-postgresql', - 'svc_systemd:docker-goauthentik-redis', - }, - 'requires': { - 'docker-goauthentik-postgresql.service', - 'docker-goauthentik-redis.service', - }, - }, - 'goauthentik-worker': { - 'image': 'ghcr.io/goauthentik/server:latest', - 'command': 'worker', - 'user': 'docker-goauthentik-server', - 'environment': { - 'AUTHENTIK_POSTGRESQL__HOST': 'goauthentik-postgresql', - 'AUTHENTIK_POSTGRESQL__NAME': 'goauthentik', - 'AUTHENTIK_POSTGRESQL__PASSWORD': repo.vault.password_for(f'{node.name} postgresql goauthentik'), - 'AUTHENTIK_POSTGRESQL__USER': 'goauthentik', - 'AUTHENTIK_REDIS__HOST': 'goauthentik-redis', - 'AUTHENTIK_SECRET_KEY': repo.vault.password_for(f'{node.name} goauthentik secret key'), - }, - 'volumes': { - '/var/opt/docker-engine/goauthentik-server/media': '/media', - '/var/opt/docker-engine/goauthentik-server/certs': '/certs', - '/var/opt/docker-engine/goauthentik-server/templates': '/templates', - }, - 'needs': { - 'svc_systemd:docker-goauthentik-postgresql', - 'svc_systemd:docker-goauthentik-redis', - }, - 'requires': { - 'docker-goauthentik-postgresql.service', - 'docker-goauthentik-redis.service', - }, - }, - 'goauthentik-postgresql': { - 'image': 'docker.io/library/postgres:16-alpine', - 'environment': { - 'POSTGRES_PASSWORD': repo.vault.password_for(f'{node.name} postgresql goauthentik'), - 'POSTGRES_USER': 'goauthentik', - 'POSTGRES_DB': 'goauthentik', - }, - 'volumes': { - 'database': '/var/lib/postgresql/data', - }, - }, - 'goauthentik-redis': { - 'image': 'docker.io/library/redis:alpine', - }, - }, - }, - 'nginx': { - 'vhosts': { - 'goauthentik': { - 'locations': { - '/': { - 'target': 'http://127.0.0.1:9000/', - 'websockets': True, - 'max_body_size': '5000m', - }, - }, - }, - }, - }, -} diff --git a/bundles/docker-immich/files/immich-auto-album-share.py b/bundles/docker-immich/files/immich-auto-album-share.py deleted file mode 100644 index cafd32c..0000000 --- a/bundles/docker-immich/files/immich-auto-album-share.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python3 - -import logging -from json import loads -from os import environ -from subprocess import check_output -from sys import exit - -import psycopg2 - -PSQL_HOST = environ['DB_HOSTNAME'] -PSQL_USER = environ['DB_USERNAME'] -PSQL_PASS = environ['DB_PASSWORD'] -PSQL_DB = environ['DB_DATABASE_NAME'] - -logging.basicConfig(level=logging.INFO) - -docker_networks = loads(check_output(['docker', 'network', 'inspect', 'aaarghhh'])) - -container_ip = None -# why the fuck is this a list of networks, even though we have to provide -# a network name to inspect ... -for network in docker_networks: - if network['Name'] != 'aaarghhh': - continue - - for _, container in network['Containers'].items(): - if container['Name'] == PSQL_HOST: - container_ip = container['IPv4Address'].split('/')[0] - -if not container_ip: - logging.error(f'could not find ip address for container {PSQL_HOST=} in json') - logging.debug(f'{docker_networks=}') - exit(0) - -logging.debug(f'{PSQL_HOST=} {container_ip=}') - -conn = psycopg2.connect( - dbname=PSQL_DB, - host=container_ip, - password=PSQL_PASS, - user=PSQL_USER, -) - -with conn: - with conn.cursor() as cur: - cur.execute('SELECT "id","ownerId","albumName" FROM albums;') - albums = { - i[0]: { - 'owner': i[1], - 'name': i[2], - } - for i in cur.fetchall() - } - logging.debug(f'{albums=}') - - with conn.cursor() as cur: - cur.execute('SELECT "id","name" FROM users;') - users = { - i[0]: i[1] - for i in cur.fetchall() - } - logging.debug(f'{users=}') - -for album_id, album in albums.items(): - log = logging.getLogger(album["name"]) - with conn: - with conn.cursor() as cur: - cur.execute('SELECT "usersId" FROM albums_shared_users_users WHERE "albumsId" = %s;', (album_id,)) - album_shares = [i[0] for i in cur.fetchall()] - log.info(f'album is shared with {len(album_shares)} users') - log.debug(f'{album_shares=}') - for user_id, user_name in users.items(): - if user_id == album['owner'] or user_id in album_shares: - continue - - log.info(f'sharing album with user {user_name}') - try: - with conn.cursor() as cur: - cur.execute( - 'INSERT INTO albums_shared_users_users ("albumsId","usersId","role") VALUES (%s, %s, %s);', - (album_id, user_id, 'viewer'), - ) - except Exception: - log.exception('failure while creating share') - -conn.close() diff --git a/bundles/docker-immich/items.py b/bundles/docker-immich/items.py deleted file mode 100644 index 8c9d54e..0000000 --- a/bundles/docker-immich/items.py +++ /dev/null @@ -1,3 +0,0 @@ -files['/usr/local/bin/immich-auto-album-share.py'] = { - 'mode': '0755', -} diff --git a/bundles/docker-immich/metadata.py b/bundles/docker-immich/metadata.py deleted file mode 100644 index 3952922..0000000 --- a/bundles/docker-immich/metadata.py +++ /dev/null @@ -1,92 +0,0 @@ -assert node.has_bundle('docker-engine') - -defaults = { - 'apt': { - 'packages': { - 'python3-psycopg2': {}, - }, - }, - 'docker-engine': { - 'containers': { - 'immich': { - 'image': 'ghcr.io/imagegenius/immich:latest', - 'environment': { - 'DB_DATABASE_NAME': 'immich', - 'DB_HOSTNAME': 'immich-postgresql', - 'DB_PASSWORD': repo.vault.password_for(f'{node.name} postgresql immich'), - 'DB_USERNAME': 'immich', - 'REDIS_HOSTNAME': 'immich-redis', - }, - 'volumes': { - 'config': '/config', - 'libraries': '/libraries', - 'photos': '/photos', - }, - 'ports': { - '8080': '8080', - }, - 'needs': { - 'svc_systemd:docker-immich-postgresql', - 'svc_systemd:docker-immich-redis', - }, - 'requires': { - 'docker-immich-postgresql.service', - 'docker-immich-redis.service', - }, - }, - 'immich-postgresql': { - 'image': 'tensorchord/pgvecto-rs:pg14-v0.2.0', - 'environment': { - 'POSTGRES_PASSWORD': repo.vault.password_for(f'{node.name} postgresql immich'), - 'POSTGRES_USER': 'immich', - 'POSTGRES_DB': 'immich', - }, - 'volumes': { - 'database': '/var/lib/postgresql/data', - }, - }, - 'immich-redis': { - 'image': 'docker.io/redis:6.2-alpine', - }, - }, - }, - 'docker-immich': { - 'enable_auto_album_share': False, - }, - 'nginx': { - 'vhosts': { - 'immich': { - 'locations': { - '/': { - 'target': 'http://127.0.0.1:8080/', - 'websockets': True, - 'max_body_size': '5000m', - }, - }, - }, - }, - }, -} - - -@metadata_reactor.provides( - 'systemd-timers/timers/immich-auto-album-share', -) -def auto_album_share(metadata): - if not metadata.get('docker-immich/enable_auto_album_share'): - return {} - - return { - 'systemd-timers': { - 'timers': { - 'immich-auto-album-share': { - 'command': '/usr/local/bin/immich-auto-album-share.py', - 'environment': metadata.get('docker-engine/containers/immich/environment'), - 'when': 'minutely', - 'requisite': { - 'docker-immich-postgresql.service', - }, - }, - }, - }, - } diff --git a/bundles/dovecot/files/dovecot-sql.conf b/bundles/dovecot/files/dovecot-sql.conf index 75c06ae..86cb8db 100644 --- a/bundles/dovecot/files/dovecot-sql.conf +++ b/bundles/dovecot/files/dovecot-sql.conf @@ -3,4 +3,3 @@ driver = pgsql default_pass_scheme = MD5-CRYPT password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active = true user_query = SELECT '/var/mail/vmail/' || maildir as home, 65534 as uid, 65534 as gid FROM mailbox WHERE username = '%u' AND active = true -iterate_query = SELECT username as user FROM mailbox WHERE active = true diff --git a/bundles/dovecot/files/dovecot.conf b/bundles/dovecot/files/dovecot.conf index 73afeaf..9a294aa 100644 --- a/bundles/dovecot/files/dovecot.conf +++ b/bundles/dovecot/files/dovecot.conf @@ -28,19 +28,19 @@ namespace inbox { mail_location = maildir:/var/mail/vmail/%d/%n protocols = imap lmtp sieve -ssl = required -ssl_cert = = 17: + # TODO verify this is still needed when upgrading to 1.12 + extra_install_cmds.append('export NODE_OPTIONS=--openssl-legacy-provider') + actions = { 'element-web_yarn': { 'command': ' && '.join([ + *extra_install_cmds, 'cd /opt/element-web', 'yarn install --pure-lockfile --ignore-scripts', 'yarn build', ]), 'needs': { - 'action:apt_execute_update_commands', + 'action:nodejs_install_yarn', 'pkg_apt:nodejs', }, 'triggered': True, diff --git a/bundles/element-web/metadata.py b/bundles/element-web/metadata.py index 5ee7449..0ce259a 100644 --- a/bundles/element-web/metadata.py +++ b/bundles/element-web/metadata.py @@ -11,26 +11,6 @@ defaults = { }, } -@metadata_reactor.provides( - 'nodejs/version', -) -def nodejs(metadata): - version = tuple([int(i) for i in metadata.get('element-web/version')[1:].split('.')]) - - if version >= (1, 11, 71): - return { - 'nodejs': { - 'version': 22, - }, - } - else: - return { - 'nodejs': { - 'version': 18, - }, - } - - @metadata_reactor.provides( 'nginx/vhosts/element-web', ) diff --git a/bundles/forgejo/items.py b/bundles/forgejo/items.py deleted file mode 100644 index f94c360..0000000 --- a/bundles/forgejo/items.py +++ /dev/null @@ -1,65 +0,0 @@ -users = { - 'git': { - 'home': '/var/lib/forgejo', - }, -} - -directories = { - '/var/lib/forgejo/.ssh': { - 'mode': '0700', - 'owner': 'git', - 'group': 'git', - }, - '/var/lib/forgejo': { - 'owner': 'git', - 'mode': '0700', - 'triggers': { - 'svc_systemd:forgejo:restart', - }, - }, -} - -files = { - '/usr/local/lib/systemd/system/forgejo.service': { - 'content_type': 'mako', - 'context': node.metadata.get('forgejo'), - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:forgejo:restart', - }, - }, - '/etc/forgejo/app.ini': { - 'content_type': 'mako', - 'context': node.metadata.get('forgejo'), - 'triggers': { - 'svc_systemd:forgejo:restart', - }, - }, - '/usr/local/bin/forgejo': { - 'content_type': 'download', - 'source': 'https://codeberg.org/forgejo/forgejo/releases/download/v{0}/forgejo-{0}-linux-amd64'.format(node.metadata.get('forgejo/version')), - 'content_hash': node.metadata.get('forgejo/sha1', None), - 'mode': '0755', - 'triggers': { - 'svc_systemd:forgejo:restart', - }, - }, -} - -if node.metadata.get('forgejo/install_ssh_key', False): - files['/var/lib/forgejo/.ssh/id_ed25519'] = { - 'content': repo.vault.decrypt_file(f'forgejo/files/ssh-keys/{node.name}.key.vault'), - 'mode': '0600', - 'owner': 'git', - 'group': 'git', - } - -svc_systemd = { - 'forgejo': { - 'needs': { - 'file:/etc/forgejo/app.ini', - 'file:/usr/local/bin/forgejo', - 'file:/usr/local/lib/systemd/system/forgejo.service', - }, - }, -} diff --git a/bundles/gce-workaround/items.py b/bundles/gce-workaround/items.py new file mode 100644 index 0000000..583e055 --- /dev/null +++ b/bundles/gce-workaround/items.py @@ -0,0 +1,33 @@ +svc_systemd = {} +pkg_apt = {} + +for i in { + 'gce-disk-expand', + 'google-cloud-packages-archive-keyring', + 'google-cloud-sdk', + 'google-compute-engine', + 'google-compute-engine-oslogin', + 'google-guest-agent', + 'google-osconfig-agent', +}: + pkg_apt[i] = { + 'installed': False, + } + +for i in { + 'google-accounts-daemon.service', + 'google-accounts-manager.service', + 'google-clock-skew-daemon.service', + 'google-clock-sync-manager.service', + 'google-guest-agent.service', + 'google-osconfig-agent.service', + 'google-shutdown-scripts.service', + 'google-startup-scripts.service', + 'sshguard.service', + + 'google-oslogin-cache.timer', +}: + svc_systemd[i] = { + 'enabled': False, + 'running': False, + } diff --git a/bundles/forgejo/files/app.ini b/bundles/gitea/files/app.ini similarity index 96% rename from bundles/forgejo/files/app.ini rename to bundles/gitea/files/app.ini index 557a20c..b55f210 100644 --- a/bundles/forgejo/files/app.ini +++ b/bundles/gitea/files/app.ini @@ -1,10 +1,9 @@ APP_NAME = ${app_name} RUN_USER = git RUN_MODE = prod -WORK_PATH = /var/lib/forgejo [repository] -ROOT = /var/lib/forgejo/repositories +ROOT = /home/git/gitea-repositories MAX_CREATION_LIMIT = 0 DEFAULT_BRANCH = main diff --git a/bundles/forgejo/files/forgejo.service b/bundles/gitea/files/gitea.service similarity index 55% rename from bundles/forgejo/files/forgejo.service rename to bundles/gitea/files/gitea.service index 76a5096..24f1505 100644 --- a/bundles/forgejo/files/forgejo.service +++ b/bundles/gitea/files/gitea.service @@ -5,13 +5,14 @@ After=network.target Requires=postgresql.service [Service] -RestartSec=10 +RestartSec=2s Type=simple User=git Group=git -WorkingDirectory=/var/lib/forgejo -ExecStart=/usr/local/bin/forgejo web -c /etc/forgejo/app.ini +WorkingDirectory=/var/lib/gitea/ +ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini Restart=always +Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea [Install] WantedBy=multi-user.target diff --git a/bundles/gitea/items.py b/bundles/gitea/items.py new file mode 100644 index 0000000..e071483 --- /dev/null +++ b/bundles/gitea/items.py @@ -0,0 +1,68 @@ +users = { + 'git': {}, +} + +directories = { + '/home/git': { + 'mode': '0755', + 'owner': 'git', + 'group': 'git', + }, + '/home/git/.ssh': { + 'mode': '0755', + 'owner': 'git', + 'group': 'git', + }, + '/var/lib/gitea': { + 'owner': 'git', + 'mode': '0700', + 'triggers': { + 'svc_systemd:gitea:restart', + }, + }, +} + +files = { + '/etc/systemd/system/gitea.service': { + 'content_type': 'mako', + 'context': node.metadata.get('gitea'), + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:gitea:restart', + }, + }, + '/etc/gitea/app.ini': { + 'content_type': 'mako', + 'context': node.metadata.get('gitea'), + 'triggers': { + 'svc_systemd:gitea:restart', + }, + }, + '/usr/local/bin/gitea': { + 'content_type': 'download', + 'source': node.metadata.get('gitea/url'), + 'content_hash': node.metadata.get('gitea/sha1', None), + 'mode': '0755', + 'triggers': { + 'svc_systemd:gitea:restart', + }, + }, +} + +if node.metadata['gitea'].get('install_ssh_key', False): + files['/home/git/.ssh/id_ed25519'] = { + 'content': repo.vault.decrypt_file(f'gitea/files/ssh-keys/{node.name}.key.vault'), + 'mode': '0600', + 'owner': 'git', + 'group': 'git', + } + +svc_systemd = { + 'gitea': { + 'needs': { + 'file:/etc/gitea/app.ini', + 'file:/etc/systemd/system/gitea.service', + 'file:/usr/local/bin/gitea', + }, + }, +} diff --git a/bundles/forgejo/metadata.py b/bundles/gitea/metadata.py similarity index 53% rename from bundles/forgejo/metadata.py rename to bundles/gitea/metadata.py index 16190e2..2b9bcbe 100644 --- a/bundles/forgejo/metadata.py +++ b/bundles/gitea/metadata.py @@ -1,31 +1,33 @@ defaults = { 'backups': { 'paths': { - '/var/lib/forgejo', + '/home/git', + '/var/lib/gitea', }, }, - 'forgejo': { + 'gitea': { 'app_name': 'Forgejo', 'database': { - 'username': 'forgejo', - 'password': repo.vault.password_for('{} postgresql forgejo'.format(node.name)), - 'database': 'forgejo', + 'username': 'gitea', + 'password': repo.vault.password_for('{} postgresql gitea'.format(node.name)), + 'database': 'gitea', }, 'disable_registration': True, 'email_domain_blocklist': set(), 'enable_git_hooks': False, - 'internal_token': repo.vault.password_for('{} forgejo internal_token'.format(node.name)), - 'lfs_secret_key': repo.vault.password_for('{} forgejo lfs_secret_key'.format(node.name)), - 'oauth_secret_key': repo.vault.password_for('{} forgejo oauth_secret_key'.format(node.name)), - 'security_secret_key': repo.vault.password_for('{} forgejo security_secret_key'.format(node.name)), + 'internal_token': repo.vault.password_for('{} gitea internal_token'.format(node.name)), + 'lfs_secret_key': repo.vault.password_for('{} gitea lfs_secret_key'.format(node.name)), + 'oauth_secret_key': repo.vault.password_for('{} gitea oauth_secret_key'.format(node.name)), + 'security_secret_key': repo.vault.password_for('{} gitea security_secret_key'.format(node.name)), }, 'icinga2_api': { - 'forgejo': { + 'gitea': { 'services': { 'FORGEJO PROCESS': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit forgejo', + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit gitea', }, 'FORGEJO UPDATE': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_forgejo_for_new_release codeberg.org forgejo/forgejo v$(gitea --version | cut -d" " -f3)', 'vars.notification.mail': True, 'check_interval': '60m', }, @@ -39,22 +41,29 @@ defaults = { }, 'postgresql': { 'roles': { - 'forgejo': { - 'password': repo.vault.password_for('{} postgresql forgejo'.format(node.name)), + 'gitea': { + 'password': repo.vault.password_for('{} postgresql gitea'.format(node.name)), }, }, 'databases': { - 'forgejo': { - 'owner': 'forgejo', + 'gitea': { + 'owner': 'gitea', }, }, }, 'zfs': { 'datasets': { - 'tank/forgejo': { - 'mountpoint': '/var/lib/forgejo', + 'tank/gitea': {}, + 'tank/gitea/home': { + 'mountpoint': '/home/git', 'needed_by': { - 'directory:/var/lib/forgejo', + 'directory:/home/git', + }, + }, + 'tank/gitea/var': { + 'mountpoint': '/var/lib/gitea', + 'needed_by': { + 'directory:/var/lib/gitea', }, }, }, @@ -62,23 +71,6 @@ defaults = { } -@metadata_reactor.provides( - 'icinga2_api/forgejo', -) -def update_monitoring(metadata): - return { - 'icinga2_api': { - 'forgejo': { - 'services': { - 'FORGEJO UPDATE': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_forgejo_for_new_release codeberg.org forgejo/forgejo v{}'.format(metadata.get('forgejo/version')), - }, - }, - }, - }, - } - - @metadata_reactor.provides( 'nginx/vhosts/forgejo', ) @@ -90,7 +82,7 @@ def nginx(metadata): 'nginx': { 'vhosts': { 'forgejo': { - 'domain': metadata.get('forgejo/domain'), + 'domain': metadata.get('gitea/domain'), 'locations': { '/': { 'target': 'http://127.0.0.1:22000', @@ -100,8 +92,16 @@ def nginx(metadata): }, }, 'website_check_path': '/user/login', - 'website_check_string': 'Sign in', + 'website_check_string': 'Sign In', }, }, }, } + + +@metadata_reactor.provides( + 'icinga2_api/gitea/services', +) +def icinga_check_for_new_release(metadata): + return { + } diff --git a/bundles/grafana/dashboard-rows/smartd.py b/bundles/grafana/dashboard-rows/smartd.py index 88b7b0b..f2fb257 100644 --- a/bundles/grafana/dashboard-rows/smartd.py +++ b/bundles/grafana/dashboard-rows/smartd.py @@ -47,7 +47,7 @@ def dashboard_row_smartd(panel_id, node): 'renderer': 'flot', 'seriesOverrides': [], 'spaceLength': 10, - 'span': 12, + 'span': 8, 'stack': False, 'steppedLine': False, 'targets': [ @@ -114,5 +114,115 @@ def dashboard_row_smartd(panel_id, node): 'alignLevel': None } }, + { + 'aliasColors': {}, + 'bars': False, + 'dashLength': 10, + 'dashes': False, + 'datasource': None, + 'fieldConfig': { + 'defaults': { + 'displayName': '${__field.labels.device}' + }, + 'overrides': [] + }, + 'fill': 0, + 'fillGradient': 0, + 'hiddenSeries': False, + 'id': next(panel_id), + 'legend': { + 'alignAsTable': False, + 'avg': False, + 'current': False, + 'hideEmpty': True, + 'hideZero': True, + 'max': False, + 'min': False, + 'rightSide': False, + 'show': True, + 'total': False, + 'values': False + }, + 'lines': True, + 'linewidth': 1, + 'NonePointMode': 'None', + 'options': { + 'alertThreshold': True + }, + 'percentage': False, + 'pluginVersion': '7.5.5', + 'pointradius': 2, + 'points': False, + 'renderer': 'flot', + 'seriesOverrides': [], + 'spaceLength': 10, + 'span': 4, + 'stack': False, + 'steppedLine': False, + 'targets': [ + { + 'groupBy': [ + {'type': 'time', 'params': ['$__interval']}, + {'type': 'fill', 'params': ['linear']}, + ], + 'orderByTime': "ASC", + 'policy': "default", + 'query': f"""from(bucket: "telegraf") + |> range(start: v.timeRangeStart, stop: v.timeRangeStop) + |> filter(fn: (r) => + r["_measurement"] == "smartd_stats" and + r["_field"] == "power_on_hours" and + r["host"] == "{node.name}" + ) + |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) + |> yield(name: "fan")""", + 'resultFormat': 'time_series', + 'select': [[ + {'type': 'field', 'params': ['value']}, + {'type': 'mean', 'params': []}, + ]], + "tags": [] + }, + ], + 'thresholds': [], + 'timeRegions': [], + 'title': 'fans', + 'tooltip': { + 'shared': True, + 'sort': 0, + 'value_type': 'individual' + }, + 'type': 'graph', + 'xaxis': { + 'buckets': None, + 'mode': 'time', + 'name': None, + 'show': True, + 'values': [] + }, + 'yaxes': [ + { + 'format': 'hours', + 'label': None, + 'logBase': 1, + 'max': None, + 'min': None, + 'show': True, + 'decimals': 0, + }, + { + 'format': 'short', + 'label': None, + 'logBase': 1, + 'max': None, + 'min': None, + 'show': False, + } + ], + 'yaxis': { + 'align': False, + 'alignLevel': None + } + }, ], } diff --git a/bundles/grafana/metadata.py b/bundles/grafana/metadata.py index f27cb81..2f0f4d7 100644 --- a/bundles/grafana/metadata.py +++ b/bundles/grafana/metadata.py @@ -43,7 +43,6 @@ def nginx(metadata): 'locations': { '/': { 'target': 'http://127.0.0.1:21010', - 'websockets': True, }, '/api/ds/query': { 'target': 'http://127.0.0.1:21010', diff --git a/bundles/hedgedoc/files/hedgedoc.service b/bundles/hedgedoc/files/hedgedoc.service index 5bafd07..2bd0de4 100644 --- a/bundles/hedgedoc/files/hedgedoc.service +++ b/bundles/hedgedoc/files/hedgedoc.service @@ -33,11 +33,7 @@ ProtectSystem=strict ProtectHome=true PrivateTmp=true SystemCallArchitectures=native -# FIXME -# causes problems on bookworm -# see https://github.com/hedgedoc/hedgedoc/issues/4686 -# cmmented out for now ... -#SystemCallFilter=@system-service +SystemCallFilter=@system-service # You may have to adjust these settings User=hedgedoc diff --git a/bundles/hedgedoc/items.py b/bundles/hedgedoc/items.py index 732f465..ac66fcb 100644 --- a/bundles/hedgedoc/items.py +++ b/bundles/hedgedoc/items.py @@ -1,5 +1,3 @@ -from semver import compare - repo.libs.tools.require_bundle(node, 'nodejs') git_deploy = { @@ -49,29 +47,16 @@ directories = { }, } -if compare(node.metadata.get('hedgedoc/version'), '1.9.7') <= 0: - command = ' && '.join([ - 'cd /opt/hedgedoc', - 'yarn workspaces focus --production', - 'yarn install --ignore-scripts', - 'yarn build', - ]) -elif compare(node.metadata.get('hedgedoc/version'), '1.9.9') >= 0: - command = ' && '.join([ - 'cd /opt/hedgedoc', - 'bin/setup', - 'yarn install --immutable', - 'yarn build', - ]) - actions = { 'hedgedoc_yarn': { 'command': ' && '.join([ 'cd /opt/hedgedoc', - 'yarn install --immutable', + 'yarn install --production=true --pure-lockfile --ignore-scripts', + 'yarn install --ignore-scripts', 'yarn build', ]), 'needs': { + 'action:nodejs_install_yarn', 'file:/opt/hedgedoc/config.json', 'git_deploy:/opt/hedgedoc', 'pkg_apt:nodejs', diff --git a/bundles/homeassistant/files/check_homeassistant_update b/bundles/homeassistant/files/check_homeassistant_update index 853c467..ff2b0d7 100644 --- a/bundles/homeassistant/files/check_homeassistant_update +++ b/bundles/homeassistant/files/check_homeassistant_update @@ -2,42 +2,48 @@ from sys import exit -from packaging.version import parse -from requests import get +import requests +from packaging import version -API_TOKEN = "${token}" -DOMAIN = "${domain}" +bearer = "${bearer}" +domain = "${domain}" +OK = 0 +WARN = 1 +CRITICAL = 2 +UNKNOWN = 3 + +status = 3 +message = "Unknown Update Status" + + +domain = "hass.home.kunbox.net" + +s = requests.Session() +s.headers.update({"Content-Type": "application/json"}) try: - r = get("https://version.home-assistant.io/stable.json") - r.raise_for_status() - stable_version = parse(r.json()["homeassistant"]["generic-x86-64"]) -except Exception as e: - print(f"Could not get stable version information from home-assistant.io: {e!r}") - exit(3) - -try: - r = get( - f"https://{DOMAIN}/api/config", - headers={"Authorization": f"Bearer {API_TOKEN}", "Content-Type": "application/json"}, + stable_version = version.parse( + s.get("https://version.home-assistant.io/stable.json").json()["homeassistant"][ + "generic-x86-64" + ] ) - r.raise_for_status() - running_version = parse(r.json()["version"]) -except Exception as e: - print(f"Could not get running version information from homeassistant: {e!r}") - exit(3) - -try: - if stable_version > running_version: - print( - f"There is a newer version available: {stable_version} (currently installed: {running_version})" - ) - exit(2) + s.headers.update( + {"Authorization": f"Bearer {bearer}", "Content-Type": "application/json"} + ) + running_version = version.parse( + s.get(f"https://{domain}/api/config").json()["version"] + ) + if running_version == stable_version: + status = 0 + message = f"OK - running version {running_version} equals stable version {stable_version}" + elif running_version > stable_version: + status = 1 + message = f"WARNING - stable version {stable_version} is lower than running version {running_version}, check if downgrade is necessary." else: - print( - f"Currently running version {running_version} matches newest release on home-assistant.io" - ) - exit(0) + status = 2 + message = f"CRITICAL - update necessary, running version {running_version} is lower than stable version {stable_version}" except Exception as e: - print(repr(e)) - exit(3) + message = f"{message}: {repr(e)}" + +print(message) +exit(status) diff --git a/bundles/homeassistant/files/homeassistant.service b/bundles/homeassistant/files/homeassistant.service index ed0f2a9..d97cec7 100644 --- a/bundles/homeassistant/files/homeassistant.service +++ b/bundles/homeassistant/files/homeassistant.service @@ -5,13 +5,9 @@ After=network-online.target [Service] Type=simple User=homeassistant -Environment="VIRTUAL_ENV=/opt/homeassistant/venv" -Environment="PATH=/opt/homeassistant/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" WorkingDirectory=/var/opt/homeassistant ExecStart=/opt/homeassistant/venv/bin/hass -c "/var/opt/homeassistant" RestartForceExitStatus=100 -Restart=on-failure -RestartSec=2 [Install] WantedBy=multi-user.target diff --git a/bundles/homeassistant/items.py b/bundles/homeassistant/items.py index 92f097b..6ceeec4 100644 --- a/bundles/homeassistant/items.py +++ b/bundles/homeassistant/items.py @@ -1,13 +1,6 @@ -if node.has_bundle('pyenv'): - python_version = sorted(node.metadata.get('pyenv/python_versions'))[-1] - python_path = f'/opt/pyenv/versions/{python_version}/bin/python' -else: - python_path = '/usr/bin/python3' - users = { 'homeassistant': { 'home': '/var/opt/homeassistant', - "groups": ["dialout"], }, } @@ -30,7 +23,7 @@ files = { '/usr/local/share/icinga/plugins/check_homeassistant_update': { 'content_type': 'mako', 'context': { - 'token': node.metadata.get('homeassistant/api_secret'), + 'bearer': repo.vault.decrypt(node.metadata.get('homeassistant/api_secret')), 'domain': node.metadata.get('homeassistant/domain'), }, 'mode': '0755', @@ -39,18 +32,11 @@ files = { actions = { 'homeassistant_create_virtualenv': { - 'command': f'sudo -u homeassistant virtualenv -p {python_path} /opt/homeassistant/venv/', + 'command': 'sudo -u homeassistant /usr/bin/python3 -m virtualenv -p python3 /opt/homeassistant/venv/', 'unless': 'test -d /opt/homeassistant/venv/', 'needs': { 'directory:/opt/homeassistant', 'user:homeassistant', - }, - }, - 'homeassistant_install': { - 'command': 'sudo -u homeassistant /opt/homeassistant/venv/bin/pip install homeassistant', - 'unless': 'test -f /opt/homeassistant/venv/bin/hass', - 'needs': { - 'action:homeassistant_create_virtualenv', 'pkg_apt:bluez', 'pkg_apt:libffi-dev', 'pkg_apt:libssl-dev', @@ -59,10 +45,17 @@ actions = { 'pkg_apt:autoconf', 'pkg_apt:build-essential', 'pkg_apt:libopenjp2-7', - 'pkg_apt:libtiff6', + 'pkg_apt:libtiff5', 'pkg_apt:libturbojpeg0-dev', 'pkg_apt:tzdata', }, + }, + 'homeassistant_install': { + 'command': 'sudo -u homeassistant /opt/homeassistant/venv/bin/pip install homeassistant', + 'unless': 'test -f /opt/homeassistant/venv/bin/hass', + 'needs': { + 'action:homeassistant_create_virtualenv', + }, 'triggers': { 'svc_systemd:homeassistant:restart', }, diff --git a/bundles/homeassistant/metadata.py b/bundles/homeassistant/metadata.py index f1c76de..0b41f39 100644 --- a/bundles/homeassistant/metadata.py +++ b/bundles/homeassistant/metadata.py @@ -4,12 +4,11 @@ defaults = { 'autoconf': {}, 'bluez': {}, 'build-essential': {}, - 'ffmpeg': {}, 'libffi-dev': {}, 'libjpeg-dev': {}, 'libopenjp2-7': {}, 'libssl-dev': {}, - 'libtiff6': {}, + 'libtiff5': {}, 'libturbojpeg0-dev': {}, 'python3-packaging': {}, 'tzdata': {}, @@ -23,8 +22,6 @@ defaults = { }, }, } - - @metadata_reactor.provides( 'icinga2_api/homeassistant/services', ) @@ -34,17 +31,15 @@ def icinga_check_for_new_release(metadata): 'homeassistant': { 'services': { 'HOMEASSISTANT UPDATE': { - 'check_interval': '60m', 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_homeassistant_update', 'vars.notification.mail': True, - 'vars.sshmon_timeout': 20, + 'check_interval': '60m', }, }, }, }, } - @metadata_reactor.provides( 'nginx/vhosts/homeassistant', ) diff --git a/bundles/icinga2-statuspage/files/icinga2-statuspage.service b/bundles/icinga2-statuspage/files/icinga2-statuspage.service deleted file mode 100644 index 8a8e4a2..0000000 --- a/bundles/icinga2-statuspage/files/icinga2-statuspage.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=icinga2-statuspage -After=network.target -Requires=postgresql.service - -[Service] -User=www-data -Group=www-data -Environment=APP_CONFIG=/opt/icinga2-statuspage/config.json -WorkingDirectory=/opt/icinga2-statuspage/src -ExecStart=/usr/bin/gunicorn statuspage:app --workers 4 --max-requests 1200 --max-requests-jitter 50 --log-level=info --bind=127.0.0.1:22110 -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target diff --git a/bundles/icinga2-statuspage/items.py b/bundles/icinga2-statuspage/items.py deleted file mode 100644 index fb3c413..0000000 --- a/bundles/icinga2-statuspage/items.py +++ /dev/null @@ -1,34 +0,0 @@ -directories['/opt/icinga2-statuspage/src'] = {} - -git_deploy['/opt/icinga2-statuspage/src'] = { - 'repo': 'https://git.franzi.business/kunsi/icinga-dynamic-statuspage.git', - 'rev': 'main', - 'triggers': { - 'svc_systemd:icinga2-statuspage:restart', - }, -} - -files['/opt/icinga2-statuspage/config.json'] = { - 'content': repo.libs.faults.dict_as_json(node.metadata.get('icinga2-statuspage')), - 'triggers': { - 'svc_systemd:icinga2-statuspage:restart', - }, -} - -files['/usr/local/lib/systemd/system/icinga2-statuspage.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:icinga2-statuspage:restart', - }, -} - - -svc_systemd['icinga2-statuspage'] = { - 'needs': { - 'file:/opt/icinga2-statuspage/config.json', - 'git_deploy:/opt/icinga2-statuspage/src', - 'pkg_apt:gunicorn', - 'pkg_apt:python3-flask', - 'pkg_apt:python3-psycopg2', - }, -} diff --git a/bundles/icinga2-statuspage/metadata.py b/bundles/icinga2-statuspage/metadata.py deleted file mode 100644 index ffe5dcf..0000000 --- a/bundles/icinga2-statuspage/metadata.py +++ /dev/null @@ -1,47 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'gunicorn': {}, - 'python3-flask': {}, - 'python3-psycopg2': {}, - }, - }, -} - - -@metadata_reactor.provides( - 'icinga2-statuspage', -) -def import_db_settings_from_icinga(metadata): - return { - 'icinga2-statuspage': { - 'DB_USER': 'icinga2', - 'DB_PASS': metadata.get('postgresql/roles/icinga2/password'), - 'DB_NAME': 'icinga2', - }, - } - - -@metadata_reactor.provides( - 'nginx/vhosts/icinga2-statuspage', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'icinga2-statuspage': { - 'domain': metadata.get('icinga2-statuspage/DOMAIN'), - 'locations': { - '/': { - 'target': 'http://127.0.0.1:22110', - }, - }, - 'website_check_path': '/', - 'website_check_string': 'status page', - }, - }, - }, - } diff --git a/bundles/icinga2/files/check_omm.py b/bundles/icinga2/files/check_omm.py deleted file mode 100644 index 25bf9b0..0000000 --- a/bundles/icinga2/files/check_omm.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python3 - -import re -from hashlib import md5 -from sys import argv, exit - -# Supress SSL certificate warnings for ssl_verify=False -import urllib3 -from lxml import html -from requests import Session - -USERNAME_FIELD = "g2" -PASSWORD_FIELD = "g3" -CRSF_FIELD = "password" - -STATUS_OK = 0 -STATUS_WARNING = 1 -STATUS_CRITICAL = 2 -STATUS_UNKNOWN = 3 - - -class OMMCrawler: - def __init__(self, hostname, username, password): - self.session = Session() - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - self.session.verify = False - - self.url = f"https://{hostname}" - self.login_data = { - USERNAME_FIELD: username, - PASSWORD_FIELD: password, - CRSF_FIELD: md5(password.encode()).hexdigest(), - } - self.logged_in = False - - def login(self): - # if we have multiple dect masters, find out which one is the current master - current_master_url = self.session.get(self.url, verify=False).url - self.hostname = re.search(r"^(.*[\\\/])", current_master_url).group(0)[:-1] - - response = self.session.post(f"{self.url}/login_set.html", data=self.login_data) - response.raise_for_status() - - # set cookie - pass_value = re.search(r"(?<=pass=)\d+(?=;)", response.text).group(0) - self.session.cookies.set("pass", pass_value) - self.logged_in = True - - def get_station_status(self): - if not self.logged_in: - self.login() - - data = {} - response = self.session.get(f"{self.url}/fp_pnp_status.html") - response.raise_for_status() - tree = html.fromstring(response.text) - xpath_results = tree.xpath('//tr[@class="l0" or @class="l1"]') - - for result in xpath_results: - bubble_is_in_inactive_cluster = False - bubble_is_connected = False - bubble_is_active = False - - bubble_name = result.xpath("td[4]/text()")[0] - try: - bubble_is_connected = result.xpath("td[11]/img/@alt")[0] == "yes" - - if bubble_is_connected: - try: - bubble_is_active = result.xpath("td[12]/img/@alt")[0] == "yes" - except IndexError: - # If an IndexError occurs, there is no image in the - # 12th td. This means this bubble is in the not inside - # an active DECT cluster, but is a backup bubble. - # This is probably fine. - bubble_is_active = False - bubble_is_in_inactive_cluster = True - else: - bubble_is_active = False - except: - # There is no Image in the 11th td. This usually means there - # is a warning message in the 10th td. We do not care about - # that, currently. - pass - - data[bubble_name] = { - "is_connected": bubble_is_connected, - "is_active": bubble_is_active, - "is_in_inactive_cluster": bubble_is_in_inactive_cluster, - } - return data - - def handle_station_data(self): - try: - data = self.get_station_status() - except Exception as e: - print(f"Something went wrong. You should take a look at {self.url}") - print(repr(e)) - exit(STATUS_UNKNOWN) - - critical = False - for name, status in data.items(): - if not status["is_active"] and not status["is_connected"]: - print( - f"Base station {name} is not active or connected! Check manually!" - ) - critical = True - elif not status["is_active"] and not status["is_in_inactive_cluster"]: - # Bubble is part of an active DECT cluster, but not active. - # This shouldn't happen. - print( - f"Base station {name} is not active but connected! Check manually!" - ) - critical = True - elif not status["is_connected"]: - # This should never happen. Seeing this state means OMM - # itself is broken. - print( - f"Base station {name} is not connected but active! Check manually!" - ) - critical = True - - if critical: - exit(STATUS_CRITICAL) - else: - print(f"OK - {len(data)} base stations connected") - exit(STATUS_OK) - - -if __name__ == "__main__": - omm = OMMCrawler(argv[1], argv[2], argv[3]) - omm.handle_station_data() diff --git a/bundles/icinga2/files/check_sipgate_account_balance b/bundles/icinga2/files/check_sipgate_account_balance index 65054ba..843dfd9 100644 --- a/bundles/icinga2/files/check_sipgate_account_balance +++ b/bundles/icinga2/files/check_sipgate_account_balance @@ -1,17 +1,16 @@ #!/usr/bin/env python3 -from json import load from sys import exit from requests import get -with open('/etc/icinga2/notification_config.json') as f: - CONFIG = load(f) +SIPGATE_USER = '${node.metadata['icinga2']['sipgate_user']}' +SIPGATE_PASS = '${node.metadata['icinga2']['sipgate_pass']}' try: r = get( 'https://api.sipgate.com/v2/balance', - auth=(CONFIG['sipgate']['user'], CONFIG['sipgate']['password']), + auth=(SIPGATE_USER, SIPGATE_PASS), headers={'Accept': 'application/json'}, ) diff --git a/bundles/icinga2/files/check_spam_blocklist b/bundles/icinga2/files/check_spam_blocklist index 2b1a3c3..5cb350d 100644 --- a/bundles/icinga2/files/check_spam_blocklist +++ b/bundles/icinga2/files/check_spam_blocklist @@ -5,33 +5,30 @@ from ipaddress import IPv6Address, ip_address from subprocess import check_output from sys import argv, exit -BLOCKLISTS = { - '0spam.fusionzero.com': set(), - 'bl.mailspike.org': set(), - 'bl.spamcop.net': set(), - 'blackholes.brainerd.net': set(), - 'dnsbl-1.uceprotect.net': set(), - 'l2.spews.dnsbl.sorbs.net': set(), - 'list.dsbl.org': set(), - 'multihop.dsbl.org': set(), - 'ns1.unsubscore.com': set(), - 'opm.blitzed.org': set(), - 'psbl.surriel.com': set(), - 'rbl.efnet.org': set(), - 'rbl.schulte.org': set(), - 'spamguard.leadmon.net': set(), - 'ubl.unsubscore.com': set(), - 'unconfirmed.dsbl.org': set(), - 'virbl.dnsbl.bit.nl': set(), - 'zen.spamhaus.org': { - # https://www.spamhaus.org/news/article/807/using-our-public-mirrors-check-your-return-codes-now. - '127.255.255.252', # Typing Error - '127.255.255.254', # public resolver / generic rdns - '127.255.255.255', # rate limited - }, -} +BLOCKLISTS = [ + '0spam.fusionzero.com', + 'bl.mailspike.org', + 'bl.spamcop.net', + 'blackholes.brainerd.net', + 'dnsbl-1.uceprotect.net', + 'dnsbl-2.uceprotect.net', + 'l2.spews.dnsbl.sorbs.net', + 'list.dsbl.org', + 'map.spam-rbl.com', + 'multihop.dsbl.org', + 'ns1.unsubscore.com', + 'opm.blitzed.org', + 'psbl.surriel.com', + 'rbl.efnet.org', + 'rbl.schulte.org', + 'spamguard.leadmon.net', + 'ubl.unsubscore.com', + 'unconfirmed.dsbl.org', + 'virbl.dnsbl.bit.nl', + 'zen.spamhaus.org', +] -def check_list(ip_list, blocklist, warn_ips): +def check_list(ip_list, blocklist): dns_name = '{}.{}'.format( '.'.join(ip_list), blocklist, @@ -44,22 +41,17 @@ def check_list(ip_list, blocklist, warn_ips): result = check_output([ 'dig', '+tries=2', - '+time=10', + '+time=5', '+short', dns_name ]).decode().splitlines() for item in result: - if item.startswith(';;'): - continue msgs.append('{} listed in {} as {}'.format( ip, blocklist, item, )) - if item in warn_ips and returncode < 2: - returncode = 1 - else: - returncode = 2 + returncode = 2 except Exception as e: if e.returncode == 9: # no reply from server @@ -86,8 +78,8 @@ exitcode = 0 with ThreadPoolExecutor(max_workers=len(BLOCKLISTS)) as executor: futures = set() - for blocklist, warn_ips in BLOCKLISTS.items(): - futures.add(executor.submit(check_list, ip_list, blocklist, warn_ips)) + for blocklist in BLOCKLISTS: + futures.add(executor.submit(check_list, ip_list, blocklist)) for future in as_completed(futures): msgs, this_exitcode = future.result() diff --git a/bundles/icinga2/files/icinga2/downtimes.conf b/bundles/icinga2/files/icinga2/downtimes.conf index 6dffabd..0052816 100644 --- a/bundles/icinga2/files/icinga2/downtimes.conf +++ b/bundles/icinga2/files/icinga2/downtimes.conf @@ -1,18 +1,31 @@ -% for dt in downtimes: -object ScheduledDowntime "${dt['name']}" { - host_name = "${dt['host']}" +% for monitored_node in sorted(repo.nodes): +<% + auto_updates_enabled = ( + monitored_node.has_any_bundle(['apt', 'c3voc-addons']) + or ( + monitored_node.has_bundle('pacman') + and monitored_node.metadata.get('pacman/unattended-upgrades/is_enabled', False) + ) + ) and not monitored_node.metadata.get('icinga_options/exclude_from_monitoring', False) +%>\ +% if auto_updates_enabled: +object ScheduledDowntime "unattended_upgrades" { + host_name = "${monitored_node.name}" - author = "${dt['name']}" - comment = "${dt['comment']}" + author = "unattended-upgrades" + comment = "Downtime for upgrade-and-reboot of node ${monitored_node.name}" fixed = true ranges = { -% for d,t in dt['times'].items(): - "${d}" = "${t}" -% endfor +% if monitored_node.has_bundle('pacman'): + "${days[monitored_node.metadata.get('pacman/unattended-upgrades/day')]}" = "${monitored_node.metadata.get('pacman/unattended-upgrades/hour')}:${monitored_node.magic_number%30}-${monitored_node.metadata.get('pacman/unattended-upgrades/hour')}:${(monitored_node.magic_number%30)+30}" +% else: + "${days[monitored_node.metadata.get('apt/unattended-upgrades/day')]}" = "${monitored_node.metadata.get('apt/unattended-upgrades/hour')}:${monitored_node.magic_number%30}-${monitored_node.metadata.get('apt/unattended-upgrades/hour')}:${(monitored_node.magic_number%30)+30}" +% endif } child_options = "DowntimeTriggeredChildren" } +% endif % endfor diff --git a/bundles/icinga2/files/icinga2/groups.conf b/bundles/icinga2/files/icinga2/groups.conf index 513568c..cc18159 100644 --- a/bundles/icinga2/files/icinga2/groups.conf +++ b/bundles/icinga2/files/icinga2/groups.conf @@ -33,11 +33,3 @@ object ServiceGroup "checks_with_sms" { assign where service.vars.notification.sms == true ignore where host.vars.notification.sms == false } - -object ServiceGroup "statuspage" { - display_name = "Checks which are show on the public status page" - - assign where service.vars.notification.sms == true - ignore where host.vars.notification.sms == false - ignore where host.vars.show_on_statuspage == false -} diff --git a/bundles/icinga2/files/icinga2/hosts_template.conf b/bundles/icinga2/files/icinga2/hosts_template.conf index ac56ef2..1c4f957 100644 --- a/bundles/icinga2/files/icinga2/hosts_template.conf +++ b/bundles/icinga2/files/icinga2/hosts_template.conf @@ -14,8 +14,7 @@ object Host "${rnode.name}" { vars.os = "${rnode.os}" # used for status page - vars.pretty_name = "${rnode.metadata.get('icinga_options/pretty_name', rnode.metadata.get('hostname'))}" - vars.show_on_statuspage = ${str(rnode.metadata.get('icinga_options/show_on_statuspage', True)).lower()} + vars.pretty_name = "${rnode.metadata.get('icinga_options/pretty_name', rnode.name)}" vars.period = "${rnode.metadata.get('icinga_options/period', '24x7')}" @@ -23,25 +22,6 @@ object Host "${rnode.name}" { vars.notification.mail = true } -% if rnode.ipmi_hostname: -object Host "${rnode.name} IPMI" { - import "generic-host" - - address = "${rnode.ipmi_hostname}" - - vars.location = "${rnode.metadata.get('location', 'unknown')}" - vars.os = "ipmi" - - vars.pretty_name = "${rnode.metadata.get('icinga_options/pretty_name', rnode.metadata.get('hostname'))} IPMI" - vars.show_on_statuspage = false - - vars.period = "${rnode.metadata.get('icinga_options/period', '24x7')}" - - vars.notification.sms = ${str(rnode.metadata.get('icinga_options/vars.notification.sms', True)).lower()} - vars.notification.mail = true -} -% endif - % for depends_on_host in sorted(rnode.metadata.get('icinga_options/also_affected_by', set())): object Dependency "${rnode.name}_depends_on_${depends_on_host}" { parent_host_name = "${depends_on_host}" diff --git a/bundles/icinga2/files/icinga_statusmonitor.py b/bundles/icinga2/files/icinga_statusmonitor.py index bc33759..e816ada 100644 --- a/bundles/icinga2/files/icinga_statusmonitor.py +++ b/bundles/icinga2/files/icinga_statusmonitor.py @@ -9,11 +9,6 @@ app = Flask(__name__) @app.route('/status') def statuspage(): everything_fine = True - try: - check_output(['/usr/local/share/icinga/plugins/check_mounts']) - except: - everything_fine = False - try: check_output(['/usr/lib/nagios/plugins/check_procs', '-C', 'icinga2', '-c', '1:']) except: diff --git a/bundles/icinga2/files/icinga_statusmonitor.service b/bundles/icinga2/files/icinga_statusmonitor.service index b651357..3bfd258 100644 --- a/bundles/icinga2/files/icinga_statusmonitor.service +++ b/bundles/icinga2/files/icinga_statusmonitor.service @@ -3,6 +3,8 @@ Description=Icinga2 Statusmonitor After=network.target [Service] +User=nagios +Group=nagios Environment="FLASK_APP=/etc/icinga2/icinga_statusmonitor.py" ExecStart=/usr/bin/python3 -m flask run WorkingDirectory=/tmp diff --git a/bundles/icinga2/files/icingaweb2/monitoring_config.ini b/bundles/icinga2/files/icingaweb2/monitoring_config.ini deleted file mode 100644 index 8194280..0000000 --- a/bundles/icinga2/files/icingaweb2/monitoring_config.ini +++ /dev/null @@ -1,5 +0,0 @@ -[settings] -acknowledge_sticky = 1 -hostdowntime_all_services = 1 -hostdowntime_end_fixed = P1W -servicedowntime_end_fixed = P2D diff --git a/bundles/icinga2/files/scripts/icinga_notification_wrapper b/bundles/icinga2/files/scripts/icinga_notification_wrapper index fbecd8e..72ab749 100644 --- a/bundles/icinga2/files/scripts/icinga_notification_wrapper +++ b/bundles/icinga2/files/scripts/icinga_notification_wrapper @@ -3,14 +3,22 @@ import email.mime.text import smtplib from argparse import ArgumentParser -from json import dumps, load +from json import dumps from subprocess import run from sys import argv from requests import post -with open('/etc/icinga2/notification_config.json') as f: - CONFIG = load(f) +SIPGATE_USER='${node.metadata['icinga2']['sipgate_user']}' +SIPGATE_PASS='${node.metadata['icinga2']['sipgate_pass']}' + +STATUS_TO_EMOJI = { + 'critical': '🔥', + 'down': '🚨🚨🚨', + 'ok': '🆗', + 'up': '👌', + 'warning': '⚡', +} parser = ArgumentParser( prog='icinga_notification_wrapper', @@ -65,31 +73,36 @@ def notify_per_sms(): output_text = '' else: output_text = '\n\n{}'.format(args.output) - - message_text = 'ICINGA: {host}{service} is {state}{output}'.format( - host=args.host_name, - service=('/'+args.service_name if args.service_name else ''), - state=args.state.upper(), - output=output_text, - ) - + if args.state.lower() in STATUS_TO_EMOJI: + message_text = '{emoji} {host}{service} {emoji}{output}'.format( + emoji=STATUS_TO_EMOJI[args.state.lower()], + host=args.host_name, + service=('/'+args.service_name if args.service_name else ''), + state=args.state.upper(), + output=output_text, + ) + else: + message_text = 'ICINGA: {host}{service} is {state}{output}'.format( + host=args.host_name, + service=('/'+args.service_name if args.service_name else ''), + state=args.state.upper(), + output=output_text, + ) message = { 'message': message_text, 'smsId': 's0', # XXX what does this mean? Documentation is unclear 'recipient': args.sms } - headers = { 'Content-type': 'application/json', 'Accept': 'application/json' } - try: r = post( 'https://api.sipgate.com/v2/sessions/sms', json=message, headers=headers, - auth=(CONFIG['sipgate']['user'], CONFIG['sipgate']['password']), + auth=(SIPGATE_USER, SIPGATE_PASS), ) if r.status_code == 204: @@ -100,45 +113,6 @@ def notify_per_sms(): log_to_syslog('Sending a SMS to "{}" failed: {}'.format(args.sms, repr(e))) -def notify_per_ntfy(): - message_text = 'ICINGA: {host}{service} is {state}\n\n{output}'.format( - host=args.host_name, - service=('/'+args.service_name if args.service_name else ''), - state=args.state.upper(), - output=args.output, - ) - - if args.service_name: - subject = '[ICINGA] {}/{}'.format(args.host_name, args.service_name) - else: - subject = '[ICINGA] {}'.format(args.host_name) - - if args.notification_type.lower() == 'recovery': - priority = 'default' - else: - priority = 'urgent' - - headers = { - 'Title': subject, - 'Priority': priority, - } - - try: - r = post( - CONFIG['ntfy']['url'], - 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(): if args.notification_type.lower() == 'recovery': # Do not send recovery emails. @@ -202,8 +176,4 @@ 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: - notify_per_sms() + notify_per_sms() diff --git a/bundles/icinga2/items.py b/bundles/icinga2/items.py index 6f8de54..1a42e70 100644 --- a/bundles/icinga2/items.py +++ b/bundles/icinga2/items.py @@ -76,6 +76,8 @@ files = { }, '/usr/local/share/icinga/plugins/check_sipgate_account_balance': { 'mode': '0755', + 'content_type': 'mako', + 'cascade_skip': False, # contains faults }, '/usr/local/share/icinga/plugins/check_freifunk_node': { 'mode': '0755', @@ -112,22 +114,11 @@ files = { 'svc_systemd:icinga2:restart', }, }, - '/etc/icinga2/notification_config.json': { - 'content': repo.libs.faults.dict_as_json({ - 'sipgate': { - 'user': node.metadata.get('icinga2/sipgate/user'), - 'password': node.metadata.get('icinga2/sipgate/pass'), - }, - 'ntfy': { - 'url': node.metadata.get('icinga2/ntfy/url'), - 'user': node.metadata.get('icinga2/ntfy/user'), - 'password': node.metadata.get('icinga2/ntfy/pass'), - }, - }), - }, '/etc/icinga2/scripts/icinga_notification_wrapper': { 'source': 'scripts/icinga_notification_wrapper', + 'content_type': 'mako', 'mode': '0755', + 'cascade_skip': False, # contains faults }, '/etc/icinga2/features-available/ido-pgsql.conf': { 'source': 'icinga2/ido-pgsql.conf', @@ -254,11 +245,6 @@ files = { 'mode': '0660', 'group': 'icingaweb2', }, - '/etc/icingaweb2/modules/monitoring/config.ini': { - 'source': 'icingaweb2/monitoring_config.ini', - 'mode': '0660', - 'group': 'icingaweb2', - }, '/etc/icingaweb2/groups.ini': { 'source': 'icingaweb2/groups.ini', 'mode': '0660', @@ -276,13 +262,13 @@ files = { 'group': 'icingaweb2', }, - # monitoring + # Statusmonitor '/etc/icinga2/icinga_statusmonitor.py': { 'triggers': { 'svc_systemd:icinga_statusmonitor:restart', }, }, - '/usr/local/lib/systemd/system/icinga_statusmonitor.service': { + '/etc/systemd/system/icinga_statusmonitor.service': { 'triggers': { 'action:systemd-reload', 'svc_systemd:icinga_statusmonitor:restart', @@ -290,12 +276,8 @@ files = { }, } -svc_systemd['icinga_statusmonitor'] = { - 'needs': { - 'file:/etc/icinga2/icinga_statusmonitor.py', - 'file:/usr/local/lib/systemd/system/icinga_statusmonitor.service', - 'pkg_apt:python3-flask', - }, +pkg_pip = { + 'easysnmp': {}, # for check_usv_snmp } actions = { @@ -337,30 +319,44 @@ for name in files: for name in symlinks: icinga_run_deps.add(f'symlink:{name}') -svc_systemd['icinga2'] = { - 'needs': icinga_run_deps, +svc_systemd = { + 'icinga2': { + 'needs': icinga_run_deps, + }, + 'icinga_statusmonitor': { + 'needs': { + 'file:/etc/icinga2/icinga_statusmonitor.py', + 'file:/etc/systemd/system/icinga_statusmonitor.service', + 'pkg_apt:python3-flask', + }, + }, } + # The actual hosts and services management starts here bundles = set() -downtimes = [] -for rnode in sorted(repo.nodes): +for rnode in repo.nodes: if rnode.metadata.get('icinga_options/exclude_from_monitoring', False): continue - host_ips = repo.libs.tools.resolve_identifier(repo, rnode.name, only_physical=True) + host_ips = repo.libs.tools.resolve_identifier(repo, rnode.name) icinga_ips = {} - for ip_type in ('ipv4', 'ipv6'): - for ip in sorted(host_ips[ip_type]): - if ip.is_private and not ip.is_link_local: - icinga_ips[ip_type] = str(ip) - break - else: - if host_ips[ip_type]: - icinga_ips[ip_type] = sorted(host_ips[ip_type])[0] + # XXX for the love of god, PLEASE remove this once DNS is no longer + # hosted at GCE + if rnode.in_group('gce'): + icinga_ips['ipv4'] = rnode.metadata.get('external_ipv4') + else: + for ip_type in ('ipv4', 'ipv6'): + for ip in sorted(host_ips[ip_type]): + if ip.is_private and not ip.is_link_local: + icinga_ips[ip_type] = str(ip) + break + else: + if host_ips[ip_type]: + icinga_ips[ip_type] = sorted(host_ips[ip_type])[0] if not icinga_ips: raise ValueError(f'{rnode.name} requests monitoring, but has neither IPv4 nor IPv6 addresses!') @@ -383,25 +379,6 @@ for rnode in sorted(repo.nodes): bundles |= set(rnode.metadata.get('icinga2_api', {}).keys()) - if rnode.has_any_bundle(['apt', 'c3voc-addons']): - day = rnode.metadata.get('apt/unattended-upgrades/day') - hour = rnode.metadata.get('apt/unattended-upgrades/hour') - minute = rnode.magic_number%30 - - spread = rnode.metadata.get('apt/unattended-upgrades/spread_in_group', None) - if spread is not None: - spread_nodes = sorted(repo.nodes_in_group(spread)) - day += spread_nodes.index(rnode) - - 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', 'content_type': 'mako', @@ -422,7 +399,7 @@ files['/etc/icinga2/conf.d/downtimes.conf'] = { 'source': 'icinga2/downtimes.conf', 'content_type': 'mako', 'context': { - 'downtimes': downtimes, + 'days': DAYS_TO_STRING, }, 'owner': 'nagios', 'group': 'nagios', diff --git a/bundles/icinga2/metadata.py b/bundles/icinga2/metadata.py index c25ca41..fcbfd13 100644 --- a/bundles/icinga2/metadata.py +++ b/bundles/icinga2/metadata.py @@ -17,9 +17,12 @@ defaults = { 'icinga2': {}, 'icinga2-ido-pgsql': {}, 'icingaweb2': {}, - 'python3-easysnmp': {}, + + # apparently no longer needed + #'icingaweb2-module-monitoring': {}, + + # neeeded for statusmonitor 'python3-flask': {}, - 'snmp': {}, } }, 'icinga2': { @@ -40,6 +43,9 @@ defaults = { 'check_interval': '30m', 'vars.notification.mail': True, }, + 'ICINGA STATUSMONITOR': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit icinga_statusmonitor', + }, 'IDO-PGSQL': { 'check_command': 'ido', 'vars.ido_type': 'IdoPgsqlConnection', @@ -53,20 +59,6 @@ defaults = { 'icingaweb2': { 'setup-token': repo.vault.password_for(f'{node.name} icingaweb2 setup-token'), }, - 'php': { - 'packages': { - 'curl', - 'gd', - 'intl', - 'imagick', - 'ldap', - 'mysql', - 'opcache', - 'pgsql', - 'readline', - 'xml', - }, - }, 'postgresql': { 'roles': { 'icinga2': { @@ -113,29 +105,13 @@ def add_users_from_json(metadata): @metadata_reactor.provides( - 'nginx/vhosts/icingaweb2', - 'nginx/vhosts/icinga_statusmonitor', + 'firewall/port_rules/5665', ) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - +def firewall(metadata): return { - 'nginx': { - 'vhosts': { - 'icingaweb2': { - 'domain': metadata.get('icinga2/web_domain'), - 'webroot': '/usr/share/icingaweb2/public', - 'locations': { - '/api/': { - 'target': 'https://127.0.0.1:5665/', - }, - '/statusmonitor/': { - 'target': 'http://127.0.0.1:5000/', - }, - }, - 'extras': True, - }, + 'firewall': { + 'port_rules': { + '5665': atomic(metadata.get('icinga2/restrict-to', set())), }, }, } diff --git a/bundles/influxdb2/metadata.py b/bundles/influxdb2/metadata.py index 1a7b2a0..68fda00 100644 --- a/bundles/influxdb2/metadata.py +++ b/bundles/influxdb2/metadata.py @@ -10,7 +10,7 @@ defaults = { 'repos': { 'influxdb': { 'items': { - 'deb https://repos.influxdata.com/{os} stable main', + 'deb https://repos.influxdata.com/{os} {os_release} stable', }, }, }, diff --git a/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.service b/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.service index bf63eb1..8be500a 100644 --- a/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.service +++ b/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.service @@ -4,8 +4,7 @@ After=network.target Requires=infobeamer-cms.service [Service] -Environment=SETTINGS=/opt/infobeamer-cms/settings.toml -WorkingDirectory=/opt/infobeamer-cms/src User=infobeamer-cms Group=infobeamer-cms -ExecStart=/opt/infobeamer-cms/venv/bin/python syncer.py +WorkingDirectory=/opt/infobeamer-cms +ExecStart=curl -s -H "Host: ${domain}" http://127.0.0.1:8000/sync diff --git a/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.timer b/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.timer index 049b063..48b52f4 100644 --- a/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.timer +++ b/bundles/infobeamer-cms/files/infobeamer-cms-runperiodic.timer @@ -2,7 +2,7 @@ Description=Run infobeamer-cms sync [Timer] -OnCalendar=minutely +OnCalendar=*:0/5 Persistent=true [Install] diff --git a/bundles/infobeamer-cms/files/settings.toml b/bundles/infobeamer-cms/files/settings.toml new file mode 100644 index 0000000..12dcdb7 --- /dev/null +++ b/bundles/infobeamer-cms/files/settings.toml @@ -0,0 +1,4 @@ +<% + from tomlkit import dumps as toml_dumps + from bundlewrap.utils.text import toml_clean +%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(config), sort_keys=True))} diff --git a/bundles/infobeamer-cms/items.py b/bundles/infobeamer-cms/items.py index aa424a1..226fc23 100644 --- a/bundles/infobeamer-cms/items.py +++ b/bundles/infobeamer-cms/items.py @@ -1,4 +1,8 @@ actions = { + 'infobeamer-cms_set_directory_permissions': { + 'triggered': True, + 'command': 'chown -R infobeamer-cms:infobeamer-cms /opt/infobeamer-cms/src/static/' + }, 'infobeamer-cms_create_virtualenv': { 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/infobeamer-cms/venv/', 'unless': 'test -d /opt/infobeamer-cms/venv/', @@ -8,11 +12,7 @@ actions = { }, }, 'infobeamer-cms_install_requirements': { - 'command': ' && '.join([ - 'cd /opt/infobeamer-cms/src', - '/opt/infobeamer-cms/venv/bin/pip install --upgrade pip gunicorn -r requirements.txt', - 'rsync /opt/infobeamer-cms/src/static/* /opt/infobeamer-cms/static/', - ]), + 'command': 'cd /opt/infobeamer-cms/src && /opt/infobeamer-cms/venv/bin/pip install --upgrade pip gunicorn -r requirements.txt', 'needs': { 'action:infobeamer-cms_create_virtualenv', }, @@ -23,12 +23,13 @@ actions = { git_deploy = { '/opt/infobeamer-cms/src': { 'rev': 'master', - 'repo': 'https://github.com/voc/infobeamer-cms.git', + 'repo': 'https://github.com/sophieschi/36c3-cms.git', 'needs': { 'directory:/opt/infobeamer-cms/src', }, 'triggers': { 'svc_systemd:infobeamer-cms:restart', + 'action:infobeamer-cms_set_directory_permissions', 'action:infobeamer-cms_install_requirements', }, }, @@ -36,9 +37,6 @@ git_deploy = { directories = { '/opt/infobeamer-cms/src': {}, - '/opt/infobeamer-cms/static': { - 'owner': 'infobeamer-cms', - }, } config = node.metadata.get('infobeamer-cms/config', {}) @@ -68,7 +66,10 @@ for room, device_id in sorted(node.metadata.get('infobeamer-cms/rooms', {}).item files = { '/opt/infobeamer-cms/settings.toml': { - 'content': repo.libs.faults.dict_as_toml(config), + 'content_type': 'mako', + 'context': { + 'config': config, + }, 'triggers': { 'svc_systemd:infobeamer-cms:restart', }, @@ -96,11 +97,19 @@ files = { }, } +pkg_pip = { + 'github-flask': { + 'needed_by': { + 'svc_systemd:infobeamer-cms', + }, + }, +} + svc_systemd = { 'infobeamer-cms': { 'needs': { 'action:infobeamer-cms_install_requirements', - 'directory:/opt/infobeamer-cms/static', + 'action:infobeamer-cms_set_directory_permissions', 'file:/etc/systemd/system/infobeamer-cms.service', 'file:/opt/infobeamer-cms/settings.toml', 'git_deploy:/opt/infobeamer-cms/src', @@ -108,12 +117,8 @@ svc_systemd = { }, 'infobeamer-cms-runperiodic.timer': { 'needs': { - 'action:infobeamer-cms_install_requirements', - 'directory:/opt/infobeamer-cms/static', - 'file:/etc/systemd/system/infobeamer-cms-runperiodic.service', 'file:/etc/systemd/system/infobeamer-cms-runperiodic.timer', - 'file:/opt/infobeamer-cms/settings.toml', - 'git_deploy:/opt/infobeamer-cms/src', + 'file:/etc/systemd/system/infobeamer-cms-runperiodic.service', }, }, } diff --git a/bundles/infobeamer-cms/metadata.py b/bundles/infobeamer-cms/metadata.py index 4413d5a..8d8703b 100644 --- a/bundles/infobeamer-cms/metadata.py +++ b/bundles/infobeamer-cms/metadata.py @@ -1,15 +1,11 @@ -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'), 'VERSION': 1, }, @@ -33,13 +29,15 @@ def nginx(metadata): '/': { 'target': 'http://127.0.0.1:8000', }, + '/sync': { + 'return': 403, + }, '/static': { - 'alias': '/opt/infobeamer-cms/static', + 'alias': '/opt/infobeamer-cms/src/static', }, }, 'website_check_path': '/', 'website_check_string': 'Share your projects', - 'do_not_set_content_security_headers': True, }, }, }, @@ -47,12 +45,11 @@ def nginx(metadata): @metadata_reactor.provides( - 'infobeamer-cms/config/DOMAIN', 'infobeamer-cms/config/TIME_MAX', '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) @@ -60,7 +57,6 @@ def event_times(metadata): return { 'infobeamer-cms': { 'config': { - 'DOMAIN': metadata.get('infobeamer-cms/domain'), 'TIME_MAX': int(event_end.timestamp()), 'TIME_MIN': int(event_start.timestamp()), }, diff --git a/bundles/infobeamer-monitor/files/infobeamer-monitor.service b/bundles/infobeamer-monitor/files/infobeamer-monitor.service deleted file mode 100644 index 7be13a2..0000000 --- a/bundles/infobeamer-monitor/files/infobeamer-monitor.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=infobeamer-monitor -After=network.target - -[Service] -Type=exec -Restart=always -RestartSec=5s -ExecStart=/opt/infobeamer-cms/venv/bin/python monitor.py -User=infobeamer-cms -Group=infobeamer-cms -WorkingDirectory=/opt/infobeamer-monitor/ - -[Install] -WantedBy=multi-user.target diff --git a/bundles/infobeamer-monitor/files/monitor.py b/bundles/infobeamer-monitor/files/monitor.py deleted file mode 100644 index 7646fa6..0000000 --- a/bundles/infobeamer-monitor/files/monitor.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python3 - -import logging -from datetime import datetime -from json import dumps -from time import sleep -from zoneinfo import ZoneInfo - -import paho.mqtt.client as mqtt -from requests import RequestException, get - -try: - # python 3.11 - from tomllib import loads as toml_load -except ImportError: - from rtoml import load as toml_load - -with open("config.toml") as f: - CONFIG = toml_load(f.read()) - - -logging.basicConfig( - format="[%(levelname)s %(name)s] %(message)s", - level=logging.INFO, -) - -LOG = logging.getLogger("main") -TZ = ZoneInfo("Europe/Berlin") -DUMP_TIME = "0900" - -state = None - -client = mqtt.Client() -client.username_pw_set(CONFIG["mqtt"]["user"], CONFIG["mqtt"]["password"]) -client.connect(CONFIG["mqtt"]["host"], 1883, 60) -client.loop_start() - - -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}" - - client.publish( - CONFIG["mqtt"]["topic"], - dumps( - { - "level": level, - "component": key, - "msg": message, - } - ), - ) - - -def mqtt_dump_state(device): - if not device["is_online"]: - return - - out = [] - if device["location"]: - 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"))) - - 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: - try: - try: - r = get( - "https://info-beamer.com/api/v1/device/list", - auth=("", CONFIG["api_key"]), - ) - r.raise_for_status() - ib_state = r.json()["devices"] - except RequestException as e: - LOG.exception("Could not get device data from info-beamer") - mqtt_out( - f"Could not get device data from info-beamer: {e!r}", - level="WARN", - ) - else: - new_state = {} - for device in sorted(ib_state, key=lambda x: x["id"]): - did = str(device["id"]) - - if did in new_state: - mqtt_out("DUPLICATE DETECTED!", level="ERROR", device=device) - continue - - new_state[did] = device - # force information output for every online device at 09:00 CE(S)T - must_dump_state = is_dump_time() - - if state is not None: - if did not in state: - LOG.info( - "new device found: {} [{}]".format( - did, - device["description"], - ) - ) - mqtt_out( - "new device found!", - device=device, - ) - must_dump_state = True - - else: - if device["is_online"] != state[did]["is_online"]: - online_status = ( - "online from {}".format(device["run"]["public_addr"]) - if device["is_online"] - else "offline" - ) - - LOG.info("device {} is now {}".format(did, online_status)) - mqtt_out( - f"status changed to {online_status}", - level="INFO" if device["is_online"] else "WARN", - device=device, - ) - must_dump_state = True - - if device["description"] != state[did]["description"]: - LOG.info( - "device {} changed name to {}".format( - did, device["description"] - ) - ) - must_dump_state = True - - if device["is_online"]: - if device["maintenance"]: - mqtt_out( - "maintenance required: {}".format( - " ".join(sorted(device["maintenance"])) - ), - level="WARN", - device=device, - ) - - if ( - device["location"] != state[did]["location"] - or device["setup"]["id"] != state[did]["setup"]["id"] - or device["run"].get("resolution") - != state[did]["run"].get("resolution") - ): - must_dump_state = True - - if must_dump_state: - mqtt_dump_state(device) - else: - LOG.info("adding device {} to empty state".format(device["id"])) - - 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) - except KeyboardInterrupt: - break - -mqtt_out("Monitor exiting") diff --git a/bundles/infobeamer-monitor/items.py b/bundles/infobeamer-monitor/items.py deleted file mode 100644 index 683d240..0000000 --- a/bundles/infobeamer-monitor/items.py +++ /dev/null @@ -1,30 +0,0 @@ -assert node.has_bundle('infobeamer-cms') # uses same venv - -files['/opt/infobeamer-monitor/config.toml'] = { - 'content': repo.libs.faults.dict_as_toml(node.metadata.get('infobeamer-monitor')), - 'triggers': { - 'svc_systemd:infobeamer-monitor:restart', - }, -} - -files['/opt/infobeamer-monitor/monitor.py'] = { - 'mode': '0755', - 'triggers': { - 'svc_systemd:infobeamer-monitor:restart', - }, -} - -files['/usr/local/lib/systemd/system/infobeamer-monitor.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:infobeamer-monitor:restart', - }, -} - -svc_systemd['infobeamer-monitor'] = { - 'needs': { - 'file:/opt/infobeamer-monitor/config.toml', - 'file:/opt/infobeamer-monitor/monitor.py', - 'file:/usr/local/lib/systemd/system/infobeamer-monitor.service', - }, -} diff --git a/bundles/ipmitool/metadata.py b/bundles/ipmitool/metadata.py index e908366..a340a7a 100644 --- a/bundles/ipmitool/metadata.py +++ b/bundles/ipmitool/metadata.py @@ -19,4 +19,9 @@ defaults = { '/usr/bin/ipmitool *', }, }, + 'pacman': { + 'packages': { + 'ipmitool': {}, + }, + }, } diff --git a/bundles/jellyfin/files/jellyfin-sudoers b/bundles/jellyfin/files/jellyfin-sudoers deleted file mode 100644 index 1d138d6..0000000 --- a/bundles/jellyfin/files/jellyfin-sudoers +++ /dev/null @@ -1,7 +0,0 @@ -Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl restart jellyfin -Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemd-run systemctl start jellyfin -Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemd-run systemctl stop jellyfin - -jellyfin ALL=(ALL) NOPASSWD: RESTARTSERVER_SYSTEMD -jellyfin ALL=(ALL) NOPASSWD: STARTSERVER_SYSTEMD -jellyfin ALL=(ALL) NOPASSWD: STOPSERVER_SYSTEMD diff --git a/bundles/jellyfin/items.py b/bundles/jellyfin/items.py deleted file mode 100644 index 6bd828d..0000000 --- a/bundles/jellyfin/items.py +++ /dev/null @@ -1,5 +0,0 @@ -files['/etc/sudoers.d/jellyfin-sudoers'] = { - 'after': { - 'pkg_apt:jellyfin', - }, -} diff --git a/bundles/jellyfin/metadata.py b/bundles/jellyfin/metadata.py deleted file mode 100644 index 8c4e9ff..0000000 --- a/bundles/jellyfin/metadata.py +++ /dev/null @@ -1,69 +0,0 @@ -from bundlewrap.metadata import atomic - -defaults = { - 'apt': { - 'packages': { - 'jellyfin': {}, - }, - 'repos': { - 'jellyfin': { - 'uris': { - 'https://repo.jellyfin.org/{os}' - }, - }, - }, - }, - 'backups': { - 'paths': { - f'/var/lib/jellyfin/{x}' for x in ('data', 'metadata', 'plugins', 'root') - }, - }, - 'icinga2_api': { - 'transmission': { - 'services': { - 'JELLYFIN PROCESS': { - 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_procs -C jellyfin -c 1:', - }, - }, - }, - }, -} - - -@metadata_reactor.provides( - 'nginx/vhosts/jellyfin', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - if 'jellyfin' not in metadata.get('nginx/vhosts', {}): - return {} - - return { - 'nginx': { - 'vhosts': { - 'jellyfin': { - 'do_not_add_content_security_headers': True, - 'locations': { - '/': { - 'target': 'http://127.0.0.1:8096', - 'websockets': True, - }, - }, - }, - }, - }, - } - -@metadata_reactor.provides( - 'firewall/port_rules', -) -def firewall(metadata): - return { - 'firewall': { - 'port_rules': { - '8096/tcp': atomic(metadata.get('jellyfin/restrict-to', set())), - }, - }, - } diff --git a/bundles/jool/items.py b/bundles/jool/items.py deleted file mode 100644 index 5ce5bac..0000000 --- a/bundles/jool/items.py +++ /dev/null @@ -1,15 +0,0 @@ -actions['modprobe_jool'] = { - 'command': 'modprobe jool', - 'unless': 'lsmod | grep -F jool', -} - -actions['jool_add_nat64_instance'] = { - 'command': 'jool instance add "nat64" --netfilter --pool6 64:ff9b::/96', - 'unless': 'jool instance display --no-headers --csv | grep -E ",nat64,netfilter$"', - 'needs': { - 'action:modprobe_jool', - 'pkg_apt:jool-dkms', - 'pkg_apt:jool-tools', - 'pkg_apt:linux-headers-amd64', - }, -} diff --git a/bundles/jool/metadata.py b/bundles/jool/metadata.py deleted file mode 100644 index 9ef83dd..0000000 --- a/bundles/jool/metadata.py +++ /dev/null @@ -1,14 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'jool-dkms': {}, - 'jool-tools': {}, - 'linux-headers-amd64': {}, - }, - }, - 'modules': { - 'jool': [ - 'jool', - ], - }, -} diff --git a/bundles/jugendhackt_tools/files/jugendhackt_tools.service b/bundles/jugendhackt_tools/files/jugendhackt_tools.service deleted file mode 100644 index 2d0a36c..0000000 --- a/bundles/jugendhackt_tools/files/jugendhackt_tools.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=jugendhackt_tools web service -After=network.target -Requires=postgresql.service - -[Service] -User=jugendhackt_tools -Group=jugendhackt_tools -Environment=CONFIG_PATH=/opt/jugendhackt_tools/config.toml -WorkingDirectory=/opt/jugendhackt_tools/src -ExecStart=/opt/jugendhackt_tools/venv/bin/gunicorn jugendhackt_tools.wsgi --name jugendhackt_tools --workers 4 --max-requests 1200 --max-requests-jitter 50 --log-level=info --bind=127.0.0.1:22090 -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target diff --git a/bundles/jugendhackt_tools/items.py b/bundles/jugendhackt_tools/items.py deleted file mode 100644 index c2d0c6e..0000000 --- a/bundles/jugendhackt_tools/items.py +++ /dev/null @@ -1,75 +0,0 @@ -directories['/opt/jugendhackt_tools/src'] = {} - -git_deploy['/opt/jugendhackt_tools/src'] = { - 'repo': 'https://github.com/kunsi/jugendhackt_schedule.git', - 'rev': 'main', - 'triggers': { - 'action:jugendhackt_tools_install', - 'action:jugendhackt_tools_migrate', - 'svc_systemd:jugendhackt_tools:restart', - }, -} - -actions['jugendhackt_tools_create_virtualenv'] = { - 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/jugendhackt_tools/venv/', - 'unless': 'test -d /opt/jugendhackt_tools/venv/', - 'needs': { - # actually /opt/jugendhackt_tools, but we don't create that - 'directory:/opt/jugendhackt_tools/src', - }, -} - -actions['jugendhackt_tools_install'] = { - 'command': ' && '.join([ - 'cd /opt/jugendhackt_tools/src', - '/opt/jugendhackt_tools/venv/bin/pip install --upgrade pip wheel gunicorn psycopg2-binary', - '/opt/jugendhackt_tools/venv/bin/pip install --upgrade -r requirements.txt', - ]), - 'needs': { - 'action:jugendhackt_tools_create_virtualenv', - }, - 'triggered': True, -} - -actions['jugendhackt_tools_migrate'] = { - 'command': ' && '.join([ - 'cd /opt/jugendhackt_tools/src', - 'CONFIG_PATH=/opt/jugendhackt_tools/config.toml /opt/jugendhackt_tools/venv/bin/python manage.py migrate', - 'CONFIG_PATH=/opt/jugendhackt_tools/config.toml /opt/jugendhackt_tools/venv/bin/python manage.py collectstatic --noinput', - ]), - 'needs': { - 'action:jugendhackt_tools_install', - 'file:/opt/jugendhackt_tools/config.toml', - 'postgres_db:jugendhackt_tools', - 'postgres_role:jugendhackt_tools', - }, - 'triggered': True, -} - -files['/opt/jugendhackt_tools/config.toml'] = { - 'content': repo.libs.faults.dict_as_toml(node.metadata.get('jugendhackt_tools')), - 'triggers': { - 'svc_systemd:jugendhackt_tools:restart', - }, -} - -files['/usr/local/lib/systemd/system/jugendhackt_tools.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:jugendhackt_tools:restart', - }, -} - -svc_systemd['jugendhackt_tools'] = { - 'needs': { - 'action:jugendhackt_tools_migrate', - 'file:/opt/jugendhackt_tools/config.toml', - 'file:/usr/local/lib/systemd/system/jugendhackt_tools.service', - 'git_deploy:/opt/jugendhackt_tools/src', - 'user:jugendhackt_tools', - }, -} - -users['jugendhackt_tools'] = { - 'home': '/opt/jugendhackt_tools/src', -} diff --git a/bundles/jugendhackt_tools/metadata.py b/bundles/jugendhackt_tools/metadata.py deleted file mode 100644 index 0b3d073..0000000 --- a/bundles/jugendhackt_tools/metadata.py +++ /dev/null @@ -1,28 +0,0 @@ -defaults = { - 'jugendhackt_tools': { - 'django_secret': repo.vault.random_bytes_as_base64_for(f'{node.name} jugendhackt_tools django_secret'), - 'django_debug': False, - 'static_root': '/opt/jugendhackt_tools/src/static/', - 'database': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'jugendhackt_tools', - 'USER': 'jugendhackt_tools', - 'PASSWORD': repo.vault.password_for(f'{node.name} postgresql jugendhackt_tools'), - 'HOST': 'localhost', - 'PORT': '5432' - }, - }, - 'postgresql': { - 'roles': { - 'jugendhackt_tools': { - 'password': repo.vault.password_for(f'{node.name} postgresql jugendhackt_tools'), - }, - }, - 'databases': { - 'jugendhackt_tools': { - 'owner': 'jugendhackt_tools', - }, - }, - }, -} - diff --git a/bundles/kea-dhcp-server/files/kea-lease-list b/bundles/kea-dhcp-server/files/kea-lease-list deleted file mode 100644 index 7919b0c..0000000 --- a/bundles/kea-dhcp-server/files/kea-lease-list +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 - -from csv import DictReader -from datetime import datetime, timezone -from os import scandir -from os.path import join - - -def parse(): - NOW = datetime.now() - active_leases = {} - for file in scandir("/var/lib/kea/"): - with open(file.path) as f: - for row in DictReader(f): - expires = datetime.fromtimestamp(int(row["expire"])) - - if expires >= NOW: - if ( - row["address"] not in active_leases - or active_leases[row["address"]]["expires_dt"] < expires - ): - row["expires_dt"] = expires - active_leases[row["address"]] = row - return active_leases.values() - - -def print_table(leases): - print(""" address | MAC | expires | hostname ------------------+-------------------+---------+----------""") - for lease in sorted(leases, key=lambda r: r["address"]): - print( - f' {lease["address"]:<15} | {lease["hwaddr"].lower()} | {lease["expires_dt"]:%H:%M} | {lease["hostname"]}' - ) - - -if __name__ == "__main__": - print_table(parse()) diff --git a/bundles/kea-dhcp-server/items.py b/bundles/kea-dhcp-server/items.py deleted file mode 100644 index c6219cf..0000000 --- a/bundles/kea-dhcp-server/items.py +++ /dev/null @@ -1,56 +0,0 @@ -kea_config = { - 'Dhcp4': { - **node.metadata.get('kea-dhcp-server/config'), - 'interfaces-config': { - 'interfaces': sorted(node.metadata.get('kea-dhcp-server/subnets', {}).keys()), - }, - 'subnet4': [], - 'loggers': [{ - 'name': 'kea-dhcp4', - 'output_options': [{ - # -> journal - 'output': 'stdout', - }], - 'severity': 'WARN', - }], - }, -} - -for iface, config in sorted(node.metadata.get('kea-dhcp-server/subnets', {}).items()): - kea_config['Dhcp4']['subnet4'].append({ - 'subnet': config['subnet'], - 'pools': [{ - 'pool': f'{config["lower"]} - {config["higher"]}', - }], - 'option-data': [ - { - 'name': k, - 'data': v, - } for k, v in sorted(config.get('options', {}).items()) - ], - 'reservations': [ - { - 'ip-address': v['ip'], - 'hw-address': v['mac'], - 'hostname': k, - } for k, v in sorted(node.metadata.get(f'kea-dhcp-server/fixed_allocations/{iface}', {}).items()) - ] - }) - -files['/etc/kea/kea-dhcp4.conf'] = { - 'content': repo.libs.faults.dict_as_json(kea_config), - 'triggers': { - 'svc_systemd:kea-dhcp4-server:restart', - }, -} - -files['/usr/local/bin/kea-lease-list'] = { - 'mode': '0500', -} - -svc_systemd['kea-dhcp4-server'] = { - 'needs': { - 'file:/etc/kea/kea-dhcp4.conf', - 'pkg_apt:kea-dhcp4-server', - }, -} diff --git a/bundles/kea-dhcp-server/metadata.py b/bundles/kea-dhcp-server/metadata.py deleted file mode 100644 index 6a25c1f..0000000 --- a/bundles/kea-dhcp-server/metadata.py +++ /dev/null @@ -1,83 +0,0 @@ -from ipaddress import ip_address, ip_network - -defaults = { - 'apt': { - 'packages': { - 'kea-dhcp4-server': {}, - }, - }, - 'kea-dhcp-server': { - 'config': { - 'authoritative': True, - 'rebind-timer': 450, - 'renew-timer': 300, - 'valid-lifetime': 600, - 'expired-leases-processing': { - 'max-reclaim-leases': 0, - 'max-reclaim-time': 0, - }, - 'lease-database': { - 'lfc-interval': 3600, - 'name': '/var/lib/kea/kea-leases4.csv', - 'persist': True, - 'type': 'memfile', - }, - }, - }, -} - - -@metadata_reactor.provides( - 'kea-dhcp-server/fixed_allocations', -) -def get_static_allocations(metadata): - result = {} - mapping = {} - - for iface, config in metadata.get('kea-dhcp-server/subnets', {}).items(): - result[iface] = {} - mapping[iface] = ip_network(config['subnet']) - - for rnode in repo.nodes: - if ( - rnode.metadata.get('location', '') != metadata.get('location', '') - or rnode == node - ): - continue - - for iface_name, iface_config in rnode.metadata.get('interfaces', {}).items(): - if iface_config.get('dhcp', False) and iface_config.get('mac'): - for ip in iface_config.get('ips', set()): - ipaddr = ip_address(ip) - - for kea_iface, kea_subnet in mapping.items(): - if ipaddr in kea_subnet: - result[kea_iface][f'{rnode.name}_{iface_name}'] = { - 'ip': ip, - 'mac': iface_config['mac'], - } - break - - return { - 'kea-dhcp-server': { - 'fixed_allocations': result, - } - } - - -@metadata_reactor.provides( - 'nftables/input/10-kea-dhcp-server', -) -def nftables(metadata): - rules = set() - for iface in node.metadata.get('kea-dhcp-server/subnets', {}): - rules.add(f'udp dport {{ 67, 68 }} iifname {iface} accept') - - return { - 'nftables': { - 'input': { - # can't use port_rules here, because we're generating interface based rules. - '10-kea-dhcp-server': sorted(rules), - }, - } - } diff --git a/bundles/kernel-modules/files/modules b/bundles/kernel-modules/files/modules deleted file mode 100644 index 5abf592..0000000 --- a/bundles/kernel-modules/files/modules +++ /dev/null @@ -1,8 +0,0 @@ -# This file is managed using bundlewrap -% for identifier, modules in sorted(node.metadata.get('modules', {}).items()): - -# ${identifier} -% for module in modules: -${module} -% endfor -% endfor diff --git a/bundles/kernel-modules/items.py b/bundles/kernel-modules/items.py deleted file mode 100644 index dd848fd..0000000 --- a/bundles/kernel-modules/items.py +++ /dev/null @@ -1,3 +0,0 @@ -files['/etc/modules'] = { - 'content_type': 'mako', -} diff --git a/bundles/kodi/metadata.py b/bundles/kodi/metadata.py index 0fe2061..e217b21 100644 --- a/bundles/kodi/metadata.py +++ b/bundles/kodi/metadata.py @@ -43,15 +43,15 @@ defaults = { @metadata_reactor.provides( - 'firewall/port_rules', - 'firewall/port_rules', + 'firewall/port_rules/8080', + 'firewall/port_rules/9090', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '8080/tcp': atomic(metadata.get('kodi/restrict-to', {'*'})), - '9090/tcp': atomic(metadata.get('kodi/restrict-to', {'*'})), + '8080': atomic(metadata.get('kodi/restrict-to', {'*'})), + '9090': atomic(metadata.get('kodi/restrict-to', {'*'})), }, }, } diff --git a/bundles/letsencrypt/items.py b/bundles/letsencrypt/items.py index dd0b9c2..585cf8e 100644 --- a/bundles/letsencrypt/items.py +++ b/bundles/letsencrypt/items.py @@ -12,10 +12,6 @@ actions = { 'needs': { 'svc_systemd:nginx', }, - 'after': { - 'svc_systemd:nginx:reload', - 'svc_systemd:nginx:restart', - }, }, } diff --git a/bundles/letsencrypt/metadata.py b/bundles/letsencrypt/metadata.py index ffeb084..310dadd 100644 --- a/bundles/letsencrypt/metadata.py +++ b/bundles/letsencrypt/metadata.py @@ -13,6 +13,15 @@ defaults = { }, }, }, + 'pacman': { + 'packages': { + 'dehydrated': { + 'needed_by': { + 'action:letsencrypt_update_certificates', + }, + }, + }, + }, } @@ -30,7 +39,6 @@ def cron(metadata): '/usr/bin/dehydrated --cleanup', ], 'when': '04:{}:00'.format(node.magic_number % 60), - 'exclude_from_monitoring': True, }, }, }, diff --git a/bundles/lldp/metadata.py b/bundles/lldp/metadata.py index 2f1875c..7a499dd 100644 --- a/bundles/lldp/metadata.py +++ b/bundles/lldp/metadata.py @@ -10,4 +10,15 @@ defaults = { }, }, }, + 'pacman': { + 'packages': { + 'lldpd': { + 'needed_by': { + 'directory:/etc/lldpd.d', + 'file:/etc/lldpd.conf', + 'svc_systemd:lldpd', + }, + }, + }, + }, } diff --git a/bundles/lm-sensors/metadata.py b/bundles/lm-sensors/metadata.py index 01a6d1a..ffd3900 100644 --- a/bundles/lm-sensors/metadata.py +++ b/bundles/lm-sensors/metadata.py @@ -4,6 +4,11 @@ defaults = { 'lm-sensors': {}, }, }, + 'pacman': { + 'packages': { + 'lm_sensors': {}, + }, + }, 'telegraf': { 'input_plugins': { 'builtin': { diff --git a/bundles/matrix-dimension/files/matrix-dimension.service b/bundles/matrix-dimension/files/matrix-dimension.service new file mode 100644 index 0000000..9d2bebc --- /dev/null +++ b/bundles/matrix-dimension/files/matrix-dimension.service @@ -0,0 +1,14 @@ +[Unit] +Description=Matrix Dimension +After=network.target + +[Service] +User=matrix-dimension +Group=matrix-dimension +Environment="NODE_ENV=production" +ExecStart=/usr/bin/node ${config['install_dir']}/build/app/index.js +WorkingDirectory=${config['install_dir']} +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/bundles/matrix-dimension/files/production.yaml b/bundles/matrix-dimension/files/production.yaml new file mode 100644 index 0000000..321f6d2 --- /dev/null +++ b/bundles/matrix-dimension/files/production.yaml @@ -0,0 +1,93 @@ +# The web settings for the service (API and UI). +# It is best to have this run on localhost and use a reverse proxy to access Dimension. +web: + port: 20030 + address: '127.0.0.1' + +# Homeserver configuration +homeserver: + # The domain name of the homeserver. This is used in many places, such as with go-neb + # setups, to identify the homeserver. + name: "${config['homeserver']['name']}" + + # The URL that Dimension, go-neb, and other services provisioned by Dimension should + # use to access the homeserver with. + clientServerUrl: "${config['homeserver']['clientServerUrl']}" + + # The URL that Dimension should use when trying to communicate with federated APIs on + # the homeserver. If not supplied or left empty Dimension will try to resolve the address + # through the normal federation process. + #federationUrl: "https://t2bot.io:8448" + + # The URL that Dimension will redirect media requests to for downloading media such as + # stickers. If not supplied or left empty Dimension will use the clientServerUrl. + #mediaUrl: "https://t2bot.io" + + # The access token Dimension should use for miscellaneous access to the homeserver, and + # for tracking custom sticker pack updates. This should be a user configured on the homeserver + # and be dedicated to Dimension (create a user named "dimension" on your homeserver). For + # information on how to acquire an access token, visit https://t2bot.io/docs/access_tokens + accessToken: "${config['homeserver']['accessToken']}" + +# These users can modify the integrations this Dimension supports. +# To access the admin interface, open Dimension in Riot and click the settings icon. +admins: +% for i in config['admins']: + - "${i}" +% endfor +# IPs and CIDR ranges listed here will be blocked from being widgets. +# Note: Widgets may still be embedded with restricted content, although not through Dimension directly. +widgetBlacklist: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + - 127.0.0.0/8 + +database: + # Where the database for Dimension is + uri: "postgres://${node.metadata['matrix-dimension']['database']['user']}:${node.metadata['matrix-dimension']['database']['password']}@${node.metadata['matrix-dimension']['database'].get('host', 'localhost')}/${node.metadata['matrix-dimension']['database']['database']}" + + # Where to store misc information for the utility bot account. + botData: "${config['data_dir']}/dimension.bot.json" + +# Display settings that apply to self-hosted go-neb instances +goneb: + # The avatars to set for each bot. Usually these don't need to be changed, however if your homeserver + # is not able to reach t2bot.io then you should specify your own here. To not use an avatar for a bot, + # make the bot's avatar an empty string. + avatars: + giphy: "mxc://t2bot.io/c5eaab3ef0133c1a61d3c849026deb27" + imgur: "mxc://t2bot.io/6749eaf2b302bb2188ae931b2eeb1513" + github: "mxc://t2bot.io/905b64b3cd8e2347f91a60c5eb0832e1" + wikipedia: "mxc://t2bot.io/7edfb54e9ad9e13fec0df22636feedf1" + travisci: "mxc://t2bot.io/7f4703126906fab8bb27df34a17707a8" + rss: "mxc://t2bot.io/aace4fcbd045f30afc1b4e5f0928f2f3" + google: "mxc://t2bot.io/636ad10742b66c4729bf89881a505142" + guggy: "mxc://t2bot.io/e7ef0ed0ba651aaf907655704f9a7526" + echo: "mxc://t2bot.io/3407ff2db96b4e954fcbf2c6c0415a13" + circleci: "mxc://t2bot.io/cf7d875845a82a6b21f5f66de78f6bee" + jira: "mxc://t2bot.io/f4a38ebcc4280ba5b950163ca3e7c329" + +# Settings for interacting with Telegram. Currently only applies for importing +# sticker packs from Telegram. +telegram: + # Talk to @BotFather on Telegram to get a token + botToken: "${config['telegram']['botToken']}" + +# Custom sticker pack options. +# Largely based on https://github.com/turt2live/matrix-sticker-manager +stickers: + # Whether or not to allow people to add custom sticker packs + enabled: true + + # The sticker manager bot to promote + stickerBot: "@stickers:t2bot.io" + + # The sticker manager URL to promote + managerUrl: "https://stickers.t2bot.io" + + +# Settings for controlling how logging works +logging: + console: true + consoleLevel: info diff --git a/bundles/matrix-dimension/items.py b/bundles/matrix-dimension/items.py new file mode 100644 index 0000000..9744754 --- /dev/null +++ b/bundles/matrix-dimension/items.py @@ -0,0 +1,78 @@ +repo.libs.tools.require_bundle(node, 'nodejs') + + +directories = { + node.metadata['matrix-dimension']['install_dir']: { + 'owner': 'matrix-dimension', + 'group': 'matrix-dimension', + }, +} + +git_deploy = { + node.metadata['matrix-dimension']['install_dir']: { + 'rev': node.metadata.get('matrix-dimension/version', 'master'), # doesn't have releases yet + 'repo': 'https://github.com/turt2live/matrix-dimension.git', + 'triggers': { + 'action:matrix_dimension_build', + }, + 'needs': { + 'directory:{}'.format(node.metadata.get('matrix-dimension/install_dir')), + 'directory:{}'.format(node.metadata.get('matrix-dimension/data_dir')), + }, + }, +} + +files = { + '{}/config/production.yaml'.format(node.metadata.get('matrix-dimension/install_dir')): { + 'owner': 'matrix-dimension', + 'group': 'matrix-dimension', + 'content_type': 'mako', + 'context': { + 'config': node.metadata.get('matrix-dimension', {}), + }, + 'needs': { + 'git_deploy:{}'.format(node.metadata.get('matrix-dimension/install_dir')), + }, + 'triggers': { + 'svc_systemd:matrix-dimension:restart', + }, + }, + '/etc/systemd/system/matrix-dimension.service': { + 'content_type': 'mako', + 'context': { + 'config': node.metadata.get('matrix-dimension', {}), + }, + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:matrix-dimension:restart', + }, + }, +} + +actions = { + 'matrix_dimension_build': { + 'command': ' && '.join([ + 'cd ' + node.metadata.get('matrix-dimension/install_dir'), + 'sudo -u matrix-dimension npm install --legacy-peer-deps', + 'sudo -u matrix-dimension NODE_OPTIONS=--openssl-legacy-provider npm run build', + ]), + 'needs': { + 'pkg_apt:nodejs', + }, + 'triggered': True, + 'triggers': { + 'svc_systemd:matrix-dimension:restart', + }, + }, +} + +svc_systemd = { + 'matrix-dimension': { + 'needs': { + 'action:matrix_dimension_build', + 'file:{}/config/production.yaml'.format(node.metadata.get('matrix-dimension/install_dir')), + 'postgres_db:matrix-dimension', + 'postgres_role:matrix-dimension', + }, + }, +} diff --git a/bundles/matrix-dimension/metadata.py b/bundles/matrix-dimension/metadata.py new file mode 100644 index 0000000..c3f037d --- /dev/null +++ b/bundles/matrix-dimension/metadata.py @@ -0,0 +1,110 @@ +defaults = { + 'backups': { + 'paths': { + '/opt/matrix-dimension', + '/var/opt/matrix-dimension', + }, + }, + 'icinga2_api': { + 'matrix-dimension': { + 'services': { + 'MATRIX-DIMENSION PROCESS': { + 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_procs -a matrix-dimension -c 1:', + }, + }, + }, + }, + 'matrix-dimension': { + 'install_dir': '/opt/matrix-dimension', + 'data_dir': '/var/opt/matrix-dimension', + 'database': { + 'user': 'matrix-dimension', + 'password': repo.vault.password_for('{} postgresql matrix-dimension'.format(node.name)), + 'database': 'matrix-dimension', + }, + }, + 'postgresql': { + 'roles': { + 'matrix-dimension': { + 'password': repo.vault.password_for('{} postgresql matrix-dimension'.format(node.name)), + }, + }, + 'databases': { + 'matrix-dimension': { + 'owner': 'matrix-dimension', + }, + }, + }, + 'users': { + 'matrix-dimension': { + 'home': '/var/opt/matrix-dimension', + }, + }, +} + + +@metadata_reactor.provides( + 'nginx/vhosts/matrix-dimension', +) +def nginx_config(metadata): + return { + 'nginx': { + 'vhosts': { + 'matrix-dimension': { + 'domain': metadata.get('matrix-dimension/url'), + 'do_not_set_content_security_headers': True, + 'max_body_size': '50M', + 'locations': { + '/': { + 'target': 'http://127.0.0.1:20030', + }, + }, + }, + }, + }, + } + + +@metadata_reactor.provides( + 'zfs/datasets', +) +def zfs(metadata): + return { + 'zfs': { + 'datasets': { + 'tank/matrix-dimension': {}, + 'tank/matrix-dimension/install': { + 'mountpoint': metadata.get('matrix-dimension/install_dir'), + 'needed_by': { + 'directory:{}'.format(metadata.get('matrix-dimension/install_dir')), + }, + }, + 'tank/matrix-dimension/var': { + 'mountpoint': metadata.get('matrix-dimension/data_dir'), + 'needed_by': { + 'directory:{}'.format(metadata.get('matrix-dimension/data_dir')), + }, + }, + }, + }, + } + + +# XXX enable this once there are releases for matrix-dimension +#@metadata_reactor.provides( +# 'icinga2_api/matrix-dimension/services', +#) +#def icinga_check_for_new_release(metadata): +# return { +# 'icinga2_api': { +# 'matrix-dimension': { +# 'services': { +# 'MATRIX-DIMENSION UPDATE': { +# 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_github_for_new_release turt2live/matrix-dimension {}'.format(metadata.get('matrix-dimension/version')), +# 'vars.notification.mail': True, +# 'check_interval': '60m', +# }, +# }, +# }, +# }, +# } diff --git a/bundles/matrix-media-repo/files/config.yaml b/bundles/matrix-media-repo/files/config.yaml index 3726bb2..3623928 100644 --- a/bundles/matrix-media-repo/files/config.yaml +++ b/bundles/matrix-media-repo/files/config.yaml @@ -1,11 +1,8 @@ # General repo configuration repo: - bindAddress: '${node.metadata.get('matrix-media-repo/listen-addr', '127.0.0.1')}' - port: ${node.metadata.get('matrix-media-repo/port', 20090)} + bindAddress: '${node.metadata['matrix-media-repo'].get('listen-addr', '127.0.0.1')}' + port: ${node.metadata['matrix-media-repo'].get('port', 20090)} logDirectory: '-' - logColors: false - jsonLogs: false - logLevel: 'info' trustAnyForwardedAddress: false useForwardedHost: true @@ -13,67 +10,73 @@ federation: backoffAt: 20 database: - postgres: "postgres://${node.metadata.get('matrix-media-repo/database/user')}:${node.metadata.get('matrix-media-repo/database/password')}@${node.metadata.get('matrix-media-repo/database/host', 'localhost')}/${node.metadata.get('matrix-media-repo/database/database')}?sslmode=disable" + postgres: "postgres://${node.metadata['matrix-media-repo']['database']['user']}:${node.metadata['matrix-media-repo']['database']['password']}@${node.metadata['matrix-media-repo']['database'].get('host', 'localhost')}/${node.metadata['matrix-media-repo']['database']['database']}?sslmode=disable" pool: maxConnections: 25 maxIdleConnections: 5 homeservers: -% for homeserver, config in node.metadata.get('matrix-media-repo/homeservers').items(): +% for homeserver, config in node.metadata['matrix-media-repo'].get('homeservers', {}).items(): - name: ${homeserver} csApi: "${config['domain']}" backoffAt: ${config.get('backoff_at', 10)} adminApiKind: "${config.get('api', 'matrix')}" -% if config.get('signing_key_path'): - signingKeyPath: "${config['signing_key_path']}" -% endif % endfor accessTokens: - maxCacheTimeSeconds: 10 + maxCacheTimeSeconds: 0 useLocalAppserviceConfig: false admins: -% for user in sorted(node.metadata.get('matrix-media-repo/admins')): +% for user in sorted(node.metadata['matrix-media-repo']['admins']): - "${user}" % endfor sharedSecretAuth: enabled: false - token: "${node.metadata.get('matrix-media-repo/shared-secret-token')}" + token: "${node.metadata['matrix-media-repo']['shared-secret-token']}" datastores: - type: file - id: "${node.metadata.get('matrix-media-repo/datastore_id')}" enabled: true - forKinds: ['all'] + forKinds: + - 'thumbnails' + - 'remote_media' + - 'local_media' + - 'archives' opts: path: /var/matrix/media archiving: enabled: true - selfService: ${str(node.metadata.get('matrix-media-repo/archive/self-service')).lower()} - targetBytesPerPart: ${node.metadata.get('matrix-media-repo/archive/mb_per_part', node.metadata.get('matrix-media-repo/upload_max_mb')*2)*1024*1024} + selfService: ${str(node.metadata['matrix-media-repo']['archive']['self-service']).lower()} + targetBytesPerPart: ${node.metadata['matrix-media-repo']['archive'].get('mb_per_part', node.metadata['matrix-media-repo']['upload_max_mb']*2)*1024*1024} uploads: - maxBytes: ${node.metadata.get('matrix-media-repo/upload_max_mb')*1024*1024} + maxBytes: ${node.metadata['matrix-media-repo']['upload_max_mb']*1024*1024} minBytes: 100 - #reportedMaxBytes: 0 - maxPending: 5 - maxAgeSeconds: 1800 + reportedMaxBytes: 0 quotas: enabled: false downloads: - maxBytes: ${node.metadata.get('matrix-media-repo/download_max_mb')*1024*1024} - numWorkers: ${node.metadata.get('matrix-media-repo/workers')} + maxBytes: ${node.metadata['matrix-media-repo']['download_max_mb']*1024*1024} + numWorkers: ${node.metadata['matrix-media-repo']['workers']} failureCacheMinutes: 5 + cache: + enabled: true + maxSizeBytes: ${node.metadata['matrix-media-repo']['download_max_mb']*10*1024*1024} + maxFileSizeBytes: ${node.metadata['matrix-media-repo']['upload_max_mb']*1024*1024} + trackedMinutes: 30 + minDownloads: 5 + minCacheTimeSeconds: 300 + minEvictedTimeSeconds: 60 expireAfterDays: 0 urlPreviews: enabled: true - maxPageSizeBytes: ${node.metadata.get('matrix-media-repo/preview_max_mb')*1024*1024} + maxPageSizeBytes: ${node.metadata['matrix-media-repo']['preview_max_mb']*1024*1024} previewUnsafeCertificates: false numWords: 50 maxLength: 200 @@ -81,7 +84,7 @@ urlPreviews: maxTitleLength: 150 filePreviewTypes: - "image/*" - numWorkers: ${node.metadata.get('matrix-media-repo/workers')} + numWorkers: ${node.metadata['matrix-media-repo']['workers']} disallowedNetworks: - "127.0.0.1/8" - "10.0.0.0/8" @@ -100,8 +103,8 @@ urlPreviews: oEmbed: false thumbnails: - maxSourceBytes: ${node.metadata.get('matrix-media-repo/preview_max_mb')*1024*1024} - numWorkers: ${node.metadata.get('matrix-media-repo/workers')} + maxSourceBytes: ${node.metadata['matrix-media-repo']['preview_max_mb']*1024*1024} + numWorkers: ${node.metadata['matrix-media-repo']['workers']} sizes: - width: 32 height: 32 @@ -131,14 +134,14 @@ thumbnails: - "video/mp4" allowAnimated: true defaultAnimated: false - maxAnimateSizeBytes: ${node.metadata.get('matrix-media-repo/preview_max_mb')*1024*1024} + maxAnimateSizeBytes: ${node.metadata['matrix-media-repo']['preview_max_mb']*1024*1024} stillFrame: 0.5 expireAfterDays: 0 rateLimit: enabled: true - requestsPerSecond: 100 - burst: 5000 + requestsPerSecond: 10 + burst: 50 identicons: enabled: true diff --git a/bundles/matrix-media-repo/items.py b/bundles/matrix-media-repo/items.py index faf08ad..ba2b2bb 100644 --- a/bundles/matrix-media-repo/items.py +++ b/bundles/matrix-media-repo/items.py @@ -19,6 +19,9 @@ files = { '/opt/matrix-media-repo/config.yaml': { 'owner': 'matrix-media-repo', 'content_type': 'mako', + 'triggers': { + 'svc_systemd:matrix-media-repo:restart', + }, }, '/etc/systemd/system/matrix-media-repo.service': { 'triggers': { diff --git a/bundles/matrix-stickerpicker/files/sticker-import b/bundles/matrix-stickerpicker/files/sticker-import deleted file mode 100644 index fd765c9..0000000 --- a/bundles/matrix-stickerpicker/files/sticker-import +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -/opt/matrix-stickerpicker/venv/bin/sticker-import \ - --config /opt/matrix-stickerpicker/config.json \ - --session /opt/matrix-stickerpicker/sticker-import.session \ - --output-dir /var/opt/matrix-stickerpicker/ \ - "$@" diff --git a/bundles/matrix-stickerpicker/items.py b/bundles/matrix-stickerpicker/items.py deleted file mode 100644 index 0cbe6c5..0000000 --- a/bundles/matrix-stickerpicker/items.py +++ /dev/null @@ -1,47 +0,0 @@ -actions['matrix-stickerpicker_create_virtualenv'] = { - 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/matrix-stickerpicker/venv/', - 'unless': 'test -d /opt/matrix-stickerpicker/venv/', - 'needs': { - # actually /opt/matrix-stickerpicker, but we don't create that - 'directory:/opt/matrix-stickerpicker/src', - }, -} - -actions['matrix-stickerpicker_install'] = { - 'command': 'cd /opt/matrix-stickerpicker/src && /opt/matrix-stickerpicker/venv/bin/pip install --upgrade pip .', - 'needs': { - 'action:matrix-stickerpicker_create_virtualenv', - }, - 'triggered': True, -} - -users['matrix-stickerpicker'] = { - 'home': '/opt/matrix-stickerpicker', -} - -files['/usr/local/bin/sticker-import'] = { - 'mode': '0700', -} - -files['/opt/matrix-stickerpicker/config.json'] = { - 'content': repo.libs.faults.dict_as_json(node.metadata.get('matrix-stickerpicker/config')), -} - -directories['/opt/matrix-stickerpicker/src'] = {} - -directories['/var/opt/matrix-stickerpicker'] = {} - -git_deploy['/opt/matrix-stickerpicker/src'] = { - 'repo': 'https://github.com/maunium/stickerpicker.git', - 'rev': node.metadata.get('matrix-stickerpicker/version', 'master'), - 'triggers': { - 'action:matrix-stickerpicker_install', - }, -} - -symlinks['/opt/matrix-stickerpicker/src/web/packs'] = { - 'target': '/var/opt/matrix-stickerpicker', - 'after': { - 'git_deploy:/opt/matrix-stickerpicker/src', - }, -} diff --git a/bundles/matrix-stickerpicker/metadata.py b/bundles/matrix-stickerpicker/metadata.py deleted file mode 100644 index e491a9d..0000000 --- a/bundles/matrix-stickerpicker/metadata.py +++ /dev/null @@ -1,37 +0,0 @@ -defaults = { - 'backups': { - 'paths': { - '/var/opt/matrix-stickerpicker', - }, - }, - 'zfs': { - 'datasets': { - 'tank/matrix-stickerpicker': { - 'mountpoint': '/var/opt/matrix-stickerpicker', - 'needed_by': { - 'directory:/var/opt/matrix-stickerpicker', - }, - }, - }, - }, -} - - -@metadata_reactor.provides( - 'nginx/vhosts/matrix-stickerpicker', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'matrix-stickerpicker': { - 'domain': metadata.get('matrix-stickerpicker/domain'), - 'do_not_set_content_security_headers': True, - 'webroot': '/opt/matrix-stickerpicker/src/web/', - }, - }, - }, - } diff --git a/bundles/matrix-synapse/files/homeserver.yaml b/bundles/matrix-synapse/files/homeserver.yaml index 9c43437..c5f9af3 100644 --- a/bundles/matrix-synapse/files/homeserver.yaml +++ b/bundles/matrix-synapse/files/homeserver.yaml @@ -62,14 +62,10 @@ allow_guest_access: false enable_metrics: True -% if appservice_configs: app_service_config_files: -% for config in sorted(appservice_configs): +% for config in sorted(appservice_configs): - "${config}" -% endfor -% else: -app_service_config_files: [] -% endif +% endfor signing_key_path: "/etc/matrix-synapse/homeserver.signing.key" trusted_key_servers: @@ -85,7 +81,7 @@ password_config: email: enable_notifs: false - notif_from: "Matrix " + notif_from: "Matrix \ -[Unit] -Description=matrix-org sliding-sync proxy -After=network.target -Requires=postgresql.service - -[Service] -User=matrix-synapse -Group=matrix-synapse -Environment=SYNCV3_SERVER=https://${node.metadata.get('matrix-synapse/baseurl')} -Environment=SYNCV3_DB=${db_string} -Environment=SYNCV3_SECRET=${node.metadata.get('matrix-synapse/sliding_sync/secret')} -Environment=SYNCV3_BINDADDR=127.0.0.1:20070 -ExecStart=/usr/local/bin/matrix-sliding-sync -Restart=always -RestartSec=10s - -[Install] -WantedBy=multi-user.target diff --git a/bundles/matrix-synapse/items.py b/bundles/matrix-synapse/items.py index 527cc5e..224d7b8 100644 --- a/bundles/matrix-synapse/items.py +++ b/bundles/matrix-synapse/items.py @@ -1,15 +1,7 @@ files = { '/etc/matrix-synapse/homeserver.yaml': { 'content_type': 'mako', - 'context': node.metadata.get('matrix-synapse'), - 'needs': { - 'pkg_apt:matrix-synapse-py3', - }, - 'triggers': { - 'svc_systemd:matrix-synapse:restart', - }, - }, - '/etc/matrix-synapse/log.yaml': { + 'context': node.metadata['matrix-synapse'], 'needs': { 'pkg_apt:matrix-synapse-py3', }, @@ -32,6 +24,9 @@ files = { 'svc_systemd:matrix-synapse:restart', }, }, + '/etc/matrix-synapse/homeserver.signing.key': { + 'content': repo.vault.decrypt_file('matrix-synapse/{}/homeserver_signing.key.vault'.format(node.name)), + }, '/etc/matrix-synapse/conf.d/server_name.yaml': { # We don't actually need this file. However, if we don't put the # server name in there, synapse will somehow remove it from @@ -39,7 +34,7 @@ files = { # Our override.conf ensures this file is never read, so we don't # need to restart synapse after changing stuff in here. 'content_type': 'mako', - 'context': node.metadata.get('matrix-synapse'), + 'context': node.metadata['matrix-synapse'], }, '/etc/matrix-synapse/conf.d/report_stats.yaml': { # see comment above @@ -50,7 +45,6 @@ svc_systemd = { 'matrix-synapse': { 'needs': { 'file:/etc/matrix-synapse/homeserver.yaml', - 'file:/etc/matrix-synapse/log.yaml', 'file:/etc/systemd/system/matrix-synapse.service.d/override.conf', 'pkg_apt:matrix-synapse-py3', 'postgres_db:synapse', diff --git a/bundles/matrix-synapse/metadata.py b/bundles/matrix-synapse/metadata.py index eac3005..3100368 100644 --- a/bundles/matrix-synapse/metadata.py +++ b/bundles/matrix-synapse/metadata.py @@ -15,7 +15,6 @@ defaults = { }, 'backups': { 'paths': { - '/etc/matrix-synapse', # to backup the signing key '/var/lib/matrix-synapse', }, }, @@ -118,9 +117,6 @@ def nginx(metadata): } locations = { - '/_client/': { - 'target': 'http://127.0.0.1:20070', - }, '/_matrix': { 'target': 'http://[::1]:20080', 'max_body_size': '50M', @@ -132,14 +128,13 @@ def nginx(metadata): } if node.has_bundle('matrix-media-repo'): - for path in ('/_matrix/media', '/_matrix/client/v1/media', '/_matrix/federation/v1/media'): - locations[path] = { - 'target': 'http://localhost:20090', - 'max_body_size': '{}M'.format(metadata.get('matrix-media-repo/upload_max_mb')), - # matrix-media-repo needs this to be the - # homeserver address. - 'x_forwarded_host': metadata.get('matrix-synapse/server_name'), - } + locations['/_matrix/media'] = { + 'target': 'http://localhost:20090', + 'max_body_size': '{}M'.format(metadata.get('matrix-media-repo/upload_max_mb')), + # matrix-media-repo needs this to be the + # homeserver address. + 'x_forwarded_host': metadata.get('matrix-synapse/server_name'), + } vhosts = { 'matrix-synapse': { @@ -160,20 +155,3 @@ def nginx(metadata): 'vhosts': vhosts }, } - -@metadata_reactor.provides( - 'matrix-synapse/trusted_key_servers', -) -def autotrust_our_own_servers(metadata): - domains = set() - for rnode in repo.nodes: - if not rnode.has_bundle('matrix-synapse'): - continue - - domains.add(rnode.metadata.get('matrix-synapse/server_name')) - - return { - 'matrix-synapse': { - 'trusted_key_servers': domains, - }, - } diff --git a/bundles/mautrix-telegram/files/config.yaml b/bundles/mautrix-telegram/files/config.yaml index 380d3a2..0a3ad1c 100644 --- a/bundles/mautrix-telegram/files/config.yaml +++ b/bundles/mautrix-telegram/files/config.yaml @@ -46,7 +46,6 @@ bridge: - username - phone number displayname_max_length: 100 - caption_in_message: true allow_avatar_remove: false max_initial_member_sync: -1 sync_channel_members: true @@ -181,7 +180,7 @@ logging: telethon: level: INFO aiohttp: - level: WARNING + level: INFO root: level: INFO handlers: [console] diff --git a/bundles/minecraft/metadata.py b/bundles/minecraft/metadata.py index 4bd5223..4c7626b 100644 --- a/bundles/minecraft/metadata.py +++ b/bundles/minecraft/metadata.py @@ -150,13 +150,13 @@ def heap_to_java_opts(metadata): @metadata_reactor.provides( - 'firewall/port_rules', + 'firewall/port_rules/25565', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '25565/tcp': atomic(metadata.get('minecraft/restrict-to', set())), + '25565': atomic(metadata.get('minecraft/restrict-to', set())), }, }, } diff --git a/bundles/miniflux/items.py b/bundles/miniflux/items.py index 6ea55ae..4e8e015 100644 --- a/bundles/miniflux/items.py +++ b/bundles/miniflux/items.py @@ -2,8 +2,8 @@ files = { '/etc/miniflux.conf': { 'content_type': 'mako', 'context': { - 'dbpassword': node.metadata.get('postgresql/roles/miniflux/password'), - 'base_url': node.metadata.get('miniflux/domain'), + 'dbpassword': node.metadata['postgresql']['roles']['miniflux']['password'], + 'base_url': node.metadata['miniflux']['domain'], }, 'triggers': { 'svc_systemd:miniflux:restart', diff --git a/bundles/mixcloud-downloader/files/download.sh b/bundles/mixcloud-downloader/files/download.sh index b7d97de..963d44d 100644 --- a/bundles/mixcloud-downloader/files/download.sh +++ b/bundles/mixcloud-downloader/files/download.sh @@ -1,15 +1,11 @@ #!/bin/bash -OPTS="--netrc" -OPTS="$OPTS --netrc-location /opt/mixcloud-downloader/netrc" -OPTS="$OPTS --retry-sleep linear=1::2" -OPTS="$OPTS --retry-sleep fragment:exp=1:60" -OPTS="$OPTS --extractor-retries 5" +OPTS="" if [[ -n "$DEBUG" ]] then set -x else - OPTS="$OPTS -q" + OPTS="-q" fi set -euo pipefail @@ -25,7 +21,7 @@ pip install --upgrade pip yt-dlp errors=0 -for i in Neosignal tasmo starkato b4m ProjectPoltergeist jakehunnter davem_dokebi El1s4 +for i in Neosignal tasmo starkato b4m Alexeyan jakehunnter davem_dokebi tasmo do echo "> mixcloud $i" >&2 if ! [[ -d "/storage/nas/Musik/mixcloud/$i" ]] @@ -57,7 +53,7 @@ do ) || errors=1 done -for i in tschunkelmusik zotanmew +for i in tschunkelmusik do echo "> soundcloud $i" >&2 if ! [[ -d "/storage/nas/Musik/mixcloud/$i" ]] diff --git a/bundles/mixcloud-downloader/files/netrc b/bundles/mixcloud-downloader/files/netrc deleted file mode 100644 index 40def1b..0000000 --- a/bundles/mixcloud-downloader/files/netrc +++ /dev/null @@ -1,3 +0,0 @@ -% for domain, data in sorted(node.metadata.get('mixcloud-downloader/netrc', {}).items()): -machine ${domain} login ${data['username']} password ${data['password']} -% endfor diff --git a/bundles/mixcloud-downloader/items.py b/bundles/mixcloud-downloader/items.py index 8c66ce8..a45acdc 100644 --- a/bundles/mixcloud-downloader/items.py +++ b/bundles/mixcloud-downloader/items.py @@ -6,9 +6,3 @@ files['/opt/mixcloud-downloader/download.sh'] = { directories['/opt/mixcloud-downloader'] = { 'owner': 'kunsi', } - -files['/opt/mixcloud-downloader/netrc'] = { - 'content_type': 'mako', - 'mode': '0400', - 'owner': 'kunsi', -} diff --git a/bundles/mosquitto/items.py b/bundles/mosquitto/items.py index 1b16413..92eb1b5 100644 --- a/bundles/mosquitto/items.py +++ b/bundles/mosquitto/items.py @@ -5,6 +5,12 @@ files = { 'svc_systemd:mosquitto:restart', }, }, + '/usr/local/bin/tasmota-telegraf-plugin': { + 'mode': '0755', + 'needs': { + 'pkg_apt:python3-paho-mqtt', + }, + }, } svc_systemd = { @@ -17,12 +23,6 @@ svc_systemd = { } if node.has_bundle('telegraf'): - files['/usr/local/bin/tasmota-telegraf-plugin'] = { - 'mode': '0755', - 'needs': { - 'pkg_apt:python3-paho-mqtt', - }, - 'triggers': { - 'svc_systemd:telegraf:restart', - }, + files['/usr/local/bin/tasmota-telegraf-plugin']['triggers'] = { + 'svc_systemd:telegraf:restart', } diff --git a/bundles/mosquitto/metadata.py b/bundles/mosquitto/metadata.py index 213dac6..c07a446 100644 --- a/bundles/mosquitto/metadata.py +++ b/bundles/mosquitto/metadata.py @@ -5,6 +5,7 @@ defaults = { 'packages': { 'mosquitto': {}, 'mosquitto-clients': {}, + 'python3-paho-mqtt': {}, # for telegraf plugin }, }, 'icinga2_api': { @@ -23,9 +24,6 @@ defaults = { }, } -if node.has_bundle('telegraf'): - defaults['apt']['packages']['python3-paho-mqtt'] = {} - @metadata_reactor.provides( 'firewall/port_rules', @@ -35,7 +33,7 @@ def firewall(metadata): result = {} for listener in metadata.get('mosquitto/listeners').keys(): - result[f'{listener}/tcp'] = atomic(sources) + result[listener] = atomic(sources) return { 'firewall': { diff --git a/bundles/netbox/items.py b/bundles/netbox/items.py index 9edbf0b..ca54922 100644 --- a/bundles/netbox/items.py +++ b/bundles/netbox/items.py @@ -1,138 +1,124 @@ -users['netbox'] = { - 'home': '/opt/netbox', -} - -directories['/opt/netbox/src'] = {} - -directories['/opt/netbox/media'] = { - 'owner': 'netbox', -} - -directories['/opt/netbox/scripts'] = { - 'owner': 'netbox', -} - -git_deploy['/opt/netbox/src'] = { - 'repo': 'https://github.com/netbox-community/netbox.git', - 'rev': node.metadata.get('netbox/version'), - 'triggers': { - 'action:netbox_install', - 'svc_systemd:netbox-web:restart', - 'svc_systemd:netbox-worker:restart', +users = { + 'netbox': { + 'home': '/opt/netbox', }, - 'tags': { - 'netbox-install', +} + +directories = { + '/opt/netbox/src': {}, + '/opt/netbox/media': { + 'owner': 'netbox', + }, + '/opt/netbox/scripts': { + 'owner': 'netbox', + }, +} + +git_deploy = { + '/opt/netbox/src': { + 'repo': 'https://github.com/netbox-community/netbox.git', + 'rev': node.metadata.get('netbox/version'), + 'triggers': { + 'action:netbox_install', + 'action:netbox_upgrade', + 'svc_systemd:netbox-web:restart', + 'svc_systemd:netbox-worker:restart', + }, }, } # This is a recreation of https://github.com/netbox-community/netbox/blob/develop/upgrade.sh -actions['netbox_create_virtualenv'] = { - 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/netbox/venv', - 'unless': 'test -d /opt/netbox/venv/', - 'needed_by': { - 'action:netbox_install', +actions = { + 'netbox_create_virtualenv': { + 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/netbox/venv', + 'unless': 'test -d /opt/netbox/venv/', + 'needed_by': { + 'action:netbox_install', + }, }, -} - -actions['netbox_install'] = { - 'triggered': True, - 'command': ' && '.join([ - 'cd /opt/netbox/src', - '/opt/netbox/venv/bin/pip install --upgrade --upgrade-strategy=eager pip wheel setuptools django-auth-ldap gunicorn', - '/opt/netbox/venv/bin/pip install --upgrade --upgrade-strategy=eager -r requirements.txt', - ]), - 'needs': { - 'pkg_apt:build-essential', - 'pkg_apt:graphviz', - 'pkg_apt:libffi-dev', - 'pkg_apt:libldap2-dev', - 'pkg_apt:libpq-dev', - 'pkg_apt:libsasl2-dev', - 'pkg_apt:libssl-dev', - 'pkg_apt:libxml2-dev', - 'pkg_apt:libxslt1-dev', - 'pkg_apt:python3-dev', - 'pkg_apt:zlib1g-dev', - }, - 'tags': { - 'netbox-install', - }, -} - -last_action = 'netbox_install' -for upgrade_command in ( - 'migrate', - 'trace_paths --no-input', - 'collectstatic --no-input', - 'remove_stale_contenttypes --no-input', - 'reindex --lazy', - 'clearsessions', -): - actions[f'netbox_upgrade_{upgrade_command.split()[0]}'] = { + 'netbox_install': { 'triggered': True, - 'command': f'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py {upgrade_command}', + 'command': ' && '.join([ + 'cd /opt/netbox/src', + '/opt/netbox/venv/bin/pip install --upgrade pip wheel setuptools django-auth-ldap gunicorn', + '/opt/netbox/venv/bin/pip install --upgrade -r requirements.txt', + ]), 'needs': { - f'action:{last_action}', + 'pkg_apt:build-essential', + 'pkg_apt:graphviz', + 'pkg_apt:libffi-dev', + 'pkg_apt:libldap2-dev', + 'pkg_apt:libpq-dev', + 'pkg_apt:libsasl2-dev', + 'pkg_apt:libssl-dev', + 'pkg_apt:libxml2-dev', + 'pkg_apt:libxslt1-dev', + 'pkg_apt:python3-dev', + 'pkg_apt:zlib1g-dev', + } + }, + 'netbox_upgrade': { + 'triggered': True, + 'command': ' && '.join([ + '/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py migrate', + '/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py collectstatic --no-input', + '/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py remove_stale_contenttypes --no-input', + '/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py clearsessions', + ]), + 'needs': { + 'action:netbox_install', + 'file:/opt/netbox/src/netbox/netbox/configuration.py', }, - 'tags': { - 'netbox-upgrade', + }, +} + +files = { + '/etc/systemd/system/netbox-web.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:netbox-web:restart', }, - 'triggered_by': { - 'tag:netbox-install', + }, + '/etc/systemd/system/netbox-worker.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:netbox-worker:restart', + }, + }, + '/opt/netbox/src/netbox/netbox/configuration.py': { + 'content_type': 'mako', + 'triggers': { + 'svc_systemd:netbox-web:restart', + 'svc_systemd:netbox-worker:restart', + }, + 'needs': { + 'git_deploy:/opt/netbox/src', + }, + }, + '/opt/netbox/gunicorn_config.py': { + 'content_type': 'mako', + 'triggers': { + 'svc_systemd:netbox-web:restart', }, - } - last_action = f'netbox_upgrade_{upgrade_command.split()[0]}' - -files['/usr/local/lib/systemd/system/netbox-web.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:netbox-web:restart', }, } -files['/usr/local/lib/systemd/system/netbox-worker.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:netbox-worker:restart', - }, -} - -files['/opt/netbox/src/netbox/netbox/configuration.py'] = { - 'content_type': 'mako', - 'triggers': { - 'svc_systemd:netbox-web:restart', - 'svc_systemd:netbox-worker:restart', - }, - 'needs': { - 'git_deploy:/opt/netbox/src', - }, - 'tags': { - 'netbox-install', - }, -} - -files['/opt/netbox/gunicorn_config.py'] = { - 'content_type': 'mako', - 'triggers': { - 'svc_systemd:netbox-web:restart', - }, -} - -svc_systemd['netbox-web'] = { - 'needs': { - 'file:/usr/local/lib/systemd/system/netbox-web.service', - 'file:/opt/netbox/gunicorn_config.py', - 'file:/opt/netbox/src/netbox/netbox/configuration.py', - 'tag:netbox-install', - 'tag:netbox-upgrade', - }, -} - -svc_systemd['netbox-worker'] = { - 'needs': { - 'file:/usr/local/lib/systemd/system/netbox-worker.service', - 'file:/opt/netbox/src/netbox/netbox/configuration.py', - 'tag:netbox-install', - 'tag:netbox-upgrade', +svc_systemd = { + 'netbox-web': { + 'needs': { + 'action:netbox_install', + 'action:netbox_upgrade', + 'file:/etc/systemd/system/netbox-web.service', + 'file:/opt/netbox/gunicorn_config.py', + 'file:/opt/netbox/src/netbox/netbox/configuration.py', + }, + }, + 'netbox-worker': { + 'needs': { + 'action:netbox_install', + 'action:netbox_upgrade', + 'file:/etc/systemd/system/netbox-worker.service', + 'file:/opt/netbox/src/netbox/netbox/configuration.py', + }, }, } diff --git a/bundles/nextcloud/metadata.py b/bundles/nextcloud/metadata.py deleted file mode 100644 index 73c7264..0000000 --- a/bundles/nextcloud/metadata.py +++ /dev/null @@ -1,93 +0,0 @@ -defaults = { - 'backups': { - 'paths': { - '/var/www/nextcloud', - }, - }, - 'php': { - 'clear_env': False, - 'memory_limit': 512, - 'post_max_size': 500, # MB - 'packages': { - 'apcu', - 'bcmath', - 'bz2', - 'curl', - 'gd', - 'gmp', - 'imagick', - 'intl', - 'mbstring', - 'opcache', - 'pgsql', - 'redis', - 'xml', - 'yaml', - 'zip', - }, - }, - 'postgresql': { - 'roles': { - 'nextcloud': { - 'password': repo.vault.password_for(f'{node.name} postgresql nextcloud'), - }, - }, - 'databases': { - 'nextcloud': { - 'owner': 'nextcloud', - }, - }, - }, - 'systemd-timers': { - 'timers': { - 'nextcloud-cron': { - 'command': '/usr/bin/php -f /var/www/nextcloud/cron.php', - 'pwd': '/var/www/nextcloud', - 'user': 'www-data', - 'when': '*:00/5', - 'requisite': { - 'postgresql.service', - }, - }, - }, - }, - 'zfs': { - 'datasets': { - 'tank/nextcloud': { - 'mountpoint': '/var/www/nextcloud', - 'needed_by': { - 'directory:/var/www/nextcloud', - }, - }, - }, - }, -} - - -@metadata_reactor.provides( - 'nginx/vhosts/nextcloud', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'nextcloud': { - 'domain': metadata.get('nextcloud/domain'), - 'php': True, - 'extras': True, - 'max_body_size': '500M', - 'index': [ - 'index.php', - 'index.html', - '/index.php$request_uri', - ], - 'webroot_config': { - 'owner': 'www-data', - }, - }, - }, - }, - } diff --git a/bundles/nfs-client/items.py b/bundles/nfs-client/items.py index 97cebc4..918d02c 100644 --- a/bundles/nfs-client/items.py +++ b/bundles/nfs-client/items.py @@ -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, }, } diff --git a/bundles/nfs-client/metadata.py b/bundles/nfs-client/metadata.py index 93bf66e..c59ee60 100644 --- a/bundles/nfs-client/metadata.py +++ b/bundles/nfs-client/metadata.py @@ -4,6 +4,11 @@ defaults = { 'nfs-common': {}, }, }, + 'pacman': { + 'packages': { + 'nfs-utils': {}, + }, + }, } if node.has_bundle('telegraf'): diff --git a/bundles/nfs-server/files/avahi.service b/bundles/nfs-server/files/avahi.service deleted file mode 100644 index 394cdca..0000000 --- a/bundles/nfs-server/files/avahi.service +++ /dev/null @@ -1,10 +0,0 @@ - - - - NFS ${path} on %h - - _nfs._tcp - 2049 - path=${path} - - diff --git a/bundles/nfs-server/files/exports b/bundles/nfs-server/files/exports index ac9c8f8..ad2ca4c 100644 --- a/bundles/nfs-server/files/exports +++ b/bundles/nfs-server/files/exports @@ -1,4 +1,4 @@ -% for path, shares in sorted(node.metadata.get('nfs-server/shares', {}).items()): +% for path, shares in sorted(node.metadata['nfs-server']['shares'].items()): % for share_target, share_options in sorted(shares.items()): % for ip_list in repo.libs.tools.resolve_identifier(repo, share_target).values(): % for ip in sorted(ip_list): diff --git a/bundles/nfs-server/items.py b/bundles/nfs-server/items.py index ce025cf..dacbc48 100644 --- a/bundles/nfs-server/items.py +++ b/bundles/nfs-server/items.py @@ -1,40 +1,25 @@ -from re import sub - -files['/etc/exports'] = { - 'content_type': 'mako', - 'triggers': { - 'action:nfs_reload_shares', +files = { + '/etc/exports': { + 'content_type': 'mako', + 'triggers': { + 'action:nfs_reload_shares', + }, + }, + '/etc/default/nfs-kernel-server': { + 'source': 'etc-default', + 'triggers': { + 'svc_systemd:nfs-server:restart', + }, }, } -files['/etc/default/nfs-kernel-server'] = { - 'source': 'etc-default', - 'triggers': { - 'svc_systemd:nfs-server:restart', +actions = { + 'nfs_reload_shares': { + 'command': 'exportfs -a', + 'triggered': True, }, } -actions['nfs_reload_shares'] = { - 'command': 'exportfs -a', - 'triggered': True, +svc_systemd = { + 'nfs-server': {}, } - -svc_systemd['nfs-server'] = {} - -if node.has_bundle('avahi-daemon'): - for path, shares in node.metadata.get('nfs-server/shares', {}).items(): - create_avahi_file = False - for share_target, share_options in shares.items(): - if ',insecure,' in f',{share_options},': - create_avahi_file = True - - if create_avahi_file: - share_name_normalized = sub('[^a-z0-9-_]+', '_', path) - - files[f'/etc/avahi/services/nfs{share_name_normalized}.service'] = { - 'source': 'avahi.service', - 'content_type': 'mako', - 'context': { - 'path': path, - }, - } diff --git a/bundles/nfs-server/metadata.py b/bundles/nfs-server/metadata.py index d2f833c..4b9e8d5 100644 --- a/bundles/nfs-server/metadata.py +++ b/bundles/nfs-server/metadata.py @@ -33,11 +33,8 @@ def firewall(metadata): ips.add(share_target) rules = {} - ports = ('111', '2049', '1110', '4045', '35295') - if metadata.get('nfs-server/version', 3) == 4: - ports = ('111', '2049') - for port in ports: - for proto in ('/tcp', '/udp'): + for port in ('111', '2049', '1110', '4045', '35295'): # TODO find out if we need more ports + for proto in ('', '/udp'): rules[port + proto] = atomic(ips) return { diff --git a/bundles/nftables/files/nftables.conf b/bundles/nftables/files/nftables.conf index 56fba34..4034ad4 100644 --- a/bundles/nftables/files/nftables.conf +++ b/bundles/nftables/files/nftables.conf @@ -14,24 +14,11 @@ table inet filter { iif lo accept -% for address in sorted(blocked_v4): - ip saddr ${address} drop -% endfor -% for address in sorted(blocked_v6): - ip6 saddr ${address} drop -% endfor - icmp type timestamp-request drop icmp type timestamp-reply drop - meta l4proto {icmp, ipv6-icmp} accept + ip protocol icmp accept -% for ruleset, rules in sorted(input.items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor -% endfor + ip6 nexthdr ipv6-icmp accept } chain output { @@ -45,36 +32,15 @@ table inet filter { icmp type timestamp-request drop icmp type timestamp-reply drop -% for ruleset, rules in sorted(forward.items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor -% endfor } } table nat { chain prerouting { type nat hook prerouting priority -100 -% for ruleset, rules in sorted(prerouting.items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor -% endfor } chain postrouting { type nat hook postrouting priority 100 -% for ruleset, rules in sorted(postrouting.items()): - - # ${ruleset} -% for rule in rules: - ${rule} -% endfor -% endfor } } diff --git a/bundles/nftables/items.py b/bundles/nftables/items.py index fc943d4..42bf2e4 100644 --- a/bundles/nftables/items.py +++ b/bundles/nftables/items.py @@ -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': { @@ -10,14 +15,8 @@ directories = { files = { '/etc/nftables.conf': { - 'content_type': 'mako', - 'context': { - 'blocked_v4': node.metadata.get('nftables/blocked_v4', set()), - 'blocked_v6': node.metadata.get('nftables/blocked_v6', set()), - 'forward': node.metadata.get('nftables/forward', {}), - 'input': node.metadata.get('nftables/input', {}), - 'postrouting': node.metadata.get('nftables/postrouting', {}), - 'prerouting': node.metadata.get('nftables/prerouting', {}), + 'needs': { + 'directory:/etc/nftables-rules.d', }, 'triggers': { 'svc_systemd:nftables:reload', @@ -33,11 +32,26 @@ files = { }, } +for ruleset, rules in node.metadata.get('nftables/rules', {}).items(): + files[f'/etc/nftables-rules.d/{ruleset}'] = { + 'source': 'rules-template', + 'content_type': 'mako', + 'context': { + 'rules': rules, + }, + 'needed_by': { + 'svc_systemd:nftables', + }, + 'triggers': { + 'svc_systemd:nftables:reload', + }, + } + svc_systemd = { 'nftables': { 'needs': { 'file:/etc/nftables.conf', - 'pkg_apt:nftables', + package, }, }, } diff --git a/bundles/nftables/metadata.py b/bundles/nftables/metadata.py index 4fac791..08396ce 100644 --- a/bundles/nftables/metadata.py +++ b/bundles/nftables/metadata.py @@ -6,13 +6,26 @@ defaults = { 'nftables': {}, }, }, - 'nftables': { - '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'): +if not node.has_bundle('vmhost'): # see comment in bundles/vmhost/items.py defaults['apt']['packages']['iptables'] = { 'installed': False, @@ -22,7 +35,7 @@ if not node.has_bundle('vmhost') and not node.has_bundle('docker-engine'): } @metadata_reactor.provides( - 'nftables/input/99-port_rules', + 'nftables/rules/99-port_rules', ) def port_rules_to_nftables(metadata): # Using this, bundles can simply set up port based rules. This @@ -36,47 +49,46 @@ def port_rules_to_nftables(metadata): if '/' in portdef: port, proto = portdef.split('/', 2) - if proto not in ('tcp', 'udp'): + if proto not in {'udp'}: raise BundleError(f'firewall/port_rules: illegal identifier {portdef} in metadata for {node.name}') else: port = portdef - proto = None + proto = 'tcp' for target in targets: - if ( - (port == '*' and target == '*') - or (target == '*' and proto is None) - or (port != '*' and proto is None) - ): - raise BundleError(f'firewall/port_rules: illegal combination of port, target and protocol: "{port}" "{target}" "{proto}"') + if port == '*' and target == '*': + raise BundleError('firewall/port_rules: setting both port and target to * is unsupported') comment = f'comment "port_rules {target}"' if port != '*': if ':' in port: parts = port.split(':') - port_str = f'{proto} dport {{ {parts[0]}-{parts[1]} }} ' + port_str = f'{proto} dport {{ {parts[0]}-{parts[1]} }}' else: - port_str = f'{proto} dport {port} ' - elif proto is not None: - port_str = f'meta l4proto {proto} ' + port_str = f'{proto} dport {port}' else: - port_str = '' + port_str = f'meta l4proto {proto}' - if target == '*': - ruleset.add(f'{port_str}accept {comment}') + if target in ('ipv4', 'ipv6'): + version_str = f'meta nfproto {target}' else: - resolved = repo.libs.tools.resolve_identifier(repo, target, linklocal=True) + version_str = '' + + if target in ('*', 'ipv4', 'ipv6'): + ruleset.add(f'inet filter input {version_str} {port_str} accept {comment}') + else: + resolved = repo.libs.tools.resolve_identifier(repo, target) for address in resolved['ipv4']: - ruleset.add(f'{port_str}ip saddr {address} accept {comment}') + ruleset.add(f'inet filter input meta nfproto ipv4 {port_str} ip saddr {address} accept {comment}') for address in resolved['ipv6']: - ruleset.add(f'{port_str}ip6 saddr {address} accept {comment}') + ruleset.add(f'inet filter input meta nfproto ipv6 {port_str} ip6 saddr {address} accept {comment}') return { 'nftables': { - 'input': { + 'rules': { # order does not matter here. '99-port_rules': sorted(ruleset), }, diff --git a/bundles/nginx/files/arch-override.conf b/bundles/nginx/files/arch-override.conf new file mode 100644 index 0000000..5496fe6 --- /dev/null +++ b/bundles/nginx/files/arch-override.conf @@ -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)" diff --git a/bundles/nginx/files/nginx.conf b/bundles/nginx/files/nginx.conf index b020d3c..3f4a9a9 100644 --- a/bundles/nginx/files/nginx.conf +++ b/bundles/nginx/files/nginx.conf @@ -1,4 +1,4 @@ -user www-data; +user ${username}; worker_processes ${worker_processes}; pid /var/run/nginx.pid; @@ -10,9 +10,6 @@ events { http { include /etc/nginx/mime.types; - types { - application/javascript mjs; - } default_type application/octet-stream; charset UTF-8; override_charset on; @@ -26,7 +23,7 @@ http { send_timeout 10; access_log off; - error_log /dev/null; + error_log off; client_body_buffer_size 16K; client_header_buffer_size 4k; diff --git a/bundles/nginx/files/site_template b/bundles/nginx/files/site_template index 96875c8..bccff8c 100644 --- a/bundles/nginx/files/site_template +++ b/bundles/nginx/files/site_template @@ -12,26 +12,27 @@ server { % if ssl: location / { - return 301 https://${domain}$request_uri; + return 308 https://$host$request_uri; } -% if ssl == 'letsencrypt': +% if ssl == 'letsencrypt': location /.well-known/acme-challenge/ { alias /var/lib/dehydrated/acme-challenges/; } -% endif +% endif } -% if domain_aliases and force_domain: server { - server_name ${' '.join(sorted(domain_aliases))}; - +% if domain_aliases: + server_name ${domain} ${' '.join(sorted(domain_aliases))}; +% else: + server_name ${domain}; +% endif root ${webroot if webroot else '/var/www/{}/'.format(vhost)}; index ${' '.join(index)}; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + listen 443 ssl http2; + listen [::]:443 ssl http2; % if ssl == 'letsencrypt': ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem; @@ -47,65 +48,17 @@ server { ssl_session_cache shared:SSL:10m; ssl_session_tickets off; - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; - -% if ssl == 'letsencrypt': - location /.well-known/acme-challenge/ { - alias /var/lib/dehydrated/acme-challenges/; - } -% endif - - location / { - return 301 https://${domain}$request_uri; - } -} - -% endif -server { -% if domain_aliases and not force_domain: - server_name ${domain} ${' '.join(sorted(domain_aliases))}; -% else: - server_name ${domain}; -% endif - - root ${webroot if webroot else '/var/www/{}/'.format(vhost)}; - index ${' '.join(index)}; - - listen 443 ssl; - listen [::]:443 ssl; - http2 on; - -% if ssl == 'letsencrypt': - ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem; - ssl_certificate_key /var/lib/dehydrated/certs/${domain}/privkey.pem; -% else: - ssl_certificate /etc/nginx/ssl/${vhost}.crt; - ssl_certificate_key /etc/nginx/ssl/${vhost}.key; -% endif - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; - ssl_dhparam /etc/ssl/certs/dhparam.pem; - ssl_prefer_server_ciphers off; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_session_cache shared:SSL:10m; - ssl_session_tickets off; - ssl_session_timeout 1d; - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; % endif resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; -% if create_logs: +% if create_access_log: access_log /var/log/nginx/access-${vhost}.log gdpr; - error_log /var/log/nginx/error-${vhost}.log; -% else: - # regular access_log is disabled - # error_log is disabled % endif -% if create_timing_log: access_log /var/log/nginx-timing/${vhost}.log anon_timing; -% endif + # error_log is disabled globally % if max_body_size: client_max_body_size ${max_body_size}; @@ -149,18 +102,18 @@ server { % if 'target' in options: proxy_pass ${options['target']}; proxy_http_version ${options.get('http_version', '1.1')}; - proxy_set_header Host ${options.get('proxy_pass_host', domain)}; + proxy_set_header Host ${domain}; % if options.get('websockets', False): proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; % endif proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host ${options.get('x_forwarded_host', options.get('proxy_pass_host', domain))}; + proxy_set_header X-Forwarded-Host ${options.get('x_forwarded_host', domain)}; % for option, value in options.get('proxy_set_header', {}).items(): proxy_set_header ${option} ${value}; % endfor -% if location != '/' and location != '= /': +% if location != '/': proxy_set_header X-Script-Name ${location}; % endif proxy_buffering off; @@ -191,18 +144,9 @@ server { % endfor % endif % if php: - location ~ \.php(?:$|/) { + location ~ \.php$ { include fastcgi.conf; fastcgi_pass unix:/run/php/php${php_version}-fpm.sock; -% if not do_not_set_content_security_headers: - fastcgi_hide_header Referrer-Policy; - fastcgi_hide_header X-Frame-Options; - fastcgi_hide_header X-Content-Type-Options; - fastcgi_hide_header X-XSS-Protection; -% endif - fastcgi_hide_header Permissions-Policy; - fastcgi_request_buffering off; - proxy_buffering off; } % if not max_body_size: client_max_body_size 5M; diff --git a/bundles/nginx/items.py b/bundles/nginx/items.py index 304dcd7..88852e0 100644 --- a/bundles/nginx/items.py +++ b/bundles/nginx/items.py @@ -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': {}, @@ -27,12 +34,12 @@ directories = { files = { '/etc/logrotate.d/nginx': { - 'content_type': 'mako', 'source': 'logrotate.conf', }, '/etc/nginx/nginx.conf': { 'content_type': 'mako', 'context': { + 'username': username, **node.metadata['nginx'], }, 'triggers': { @@ -61,13 +68,28 @@ 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', + }, + } + +actions = { + 'nginx-generate-dhparam': { + 'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048', + 'unless': 'test -f /etc/ssl/certs/dhparam.pem', + }, +} svc_systemd = { 'nginx': { 'needs': { - 'action:generate-dhparam', + 'action:nginx-generate-dhparam', 'directory:/var/log/nginx-timing', - 'pkg_apt:nginx', + package, }, }, } @@ -102,9 +124,8 @@ for vhost, config in node.metadata.get('nginx/vhosts', {}).items(): 'source': 'site_template', 'content_type': 'mako', 'context': { - 'create_logs': config.get('create_logs', False), - 'create_timing_log': config.get('timing_log', True), - 'php_version': node.metadata.get('php/__version', ''), + 'create_access_log': config.get('access_log', node.metadata.get('nginx/access_log', False)), + 'php_version': node.metadata.get('php/version', ''), 'security_txt': security_txt_enabled, 'vhost': vhost, **config, diff --git a/bundles/nginx/metadata.py b/bundles/nginx/metadata.py index 28395ff..ba2d18a 100644 --- a/bundles/nginx/metadata.py +++ b/bundles/nginx/metadata.py @@ -33,6 +33,11 @@ defaults = { 'nginx': { 'worker_connections': 768, }, + 'pacman': { + 'packages': { + 'nginx': {}, + }, + }, } if node.has_bundle('telegraf'): @@ -76,7 +81,6 @@ def letsencrypt(metadata): domains[domain] = config.get('domain_aliases', set()) vhosts[vhost] = { 'ssl': 'letsencrypt', - 'force_domain': True, } return { @@ -99,9 +103,6 @@ def index_files(metadata): vhosts = {} for vhost, config in metadata.get('nginx/vhosts', {}).items(): - if 'index' in config: - continue - vhosts[vhost] = { 'index': [ 'index.html', @@ -168,15 +169,15 @@ def monitoring(metadata): @metadata_reactor.provides( - 'firewall/port_rules', - 'firewall/port_rules', + 'firewall/port_rules/80', + 'firewall/port_rules/443', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '80/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), - '443/tcp': atomic(metadata.get('nginx/restrict-to', {'*'})), + '80': atomic(metadata.get('nginx/restrict-to', {'*'})), + '443': atomic(metadata.get('nginx/restrict-to', {'*'})), }, }, } @@ -188,15 +189,12 @@ def firewall(metadata): def telegraf_anon_timing(metadata): result = {} - for vname, vconfig in metadata.get('nginx/vhosts', {}).items(): - if not vconfig.get('timing_log', True): - continue - - result[f'nginx-{vname}'] = { - 'files': [f'/var/log/nginx-timing/{vname}.log'], + for vhost in metadata.get('nginx/vhosts', {}): + result[f'nginx-{vhost}'] = { + 'files': [f'/var/log/nginx-timing/{vhost}.log'], 'from_beginning': False, - 'grok_patterns': [r'%{LOGPATTERN}'], - 'grok_custom_patterns': r'LOGPATTERN \[%{HTTPDATE:ts:ts-httpd}\] %{NUMBER:request_time:float} (?:%{NUMBER:upstream_response_time:float}|-) "%{WORD:verb:tag} %{NOTSPACE:request} HTTP/%{NUMBER:http_version:float}" %{NUMBER:resp_code:tag}', + 'grok_patterns': ['%{LOGPATTERN}'], + 'grok_custom_patterns': 'LOGPATTERN \[%{HTTPDATE:ts:ts-httpd}\] %{NUMBER:request_time:float} (?:%{NUMBER:upstream_response_time:float}|-) "%{WORD:verb:tag} %{NOTSPACE:request} HTTP/%{NUMBER:http_version:float}" %{NUMBER:resp_code:tag}', 'data_format': 'grok', 'name_override': 'nginx_timing', } diff --git a/bundles/nodejs/items.py b/bundles/nodejs/items.py index e69de29..dc8607c 100644 --- a/bundles/nodejs/items.py +++ b/bundles/nodejs/items.py @@ -0,0 +1,9 @@ +actions = { + 'nodejs_install_yarn': { + 'command': 'npm install -g yarn@latest', + 'unless': 'test -e /usr/lib/node_modules/yarn', + 'needs': { + 'pkg_apt:nodejs', + }, + }, +} diff --git a/bundles/nodejs/metadata.py b/bundles/nodejs/metadata.py index 5c0f7ad..18f0de6 100644 --- a/bundles/nodejs/metadata.py +++ b/bundles/nodejs/metadata.py @@ -1,24 +1,17 @@ defaults = { 'apt': { 'additional_update_commands': { - # update npm and yarn to latest version + # update npm to latest version 'npm install -g npm@latest', 'npm install -g yarn@latest', }, 'packages': { - 'nodejs': { - 'triggers': { - 'action:apt_execute_update_commands', - }, - }, - 'npm': { - 'installed': False, - 'triggers': { - 'action:apt_execute_update_commands', - }, - }, + 'nodejs': {}, }, }, + 'nodejs': { + 'version': 18, + }, } @metadata_reactor.provides( @@ -26,13 +19,13 @@ defaults = { ) def nodejs_from_version(metadata): version = metadata.get('nodejs/version') - return { 'apt': { 'repos': { 'nodejs': { 'items': { - f'deb https://deb.nodesource.com/node_{version}.x nodistro main', + f'deb https://deb.nodesource.com/node_{version}.x {{os_release}} main', + f'deb-src https://deb.nodesource.com/node_{version}.x {{os_release}} main', }, }, }, diff --git a/bundles/ntfy/files/server.yml b/bundles/ntfy/files/server.yml index babb90b..8add6f3 100644 --- a/bundles/ntfy/files/server.yml +++ b/bundles/ntfy/files/server.yml @@ -11,7 +11,7 @@ # - iOS push notifications for self-hosted servers (to calculate the Firebase poll_request topic) # - Matrix Push Gateway (to validate that the pushkey is correct) # -base-url: "https://${node.metadata.get('ntfy/domain')}" +base-url: "https://${node.metadata.get('ntfy/domain', 'ntfy')}" # Listen address for the HTTP & HTTPS web server. If "listen-https" is set, you must also # set "key-file" and "cert-file". Format: []:, e.g. "1.2.3.4:8080". @@ -85,11 +85,7 @@ cache-startup-queries: | # ntfy user and group by running: chown ntfy.ntfy . # auth-file: "/var/lib/ntfy/user.db" -% if node.metadata.get('ntfy/allow_unauthorized_write'): auth-default-access: "write-only" -% else: -auth-default-access: "deny-all" -% endif # If set, the X-Forwarded-For header is used to determine the visitor IP address # instead of the remote address of the connection. @@ -97,7 +93,7 @@ auth-default-access: "deny-all" # WARNING: If you are behind a proxy, you must set this, otherwise all visitors are rate limited # as if they are one. # -behind-proxy: true +# behind-proxy: false # If enabled, clients can attach files to notifications as attachments. Minimum settings to enable attachments # are "attachment-cache-dir" and "base-url". @@ -157,17 +153,6 @@ manager-interval: "1m" # # web-root: app -# Various feature flags used to control the web app, and API access, mainly around user and -# account management. -# -# - enable-signup allows users to sign up via the web app, or API -# - enable-login allows users to log in via the web app, or API -# - enable-reservations allows users to reserve topics (if their tier allows it) -# -enable-signup: false -enable-login: true -enable-reservations: false - # Server URL of a Firebase/APNS-connected ntfy server (likely "https://ntfy.sh"). # # iOS users: @@ -196,7 +181,7 @@ visitor-subscription-limit: 64 # visitor-request-limit-burst: 60 visitor-request-limit-replenish: "5s" -visitor-request-limit-exempt-hosts: "${','.join(sorted(ratelimit_exempt_hosts))}" +visitor-request-limit-exempt-hosts: "localhost" # Rate limiting: Allowed emails per visitor: # - visitor-email-limit-burst is the initial bucket of emails each visitor has @@ -205,54 +190,12 @@ visitor-request-limit-exempt-hosts: "${','.join(sorted(ratelimit_exempt_hosts))} # visitor-email-limit-burst: 16 # visitor-email-limit-replenish: "1h" -# Rate limiting: Enable subscriber-based rate limiting (mostly used for UnifiedPush) +# Rate limiting: Attachment size and bandwidth limits per visitor: +# - visitor-attachment-total-size-limit is the total storage limit used for attachments per visitor +# - visitor-attachment-daily-bandwidth-limit is the total daily attachment download/upload traffic limit per visitor # -# If enabled, subscribers may opt to have published messages counted against their own rate limits, as opposed -# to the publisher's rate limits. This is especially useful to increase the amount of messages that high-volume -# publishers (e.g. Matrix/Mastodon servers) are allowed to send. -# -# Once enabled, a client may send a "Rate-Topics: ,,..." header when subscribing to topics via -# HTTP stream, or websockets, thereby registering itself as the "rate visitor", i.e. the visitor whose rate limits -# to use when publishing on this topic. Note: Setting the rate visitor requires READ-WRITE permission on the topic. -# -# UnifiedPush only: If this setting is enabled, publishing to UnifiedPush topics will lead to a HTTP 507 response if -# no "rate visitor" has been previously registered. This is to avoid burning the publisher's "visitor-message-daily-limit". -# -# visitor-subscriber-rate-limiting: false - -# Payments integration via Stripe -# -# - stripe-secret-key is the key used for the Stripe API communication. Setting this values -# enables payments in the ntfy web app (e.g. Upgrade dialog). See https://dashboard.stripe.com/apikeys. -# - stripe-webhook-key is the key required to validate the authenticity of incoming webhooks from Stripe. -# Webhooks are essential up keep the local database in sync with the payment provider. See https://dashboard.stripe.com/webhooks. -# - billing-contact is an email address or website displayed in the "Upgrade tier" dialog to let people reach -# out with billing questions. If unset, nothing will be displayed. -# -# stripe-secret-key: -# stripe-webhook-key: -# billing-contact: - -# Metrics -# -# ntfy can expose Prometheus-style metrics via a /metrics endpoint, or on a dedicated listen IP/port. -# Metrics may be considered sensitive information, so before you enable them, be sure you know what you are -# doing, and/or secure access to the endpoint in your reverse proxy. -# -# - enable-metrics enables the /metrics endpoint for the default ntfy server (i.e. HTTP, HTTPS and/or Unix socket) -# - metrics-listen-http exposes the metrics endpoint via a dedicated [IP]:port. If set, this option implicitly -# enables metrics as well, e.g. "10.0.1.1:9090" or ":9090" -# -# enable-metrics: false -# metrics-listen-http: - -# Profiling -# -# ntfy can expose Go's net/http/pprof endpoints to support profiling of the ntfy server. If enabled, ntfy will listen -# on a dedicated listen IP/port, which can be accessed via the web browser on http://:/debug/pprof/. -# This can be helpful to expose bottlenecks, and visualize call flows. See https://pkg.go.dev/net/http/pprof for details. -# -# profile-listen-http: +# visitor-attachment-total-size-limit: "100M" +# visitor-attachment-daily-bandwidth-limit: "500M" # Log level, can be TRACE, DEBUG, INFO, WARN or ERROR # This option can be hot-reloaded by calling "kill -HUP $pid" or "systemctl reload ntfy". diff --git a/bundles/ntfy/items.py b/bundles/ntfy/items.py index cb3c50b..d9a93bb 100644 --- a/bundles/ntfy/items.py +++ b/bundles/ntfy/items.py @@ -1,57 +1,43 @@ -ratelimit_exempt_hosts = set() -for identifier in node.metadata.get('ntfy/ratelimit-exempt-hosts', set()): - ips = repo.libs.tools.resolve_identifier(repo, identifier) - ratelimit_exempt_hosts |= {str(ip) for ip in ips['ipv4']} - ratelimit_exempt_hosts |= {str(ip) for ip in ips['ipv6']} - - -files['/etc/ntfy/server.yml'] = { - 'content_type': 'mako', - 'context': { - 'ratelimit_exempt_hosts': ratelimit_exempt_hosts, - }, - 'after': { - 'pkg_apt:ntfy', - }, - 'triggers': { - 'svc_systemd:ntfy:restart', +files = { + '/etc/ntfy/server.yml': { + 'content_type': 'mako', + 'needs': { + 'pkg_apt:ntfy', + }, + 'triggers': { + 'svc_systemd:ntfy:restart', + }, }, } -directories['/var/lib/ntfy'] = { - 'owner': 'ntfy', - 'group': 'ntfy', - 'mode': '0700', - 'before': { - 'pkg_apt:ntfy', +directories = { + '/opt/ntfy': {}, + '/var/lib/ntfy': { + 'owner': 'ntfy', + 'group': 'ntfy', + }, + '/var/cache/ntfy': { + 'owner': 'ntfy', + 'group': 'ntfy', + }, + '/var/opt/ntfy': { + 'owner': 'ntfy', + 'group': 'ntfy', }, } -directories['/var/cache/ntfy'] = { - 'owner': 'ntfy', - 'group': 'ntfy', - 'mode': '0700', - 'before': { - 'pkg_apt:ntfy', +svc_systemd = { + 'ntfy': { + 'needs': { + 'file:/etc/ntfy/server.yml', + 'pkg_apt:ntfy', + }, }, } -directories['/var/opt/ntfy'] = { - 'owner': 'ntfy', - 'group': 'ntfy', - 'before': { - 'pkg_apt:ntfy', +users = { + 'ntfy': { + 'home': '/opt/ntfy', }, } - -svc_systemd['ntfy'] = { - 'needs': { - 'file:/etc/ntfy/server.yml', - 'pkg_apt:ntfy', - }, -} - -users['ntfy'] = { - 'home': '/var/lib/ntfy', -} diff --git a/bundles/ntfy/metadata.py b/bundles/ntfy/metadata.py index 5b6f81d..a49ae55 100644 --- a/bundles/ntfy/metadata.py +++ b/bundles/ntfy/metadata.py @@ -19,9 +19,6 @@ defaults = { "/var/opt/ntfy", }, }, - 'ntfy': { - 'allow_unauthorized_write': False, - }, 'zfs': { 'datasets': { 'tank/ntfy': {}, @@ -76,10 +73,6 @@ def nginx(metadata): 'ntfy': { 'domain': metadata.get('ntfy/domain'), 'locations': locations, - # This only does websockets connections, which stay - # open for a very long time. This only generates - # useless metrics. - 'timing_log': False, 'website_check_path': '/', 'website_check_string': 'ntfy', }, diff --git a/bundles/oidentd/files/oidentd.service b/bundles/oidentd/files/oidentd.service index 64ac97f..06b9a6d 100644 --- a/bundles/oidentd/files/oidentd.service +++ b/bundles/oidentd/files/oidentd.service @@ -1,7 +1,6 @@ [Unit] Description=RFC 1413 compliant ident daemon -Requires=network.target -After=network-online.target +After=network.target [Service] ExecStart=/usr/sbin/oidentd -i -u oident -g oident diff --git a/bundles/oidentd/items.py b/bundles/oidentd/items.py index fae03b3..723f9fe 100644 --- a/bundles/oidentd/items.py +++ b/bundles/oidentd/items.py @@ -1,26 +1,24 @@ -files['/etc/oidentd.conf'] = { - 'content_type': 'mako', - 'triggers': { - 'svc_systemd:oidentd:restart', +files = { + '/etc/oidentd.conf': { + 'content_type': 'mako', + 'triggers': { + 'svc_systemd:oidentd:restart', + }, + }, + '/usr/local/lib/systemd/system/oidentd.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:oidentd:restart', + }, }, } -files['/usr/local/lib/systemd/system/oidentd.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:oidentd:restart', +svc_systemd = { + 'oidentd': { + 'needs': { + 'pkg_apt:oidentd', + 'file:/etc/oidentd.conf', + 'file:/usr/local/lib/systemd/system/oidentd.service', + }, }, } - -svc_systemd['oidentd'] = { - 'needs': { - 'pkg_apt:oidentd', - 'file:/etc/oidentd.conf', - 'file:/usr/local/lib/systemd/system/oidentd.service', - }, -} - -svc_systemd['oidentd.socket'] = { - 'running': False, - 'enabled': False, -} diff --git a/bundles/oidentd/metadata.py b/bundles/oidentd/metadata.py index dbc27a1..f9d4390 100644 --- a/bundles/oidentd/metadata.py +++ b/bundles/oidentd/metadata.py @@ -10,13 +10,13 @@ defaults = { @metadata_reactor.provides( - 'firewall/port_rules', + 'firewall/port_rules/113', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '113/tcp': atomic(metadata.get('oidentd/restrict-to', {'*'})), + '113': atomic(metadata.get('oidentd/restrict-to', {'*'})), }, }, } diff --git a/bundles/openssh/items.py b/bundles/openssh/items.py index 0b9fa04..a93b873 100644 --- a/bundles/openssh/items.py +++ b/bundles/openssh/items.py @@ -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, }, }, } diff --git a/bundles/openssh/metadata.py b/bundles/openssh/metadata.py index 4db6d78..3cad1b9 100644 --- a/bundles/openssh/metadata.py +++ b/bundles/openssh/metadata.py @@ -8,16 +8,21 @@ defaults = { 'openssh-sftp-server': {}, }, }, + 'pacman': { + 'packages': { + 'openssh': {}, + }, + }, } @metadata_reactor.provides( - 'firewall/port_rules', + 'firewall/port_rules/22', ) def firewall(metadata): return { 'firewall': { 'port_rules': { - '22/tcp': atomic(metadata.get('openssh/restrict-to', {'*'})), + '22': atomic(metadata.get('openssh/restrict-to', {'*'})), }, }, } diff --git a/bundles/openvpn-client/items.py b/bundles/openvpn-client/items.py new file mode 100644 index 0000000..7d35517 --- /dev/null +++ b/bundles/openvpn-client/items.py @@ -0,0 +1,25 @@ +from os.path import join + +directories = { + '/etc/openvpn/client': { + 'mode': '0750', + 'owner': 'openvpn', + 'group': None, + 'purge': True, + }, +} + +for fname, config in node.metadata.get('openvpn-client/configs', {}).items(): + files[f'/etc/openvpn/client/{fname}.conf'] = { + 'content': repo.vault.decrypt_file(join('openvpn-client', f'{fname}.conf.vault')), + 'triggers': { + f'svc_systemd:openvpn-client@{config}:restart', + } if config.get('running', True) else set(), + } + + svc_systemd[f'openvpn-client@{fname}'] = { + 'needs': { + f'file:/etc/openvpn/client/{fname}.conf', + }, + **config, + } diff --git a/bundles/openvpn-client/metadata.py b/bundles/openvpn-client/metadata.py new file mode 100644 index 0000000..9c5b722 --- /dev/null +++ b/bundles/openvpn-client/metadata.py @@ -0,0 +1,20 @@ +defaults = { + 'apt': { + 'packages': { + 'openvpn': { + 'needed_by': { + 'directory:/etc/openvpn/client', + }, + }, + }, + }, + 'pacman': { + 'packages': { + 'openvpn': { + 'needed_by': { + 'directory:/etc/openvpn/client', + }, + }, + }, + }, +} diff --git a/bundles/pacman/files/check_unattended_upgrades b/bundles/pacman/files/check_unattended_upgrades new file mode 100644 index 0000000..1cafab5 --- /dev/null +++ b/bundles/pacman/files/check_unattended_upgrades @@ -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 diff --git a/bundles/pacman/files/do-unattended-upgrades b/bundles/pacman/files/do-unattended-upgrades new file mode 100644 index 0000000..a04b5fc --- /dev/null +++ b/bundles/pacman/files/do-unattended-upgrades @@ -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 diff --git a/bundles/pacman/files/faillock.conf b/bundles/pacman/files/faillock.conf new file mode 100644 index 0000000..19c0ff3 --- /dev/null +++ b/bundles/pacman/files/faillock.conf @@ -0,0 +1,2 @@ +# just disable faillock. +deny = 0 diff --git a/bundles/pacman/files/pacman.conf b/bundles/pacman/files/pacman.conf new file mode 100644 index 0000000..834108e --- /dev/null +++ b/bundles/pacman/files/pacman.conf @@ -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 diff --git a/bundles/pacman/files/upgrade-and-reboot b/bundles/pacman/files/upgrade-and-reboot new file mode 100644 index 0000000..8f1e9c1 --- /dev/null +++ b/bundles/pacman/files/upgrade-and-reboot @@ -0,0 +1,53 @@ +#!/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 + +if [[ -n "$reboot_mail_to" ]] +then + date | mail -s "SYSREBOOTNOW $nodename" "$reboot_mail_to" +fi +systemctl reboot + +echo "upgrade-and-reboot for node $nodename is DONE" diff --git a/bundles/pacman/files/upgrade-and-reboot.conf b/bundles/pacman/files/upgrade-and-reboot.conf new file mode 100644 index 0000000..ca71dce --- /dev/null +++ b/bundles/pacman/files/upgrade-and-reboot.conf @@ -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)}" diff --git a/bundles/pacman/items.py b/bundles/pacman/items.py new file mode 100644 index 0000000..4d95a99 --- /dev/null +++ b/bundles/pacman/items.py @@ -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': {}, + 'binutils': {}, + 'bison': {}, + 'bzip2': {}, + 'curl': {}, + 'dialog': {}, + 'diffutils': {}, + 'dnsutils': {}, + '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 diff --git a/bundles/pacman/metadata.py b/bundles/pacman/metadata.py new file mode 100644 index 0000000..fb69a04 --- /dev/null +++ b/bundles/pacman/metadata.py @@ -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', + }, + }, + }, + }, + } diff --git a/bundles/paperless-ng/files/paperless-consumer.service b/bundles/paperless-ng/files/paperless-consumer.service index 5f43db2..60a95f9 100644 --- a/bundles/paperless-ng/files/paperless-consumer.service +++ b/bundles/paperless-ng/files/paperless-consumer.service @@ -5,12 +5,8 @@ Requires=redis.service [Service] User=paperless Group=paperless -Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf -WorkingDirectory=/opt/paperless/src/paperless-ngx/src +WorkingDirectory=/opt/paperless/src/src ExecStart=/opt/paperless/venv/bin/python manage.py document_consumer -Restart=always -RestartSec=10 -SyslogIdentifier=paperless-consumer [Install] WantedBy=multi-user.target diff --git a/bundles/paperless-ng/files/paperless-scheduler.service b/bundles/paperless-ng/files/paperless-scheduler.service index 5ed83f0..54cfeae 100644 --- a/bundles/paperless-ng/files/paperless-scheduler.service +++ b/bundles/paperless-ng/files/paperless-scheduler.service @@ -5,12 +5,8 @@ Requires=redis.service [Service] User=paperless Group=paperless -Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf -WorkingDirectory=/opt/paperless/src/paperless-ngx/src -ExecStart=/opt/paperless/venv/bin/celery --app paperless beat --loglevel INFO -Restart=always -RestartSec=10 -SyslogIdentifier=paperless-scheduler +WorkingDirectory=/opt/paperless/src/src +ExecStart=/opt/paperless/venv/bin/python manage.py qcluster [Install] WantedBy=multi-user.target diff --git a/bundles/paperless-ng/files/paperless-taskqueue.service b/bundles/paperless-ng/files/paperless-taskqueue.service deleted file mode 100644 index d7be698..0000000 --- a/bundles/paperless-ng/files/paperless-taskqueue.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Paperless task queue -Requires=redis.service - -[Service] -User=paperless -Group=paperless -Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf -WorkingDirectory=/opt/paperless/src/paperless-ngx/src -ExecStart=/opt/paperless/venv/bin/celery --app paperless worker --loglevel INFO -Restart=always -RestartSec=10 -SyslogIdentifier=paperless-taskqueue - -[Install] -WantedBy=multi-user.target diff --git a/bundles/paperless-ng/files/paperless-webserver.service b/bundles/paperless-ng/files/paperless-webserver.service index 7c41aa7..9bcd926 100644 --- a/bundles/paperless-ng/files/paperless-webserver.service +++ b/bundles/paperless-ng/files/paperless-webserver.service @@ -7,15 +7,8 @@ Requires=redis.service [Service] User=paperless Group=paperless -Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf -Environment=GRANIAN_PORT=22070 -Environment=GRANIAN_WORKERS=4 -Environment=GRANIAN_HOST=::1 -WorkingDirectory=/opt/paperless/src/paperless-ngx/src -ExecStart=/opt/paperless/venv/bin/granian --interface asginl --ws "paperless.asgi:application" -Restart=always -RestartSec=10 -SyslogIdentifier=paperless-webserver +WorkingDirectory=/opt/paperless/src/src +ExecStart=/opt/paperless/venv/bin/gunicorn -c /opt/paperless/src/gunicorn.conf.py -b 127.0.0.1:22070 paperless.asgi:application [Install] WantedBy=multi-user.target diff --git a/bundles/paperless-ng/files/paperless.conf b/bundles/paperless-ng/files/paperless.conf index 84f1b65..7972eef 100644 --- a/bundles/paperless-ng/files/paperless.conf +++ b/bundles/paperless-ng/files/paperless.conf @@ -11,15 +11,14 @@ PAPERLESS_DBSSLMODE=disable PAPERLESS_CONSUMPTION_DIR=/mnt/paperless/consume PAPERLESS_DATA_DIR=/mnt/paperless/data PAPERLESS_MEDIA_ROOT=/mnt/paperless/media -PAPERLESS_STATICDIR=/opt/paperless/src/paperless-ngx/static -PAPERLESS_FILENAME_FORMAT={{ created_year }}/{{ created_month }}/{{ correspondent }}/{{ asn }}_{{ title }} +PAPERLESS_STATICDIR=/opt/paperless/static +PAPERLESS_FILENAME_FORMAT={created_year}/{created_month}/{correspondent}/{asn}_{title} # Security and hosting PAPERLESS_SECRET_KEY=${repo.vault.random_bytes_as_base64_for(f'{node.name} paperless secret key')} -PAPERLESS_CSRF_TRUSTED_ORIGINS=https://${node.metadata.get('paperless/domain')} -PAPERLESS_ALLOWED_HOSTS=${node.metadata.get('paperless/domain')} -PAPERLESS_CORS_ALLOWED_HOSTS=http://${node.metadata.get('paperless/domain')},https://${node.metadata.get('paperless/domain')} +PAPERLESS_ALLOWED_HOSTS=${node.metadata.get('nginx/vhosts/paperless/domain', '127.0.0.1')} +PAPERLESS_CORS_ALLOWED_HOSTS=http://${node.metadata.get('nginx/vhosts/paperless/domain', '127.0.0.1')},https://${node.metadata.get('nginx/vhosts/paperless/domain', '127.0.0.1')} #PAPERLESS_FORCE_SCRIPT_NAME= #PAPERLESS_STATIC_URL=/static/ #PAPERLESS_AUTO_LOGIN_USERNAME= @@ -29,10 +28,7 @@ PAPERLESS_CORS_ALLOWED_HOSTS=http://${node.metadata.get('paperless/domain')},htt # OCR settings PAPERLESS_OCR_LANGUAGE=${'+'.join(sorted(node.metadata.get('paperless/ocr_languages', {'deu', 'eng'})))} -PAPERLESS_OCR_MODE=skip -PAPERLESS_OCR_SKIP_ARCHIVE_FILE=never -PAPERLESS_OCR_USER_ARGS='{"invalidate_digital_signatures": true}' -PAPERLESS_PRE_CONSUME_SCRIPT=/opt/paperless/pre-consume.sh +PAPERLESS_OCR_MODE=skip_noarchive #PAPERLESS_OCR_OUTPUT_TYPE=pdfa #PAPERLESS_OCR_PAGES=1 #PAPERLESS_OCR_IMAGE_DPI=300 diff --git a/bundles/paperless-ng/files/pre-consume.sh b/bundles/paperless-ng/files/pre-consume.sh deleted file mode 100644 index e7937ba..0000000 --- a/bundles/paperless-ng/files/pre-consume.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -[[ -n "$DEBUG" ]] && set -x -set -euo pipefail - -pdfinfo "${DOCUMENT_WORKING_PATH}" | grep -q "Encrypted:" - -if pdfinfo "${DOCUMENT_WORKING_PATH}" | grep -q "Encrypted: yes" -then - qpdf --replace-input --decrypt "${DOCUMENT_WORKING_PATH}" -fi diff --git a/bundles/paperless-ng/items.py b/bundles/paperless-ng/items.py index 6b80397..84e9e43 100644 --- a/bundles/paperless-ng/items.py +++ b/bundles/paperless-ng/items.py @@ -1,97 +1,146 @@ -version = node.metadata.get('paperless/version') -workers = ('consumer', 'scheduler', 'taskqueue', 'webserver') - -users['paperless'] = { - 'home': '/opt/paperless', -} - -directories['/opt/paperless'] = {} - -files['/opt/paperless/paperless.conf'] = { - 'content_type': 'mako', - 'triggers': { - f'svc_systemd:paperless-{worker}:restart' - for worker in workers +users = { + 'paperless': { + 'home': '/opt/paperless', }, } -files['/opt/paperless/pre-consume.sh'] = { - 'mode': '0755', -} - -actions['paperless_create_virtualenv'] = { - 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/paperless/venv/', - 'unless': 'test -d /opt/paperless/venv/', - 'needs': { - 'directory:/opt/paperless', - 'pkg_apt:python3', - 'pkg_apt:python3-pip', - 'pkg_apt:python3-virtualenv', +directories = { + '/opt/paperless/src': {}, + '/opt/paperless/static': { + 'owner': 'paperless', }, } -actions['paperless_install'] = { - 'command': ' && '.join([ - f'wget -qO /opt/paperless/{version}.tar.xz https://github.com/paperless-ngx/paperless-ngx/releases/download/{version}/paperless-ngx-{version}.tar.xz', - 'rm -rf /opt/paperless/src/', - 'mkdir -p /opt/paperless/src/', - f'tar -C /opt/paperless/src -xf /opt/paperless/{version}.tar.xz', - f'rm /opt/paperless/{version}.tar.xz', - 'cd /opt/paperless/src/paperless-ngx', - '/opt/paperless/venv/bin/pip install --upgrade pip', - '/opt/paperless/venv/bin/pip install --upgrade -r requirements.txt', - f'echo "{version}" > /opt/paperless/version', - ]), - 'unless': f'''bash -c '[[ "$(cat /opt/paperless/version)" == "{version}" ]]' ''', - 'after': { - 'pkg_apt:', - }, - 'needs': { - 'action:paperless_create_virtualenv', - }, - 'triggers': { - 'action:paperless_migrate_database', - *{ - f'svc_systemd:paperless-{worker}:restart' for worker in workers - } - }, -} - -actions['paperless_migrate_database'] = { - 'command': ' && '.join([ - 'cd /opt/paperless/src/paperless-ngx/src', - 'sudo -Hu paperless PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf /opt/paperless/venv/bin/python manage.py migrate', - ]), - 'triggered': True, - 'needs': { - # /mnt/paperless is NOT created by this bundle. - 'action:paperless_install', - 'directory:/mnt/paperless', - 'file:/opt/paperless/paperless.conf', - 'user:paperless', - 'postgres_db:paperless', - }, -} - -for worker in workers: - files[f'/etc/systemd/system/paperless-{worker}.service'] = { - 'delete': True, +git_deploy = { + '/opt/paperless/src': { + 'repo': 'https://github.com/jonaswinkler/paperless-ng.git', + 'rev': node.metadata.get('paperless/version'), 'triggers': { - 'action:systemd-reload', - }, - } - - files[f'/usr/local/lib/systemd/system/paperless-{worker}.service'] = { - 'triggers': { - 'action:systemd-reload', - f'svc_systemd:paperless-{worker}:restart', - }, - } - - svc_systemd[f'paperless-{worker}'] = { - 'needs': { - 'action:paperless_install', + 'action:paperless_collectstatic', + 'action:paperless_compile_frontend', + 'action:paperless_install_deps', 'action:paperless_migrate_database', - f'file:/usr/local/lib/systemd/system/paperless-{worker}.service', + 'svc_systemd:paperless-consumer:restart', + 'svc_systemd:paperless-scheduler:restart', + 'svc_systemd:paperless-webserver:restart', }, - } + }, +} + +files = { + '/etc/systemd/system/paperless-consumer.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:paperless-consumer:restart', + }, + }, + '/etc/systemd/system/paperless-scheduler.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:paperless-scheduler:restart', + }, + }, + '/etc/systemd/system/paperless-webserver.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:paperless-webserver:restart', + }, + }, + '/opt/paperless/src/paperless.conf': { + 'content_type': 'mako', + 'needs': { + 'git_deploy:/opt/paperless/src', + }, + 'triggers': { + 'svc_systemd:paperless-consumer:restart', + 'svc_systemd:paperless-scheduler:restart', + 'svc_systemd:paperless-webserver:restart', + }, + }, +} + +actions = { + 'paperless_create_virtualenv': { + 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/paperless/venv/', + 'unless': 'test -d /opt/paperless/venv/', + 'needs': { + # actually /opt/paperless, but we don't create that + 'directory:/opt/paperless/src', + 'pkg_apt:python3', + 'pkg_apt:python3-pip', + 'pkg_apt:python3-virtualenv', + }, + }, + 'paperless_install_deps': { + 'command': + 'cd /opt/paperless/src && ' + '/opt/paperless/venv/bin/pip install --upgrade pip && ' + '/opt/paperless/venv/bin/pip install --upgrade -r requirements.txt', + 'triggered': True, + 'needs': { + 'action:paperless_create_virtualenv', + }, + }, + 'paperless_migrate_database': { + 'command': + 'cd /opt/paperless/src/src && ' + 'sudo -Hu paperless /opt/paperless/venv/bin/python manage.py migrate', + 'triggered': True, + 'needs': { + # /mnt/paperless is NOT created by this bundle. + 'action:paperless_install_deps', + 'directory:/mnt/paperless', + 'directory:/opt/paperless/static', + 'file:/opt/paperless/src/paperless.conf', + 'user:paperless', + 'postgres_db:paperless', + }, + }, + 'paperless_compile_frontend': { + 'command': + 'cd /opt/paperless/src/src-ui && ' + 'npm install && ' + 'node_modules/.bin/ng build --prod', + 'triggered': True, + 'needs': { + 'file:/opt/paperless/src/paperless.conf', + 'pkg_apt:nodejs', + }, + }, + 'paperless_collectstatic': { + 'command': + 'cd /opt/paperless/src/src && ' + 'sudo -Hu paperless /opt/paperless/venv/bin/python manage.py collectstatic', + 'triggered': True, + 'needs': { + 'directory:/opt/paperless/static', + 'file:/opt/paperless/src/paperless.conf', + 'action:paperless_create_virtualenv', + }, + }, +} + +svc_systemd = { + 'paperless-consumer': { + 'needs': { + 'action:paperless_migrate_database', + 'file:/etc/systemd/system/paperless-consumer.service', + 'git_deploy:/opt/paperless/src', + }, + }, + 'paperless-scheduler': { + 'needs': { + 'action:paperless_migrate_database', + 'file:/etc/systemd/system/paperless-scheduler.service', + 'git_deploy:/opt/paperless/src', + }, + }, + 'paperless-webserver': { + 'needs': { + 'action:paperless_compile_frontend', + 'action:paperless_migrate_database', + 'file:/etc/systemd/system/paperless-webserver.service', + 'git_deploy:/opt/paperless/src', + }, + }, +} diff --git a/bundles/paperless-ng/metadata.py b/bundles/paperless-ng/metadata.py index 8db5342..1424e08 100644 --- a/bundles/paperless-ng/metadata.py +++ b/bundles/paperless-ng/metadata.py @@ -6,12 +6,9 @@ defaults = { 'gnupg': {}, 'imagemagick': {}, 'libmagic-dev': {}, - 'default-libmysqlclient-dev': {}, 'libpq-dev': {}, - 'mariadb-client': {}, 'mime-support': {}, 'optipng': {}, - 'poppler-utils': {}, 'python3-wheel': {}, # for OCRmyPDF @@ -22,8 +19,6 @@ defaults = { 'pngquant': {}, 'qpdf': {}, 'tesseract-ocr': {}, - 'tesseract-ocr-deu': {}, - 'tesseract-ocr-eng': {}, 'unpaper': {}, 'zlib1g': {}, }, @@ -33,9 +28,6 @@ defaults = { '/mnt/paperless', }, }, - 'nodejs': { - 'version': 22, - }, 'postgresql': { 'roles': { 'paperless': { @@ -64,55 +56,3 @@ def paperless_tesseract_languages(metadata): 'packages': packages, }, } - - -@metadata_reactor.provides( - 'icinga2_api/paperless/services', -) -def icinga_check_for_new_release(metadata): - return { - 'icinga2_api': { - 'paperless': { - 'services': { - 'PAPERLESS UPDATE': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_github_for_new_release paperless-ngx/paperless-ngx {}'.format(metadata.get('paperless/version')), - 'vars.notification.mail': True, - 'check_interval': '60m', - }, - }, - }, - }, - } - - -@metadata_reactor.provides( - 'nginx/vhosts/paperless', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'paperless': { - 'domain': metadata.get('paperless/domain'), - 'locations': { - '/': { - 'target': 'http://[::1]:22070', - 'websockets': True, - 'proxy_set_header': { - 'X-Forwarded-Host': '$server_name', - }, - }, - '/static/': { - 'alias': '/opt/paperless/src/paperless-ngx/static/', - }, - }, - 'max_body_size': '100M', - 'website_check_path': '/accounts/login/', - 'website_check_string': 'Paperless-ngx', - }, - }, - }, - } diff --git a/bundles/php/files/8.2/fpm.conf b/bundles/php/files/8.2/fpm.conf deleted file mode 100644 index f3aa189..0000000 --- a/bundles/php/files/8.2/fpm.conf +++ /dev/null @@ -1,27 +0,0 @@ -[global] -pid=/run/php/php8.0-fpm.pid -; We're using journal, put logs there -error_log=/var/log/php8.0-fpm.log -daemonize=yes - -; The one and only worker pool we have -[www] -user=www-data -group=www-data -listen=/run/php/php8.2-fpm.sock -listen.owner=www-data -listen.group=www-data -listen.mode=0600 - -; Process Manager Settings -pm=dynamic -pm.max_children=${num_cpus*4} -pm.start_servers=${num_cpus} -pm.max_spare_servers=${num_cpus*2} -pm.min_spare_servers=${num_cpus} -pm.process_idle_timeout=30s -pm.max_requests=1024 - -% if not clear_env: -clear_env=no -% endif diff --git a/bundles/php/files/8.2/php.ini b/bundles/php/files/8.2/php.ini deleted file mode 100644 index 40c16d5..0000000 --- a/bundles/php/files/8.2/php.ini +++ /dev/null @@ -1,108 +0,0 @@ -[PHP] -; Only needed for libapache2-mod-php? -engine = On -short_open_tag = Off -precision = 14 -output_buffering = 4096 -zlib.output_compression = Off -implicit_flush = Off -serialize_precision = -1 -disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals -ignore_user_abort = Off -zend.enable_gc = On -expose_php = Off - -max_execution_time = 30 -max_input_time = 60 -memory_limit = ${memory_limit}M - -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT -display_startup_errors = Off -log_errors = On -log_errors_max_len = 1024 -ignore_repeated_errors = Off -ignore_repeated_source = Off -report_memleaks = On -html_errors = On -error_log = syslog -syslog.ident = php8.2 -syslog.filter = ascii - -arg_separator.output = "&" -variables_order = "GPCS" -request_order = "GP" -register_argc_argv = Off -auto_globals_jit = On -post_max_size = ${post_max_size}M -default_mimetype = "text/html" -default_charset = "UTF-8" - -enable_dl = Off -file_uploads = On -upload_max_filesize = ${post_max_size}M -max_file_uploads = 20 - -allow_url_fopen = On -allow_url_include = Off -default_socket_timeout = 10 - -[CLI Server] -cli_server.color = On - -[mail function] -mail.add_x_header = Off - -[ODBC] -odbc.allow_persistent = On -odbc.check_persistent = On -odbc.max_persistent = -1 -odbc.max_links = -1 -odbc.defaultlrl = 4096 -odbc.defaultbinmode = 1 - -[PostgreSQL] -pgsql.allow_persistent = On -pgsql.auto_reset_persistent = Off -pgsql.max_persistent = -1 -pgsql.max_links = -1 -pgsql.ignore_notice = 0 -pgsql.log_notice = 0 - -[bcmath] -bcmath.scale = 0 - -[Session] -session.save_handler = files -session.use_strict_mode = 0 -session.use_cookies = 1 -session.use_only_cookies = 1 -session.name = PHPSESSID -session.auto_start = 0 -session.cookie_lifetime = 0 -session.cookie_path = / -session.cookie_domain = -session.cookie_httponly = -session.cookie_samesite = -session.serialize_handler = php -session.gc_probability = 1 -session.gc_divisor = 1000 -session.gc_maxlifetime = 1440 -session.referer_check = -session.cache_limiter = nocache -session.cache_expire = 180 -session.use_trans_sid = 0 -session.sid_length = 32 -session.trans_sid_tags = "a=href,area=href,frame=src,form=" -session.sid_bits_per_character = 6 - -[Assertion] -zend.assertions = -1 - -[opcache] -opcache.enable = 1 -opcache.save_comments = 1 -opcache.revalidate_freq = 60 -opcache.jit = 1255 -opcache.jit_buffer_size = 256M -opcache.memory_consumption = 256 -opcache.max_accelerated_files = 1048793 diff --git a/bundles/php/items.py b/bundles/php/items.py index c836efa..45b149a 100644 --- a/bundles/php/items.py +++ b/bundles/php/items.py @@ -1,4 +1,4 @@ -version = node.metadata.get('php/__version') +version = node.metadata.get('php/version') directories['/var/lib/php/sessions'] = { 'owner': 'www-data', @@ -29,7 +29,7 @@ files[f'/etc/php/{version}/fpm/php.ini'] = { 'content_type': 'mako', 'context': { 'num_cpus': node.metadata.get('vm/cpu'), - 'post_max_size': node.metadata.get('php/post_max_size', 10), + 'post_max_size': node.metadata.get('phppost_max_size', 10), 'memory_limit': node.metadata.get('php/memory_limit', 256), }, 'after': { diff --git a/bundles/php/metadata.py b/bundles/php/metadata.py index edb8399..d14954e 100644 --- a/bundles/php/metadata.py +++ b/bundles/php/metadata.py @@ -1,11 +1,12 @@ -OS_PHP_VERSION = { - 12: '8.2', - 13: '8.4', -} - defaults = { - 'php': { - '__version': OS_PHP_VERSION[node.os_version[0]], + 'apt': { + 'repos': { + 'php': { + 'items': { + 'deb https://packages.sury.org/php/ {os_release} main', + }, + }, + }, }, } @@ -14,7 +15,7 @@ defaults = { 'apt/packages', ) def php_packages_with_features(metadata): - version = metadata.get('php/__version') + version = metadata.get('php/version') packages = { f'php{version}': {}, diff --git a/bundles/pleroma/files/pleroma.config.exs b/bundles/pleroma/files/pleroma.config.exs new file mode 100644 index 0000000..64c2c0b --- /dev/null +++ b/bundles/pleroma/files/pleroma.config.exs @@ -0,0 +1,35 @@ +import Config + +config :pleroma, + configurable_from_database: true + +config :pleroma, Pleroma.Web.Endpoint, + url: [host: "${node.metadata['pleroma']['url']}", scheme: "https", port: 443], + http: [port: 21000, ip: {127, 0, 0, 1}], + secret_key_base: "${node.metadata['pleroma']['secret_key']}", + secure_cookie_flag: true + +config :pleroma, :instance, + static_dir: "/var/pleroma/static/" + +config :pleroma, Pleroma.Upload, + uploader: Pleroma.Uploaders.Local, + filters: [Pleroma.Upload.Filter.Dedupe] + +config :pleroma, Pleroma.Uploaders.Local, + uploads: "/var/pleroma/uploads/" + +config :pleroma, :media_proxy, + enabled: false, + redirect_on_failure: true + #base_url: "https://cache.pleroma.social" + +# Configure your database +config :pleroma, Pleroma.Repo, + adapter: Ecto.Adapters.Postgres, + username: "pleroma", + password: "${node.metadata['postgresql']['roles']['pleroma']['password']}", + database: "pleroma", + hostname: "localhost", + pool_size: 10, + timeout: 60000 diff --git a/bundles/pleroma/files/pleroma.service b/bundles/pleroma/files/pleroma.service new file mode 100644 index 0000000..085b041 --- /dev/null +++ b/bundles/pleroma/files/pleroma.service @@ -0,0 +1,22 @@ +[Unit] +Description=Pleroma social network +After=network.target +Requires=postgresql.service + +[Service] +User=pleroma +WorkingDirectory=/opt/pleroma +Environment="HOME=/opt/pleroma" +Environment="PLEROMA_CONFIG_PATH=/opt/pleroma/pleroma.config.exs" +Environment="PLUG_TMPDIR=/tmp/pleroma" +ExecStart=/opt/pleroma/release/bin/pleroma start +ExecStop=/opt/pleroma/release/bin/pleroma stop +Restart=always + +PrivateTmp=true +ProtectHome=true +ProtectSystem=full +CapabilityBoundingSet=~CAP_SYS_ADMIN + +[Install] +WantedBy=multi-user.target diff --git a/bundles/pleroma/items.py b/bundles/pleroma/items.py new file mode 100644 index 0000000..a03b973 --- /dev/null +++ b/bundles/pleroma/items.py @@ -0,0 +1,88 @@ +version = node.metadata['pleroma']['version'] + +users = { + 'pleroma': { + 'home': '/opt/pleroma', + }, +} + +directories = { + '/opt/pleroma': {}, + '/var/pleroma': { + 'owner': 'pleroma', + }, + '/var/pleroma/uploads': { + 'owner': 'pleroma', + }, + '/var/pleroma/static': { + 'owner': 'pleroma', + }, + '/var/pleroma/static/emoji': { + 'owner': 'pleroma', + }, +} + +if node.has_bundle('zfs'): + directories['/var/pleroma']['needs'] = { + 'zfs_dataset:tank/pleroma-data', + } + +actions = { + 'pleroma_download_release': { + 'command': \ + 'cd /opt/pleroma/ && '\ + f'wget -O/opt/pleroma/pleroma.zip https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/release/{version}/download?job=amd64 && '\ + 'rm -rf release && '\ + 'unzip /opt/pleroma/pleroma.zip && '\ + 'chown -R pleroma:pleroma /opt/pleroma/release && '\ + f'echo -n "{version}" > /opt/pleroma/.bundlewrap_installed_version', + 'unless': f'[ "$(cat /opt/pleroma/.bundlewrap_installed_version)" = "{version}" ]', + 'needs': { + 'directory:/opt/pleroma', + }, + 'preceded_by': { + 'svc_systemd:pleroma:stop', + }, + 'triggers': { + 'action:pleroma_migrate_database', + 'svc_systemd:pleroma:restart', + }, + }, + 'pleroma_migrate_database': { + 'triggered': True, + 'command': \ + 'echo "CREATE EXTENSION IF NOT EXISTS citext;" | psql pleroma && '\ + 'echo "CREATE EXTENSION IF NOT EXISTS pg_trgm;" | psql pleroma && '\ + 'echo "CREATE EXTENSION IF NOT EXISTS \\\"uuid-ossp\\\";" | psql pleroma && '\ + 'sudo -u pleroma PLEROMA_CONFIG_PATH=/opt/pleroma/pleroma.config.exs /opt/pleroma/release/bin/pleroma_ctl create', + 'needs': { + 'postgres_db:pleroma', + }, + }, +} + +files = { + '/etc/systemd/system/pleroma.service': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:pleroma:restart', + }, + }, + '/opt/pleroma/pleroma.config.exs': { + 'content_type': 'mako', + 'triggers': { + 'svc_systemd:pleroma:restart', + }, + }, +} + +svc_systemd = { + 'pleroma': { + 'needs': { + 'action:pleroma_download_release', + 'action:pleroma_migrate_database', + 'file:/etc/systemd/system/pleroma.service', + 'file:/opt/pleroma/pleroma.config.exs', + }, + }, +} diff --git a/bundles/pleroma/metadata.py b/bundles/pleroma/metadata.py new file mode 100644 index 0000000..44e7a3b --- /dev/null +++ b/bundles/pleroma/metadata.py @@ -0,0 +1,62 @@ +defaults = { + 'apt': { + 'packages': { + 'imagemagick': {}, + 'ffmpeg': {}, + 'libimage-exiftool-perl': {}, + }, + }, + 'backups': { + 'paths': { + '/var/pleroma', + }, + }, + 'zfs': { + 'datasets': { + 'tank/pleroma-data': { + 'mountpoint': '/var/pleroma', + 'needed_by': { + 'directory:/var/pleroma', + }, + }, + }, + }, + 'postgresql': { + 'roles': { + 'pleroma': { + 'password': repo.vault.password_for(f'{node.name} postgresql pleroma'), + }, + }, + 'databases': { + 'pleroma': { + 'owner': 'pleroma', + }, + }, + }, +} + + +@metadata_reactor.provides( + 'nginx/vhosts/pleroma', +) +def nginx(metadata): + if not node.has_bundle('nginx'): + raise DoNotRunAgain + + return { + 'nginx': { + 'vhosts': { + 'pleroma': { + 'domain': metadata.get('pleroma/url'), + 'locations': { + '/': { + 'target': 'http://127.0.0.1:21000', + 'websockets': True, + }, + }, + 'website_check_path': '/main/all', + 'website_check_string': 'use Pleroma', + }, + }, + }, + } diff --git a/bundles/postfix/files/arch-override.conf b/bundles/postfix/files/arch-override.conf new file mode 100644 index 0000000..3b3e46d --- /dev/null +++ b/bundles/postfix/files/arch-override.conf @@ -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 diff --git a/bundles/postfix/files/blocked_recipients b/bundles/postfix/files/blocked_recipients deleted file mode 100644 index 4aff372..0000000 --- a/bundles/postfix/files/blocked_recipients +++ /dev/null @@ -1,5 +0,0 @@ -devnull@${node.metadata.get('postfix/myhostname')} DISCARD DEV-NULL - -% for address in sorted(blocked): -${address} REJECT -% endfor diff --git a/bundles/postfix/files/main.cf b/bundles/postfix/files/main.cf index 9d74175..bb647fc 100644 --- a/bundles/postfix/files/main.cf +++ b/bundles/postfix/files/main.cf @@ -3,7 +3,7 @@ biff = no append_dot_mydomain = no readme_directory = no compatibility_level = 2 -myhostname = ${node.metadata.get('postfix/myhostname')} +myhostname = ${node.metadata.get('postfix/myhostname', node.metadata['hostname'])} myorigin = /etc/mailname mydestination = $myhostname, localhost mynetworks = ${' '.join(sorted(mynetworks))} @@ -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 @@ -37,8 +38,8 @@ smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt % if node.has_bundle('postfixadmin'): -smtpd_tls_cert_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/fullchain.pem -smtpd_tls_key_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/privkey.pem +smtpd_tls_cert_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/fullchain.pem +smtpd_tls_key_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/privkey.pem <%text> smtpd_use_tls=yes smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache @@ -47,18 +48,17 @@ smtpd_client_restrictions = permit_mynetworks permit_sasl_authenticated smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks reject_invalid_helo_hostname smtpd_data_restrictions = reject_unauth_pipelining -smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/blocked_recipients, permit_mynetworks -smtpd_relay_before_recipient_restrictions = yes -# https://ssl-config.mozilla.org/#server=postfix&version=3.7.10&config=intermediate&openssl=3.0.11&guideline=5.7 +# generated using mozilla ssl generator, using "old" configuration. +# we need this to support CentOS 7 systems, sadly ... +# https://ssl-config.mozilla.org/#server=postfix&version=3.5.13&config=old&openssl=1.1.1k&guideline=5.6 smtpd_tls_security_level = may smtpd_tls_auth_only = yes -smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 -smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 +smtpd_tls_protocols = !SSLv2, !SSLv3 smtpd_tls_mandatory_ciphers = medium -smtpd_tls_dh1024_param_file = /etc/ssl/certs/dhparam.pem -tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305 -tls_preempt_cipherlist = no +tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA +tls_preempt_cipherlist = yes relay_domains = $mydestination, pgsql:/etc/postfix/pgsql/relay_domains.cf diff --git a/bundles/postfix/items.py b/bundles/postfix/items.py index aeceed1..e66185f 100644 --- a/bundles/postfix/items.py +++ b/bundles/postfix/items.py @@ -21,13 +21,11 @@ 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', - }, + 'content': node.metadata.get('postfix/myhostname', node.metadata['hostname']), 'triggers': { 'svc_systemd:postfix:restart', }, @@ -38,16 +36,6 @@ files = { 'action:postfix_newaliases', }, }, - '/etc/postfix/blocked_recipients': { - 'content_type': 'mako', - 'context': { - 'blocked': node.metadata.get('postfix/blocked_recipients', set()), - }, - 'triggers': { - 'action:postfix_postmap_blocked_recipients', - 'svc_systemd:postfix:restart', - }, - }, '/etc/postfix/master.cf': { 'content_type': 'mako', 'triggers': { @@ -81,20 +69,7 @@ actions = { 'command': 'newaliases', 'triggered': True, 'needs': { - 'pkg_apt:postfix', - }, - 'before': { - 'svc_systemd:postfix', - }, - }, - 'postfix_postmap_blocked_recipients': { - 'command': 'postmap hash:/etc/postfix/blocked_recipients', - 'triggered': True, - 'needs': { - 'pkg_apt:postfix', - }, - 'before': { - 'svc_systemd:postfix', + my_package, }, }, } @@ -104,7 +79,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', + }, + } diff --git a/bundles/postfix/metadata.py b/bundles/postfix/metadata.py index f457b9b..e0dbe61 100644 --- a/bundles/postfix/metadata.py +++ b/bundles/postfix/metadata.py @@ -14,7 +14,7 @@ defaults = { 'postfix': { 'services': { 'POSTFIX PROCESS': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit postfix' + ('' if node.os_version >= (13,) else '@-'), + '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'): @@ -81,7 +87,7 @@ def letsencrypt(metadata): } result['domains'] = { - metadata.get('postfix/myhostname'): set(), + metadata.get('postfix/myhostname', metadata.get('hostname')): set(), } return { @@ -90,10 +96,10 @@ def letsencrypt(metadata): @metadata_reactor.provides( - 'firewall/port_rules', - 'firewall/port_rules', - 'firewall/port_rules', - 'firewall/port_rules', + 'firewall/port_rules/25', + 'firewall/port_rules/465', + 'firewall/port_rules/587', + 'firewall/port_rules/2525', ) def firewall(metadata): if node.has_bundle('postfixadmin'): @@ -102,13 +108,13 @@ def firewall(metadata): default = metadata.get('postfix/mynetworks', set()) rules = { - '25/tcp': atomic(metadata.get('postfix/restrict-to', default)), - '465/tcp': atomic(metadata.get('postfix/restrict-to', default)), + '25': atomic(metadata.get('postfix/restrict-to', default)), + '465': atomic(metadata.get('postfix/restrict-to', default)), } if node.has_bundle('postfixadmin'): - rules['587/tcp'] = atomic(metadata.get('postfix/restrict-to', default)) - rules['2525/tcp'] = atomic(metadata.get('postfix/restrict-to', default)) + rules['587'] = atomic(metadata.get('postfix/restrict-to', default)) + rules['2525'] = atomic(metadata.get('postfix/restrict-to', default)) return { 'firewall': { @@ -142,14 +148,3 @@ def icinga2(metadata): }, }, } - - -@metadata_reactor.provides( - 'postfix/myhostname', -) -def myhostname(metadata): - return { - 'postfix': { - 'myhostname': metadata.get('hostname'), - }, - } diff --git a/bundles/postfixadmin/metadata.py b/bundles/postfixadmin/metadata.py index b9d6379..bed7ab6 100644 --- a/bundles/postfixadmin/metadata.py +++ b/bundles/postfixadmin/metadata.py @@ -60,23 +60,3 @@ def icinga_check_for_new_release(metadata): }, }, } - - -@metadata_reactor.provides( - 'nginx/vhosts/postfixadmin', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'postfixadmin': { - 'domain': metadata.get('postfixadmin/domain'), - 'webroot': '/opt/postfixadmin/public/', - 'php': True, - }, - }, - }, - } diff --git a/bundles/postgresql/files/postgresql.conf b/bundles/postgresql/files/postgresql.conf index 0996a13..56fa5af 100644 --- a/bundles/postgresql/files/postgresql.conf +++ b/bundles/postgresql/files/postgresql.conf @@ -9,7 +9,6 @@ max_connections = ${max_connections} autovacuum_max_workers = ${autovacuum_max_workers} maintenance_work_mem = ${maintenance_work_mem}MB work_mem = ${work_mem}MB -effective_cache_size = ${cache_size}MB shared_buffers = ${shared_buffers}MB temp_buffers = ${temp_buffers}MB log_destination = syslog @@ -27,5 +26,7 @@ log_min_duration_statement = -1 % endif effective_io_concurrency = ${effective_io_concurrency} max_worker_processes = ${max_worker_processes} +% if version_list >= [10]: max_parallel_workers = ${max_parallel_workers} +% endif max_parallel_workers_per_gather = ${max_parallel_workers_per_gather} diff --git a/bundles/postgresql/items.py b/bundles/postgresql/items.py index 0a1b09f..5f21b42 100644 --- a/bundles/postgresql/items.py +++ b/bundles/postgresql/items.py @@ -1,4 +1,4 @@ -postgresql_version = int(node.metadata.get('postgresql/version')) +postgresql_version = node.metadata['postgresql']['version'] pkg_apt = { 'postgresql-common': {}, @@ -44,7 +44,10 @@ files = { }, "/etc/postgresql/{}/main/postgresql.conf".format(postgresql_version): { 'content_type': 'mako', - 'context': node.metadata.get('postgresql'), + 'context': { + 'version_list': [int(i) for i in node.metadata['postgresql']['version'].split('.')], + **node.metadata['postgresql'], + }, 'owner': 'postgres', 'group': 'postgres', 'needs': { @@ -57,7 +60,7 @@ files = { }, } -if node.has_bundle('backup-client'): +if node.has_bundle('backup-client') and not node.has_bundle('zfs'): files['/etc/backup-pre-hooks.d/90-postgresql-dump-all'] = { 'source': 'backup-pre-hook', 'content_type': 'mako', @@ -67,6 +70,10 @@ if node.has_bundle('backup-client'): 'mode': '0700', } directories['/var/tmp/postgresdumps'] = {} +else: + files['/var/tmp/postgresdumps'] = { + 'delete': True, + } postgres_roles = { 'root': { diff --git a/bundles/postgresql/metadata.py b/bundles/postgresql/metadata.py index b624bae..fce9bb6 100644 --- a/bundles/postgresql/metadata.py +++ b/bundles/postgresql/metadata.py @@ -1,17 +1,7 @@ defaults = { - 'apt': { - 'repos': { - 'postgresql': { - 'items': { - 'deb https://apt.postgresql.org/pub/repos/apt/ {os_release}-pgdg main', - }, - }, - }, - }, 'backups': { 'paths': { '/var/lib/postgresql', - '/var/tmp/postgresdumps', }, }, 'bash_functions': { @@ -34,7 +24,6 @@ defaults = { 'shared_buffers': 128, 'temp_buffers': 8, 'slow_query_log_sec': 0, - 'cache_size': 256, }, } @@ -75,6 +64,36 @@ if node.has_bundle('zfs'): }, }, } +else: + defaults['backups']['paths'].add('/var/tmp/postgresdumps') + + +@metadata_reactor.provides( + 'apt/repos/postgresql', +) +def default_postgresql_version_for_debian(metadata): + # + versions_in_debian = { + '10': '11', # buster + '11': '13', # bullseye + } + os = str(node.os_version[0]) + version_to_be_installed = metadata.get('postgresql/version') + + if version_to_be_installed != versions_in_debian[os]: + return { + 'apt': { + 'repos': { + 'postgresql': { + 'items': { + 'deb https://apt.postgresql.org/pub/repos/apt/ {os_release}-pgdg main', + }, + }, + }, + }, + } + + return {} @metadata_reactor.provides( diff --git a/bundles/powerdns/files/schema.pgsql.sql b/bundles/powerdns/files/schema.pgsql.sql new file mode 100644 index 0000000..9635168 --- /dev/null +++ b/bundles/powerdns/files/schema.pgsql.sql @@ -0,0 +1,105 @@ +-- 4.3 schema, https://doc.powerdns.com/authoritative/backends/generic-postgresql.html + +CREATE TABLE domains ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial BIGINT DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX name_index ON domains(name); + +ALTER TABLE domains OWNER TO ${user}; + +CREATE TABLE records ( + id BIGSERIAL PRIMARY KEY, + domain_id INT DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + change_date INT DEFAULT NULL, + disabled BOOL DEFAULT 'f', + ordername VARCHAR(255), + auth BOOL DEFAULT 't', + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX rec_name_index ON records(name); +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops); + +ALTER TABLE records OWNER TO ${user}; + +CREATE TABLE supermasters ( + ip INET NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) NOT NULL, + PRIMARY KEY(ip, nameserver) +); + +ALTER TABLE supermasters OWNER TO ${user}; + +CREATE TABLE comments ( + id SERIAL PRIMARY KEY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + +ALTER TABLE comments OWNER TO ${user}; + +CREATE TABLE domainmetadata ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + kind VARCHAR(32), + content TEXT +); + +CREATE INDEX domainidmetaindex ON domainmetadata(domain_id); + +ALTER TABLE domainmetadata OWNER TO ${user}; + +CREATE TABLE cryptokeys ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); +ALTER TABLE cryptokeys OWNER TO ${user}; + + +CREATE TABLE tsigkeys ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); + +ALTER TABLE tsigkeys OWNER TO ${user}; diff --git a/bundles/powerdns/items.py b/bundles/powerdns/items.py index c972f90..2aad214 100644 --- a/bundles/powerdns/items.py +++ b/bundles/powerdns/items.py @@ -2,20 +2,16 @@ from datetime import datetime from os import listdir from os.path import isfile, join from subprocess import check_output -from textwrap import dedent - -from bundlewrap.utils.ui import io zone_path = join(repo.path, 'data', 'powerdns', 'files', 'bind-zones') nameservers = set() -for rnode in repo.nodes_in_group('dns'): +for rnode in sorted(repo.nodes_in_group('dns')): + if not rnode.metadata.get('powerdns/is_secondary'): + # hide the primary nameserver from auto-generated nameserver lists + continue nameservers.add(rnode.metadata.get('powerdns/my_hostname', rnode.metadata.get('hostname'))) -my_primary_servers = set() -for ips in node.metadata.get('powerdns/my_primary_servers', {}).values(): - my_primary_servers.update(ips) - directories = { '/etc/powerdns/pdns.d': { 'purge': True, @@ -43,7 +39,7 @@ files = { 'api_key': node.metadata.get('powerdns/api_key'), 'my_hostname': node.metadata.get('powerdns/my_hostname', node.metadata.get('hostname')), 'is_secondary': node.metadata.get('powerdns/is_secondary', False), - 'my_primary_servers': my_primary_servers, + 'my_primary_servers': node.metadata.get('powerdns/my_primary_servers', set()), 'my_secondary_servers': node.metadata.get('powerdns/my_secondary_servers', set()), }, 'needs': { @@ -68,53 +64,32 @@ svc_systemd = { actions = { 'powerdns_reload_zones': { 'triggered': True, - 'command': r'pdns_control rediscover; pdns_control reload; pdns_control notify \*', - 'after': { + 'command': 'pdns_control rediscover; pdns_control reload; pdns_control notify \*', + 'needs': { 'svc_systemd:pdns', }, }, } if node.metadata.get('powerdns/features/bind', False): - try: - output = check_output(['git', 'log', '-1', '--pretty=%ci']).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"{node.name} Error while parsing commit time for powerdns zone serial: {e!r}") - serial = datetime.now().strftime('%y%m%d0000') - - HEADER = dedent(f""" - $TTL 60 - @ IN SOA ns-mephisto.kunbox.net. hostmaster.kunbox.net. ( - {serial} - 3600 - 600 - 86400 - 300 - ) - """).strip() - - for ns in sorted(nameservers): - HEADER += f"\n@ IN NS {ns}." - primary_zones = set() for zone in listdir(zone_path): - if ( - not ( - isfile(join(zone_path, zone)) - or islink(join(zone_path, zone)) - ) - or zone.startswith(".") - or zone.startswith("_") - ): + if not isfile(join(zone_path, zone)) or zone.startswith(".") or zone.startswith("_"): continue + try: + 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: + serial = datetime.now().strftime('%y%m%d0000') + primary_zones.add(zone) files[f'/var/lib/powerdns/zones/{zone}'] = { 'content_type': 'mako', 'context': { - 'HEADER': HEADER + f"\n$ORIGIN {zone}.", + 'NAMESERVERS': '\n'.join(sorted({f'@ IN NS {ns}.' for ns in nameservers})), + 'SERIAL': serial, 'metadata_records': node.metadata.get(f'powerdns/bind-zones/{zone}/records', []), }, 'source': f'bind-zones/{zone}', @@ -182,45 +157,16 @@ if node.metadata.get('powerdns/features/pgsql', node.has_bundle('postgresql')): }, } + files['/etc/powerdns/schema.pgsql.sql'] = {} + actions['powerdns_load_pgsql_schema'] = { - 'command': node.metadata.get('postgresql/roles/powerdns/password').format_into('PGPASSWORD={} psql -h 127.0.0.1 -d powerdns -U powerdns -w < /usr/share/pdns-backend-pgsql/schema/schema.pgsql.sql'), - 'unless': r'sudo -u postgres psql -d powerdns -c "\dt" | grep domains 2>&1 >/dev/null', + 'command': node.metadata.get('postgresql/roles/powerdns/password').format_into('PGPASSWORD={} psql -h 127.0.0.1 -d powerdns -U powerdns -w < /etc/powerdns/schema.pgsql.sql'), + 'unless': 'sudo -u postgres psql -d powerdns -c "\dt" | grep domains 2>&1 >/dev/null', 'needs': { 'bundle:postgresql', - 'pkg_apt:pdns-backend-pgsql', + 'file:/etc/powerdns/schema.pgsql.sql', }, 'needed_by': { 'svc_systemd:pdns', }, } - - for hostname, ips in node.metadata.get('powerdns/my_primary_servers', {}).items(): - for ip in ips: - ip_name = ip.replace(':', '-') - - actions[f'powerdns_ensure_{ip_name}_in_autoprimaries'] = { - 'command': f'psql -c "INSERT INTO supermasters (ip, nameserver, account) VALUES (\'{ip}\', \'{hostname}\', \'admin\')" powerdns', - 'unless': f'test -n \"$(psql -tAqc "SELECT nameserver FROM supermasters WHERE ip = \'{ip}\'" powerdns)\"', - 'triggers': { - 'action:powerdns_fix_primaries', - }, - 'after': { - 'action:powerdns_load_pgsql_schema', - }, - } - - actions[f'powerdns_ensure_{hostname}_matches_{ip_name}_in_autoprimaries'] = { - 'command': f'psql -c "UPDATE supermasters SET nameserver = \'{hostname}\' WHERE ip = \'{ip}\'" powerdns', - 'unless': f'bash -c "[ \"$(psql -tAqc "SELECT nameserver FROM supermasters WHERE ip = \'{ip}\'" powerdns)\" == \"{hostname}\" ]"', - 'triggers': { - 'action:powerdns_fix_primaries', - }, - 'after': { - f'action:powerdns_ensure_{ip_name}_in_autoprimaries', - }, - } - - actions['powerdns_fix_primaries'] = { - 'command': f'psql -c "UPDATE domains SET master = \'{", ".join(sorted(my_primary_servers))}\'" powerdns', - 'triggered': True, - } diff --git a/bundles/powerdns/metadata.py b/bundles/powerdns/metadata.py index 5437657..e93c7de 100644 --- a/bundles/powerdns/metadata.py +++ b/bundles/powerdns/metadata.py @@ -86,8 +86,6 @@ def get_ips_of_secondary_nameservers(metadata): ips = set() for rnode in repo.nodes_in_group('dns'): if rnode.metadata.get('powerdns/is_secondary', False): - if rnode.name == node.name: - raise BundleError(f'{node.name} cannot be its own secondary') for _, found_ips in repo.libs.tools.resolve_identifier(repo, rnode.name).items(): ips.update({str(ip) for ip in found_ips}) @@ -104,15 +102,11 @@ def get_ips_of_primary_nameservers(metadata): if not metadata.get('powerdns/is_secondary', False): return {} - ips = {} + ips = set() for rnode in repo.nodes_in_group('dns'): if not rnode.metadata.get('powerdns/is_secondary', False): - if rnode.name == node.name: - raise BundleError(f'{node.name} cannot be its own secondary') - hostname = rnode.metadata.get('hostname') - ips[hostname] = set() for _, found_ips in repo.libs.tools.resolve_identifier(repo, rnode.name).items(): - ips[hostname].update({str(ip) for ip in found_ips}) + ips.update({str(ip) for ip in found_ips}) return { 'powerdns': { @@ -134,7 +128,7 @@ def generate_dns_entries_for_nodes(metadata): ip4 = None ip6 = None - found_ips = repo.libs.tools.resolve_identifier(repo, rnode.name, only_physical=True) + found_ips = repo.libs.tools.resolve_identifier(repo, rnode.name) for ip in sorted(found_ips['ipv4']): if not ip4 and not ip.is_private: ip4 = ip @@ -143,14 +137,31 @@ def generate_dns_entries_for_nodes(metadata): if not ip6 and not ip.is_private: ip6 = ip - if not (ip4 or ip6) and (found_ips['ipv4'] or found_ips['ipv6']): - # do it again, but do not filter out private addresses - for ip in sorted(found_ips['ipv4']): - if not ip4: - ip4 = ip - for ip in sorted(found_ips['ipv6']): - if not ip6: - ip6 = ip + if not ip4 and found_ips['ipv4']: + # This node apparently does not have a public IPv4 address. + # We now manually iterate over that nodes interfaces to get + # a IPv4 address which is tied to a physical interface. + # Note we can't use resolve_identifier() here, because we + # only want physical interfaces. + for interface, config in rnode.metadata.get('interfaces', {}).items(): + if not ( + interface.startswith('bond') or + interface.startswith('br') or + interface.startswith('eno') or + interface.startswith('enp') or + interface.startswith('eth') or + interface == 'default' # dummy nodes use these + ): + continue + + for ip in sorted(config.get('ips', set())): + if '/' in ip: + addr = ip_address(ip.split('/')[0]) + else: + addr = ip_address(ip) + + if not ip4 and isinstance(addr, IPv4Address): + ip4 = addr if ip4: results.add('{} IN A {}'.format(dns_name, ip4)) @@ -204,9 +215,9 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '53/tcp': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), + '53': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), '53/udp': atomic(metadata.get('powerdns/restrict-to/dns', {'*'})), - '8081/tcp': atomic(metadata.get('powerdns/restrict-to/api', set())), + '8081': atomic(metadata.get('powerdns/restrict-to/api', set())), }, }, } diff --git a/bundles/powerdnsadmin/files/powerdnsadmin.service b/bundles/powerdnsadmin/files/powerdnsadmin.service index 1153886..333cfe7 100644 --- a/bundles/powerdnsadmin/files/powerdnsadmin.service +++ b/bundles/powerdnsadmin/files/powerdnsadmin.service @@ -9,7 +9,7 @@ Group=powerdnsadmin Environment=FLASK_CONF=/opt/powerdnsadmin/config.py WorkingDirectory=/opt/powerdnsadmin/src ExecStartPre=-/bin/chown powerdnsadmin:powerdnsadmin /opt/powerdnsadmin/src/powerdnsadmin/static -ExecStart=/opt/powerdnsadmin/venv/bin/gunicorn 'powerdnsadmin:create_app()' --name powerdnsadmin --workers 4 --max-requests 1200 --max-requests-jitter 50 --log-level=info --bind=127.0.0.1:22100 +ExecStart=/opt/powerdnsadmin/venv/bin/gunicorn 'powerdnsadmin:create_app()' [Install] WantedBy=multi-user.target diff --git a/bundles/powerdnsadmin/items.py b/bundles/powerdnsadmin/items.py index 8398916..ea256ea 100644 --- a/bundles/powerdnsadmin/items.py +++ b/bundles/powerdnsadmin/items.py @@ -21,14 +21,10 @@ git_deploy = { files = { '/opt/powerdnsadmin/config.py': { 'content_type': 'mako', - 'triggers': { - 'svc_systemd:powerdnsadmin:restart', - }, }, '/etc/systemd/system/powerdnsadmin.service': { 'triggers': { 'action:systemd-reload', - 'svc_systemd:powerdnsadmin:restart', }, }, } @@ -71,8 +67,8 @@ actions = { 'chown -R powerdnsadmin:powerdnsadmin /opt/powerdnsadmin/src/powerdnsadmin/static/', ]), 'needs': { + 'action:nodejs_install_yarn', 'action:powerdnsadmin_install_deps', - 'bundle:nodejs', 'pkg_apt:', }, }, diff --git a/bundles/powerdnsadmin/metadata.py b/bundles/powerdnsadmin/metadata.py index c2b2c1e..0617b03 100644 --- a/bundles/powerdnsadmin/metadata.py +++ b/bundles/powerdnsadmin/metadata.py @@ -13,9 +13,6 @@ defaults = { 'python3-wheel': {}, }, }, - 'nodejs': { - 'version': 22, - }, 'users': { 'powerdnsadmin': { 'home': '/opt/powerdnsadmin', @@ -53,27 +50,3 @@ def icinga_check_for_new_release(metadata): }, }, } - - -@metadata_reactor.provides( - 'nginx/vhosts/powerdnsadmin', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - 'powerdnsadmin': { - 'locations': { - '/': { - 'target': 'http://127.0.0.1:22100', - }, - }, - 'website_check_path': '/login', - 'website_check_string': 'PowerDNS', - }, - }, - }, - } diff --git a/bundles/pppd/files/check_dyndns_update b/bundles/pppd/files/check_dyndns_update new file mode 100644 index 0000000..eaf8dfe --- /dev/null +++ b/bundles/pppd/files/check_dyndns_update @@ -0,0 +1,20 @@ +#!/bin/bash + +[[ -n "$DEBUG" ]] && set -x + +interface="$(ip link show | awk '/ ppp/ {print substr($2, 1, length($2)-1)}')" +addr="$(ip addr show dev "$interface" | awk '/inet / {print $2}')" +resolved="$(dig +short "${domain}" A)" + +if [[ -z "$addr" ]] || [[ -z "$resolved" ]] +then + echo "Address on '$interface' is '$addr' - resolved '$resolved'" + exit 3 +elif [[ "$addr" == "$resolved" ]] +then + echo "Resolved IP for ${domain} matches current ip on $interface" + exit 0 +else + echo "Resolved $resolved for ${domain}, but got $addr on $interface!" + exit 2 +fi diff --git a/bundles/pppd/files/dyndns b/bundles/pppd/files/dyndns index 633915f..f1760d8 100644 --- a/bundles/pppd/files/dyndns +++ b/bundles/pppd/files/dyndns @@ -1,58 +1,24 @@ #!/usr/bin/env python3 -import logging -from ipaddress import ip_address -from json import loads -from subprocess import check_output +from sys import argv -from requests import get +import requests + +INTERFACE = argv[1] +LOCAL_IP = argv[4] UPDATE_URL = '${url}' USERNAME = '${username}' PASSWORD = '${password}' -# <%text> -logging.basicConfig(level=logging.INFO) -LOG = logging.getLogger('DynDNS') -try: - ips = set() - - iproute = loads(check_output(['ip', '-json', 'address', 'show', 'scope', 'global'])) - - for iface in iproute: - if not iface['ifname'].startswith('ppp'): - LOG.debug(f'ignoring {iface["ifname"]}') - continue - - LOG.info(f'working on {iface["ifname"]}') - for ip in iface['addr_info']: - try: - addr = ip_address(ip['local']) - - LOG.info(f'{iface["ifname"]} has ip {addr.compressed}') - ips.add(addr.compressed) - except Exception: - continue - - if ips: - LOG.info('got some addresses!') - break - - url = UPDATE_URL.format( - ips=','.join(sorted(ips)) +r = requests.get( + UPDATE_URL.format( + ip=LOCAL_IP, + ), + auth=( + USERNAME, + PASSWORD, ) +) - LOG.info(url) - - r = get( - url, - auth=( - USERNAME, - PASSWORD, - ), - ) - r.raise_for_status() -except Exception as e: - logging.exception(e) - -# +print('got status {} when updating dns'.format(r.status_code)) diff --git a/bundles/pppd/files/dyndns_periodic b/bundles/pppd/files/dyndns_periodic index 353ee6d..3aebb47 100644 --- a/bundles/pppd/files/dyndns_periodic +++ b/bundles/pppd/files/dyndns_periodic @@ -1,51 +1,17 @@ -#!/usr/bin/env python3 +#!/bin/bash -import logging -from ipaddress import ip_address -from json import loads -from subprocess import check_output, run +[[ -n "$DEBUG" ]] && set -x -DOMAIN = '${domain}' +interface="$(ip link show | awk '/ ppp/ {print substr($2, 1, length($2)-1)}')" +addr="$(ip addr show dev "$interface" | awk '/inet / {print $2}')" +resolved="$(dig +short "${domain}" A)" -# <%text> -logging.basicConfig(level=logging.INFO) -LOG = logging.getLogger('DynDNS checker') -try: - iproute = loads(check_output(['ip', '-json', 'address', 'show', 'scope', 'global'])) - resolved_ipv4 = check_output(['dig', '+short', DOMAIN, 'A']).decode().strip() - resolved_ipv6 = check_output(['dig', '+short', DOMAIN, 'AAAA']).decode().strip() - - LOG.info(f'resolved ipv4 is "{resolved_ipv4}"') - LOG.info(f'resolved ipv6 is "{resolved_ipv6}"') - - needs_changing = False - - for iface in iproute: - if not iface['ifname'].startswith('ppp'): - LOG.debug(f'ignoring {iface["ifname"]}') - continue - - LOG.info(f'working on {iface["ifname"]}') - for ip in iface['addr_info']: - try: - addr = ip_address(ip['local']) - - LOG.info(f'{iface["ifname"]} has ip {addr.compressed}') - - if ( - (addr.version == 4 and addr.compressed != resolved_ipv4) - or (addr.version == 6 and addr.compressed != resolved_ipv6) - ): - needs_changing = True - except Exception: - continue - - if needs_changing: - LOG.warning('addresses have changed, calling update script!') - run(['/etc/ppp/ip-up.d/dyndns']) - else: - LOG.info('everything is fine') -except Exception as e: - logging.exception(e) - -# +if [[ -z "$addr" ]] || [[ -z "$resolved" ]] +then + echo "Something is wrong:" + echo "Address on '$interface' is '$addr'" + echo "Resolved DNS is '$resolved'" +elif [[ "$addr" != "$resolved" ]] +then + /etc/ppp/ip-up.d/dyndns "$interface" "doesnt" "matter" "$addr" +fi diff --git a/bundles/pppd/files/ip-up b/bundles/pppd/files/ip-up index 2ac4934..8eba2b9 100644 --- a/bundles/pppd/files/ip-up +++ b/bundles/pppd/files/ip-up @@ -2,7 +2,7 @@ INTERFACE=$1 -echo "add rule nat postrouting oifname $INTERFACE masquerade" > /etc/nftables-rules.d/90-pppd +echo "add rule nat postrouting oif $INTERFACE masquerade" > /etc/nftables-rules.d/90-pppd % for rule in sorted(nftables): echo "add rule ${rule}" >> /etc/nftables-rules.d/90-pppd % endfor diff --git a/bundles/pppd/items.py b/bundles/pppd/items.py index cf21a6f..8d94950 100644 --- a/bundles/pppd/items.py +++ b/bundles/pppd/items.py @@ -110,6 +110,11 @@ if node.metadata.get('pppd/dyndns', {}): 'context': node.metadata.get('pppd/dyndns'), 'mode': '0755', } + files['/usr/local/share/icinga/plugins/check_dyndns_update'] = { + 'content_type': 'mako', + 'context': node.metadata.get('pppd/dyndns'), + 'mode': '0755', + } files['/usr/local/bin/dyndns_periodic'] = { 'content_type': 'mako', 'context': node.metadata.get('pppd/dyndns'), diff --git a/bundles/pppd/metadata.py b/bundles/pppd/metadata.py index 75274a5..9d8792b 100644 --- a/bundles/pppd/metadata.py +++ b/bundles/pppd/metadata.py @@ -39,3 +39,24 @@ def ignore_interface(metadata): }, }, } + + +@metadata_reactor.provides( + 'icinga2_api/pppd/services', +) +def icinga_dyndns(metadata): + if not metadata.get('pppd/dyndns', {}): + return {} + + return { + 'icinga2_api': { + 'pppd': { + 'services': { + 'DYNDNS UPDATE': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_dyndns_update', + 'vars.notification.mail': True, + }, + }, + }, + }, + } diff --git a/bundles/pretalx/items.py b/bundles/pretalx/items.py index e6b22a4..e5b65d1 100644 --- a/bundles/pretalx/items.py +++ b/bundles/pretalx/items.py @@ -1,6 +1,3 @@ -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' - actions = { 'pretalx_create_virtualenv': { 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/pretalx/venv/', @@ -11,20 +8,17 @@ actions = { }, }, 'pretalx_install': { - 'command': ' && '.join([ - 'cd /opt/pretalx/src', - '/opt/pretalx/venv/bin/pip install --upgrade pip wheel gunicorn psycopg2-binary', + 'command': + 'cd /opt/pretalx/src/src && ' + '/opt/pretalx/venv/bin/pip install --upgrade pip wheel gunicorn psycopg2-binary && ' '/opt/pretalx/venv/bin/pip install --upgrade -e .[redis]', - ]), 'needs': { 'action:pretalx_create_virtualenv', - 'pkg_apt:gcc', - 'pkg_apt:python3-dev', }, 'triggered': True, }, 'pretalx_migrate': { - 'command': '/usr/bin/sudo -Hu pretalx PRETALX_CONFIG_FILE=/opt/pretalx/pretalx.cfg /opt/pretalx/venv/bin/python -m pretalx migrate', + 'command': 'PRETALX_CONFIG_FILE=/opt/pretalx/pretalx.cfg /opt/pretalx/venv/bin/python -m pretalx migrate', 'needs': { 'action:pretalx_install', 'file:/opt/pretalx/pretalx.cfg', @@ -34,22 +28,24 @@ actions = { 'triggered': True, }, 'pretalx_rebuild': { - 'command': ' && '.join([ - 'cd /opt/pretalx/src/src/pretalx/frontend/schedule-editor/', - 'npm install', - 'PRETALX_CONFIG_FILE=/opt/pretalx/pretalx.cfg /opt/pretalx/venv/bin/python -m pretalx rebuild', - ]), + 'command': 'PRETALX_CONFIG_FILE=/opt/pretalx/pretalx.cfg /opt/pretalx/venv/bin/python -m pretalx rebuild', 'needs': { 'action:pretalx_install', 'action:pretalx_migrate', 'directory:/opt/pretalx/data', 'directory:/opt/pretalx/static', 'file:/opt/pretalx/pretalx.cfg', - 'bundle:nodejs', }, - 'triggers': { - # pretalx-web reads the manifest.json generated by this build-step upon startup - 'svc_systemd:pretalx-web:restart', + '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_install', + 'action:pretalx_migrate', + 'directory:/opt/pretalx/data', + 'directory:/opt/pretalx/static', + 'file:/opt/pretalx/pretalx.cfg', }, 'triggered': True, }, @@ -74,17 +70,19 @@ directories = { git_deploy = { '/opt/pretalx/src': { 'repo': 'https://github.com/pretalx/pretalx.git', - 'rev': node.metadata.get('pretalx/version'), + 'rev': node.metadata['pretalx']['version'], 'triggers': { 'action:pretalx_install', 'action:pretalx_migrate', 'action:pretalx_rebuild', + 'action:pretalx_regenerate-css', 'svc_systemd:pretalx-web:restart', 'svc_systemd:pretalx-worker:restart', }, }, } + svc_systemd = { 'pretalx-runperiodic.timer': { 'needs': { @@ -109,6 +107,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 +116,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', }, @@ -127,12 +125,15 @@ svc_systemd = { files = { '/opt/pretalx/pretalx.cfg': { 'content_type': 'mako', - 'context': node.metadata.get('pretalx'), + 'context': node.metadata['pretalx'], 'triggers': { 'svc_systemd:pretalx-web:restart', 'svc_systemd:pretalx-worker:restart', }, }, + '/opt/pretalx/pretalx-administrators-from-group': { + 'mode': '0755', + }, '/etc/systemd/system/pretalx-runperiodic.timer': { 'triggers': { 'action:systemd-reload', @@ -169,16 +170,24 @@ files = { }, } +if node.metadata.get('pretalx/administrators-from-group-id', None): + files['/etc/cron.d/pretalx-administrators-from-group'] = { + 'source': 'cron-pretalx-administrators-from-group', + 'content_type': 'mako', + } +else: + files['/etc/cron.d/pretalx-administrators-from-group'] = { + 'delete': True, + } + # run `pip install` one after another due to concurrency issues last_action = 'action:pretalx_install' for plugin_name, plugin_config in node.metadata.get('pretalx/plugins', {}).items(): - assert '-' not in plugin_name, f'{node.name} pretalx plugin {plugin_name} must not contain dashes' - directories[f'/opt/pretalx/plugin_{plugin_name}'] = {} git_deploy[f'/opt/pretalx/plugin_{plugin_name}'] = { 'repo': plugin_config['repo'], - 'rev': plugin_config.get('rev', 'master'), + 'rev': plugin_config['rev'], 'triggers': { f'action:pretalx_install_plugin_{plugin_name}', }, @@ -192,6 +201,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', }, diff --git a/bundles/pretalx/metadata.py b/bundles/pretalx/metadata.py index 15b61e3..3c52e15 100644 --- a/bundles/pretalx/metadata.py +++ b/bundles/pretalx/metadata.py @@ -1,19 +1,17 @@ defaults = { 'apt': { 'packages': { - 'gcc': {}, # for compiling some python deps 'gettext': {}, - 'python3-dev': {}, }, }, - 'bash_aliases': { - 'pretalx': 'sudo /opt/pretalx/venv/bin/python -m pretalx', - }, 'backups': { 'paths': { '/opt/pretalx/data', }, }, + 'bash_aliases': { + 'pretalx': 'sudo /opt/pretalx/venv/bin/python -m pretalx', + }, 'icinga2_api': { 'pretalx': { 'services': { @@ -26,9 +24,6 @@ defaults = { }, }, }, - 'nodejs': { - 'version': 22, - }, 'pretalx': { 'database': { 'user': 'pretalx', diff --git a/bundles/proftpd/items.py b/bundles/proftpd/items.py deleted file mode 100644 index 506fb1b..0000000 --- a/bundles/proftpd/items.py +++ /dev/null @@ -1,13 +0,0 @@ -files['/etc/proftpd/proftpd.conf'] = { - 'source': f'{node.name}.conf', - 'triggers': { - 'svc_systemd:proftpd:restart', - }, -} - -svc_systemd['proftpd'] = { - 'needs': { - 'file:/etc/proftpd/proftpd.conf', - 'pkg_apt:proftpd-core', - }, -} diff --git a/bundles/proftpd/metadata.py b/bundles/proftpd/metadata.py deleted file mode 100644 index ad33bfb..0000000 --- a/bundles/proftpd/metadata.py +++ /dev/null @@ -1,26 +0,0 @@ -from bundlewrap.metadata import atomic - -defaults = { - 'apt': { - 'packages': { - 'proftpd-core': {}, - }, - }, -} - - -@metadata_reactor.provides( - 'firewall/port_rules', -) -def firewall(metadata): - sources = atomic(metadata.get('mosquitto/restrict-to', set())) - - return { - 'firewall': { - 'port_rules': { - '20/tcp': sources, - '21/tcp': sources, - '49152-50192/tcp': sources, - }, - }, - } diff --git a/bundles/pyenv/items.py b/bundles/pyenv/items.py deleted file mode 100644 index 97f1439..0000000 --- a/bundles/pyenv/items.py +++ /dev/null @@ -1,28 +0,0 @@ -from shlex import quote - -directories = { - '/opt/pyenv': {}, - '/opt/pyenv/install': {}, -} - -git_deploy = { - '/opt/pyenv/install': { - 'repo': 'https://github.com/pyenv/pyenv.git', - 'rev': node.metadata.get('pyenv/version'), - 'needs': { - 'directory:/opt/pyenv/install', - }, - }, -} - -for version in node.metadata.get('pyenv/python_versions', set()): - actions[f'pyenv_install_{version}'] = { - 'command': f'PYENV_ROOT=/opt/pyenv /opt/pyenv/install/bin/pyenv install {quote(version)}', - 'unless': f'PYENV_ROOT=/opt/pyenv /opt/pyenv/install/bin/pyenv versions --bare | grep -E "^{quote(version)}$"', - 'needs': { - 'git_deploy:/opt/pyenv/install', - }, - 'after': { - 'pkg_apt:', - }, - } diff --git a/bundles/pyenv/metadata.py b/bundles/pyenv/metadata.py deleted file mode 100644 index 177a2b3..0000000 --- a/bundles/pyenv/metadata.py +++ /dev/null @@ -1,20 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'build-essential': {}, - 'curl': {}, - 'libbz2-dev': {}, - 'libffi-dev': {}, - 'liblzma-dev': {}, - 'libncurses-dev': {}, - 'libreadline-dev': {}, - 'libsqlite3-dev': {}, - 'libssl-dev': {}, - 'libxml2-dev': {}, - 'libxmlsec1-dev': {}, - 'tk-dev': {}, - 'xz-utils': {}, - 'zlib1g-dev': {}, - }, - }, -} diff --git a/bundles/radvd/files/radvd.conf b/bundles/radvd/files/radvd.conf index ee40111..10b7fc7 100644 --- a/bundles/radvd/files/radvd.conf +++ b/bundles/radvd/files/radvd.conf @@ -2,21 +2,19 @@ interface ${interface} { AdvSendAdvert on; - MinRtrAdvInterval 60; - MaxRtrAdvInterval 300; + MinRtrAdvInterval 10; + MaxRtrAdvInterval 30; MinDelayBetweenRAs 10; prefix ${config.get('prefix', '::/64')} { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; - AdvPreferredLifetime 600; - AdvValidLifetime 900; }; -% if config.get('rdnss'): +% if 'rdnss' in config: RDNSS ${' '.join(sorted(config['rdnss']))} { - AdvRDNSSLifetime 600; + AdvRDNSSLifetime 900; }; % endif }; diff --git a/bundles/raspberrypi/files/config.txt b/bundles/raspberrypi/files/config.txt index bf6751e..00079b2 100644 --- a/bundles/raspberrypi/files/config.txt +++ b/bundles/raspberrypi/files/config.txt @@ -1,30 +1,22 @@ disable_overscan=1 +hdmi_force_hotplug=1 +dtparam=spi=on dtparam=audio=on -dtoverlay=vc4-kms-v3d +dtoverlay=vc4-fkms-v3d max_framebuffers=2 +hdmi_drive=2 force_turbo=1 -gpu_mem=${node.metadata.get('raspberrypi/gpu_mem', 128)} - -% if node.metadata.get('raspberrypi/enable_display'): -display_auto_detect=1 -% else: -dtparam=i2c_arm=on -dtparam=i2s=on -dtparam=spi=on -hdmi_drive=2 -hdmi_force_hotplug=1 -% endif +gpu_mem=${node.metadata['raspberrypi'].get('gpu_mem', 128)} % if node.os == 'debian': arm_64bit=1 % endif -arm_boost=1 -% for item in sorted(node.metadata.get('raspberrypi/config.txt', set())): +% for item in sorted(node.metadata['raspberrypi'].get('config.txt', set())): ${item} % endfor -% if node.metadata.get('raspberrypi/enable_camera', False): -camera_auto_detect=1 +% if node.metadata['raspberrypi'].get('camera', False): +start_x=1 % endif diff --git a/bundles/raspberrypi/items.py b/bundles/raspberrypi/items.py index 41f5544..aab459a 100644 --- a/bundles/raspberrypi/items.py +++ b/bundles/raspberrypi/items.py @@ -15,11 +15,11 @@ actions = { } files = { - '/boot/firmware/cmdline.txt': { + '/boot/cmdline.txt': { 'content': ' '.join(sorted(node.metadata['raspberrypi']['cmdline'])), **file_perms, }, - '/boot/firmware/config.txt': { + '/boot/config.txt': { 'content_type': 'mako', 'context': node.metadata['raspberrypi'], **file_perms, diff --git a/bundles/raspberrypi/metadata.py b/bundles/raspberrypi/metadata.py index 80eac1a..a4c10c2 100644 --- a/bundles/raspberrypi/metadata.py +++ b/bundles/raspberrypi/metadata.py @@ -1,6 +1,5 @@ defaults = { 'apt': { - 'clean_old_kernels': False, 'packages': { 'dhcpcd5': { 'installed': False, @@ -15,16 +14,9 @@ defaults = { 'installed': False, }, }, - 'repos': { - 'raspi': { - 'install_gpg_key': False, - 'items': { - 'deb http://archive.raspberrypi.org/debian/ {os_release} main', - }, - }, - }, }, 'raspberrypi': { + 'default-target': 'multi-user.target', 'cmdline': { 'console=tty1', 'root=/dev/mmcblk0p2', @@ -36,8 +28,6 @@ defaults = { 'plymouth.ignore-serial-consoles', 'net.ifnames=0', }, - 'default-target': 'multi-user.target', - 'enable_display': False, }, 'systemd': { 'journal': { @@ -47,19 +37,3 @@ defaults = { }, }, } - - -@metadata_reactor.provides( - 'raspberrypi/cmdline', -) -def display(metadata): - if not metadata.get('raspberrypi/enable_display'): - return {} - - return { - 'raspberrypi': { - 'cmdline': { - 'video=DSI-1:800x480@60,rotate=180', - }, - }, - } diff --git a/bundles/redis/files/redis.conf b/bundles/redis/files/redis.conf index f636ddf..f479be2 100644 --- a/bundles/redis/files/redis.conf +++ b/bundles/redis/files/redis.conf @@ -48,4 +48,3 @@ tcp-keepalive 0 timeout 0 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 -protected-mode no diff --git a/bundles/redis/metadata.py b/bundles/redis/metadata.py index db31a84..cf15c20 100644 --- a/bundles/redis/metadata.py +++ b/bundles/redis/metadata.py @@ -1,5 +1,3 @@ -from bundlewrap.metadata import atomic - defaults = { 'apt': { 'packages': { @@ -50,16 +48,3 @@ if node.has_bundle('telegraf'): }, }, } - - -@metadata_reactor.provides( - 'firewall/port_rules', -) -def firewall(metadata): - return { - 'firewall': { - 'port_rules': { - '6379/tcp': atomic(metadata.get('redis/restrict-to', set())), - }, - }, - } diff --git a/bundles/routeros/metadata.py b/bundles/routeros/metadata.py index e987a4e..72bc063 100644 --- a/bundles/routeros/metadata.py +++ b/bundles/routeros/metadata.py @@ -2,84 +2,6 @@ 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) - -ips = {} -ports = {} -vlans = { - v['name']: { - 'id': v['vid'], - 'delete': False, - 'tagged': set(), - 'untagged': set(), - } - for v in netbox['vlans'] -} - -for port, conf in netbox['interfaces'].items(): - for ip in conf['ips']: - ips[ip] = {'interface': port} - - if conf['type'].lower() == 'virtual': - # these are VLAN interfaces (for management IPs) - if conf['ips']: - # this makes management services available in the VLAN - try: - vlans[port]['tagged'].add('bridge') - except KeyError: - raise ValueError( - f'name of virtual interface "{port}" on {node.name} ' - f'matches none of the known VLANs: {list(vlans.keys())} ' - '(you probably need to rename the interface in Netbox ' - 'and/or run netbox-dump)' - ) - # We do not create the actual VLAN interface here, that - # happens automatically in items.py. - continue - elif not conf['enabled'] or not conf['mode']: - # disable unconfigured ports - ports[port] = { - 'disabled': True, - 'description': conf.get('description', ''), - } - # dont add vlans for this port - continue - else: - ports[port] = { - 'disabled': False, - 'description': conf.get('description', ''), - } - if conf.get('ips', []): - ports[port]['ips'] = set(conf['ips']) - if conf['type'] in ( - '1000base-t', - '10gbase-x-sfpp', - 'A_1000BASE_T', - 'A_10GBASE_X_SFPP', - ): - ports[port]['hw'] = True - - if conf['untagged_vlan']: - vlans[conf['untagged_vlan']]['untagged'].add(port) - if conf['ips']: - # this makes management services available in the VLAN - vlans[conf['untagged_vlan']]['tagged'].add('bridge') - - # tagged - - if conf['mode'] in ('TAGGED_ALL', 'tagged-all'): - tagged = set(vlans.keys()) - {conf['untagged_vlan']} - else: - tagged = conf['tagged_vlans'] - - for vlan in tagged: - vlans[vlan]['tagged'].add(port) - - # this makes management services available in the VLAN - if conf['ips']: - vlans[vlan]['tagged'].add('bridge') - defaults = { 'icinga2_api': { 'routeros': { @@ -95,14 +17,100 @@ defaults = { }, }, }, - 'routeros': { - 'ips': ips, - 'ports': ports, - 'vlans': vlans, - }, } +@metadata_reactor.provides( + 'routeros/ips', + 'routeros/ports', + 'routeros/vlans', +) +def get_ports_from_netbox_dump(metadata): + with open(join(repo.path, 'configs', f'netbox_device_{node.name}.json')) as f: + netbox = load(f) + + ips = {} + ports = {} + vlans = { + v['name']: { + 'id': v['vid'], + 'delete': False, + 'tagged': set(), + 'untagged': set(), + } + for v in netbox['vlans'] + } + + for port, conf in netbox['interfaces'].items(): + for ip in conf['ips']: + ips[ip] = {'interface': port} + + if conf['type'] == 'VIRTUAL': + # these are VLAN interfaces (for management IPs) + if conf['ips']: + # this makes management services available in the VLAN + try: + vlans[port]['tagged'].add('bridge') + except KeyError: + raise ValueError( + f'name of virtual interface "{port}" on {node.name} ' + f'matches none of the known VLANs: {list(vlans.keys())} ' + '(you probably need to rename the interface in Netbox ' + 'and/or run netbox-dump)' + ) + # We do not create the actual VLAN interface here, that + # happens automatically in items.py. + continue + elif not conf['enabled'] or not conf['mode']: + # disable unconfigured ports + ports[port] = { + 'disabled': True, + 'description': conf.get('description', ''), + } + # dont add vlans for this port + continue + else: + ports[port] = { + 'disabled': False, + 'description': conf.get('description', ''), + } + if conf.get('ips', []): + ports[port]['ips'] = set(conf['ips']) + if conf['type'] in ( + 'A_1000BASE_T', + 'A_10GBASE_X_SFPP', + ): + ports[port]['hw'] = True + + if conf['untagged_vlan']: + vlans[conf['untagged_vlan']]['untagged'].add(port) + if conf['ips']: + # this makes management services available in the VLAN + vlans[conf['untagged_vlan']]['tagged'].add('bridge') + + # tagged + + if conf['mode'] == 'TAGGED_ALL': + tagged = set(vlans.keys()) - {conf['untagged_vlan']} + else: + tagged = conf['tagged_vlans'] + + for vlan in tagged: + vlans[vlan]['tagged'].add(port) + + # this makes management services available in the VLAN + if conf['ips']: + vlans[vlan]['tagged'].add('bridge') + + return { + 'routeros': { + 'ips': ips, + 'ports': ports, + 'vlans': vlans, + } + } + + @metadata_reactor.provides('routeros/gateway') def gateway(metadata): ip_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.)\d{1,3}') diff --git a/bundles/rspamd/files/local.d/dmarc.conf b/bundles/rspamd/files/local.d/dmarc.conf index 195361e..fa42ec0 100644 --- a/bundles/rspamd/files/local.d/dmarc.conf +++ b/bundles/rspamd/files/local.d/dmarc.conf @@ -1,7 +1,7 @@ reporting { enabled = true; - email = 'devnull@${node.metadata.get('postfix/myhostname')}'; - domain = '${node.metadata.get('postfix/myhostname')}'; + email = 'dmarc+${node.name.replace('.', '-')}@kunbox.net'; + domain = '${node.metadata.get('hostname')}'; org_name = 'kunbox.net'; smtp = '127.0.0.1'; smtp_port = 25; diff --git a/bundles/rspamd/files/local.d/greylist.conf b/bundles/rspamd/files/local.d/greylist.conf deleted file mode 100644 index a6ee831..0000000 --- a/bundles/rspamd/files/local.d/greylist.conf +++ /dev/null @@ -1 +0,0 @@ -enabled = false; diff --git a/bundles/rspamd/items.py b/bundles/rspamd/items.py index 2f9aacb..8fa793c 100644 --- a/bundles/rspamd/items.py +++ b/bundles/rspamd/items.py @@ -96,12 +96,12 @@ 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': { 'command': 'chown _rspamd:_rspamd /var/lib/rspamd/dkim/*.key', - 'unless': r'test -z "$(find /var/lib/rspamd/ -iname \"*.key\" \! -user _rspamd)"', + 'unless': 'test -z "$(find /var/lib/rspamd/ -iname \"*.key\" \! -user _rspamd)"', 'needs': { 'action:rspamd_generate_dkim_key', 'directory:/var/lib/rspamd/dkim', diff --git a/bundles/rsyslogd/files/logrotate.conf b/bundles/rsyslogd/files/logrotate.conf deleted file mode 100644 index 66c90fa..0000000 --- a/bundles/rsyslogd/files/logrotate.conf +++ /dev/null @@ -1,10 +0,0 @@ -/var/log/rsyslog/*/*.log -{ - rotate 30 - daily - missingok - notifempty - compress - delaycompress - copytruncate -} diff --git a/bundles/rsyslogd/files/rsyslog.conf b/bundles/rsyslogd/files/rsyslog.conf deleted file mode 100644 index b7ca916..0000000 --- a/bundles/rsyslogd/files/rsyslog.conf +++ /dev/null @@ -1,18 +0,0 @@ -# provides UDP syslog reception -module(load="imudp") -input(type="imudp" port="514") - -# provides TCP syslog reception -module(load="imtcp") -input(type="imtcp" port="514") - -$FileOwner root -$FileGroup adm -$FileCreateMode 0640 -$DirCreateMode 0755 -$Umask 0022 - -$WorkDirectory /var/spool/rsyslog - -$template remote-incoming-logs,"/var/log/rsyslog/%HOSTNAME%/%PROGRAMNAME%.log" -*.* ?remote-incoming-logs diff --git a/bundles/rsyslogd/items.py b/bundles/rsyslogd/items.py deleted file mode 100644 index 1ef2572..0000000 --- a/bundles/rsyslogd/items.py +++ /dev/null @@ -1,18 +0,0 @@ -files['/etc/logrotate.d/rsyslog'] = { - 'source': 'logrotate.conf', -} - -files['/etc/rsyslog.conf'] = { - 'triggers': { - 'svc_systemd:rsyslog:restart', - }, -} - -svc_systemd['rsyslog'] = { - 'needs': { - 'pkg_apt:rsyslog', - }, - 'after': { - 'file:/etc/rsyslog.conf', - }, -} diff --git a/bundles/rsyslogd/metadata.py b/bundles/rsyslogd/metadata.py deleted file mode 100644 index 877e93b..0000000 --- a/bundles/rsyslogd/metadata.py +++ /dev/null @@ -1,37 +0,0 @@ -from bundlewrap.metadata import atomic - -defaults = { - 'apt': { - 'packages': { - 'rsyslog': {}, - }, - }, - 'backups': { - 'paths': { - '/var/log/rsyslog', - }, - }, - 'icinga2_api': { - 'rsyslog': { - 'services': { - 'RSYSLOGD PROCESS': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit rsyslog', - }, - }, - }, - }, -} - - -@metadata_reactor.provides( - 'firewall/port_rules', -) -def firewall(metadata): - return { - 'firewall': { - 'port_rules': { - '514/tcp': atomic(metadata.get('rsyslogd/restrict-to', set())), - '514/udp': atomic(metadata.get('rsyslogd/restrict-to', set())), - }, - }, - } diff --git a/bundles/samba/files/override.conf b/bundles/samba/files/override.conf deleted file mode 100644 index 35693b4..0000000 --- a/bundles/samba/files/override.conf +++ /dev/null @@ -1,3 +0,0 @@ -[Service] -RestartSec=10 -Restart=on-failure diff --git a/bundles/samba/files/smb.conf b/bundles/samba/files/smb.conf deleted file mode 100644 index 7c4ad0b..0000000 --- a/bundles/samba/files/smb.conf +++ /dev/null @@ -1,67 +0,0 @@ -[global] -workgroup = KUNBOX -server string = ${node.name} samba -dns proxy = no -max log size = 1000 -syslog = 1 -syslog only = 1 -panic action = /usr/share/samba/panic-action %d -encrypt passwords = true -passdb backend = tdbsam -obey pam restrictions = yes -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}] -browseable = yes -comment = ${opts.get('comment', f'share of {opts["path"]}')} -fake oplocks = yes -force group = ${opts.get('force_group', 'nogroup')} -force user = ${opts.get('force_user', 'nobody')} -% if opts.get('guest_ok', True): -guest ok = yes -% else: -guest ok = no -% endif -locking = no -path = ${opts['path']} -printable = no -read only = no -vfs objects = catia fruit -writable = ${'yes' if opts.get('writable', False) else 'no'} -% if opts.get('follow_symlinks', True): -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 diff --git a/bundles/samba/files/timemachine.service b/bundles/samba/files/timemachine.service deleted file mode 100644 index d25e6e5..0000000 --- a/bundles/samba/files/timemachine.service +++ /dev/null @@ -1,21 +0,0 @@ - - - - %h - - _smb._tcp - 445 - - - _device-info._tcp - 0 - model=RackMac1,2 - - - _adisk._tcp -% for idx, share_name in enumerate(sorted(shares)): - dk${idx}=adVN=timemachine-${share_name},adVF=0x82 -% endfor - sys=waMa=0,adVF=0x100 - - diff --git a/bundles/samba/items.py b/bundles/samba/items.py deleted file mode 100644 index 2f5090e..0000000 --- a/bundles/samba/items.py +++ /dev/null @@ -1,91 +0,0 @@ -svc_systemd = { - 'nmbd': { - 'needs': { - 'pkg_apt:samba', - }, - }, - 'smbd': { - 'needs': { - 'pkg_apt:samba', - }, - }, -} - -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', - }, - }, - '/etc/systemd/system/nmbd.service.d/bundlewrap.conf': { - 'source': 'override.conf', - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:nmbd:restart', - }, - }, - '/etc/systemd/system/smbd.service.d/bundlewrap.conf': { - 'source': 'override.conf', - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:smbd:restart', - }, - }, -} - -last_action = set() -for user, uconfig in node.metadata.get('users', {}).items(): - if ( - 'password' not in uconfig - or uconfig.get('delete') - or user in ('root',) - ): - continue - - actions[f'smbpasswd_for_user_{user}'] = { - 'command': f'smbpasswd -a -s {user}', - 'unless': f'pdbedit -L | grep -E "^{user}:"', - 'data_stdin': uconfig['password'] + '\n' + uconfig['password'], - 'needs': { - 'pkg_apt:samba', - f'user:{user}', - }, - 'after': last_action, - } - 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' - - for share, share_config in node.metadata.get('samba/shares', {}).items(): - assert not share_config.get('guest_ok', True), f'{node.name} samba {share}: cannot have time machine shares and "guest ok" shares on the same machine' - - 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', - 'needs': { - f'zfs_dataset:tank/timemachine/{share_name}', - }, - } diff --git a/bundles/samba/metadata.py b/bundles/samba/metadata.py deleted file mode 100644 index c8243af..0000000 --- a/bundles/samba/metadata.py +++ /dev/null @@ -1,53 +0,0 @@ -from bundlewrap.metadata import atomic - -defaults = { - 'apt': { - 'packages': { - 'samba': {}, - 'samba-vfs-modules': {}, - } - } -} - - -@metadata_reactor.provides( - 'firewall/port_rules', -) -def firewall(metadata): - return { - 'firewall': { - 'port_rules': { - '137/udp': atomic(metadata.get('samba/restrict-to', set())), - '138/udp': atomic(metadata.get('samba/restrict-to', set())), - '139/tcp': atomic(metadata.get('samba/restrict-to', set())), - '445/tcp': atomic(metadata.get('samba/restrict-to', set())), - }, - }, - } - - -@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, - }, - } diff --git a/bundles/scansnap/files/ocr.sh b/bundles/scansnap/files/ocr.sh new file mode 100644 index 0000000..04e98f9 --- /dev/null +++ b/bundles/scansnap/files/ocr.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -euo pipefail + +DATE=$(date +%F_%H-%M-%S) + +cd "$1" + +convert *.tiff no_ocr.pdf +ocrmypdf -l deu no_ocr.pdf has_ocr.pdf + +rm -f *.tiff +rm -f no_ocr.pdf + +chown nobody:nogroup has_ocr.pdf + +mv has_ocr.pdf "/srv/scansnap/${DATE}.pdf" + +cd / + +rm -r "$1" diff --git a/bundles/scansnap/files/scan.sh b/bundles/scansnap/files/scan.sh new file mode 100644 index 0000000..ab5800f --- /dev/null +++ b/bundles/scansnap/files/scan.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -euo pipefail + +OUTFILE=$(mktemp -d) + +scanimage --source 'ADF Duplex' --format tiff --mode Color --brightness 23 --resolution 300 --page-width 210 --page-height 297.3 -x 210 -y 297.3 --batch=${OUTFILE}/p%04d.tiff + +/etc/scanbd/scripts/ocr.sh "$OUTFILE" & diff --git a/bundles/scansnap/files/scanbd.conf b/bundles/scansnap/files/scanbd.conf new file mode 100644 index 0000000..f425338 --- /dev/null +++ b/bundles/scansnap/files/scanbd.conf @@ -0,0 +1,52 @@ +global { + debug = true + debug-level = 2 + + user = saned + group = scanner + + saned = "/usr/sbin/saned" + saned_opt = {} + saned_env = { "SANE_CONFIG_DIR=/etc/scanbd" } + + scriptdir = /etc/scanbd/scripts + + timeout = 500 + + pidfile = "/var/run/scanbd.pid" + + environment { + device = "SCANBD_DEVICE" + action = "SCANBD_ACTION" + } + + function function_knob { + filter = "^message.*" + desc = "The value of the function knob / wheel / selector" + env = "SCANBD_FUNCTION" + } + function function_mode { + filter = "^mode.*" + desc = "Color mode" + env = "SCANBD_FUNCTION_MODE" + } + + multiple_actions = false + action scan { + filter = "^scan.*" + numerical-trigger { + from-value = 0 + to-value = 1 + } + desc = "Scan to file" + script = "scan.sh" + } +} + +include(scanner.d/avision.conf) +include(scanner.d/fujitsu.conf) +include(scanner.d/hp.conf) +include(scanner.d/pixma.conf) +include(scanner.d/snapscan.conf) +include(scanner.d/canon.conf) +include(scanner.d/plustek.conf) diff --git a/bundles/scansnap/items.py b/bundles/scansnap/items.py new file mode 100644 index 0000000..23f9305 --- /dev/null +++ b/bundles/scansnap/items.py @@ -0,0 +1,39 @@ +directories = { + '/etc/scanbd/scripts': { + 'purge': True, + }, + '/srv/scansnap': { + 'owner': 'nobody', + 'group': 'nogroup', + }, +} + +files = { + '/etc/scanbd/scanbd.conf': { + 'triggers': { + 'svc_systemd:scanbd:restart', + }, + }, + '/etc/scanbd/scripts/ocr.sh': { + 'mode': '0755', + 'needs': { + 'directory:/srv/scansnap', + }, + }, + '/etc/scanbd/scripts/scan.sh': { + 'mode': '0755', + 'needs': { + 'directory:/srv/scansnap', + 'file:/etc/scanbd/scripts/ocr.sh', + }, + }, +} + +svc_systemd = { + 'scanbd': { + 'needs': { + 'file:/etc/scanbd/scanbd.conf', + 'pkg_apt:scanbd', + }, + }, +} diff --git a/bundles/scansnap/metadata.py b/bundles/scansnap/metadata.py new file mode 100644 index 0000000..b1d5535 --- /dev/null +++ b/bundles/scansnap/metadata.py @@ -0,0 +1,22 @@ +defaults = { + 'apt': { + 'packages': { + 'sane-utils': {}, + 'scanbd': {}, + 'imagemagick': {}, + 'ocrmypdf': {}, + 'tesseract-ocr-deu': {}, + }, + }, + 'backups': { + 'paths': { + '/srv/scansnap', + }, + }, + 'cron': { + 'jobs': { + # Automatically remove files which are older than 14 days + 'scansnap_cleanup': '00 00 * * * root /usr/bin/find /srv/scansnap/ -mindepth 1 -mtime +14 -delete', + }, + }, +} diff --git a/bundles/sdm630_mqtt/files/sdm630_printout.service b/bundles/sdm630_mqtt/files/sdm630_printout.service deleted file mode 100644 index 8ba5a23..0000000 --- a/bundles/sdm630_mqtt/files/sdm630_printout.service +++ /dev/null @@ -1,21 +0,0 @@ -[Unit] -Description=SDM630 stats printout -Conflicts=getty@tty1.service -After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service - -[Service] -User=sdm630_mqtt -Group=sdm630_mqtt -ExecStart=/opt/sdm630_mqtt/venv/bin/python printout.py /opt/sdm630_mqtt/config.toml -WorkingDirectory=/opt/sdm630_mqtt/src -Restart=always -RestartSec=10 -StandardInput=tty -StandardOutput=tty -StandardError=journal -TTYPath=/dev/tty1 -TTYReset=yes -TTYVHangup=yes - -[Install] -WantedBy=multi-user.target diff --git a/bundles/sdm630_mqtt/files/sdm630_to_mqtt.service b/bundles/sdm630_mqtt/files/sdm630_to_mqtt.service deleted file mode 100644 index b1e67d7..0000000 --- a/bundles/sdm630_mqtt/files/sdm630_to_mqtt.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=SDM630-to-MQTT bridge -After=network.target - -[Service] -User=sdm630_mqtt -Group=sdm630_mqtt -ExecStart=/opt/sdm630_mqtt/venv/bin/python sdm630_mqtt.py /opt/sdm630_mqtt/config.toml -WorkingDirectory=/opt/sdm630_mqtt/src -Restart=always -RestartSec=1 - -[Install] -WantedBy=multi-user.target diff --git a/bundles/sdm630_mqtt/items.py b/bundles/sdm630_mqtt/items.py deleted file mode 100644 index 6a691c9..0000000 --- a/bundles/sdm630_mqtt/items.py +++ /dev/null @@ -1,76 +0,0 @@ -directories['/opt/sdm630_mqtt/src'] = {} - -git_deploy['/opt/sdm630_mqtt/src'] = { - 'repo': 'https://git.franzi.business/kunsi/sdm630_mqtt.git', - 'rev': 'main', - 'triggers': { - 'action:sdm630_mqtt_install_deps', - }, -} - -actions['sdm630_mqtt_create_virtualenv'] = { - 'command': 'python3 -m virtualenv /opt/sdm630_mqtt/venv', - 'unless': 'test -x /opt/sdm630_mqtt/venv/bin/python3', - 'needs': { - 'directory:/opt/sdm630_mqtt/src', - }, -} - -actions['sdm630_mqtt_install_deps'] = { - 'command': 'cd /opt/sdm630_mqtt/src && /opt/sdm630_mqtt/venv/bin/pip install -r requirements.txt', - 'triggered': True, - 'needs': { - 'action:sdm630_mqtt_create_virtualenv', - }, -} - -users['sdm630_mqtt'] = { - 'home': '/opt/sdm630_mqtt', -} - -files['/opt/sdm630_mqtt/config.toml'] = { - 'content': repo.libs.faults.dict_as_toml(node.metadata.get('sdm630_mqtt/config')), - 'triggers': set(), -} - -if node.has_bundle('telegraf'): - files['/opt/sdm630_mqtt/config.toml']['triggers'].add('svc_systemd:telegraf:restart') - git_deploy['/opt/sdm630_mqtt/src']['triggers'].add('svc_systemd:telegraf:restart') - -if node.metadata.get('sdm630_mqtt/enable_stats_collection', True): - files['/usr/local/lib/systemd/system/sdm630_to_mqtt.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:sdm630_to_mqtt:restart', - }, - } - - svc_systemd['sdm630_to_mqtt'] = { - 'needs': { - 'git_deploy:/opt/sdm630_mqtt/src', - 'action:sdm630_mqtt_install_deps', - 'file:/usr/local/lib/systemd/system/sdm630_to_mqtt.service', - }, - } - - files['/opt/sdm630_mqtt/config.toml']['triggers'].add('svc_systemd:sdm630_to_mqtt:restart') - git_deploy['/opt/sdm630_mqtt/src']['triggers'].add('svc_systemd:sdm630_to_mqtt:restart') - -if node.metadata.get('sdm630_mqtt/enable_local_printout', False): - files['/usr/local/lib/systemd/system/sdm630_printout.service'] = { - 'triggers': { - 'action:systemd-reload', - 'svc_systemd:sdm630_printout:restart', - }, - } - - svc_systemd['sdm630_printout'] = { - 'needs': { - 'git_deploy:/opt/sdm630_mqtt/src', - 'action:sdm630_mqtt_install_deps', - 'file:/usr/local/lib/systemd/system/sdm630_printout.service', - }, - } - - files['/opt/sdm630_mqtt/config.toml']['triggers'].add('svc_systemd:sdm630_printout:restart') - git_deploy['/opt/sdm630_mqtt/src']['triggers'].add('svc_systemd:sdm630_printout:restart') diff --git a/bundles/sdm630_mqtt/metadata.py b/bundles/sdm630_mqtt/metadata.py deleted file mode 100644 index 944b8b2..0000000 --- a/bundles/sdm630_mqtt/metadata.py +++ /dev/null @@ -1,38 +0,0 @@ -defaults = { - 'sdm630_mqtt': { - 'config': { - 'modbus': { - 'host': '127.0.0.1', - 'port': 501, - 'unit_id': 1, - }, - 'mqtt': { - 'prefix': 'sdm630', - 'host': '127.0.0.1', - 'port': 1883, - }, - 'printout': { - 'title': 'SDM630', - }, - 'telegraf': { - 'identifier': 'unknown', - }, - }, - }, - 'telegraf': { - 'input_plugins': { - 'execd': { - 'sdm630_mqtt': { - 'command': [ - '/opt/sdm630_mqtt/venv/bin/python', - '/opt/sdm630_mqtt/src/telegraf.py', - '/opt/sdm630_mqtt/config.toml', - ], - 'signal': 'none', - 'restart_delay': '1s', - 'data_format': 'influx', - }, - }, - }, - }, -} diff --git a/bundles/seafile/files/seafile.service b/bundles/seafile/files/seafile.service new file mode 100644 index 0000000..5b0a959 --- /dev/null +++ b/bundles/seafile/files/seafile.service @@ -0,0 +1,13 @@ +[Unit] +Description=Seafile +After=network.target mysql.service + +[Service] +Type=forking +ExecStart=/opt/seafile/seafile-server-latest/seafile.sh start +ExecStop=/opt/seafile/seafile-server-latest/seafile.sh stop +User=seafile +Group=seafile + +[Install] +WantedBy=multi-user.target diff --git a/bundles/seafile/files/seahub.service b/bundles/seafile/files/seahub.service new file mode 100644 index 0000000..b554599 --- /dev/null +++ b/bundles/seafile/files/seahub.service @@ -0,0 +1,13 @@ +[Unit] +Description=Seafile hub +After=network.target seafile.service + +[Service] +Type=forking +ExecStart=/opt/seafile/seafile-server-latest/seahub.sh start +ExecStop=/opt/seafile/seafile-server-latest/seahub.sh stop +User=seafile +Group=seafile + +[Install] +WantedBy=multi-user.target diff --git a/bundles/seafile/items.py b/bundles/seafile/items.py new file mode 100644 index 0000000..24c6c72 --- /dev/null +++ b/bundles/seafile/items.py @@ -0,0 +1,41 @@ +users = { + 'seafile': { + 'home': '/opt/seafile', + }, +} + +directories = { + '/opt/seafile': { + 'mode': '0755', + 'owner': 'seafile', + 'group': 'seafile', + }, +} + +files = { + '/etc/systemd/system/seafile.service': { + 'needed_by': { + 'svc_systemd:seafile', + }, + 'triggers': { + 'action:systemd-reload', + }, + }, + '/etc/systemd/system/seahub.service': { + 'needed_by': { + 'svc_systemd:seafile', + }, + 'triggers': { + 'action:systemd-reload', + }, + }, +} + +svc_systemd = { + 'seafile': {}, + 'seahub': { + 'needs': { + 'svc_systemd:seafile', + }, + }, +} diff --git a/bundles/seafile/metadata.py b/bundles/seafile/metadata.py new file mode 100644 index 0000000..66a586d --- /dev/null +++ b/bundles/seafile/metadata.py @@ -0,0 +1,27 @@ +defaults = { + 'apt': { + 'packages': { + 'mariadb-server': {}, + 'python3': {}, + 'python3-setuptools': {}, + 'python3-pip': {}, + }, + }, + 'backups': { + 'paths': { + '/opt/seafile', + }, + }, + 'icinga2_api': { + 'seafile': { + 'services': { + 'SEAFILE PROCESS': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit seafile', + }, + 'SEAHUB PROCESS': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit seahub', + }, + }, + }, + }, +} diff --git a/bundles/simple-icinga-dashboard/files/config.toml b/bundles/simple-icinga-dashboard/files/config.toml new file mode 100644 index 0000000..b72063a --- /dev/null +++ b/bundles/simple-icinga-dashboard/files/config.toml @@ -0,0 +1,4 @@ +<% + from tomlkit import dumps as toml_dumps + from bundlewrap.utils.text import toml_clean +%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(node.metadata['simple-icinga-dashboard']), sort_keys=True))} diff --git a/bundles/simple-icinga-dashboard/items.py b/bundles/simple-icinga-dashboard/items.py index a2b6f47..74f05db 100644 --- a/bundles/simple-icinga-dashboard/items.py +++ b/bundles/simple-icinga-dashboard/items.py @@ -43,8 +43,18 @@ git_deploy = { } files = { + '/etc/systemd/system/simple-icinga-dashboard.service': { + 'triggers': { + 'action:systemd-reload', + }, + }, + '/etc/systemd/system/simple-icinga-dashboard.timer': { + 'triggers': { + 'action:systemd-reload', + }, + }, '/opt/simple-icinga-dashboard/config.toml': { - 'content': repo.libs.faults.dict_as_toml(node.metadata.get('simple-icinga-dashboard')), + 'content_type': 'mako', 'needs': { 'git_deploy:/opt/simple-icinga-dashboard/src', }, @@ -59,3 +69,13 @@ symlinks = { }, }, } + +svc_systemd = { + 'simple-icinga-dashboard.timer': { + 'needs': { + 'action:simple-icinga-dashboard_install_requirements', + 'file:/etc/systemd/system/simple-icinga-dashboard.service', + 'file:/etc/systemd/system/simple-icinga-dashboard.timer', + }, + }, +} diff --git a/bundles/simple-icinga-dashboard/metadata.py b/bundles/simple-icinga-dashboard/metadata.py index 91c5cf5..1d1b905 100644 --- a/bundles/simple-icinga-dashboard/metadata.py +++ b/bundles/simple-icinga-dashboard/metadata.py @@ -11,17 +11,4 @@ defaults = { 'filename': '/opt/simple-icinga-dashboard/out/index.html', }, }, - 'systemd-timers': { - 'timers': { - 'simple-icinga-dashboard': { - 'when': 'minutely', - 'command': '/opt/simple-icinga-dashboard/venv/bin/python /opt/simple-icinga-dashboard/src/service.py', - 'pwd': '/opt/simple-icinga-dashboard/src/', - 'user': 'icinga_dashboard', - 'environment': { - 'STATUSPAGE_CONFIG': '/opt/simple-icinga-dashboard/config.toml', - }, - }, - }, - }, } diff --git a/bundles/smartd/files/telegraf_plugin b/bundles/smartd/files/telegraf_plugin index 46144bf..5bd10f2 100644 --- a/bundles/smartd/files/telegraf_plugin +++ b/bundles/smartd/files/telegraf_plugin @@ -29,16 +29,10 @@ for device in devices: if 'nvme_smart_health_information_log' in json: for k, v in json['nvme_smart_health_information_log'].items(): - if not str(v).isdigit(): - continue - telegraf_output.add(f'{k}={v}') if 'ata_smart_attributes' in json: for entry in json['ata_smart_attributes']['table']: - if not str(entry['raw']['value']).isdigit(): - continue - telegraf_output.add('{}={}'.format( entry['name'], entry['raw']['value'], diff --git a/bundles/smartd/items.py b/bundles/smartd/items.py index e18270f..540a6a9 100644 --- a/bundles/smartd/items.py +++ b/bundles/smartd/items.py @@ -2,7 +2,7 @@ files = { '/etc/smartd.conf': { 'content_type': 'mako', 'triggers': { - 'svc_systemd:smartmontools:reload', + 'svc_systemd:smartd:reload', }, }, '/usr/local/share/icinga/plugins/check_smart': { @@ -15,5 +15,7 @@ files = { } svc_systemd = { - 'smartmontools': {}, + 'smartd': { + 'enabled': None, # FIXME this is symlinked to smartmontools.service on bullseye + }, } diff --git a/bundles/smartd/metadata.py b/bundles/smartd/metadata.py index 5202068..63af59a 100644 --- a/bundles/smartd/metadata.py +++ b/bundles/smartd/metadata.py @@ -1,16 +1,14 @@ -from re import search - defaults = { 'apt': { 'packages': { 'smartmontools': { 'needed_by': { - 'svc_systemd:smartmontools', + 'svc_systemd:smartd', }, }, 'nvme-cli': { 'needed_by': { - 'svc_systemd:smartmontools', + 'svc_systemd:smartd', }, }, }, @@ -19,7 +17,7 @@ defaults = { 'smartd': { 'services': { 'SMARTD PROCESS': { - 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit smartmontools', + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_systemd_unit smartd', }, }, }, @@ -43,6 +41,27 @@ if node.has_bundle('telegraf'): } +@metadata_reactor.provides( + 'smartd/disks', +) +def zfs_disks_to_metadata(metadata): + disks = set() + + for config in metadata.get('zfs/pools', {}).values(): + for option in config['when_creating']['config']: + if option.get('type', '') in {'log', 'cache'}: + continue + + for disk in option['devices']: + disks.add(disk) + + return { + 'smartd': { + 'disks': disks, + }, + } + + @metadata_reactor.provides( 'icinga2_api/smartd/services', ) @@ -65,19 +84,21 @@ def icinga(metadata): @metadata_reactor.provides( - 'systemd-timers/timers', + 'cron/jobs/smartd', ) def monthly_long_test(metadata): - timers = {} + lines = set() - for day, disk in enumerate(sorted(metadata.get('smartd/disks', set())), start=1): - timers[f'smartd{disk.replace("/", "-")}'] = { - 'command': f'/usr/sbin/smartctl --test=long {disk}', - 'when': f'*-*-{day} 03:00:00 UTC', - } + for number, disk in enumerate(sorted(metadata.get('smartd/disks', set()))): + lines.add('0 3 {} * * root /usr/sbin/smartctl --test=long {} >/dev/null'.format( + number+1, # enumerate() starts at 0 + disk, + )) return { - 'systemd-timers': { - 'timers': timers, + 'cron': { + 'jobs': { + 'smartd': '\n'.join(sorted(lines)), + }, }, } diff --git a/bundles/sshmon/files/check_cpu_stats b/bundles/sshmon/files/check_cpu_stats index f0c3a35..36e5ae3 100644 --- a/bundles/sshmon/files/check_cpu_stats +++ b/bundles/sshmon/files/check_cpu_stats @@ -4,30 +4,27 @@ from re import findall from subprocess import check_output from sys import exit -ITERATIONS = 10 - try: top_output = None - top_output = check_output(rf"top -b -n{ITERATIONS} -d1 | grep -i '^%cpu'", shell=True).decode('UTF-8') + for line in check_output(['top', '-b', '-n1', '-d1']).decode('UTF-8').splitlines(): + if line.lower().strip().startswith('%cpu'): + top_output = line.lower().split(':', 2)[1] + break + + if not top_output: + print('%cpu not found in top output') + exit(3) cpu_usage = {} - for value, identifier in findall(r'([0-9\.\,]{3,5}) ([a-z]{2})', top_output): - if identifier not in cpu_usage: - cpu_usage[identifier] = 0.0 - cpu_usage[identifier] += float(value.replace(',', '.')) - - output = [] - for identifier, value_added in cpu_usage.items(): - value = value_added / ITERATIONS - output.append(f"{value:.2f} {identifier}") - cpu_usage[identifier] = value - - print(f"Average over {ITERATIONS} seconds: " + ", ".join(output)) + for value, identifier in findall('([0-9\.\,]{3,5}) ([a-z]{2})', top_output): + cpu_usage[identifier] = float(value.replace(',', '.')) warn = set() crit = set() + print(top_output) + # steal if cpu_usage['st'] > 10: crit.add('CPU steal is {}% (>10%)'.format(cpu_usage['st'])) diff --git a/bundles/sshmon/files/check_forgejo_for_new_release b/bundles/sshmon/files/check_forgejo_for_new_release index 99dcd30..3db5bcd 100644 --- a/bundles/sshmon/files/check_forgejo_for_new_release +++ b/bundles/sshmon/files/check_forgejo_for_new_release @@ -38,10 +38,10 @@ try: for i in releases: if i["tag_name"].startswith(tag_prefix): - if not (i["prerelease"] or i["draft"]) and ( + if ( newest_release is None or parse(i["tag_name"]) > parse(newest_release["tag_name"]) - ): + ) and not (i["prerelease"] or i["draft"]): newest_release = i assert newest_release is not None, "Could not determine latest release" diff --git a/bundles/sshmon/files/check_github_for_new_release b/bundles/sshmon/files/check_github_for_new_release index ec510de..3a50d94 100644 --- a/bundles/sshmon/files/check_github_for_new_release +++ b/bundles/sshmon/files/check_github_for_new_release @@ -37,10 +37,10 @@ try: for i in releases: if i["tag_name"].startswith(tag_prefix): - if not (i["prerelease"] or i["draft"]) and ( + if ( newest_release is None or parse(i["tag_name"]) > parse(newest_release["tag_name"]) - ): + ) and not (i["prerelease"] or i["draft"]): newest_release = i assert newest_release is not None, "Could not determine latest release" diff --git a/bundles/sshmon/files/check_https_certificate_at_url b/bundles/sshmon/files/check_https_certificate_at_url index ce0f0ba..7c22cfe 100644 --- a/bundles/sshmon/files/check_https_certificate_at_url +++ b/bundles/sshmon/files/check_https_certificate_at_url @@ -19,11 +19,7 @@ crit_days=30 case "$issuer_hash" in # 4f06f81d: issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 # 8d33f237: issuer=C = US, O = Let's Encrypt, CN = R3 - # 462422cf: issuer=C = US, O = Let's Encrypt, CN = E5 - # 9aad238c: issuer=C = US, O = Let's Encrypt, CN = E6 - # 31dfb39d: issuer=C = US, O = Let's Encrypt, CN = R11 - # aa578057: issuer=C = US, O = Let's Encrypt, CN = R10 - 4f06f81d|8d33f237|462422cf|9aad238c|31dfb39d|aa578057) + 4f06f81d|8d33f237) warn_days=10 crit_days=3 ;; diff --git a/bundles/sshmon/items.py b/bundles/sshmon/items.py index be9a9a4..3250f39 100644 --- a/bundles/sshmon/items.py +++ b/bundles/sshmon/items.py @@ -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', + }, + } diff --git a/bundles/sshmon/metadata.py b/bundles/sshmon/metadata.py index 3026479..8d5bb6b 100644 --- a/bundles/sshmon/metadata.py +++ b/bundles/sshmon/metadata.py @@ -19,8 +19,6 @@ defaults = { 'services': { 'CPU': { 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_cpu_stats', - # takes samples over 10 seconds - 'vars.sshmon_timeout': 20 }, 'LOAD': { 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_load -r -w 4,2,1 -c 8,4,2', @@ -36,6 +34,14 @@ defaults = { 'sshmon', }, }, + 'pacman': { + 'packages': { + 'gawk': {}, + 'perl-libwww': {}, + 'monitoring-plugins': {}, + 'python-requests': {}, + }, + }, } diff --git a/bundles/sudo/files/bwusers b/bundles/sudo/files/bwusers index 00dfafa..6c47ecd 100644 --- a/bundles/sudo/files/bwusers +++ b/bundles/sudo/files/bwusers @@ -1,5 +1,9 @@ % for user, config in sorted(node.metadata['users'].items()): -% for p in sorted(config.get('sudo_commands', [])): +% if config.get('is_admin', False): +${user} ALL=(ALL) NOPASSWD:ALL +% else: +% for p in sorted(config.get('sudo_commands', [])): ${user} ALL=(ALL) NOPASSWD:${p} -% endfor +% endfor +% endif % endfor diff --git a/bundles/sudo/metadata.py b/bundles/sudo/metadata.py index e76edaf..82b007d 100644 --- a/bundles/sudo/metadata.py +++ b/bundles/sudo/metadata.py @@ -4,4 +4,9 @@ defaults = { 'sudo': {}, }, }, + 'pacman': { + 'packages': { + 'sudo': {}, + }, + }, } diff --git a/bundles/sysctl/items.py b/bundles/sysctl/items.py index ee63cf0..c4c448c 100644 --- a/bundles/sysctl/items.py +++ b/bundles/sysctl/items.py @@ -20,14 +20,6 @@ files = { }, } -if node.os == 'debian' and node.os_version < (13,): - # debian insists on creating that file during almost every - # unattended-upgrades run. Make it known to bundlewrap, so - # it does not get removed during applies. - symlinks['/etc/sysctl.d/99-sysctl.conf'] = { - 'target': '../sysctl.conf', - } - directories = { '/etc/sysctl.d': { 'purge': True, diff --git a/bundles/systemd-boot/files/entry b/bundles/systemd-boot/files/entry new file mode 100755 index 0000000..00d3d8f --- /dev/null +++ b/bundles/systemd-boot/files/entry @@ -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 diff --git a/bundles/systemd-boot/files/loader.conf b/bundles/systemd-boot/files/loader.conf new file mode 100755 index 0000000..b30de61 --- /dev/null +++ b/bundles/systemd-boot/files/loader.conf @@ -0,0 +1,5 @@ +auto-entries no +auto-firmware yes +console-mode keep +default ${config['default']} +timeout ${config.get('timeout', 5)} diff --git a/bundles/systemd-boot/files/pacman_hook b/bundles/systemd-boot/files/pacman_hook new file mode 100644 index 0000000..d65c027 --- /dev/null +++ b/bundles/systemd-boot/files/pacman_hook @@ -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 diff --git a/bundles/systemd-boot/items.py b/bundles/systemd-boot/items.py new file mode 100644 index 0000000..0f26d00 --- /dev/null +++ b/bundles/systemd-boot/items.py @@ -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, + } diff --git a/bundles/systemd-networkd/files/template-bridge.network b/bundles/systemd-networkd/files/template-bridge.network index d7ea47c..0487f79 100644 --- a/bundles/systemd-networkd/files/template-bridge.network +++ b/bundles/systemd-networkd/files/template-bridge.network @@ -3,6 +3,3 @@ Name=${' '.join(sorted(match))} [Network] Bridge=${bridge} - -[Link] -ActivationPolicy=always-up diff --git a/bundles/systemd-networkd/files/template-iface-dhcp.network b/bundles/systemd-networkd/files/template-iface-dhcp.network new file mode 100644 index 0000000..19fd0d8 --- /dev/null +++ b/bundles/systemd-networkd/files/template-iface-dhcp.network @@ -0,0 +1,27 @@ +<% + from ipaddress import ip_network +%>\ +[Match] +Name=${interface} + +[Network] +DHCP=yes +IPv6AcceptRA=yes + +[DHCPv4] +UseDomains=${str(config.get('use_dhcp_domains', False)).lower()} +UseHostname=no +UseMTU=${str(config.get('use_dhcp_mtu', True)).lower()} +UseNTP=${str(config.get('use_dhcp_ntp', False)).lower()} +UseTimezone=no + +% if config.get('send_hostname', True): +SendHostname=yes +Hostname=${node.name.split('.')[-1]} +% else: +SendHostname=no +% endif + +% if config.get('forwarding', False): +IPForward=yes +%endif diff --git a/bundles/systemd-networkd/files/template-iface.network b/bundles/systemd-networkd/files/template-iface-nodhcp.network similarity index 62% rename from bundles/systemd-networkd/files/template-iface.network rename to bundles/systemd-networkd/files/template-iface-nodhcp.network index cbb10b6..59c2d91 100644 --- a/bundles/systemd-networkd/files/template-iface.network +++ b/bundles/systemd-networkd/files/template-iface-nodhcp.network @@ -25,47 +25,30 @@ Destination=${route} GatewayOnlink=yes % endfor -% if not config.get('dhcp', False): -% if 'gateway4' in config: +% if 'gateway4' in config: [Route] Gateway=${config['gateway4']} GatewayOnlink=yes -% endif -% if 'gateway6' in config: +% endif +% if 'gateway6' in config: [Route] Gateway=${config['gateway6']} GatewayOnlink=yes -% endif % endif [Network] -% if config.get('ipv6_accept_ra', False) or config.get('dhcp', False): +DHCP=no +% if config.get('ipv6_accept_ra', False): IPv6AcceptRA=yes % else: IPv6AcceptRA=no % endif -% if config.get('dhcp', False): -DHCP=yes -IPv6AcceptRA=yes -[DHCPv4] -UseDomains=false -UseHostname=no -UseMTU=true -UseNTP=false -UseTimezone=no - -SendHostname=no -% else: -DHCP=no -% endif +% if config.get('forwarding', False): +IPForward=yes +%endif % for vlan in sorted(config.get('vlans', set())): VLAN=${interface}.${vlan} % endfor -% if 'activation_policy' in config: - -[Link] -ActivationPolicy=${config['activation_policy']} -% endif diff --git a/bundles/systemd-networkd/items.py b/bundles/systemd-networkd/items.py index 7bd0808..969c3e2 100644 --- a/bundles/systemd-networkd/items.py +++ b/bundles/systemd-networkd/items.py @@ -40,7 +40,9 @@ for interface, config in node.metadata.get('interfaces').items(): if config.get('dhcp', False): if 'vlans' in config: raise BundleError(f'{node.name} interface {interface} cannot use vlans and dhcp!') + template = 'template-iface-dhcp.network' else: + template = 'template-iface-nodhcp.network' all_interfaces_use_dhcp = False if '.' in interface: @@ -78,7 +80,7 @@ for interface, config in node.metadata.get('interfaces').items(): if not config.get('ignore', False): files[f'/etc/systemd/network/{interface}.network'] = { - 'source': 'template-iface.network', + 'source': template, 'content_type': 'mako', 'context': { 'interface': interface, diff --git a/bundles/systemd-networkd/metadata.py b/bundles/systemd-networkd/metadata.py index 6e67af9..46cd893 100644 --- a/bundles/systemd-networkd/metadata.py +++ b/bundles/systemd-networkd/metadata.py @@ -4,9 +4,6 @@ defaults = { 'isc-dhcp-client': { 'installed': False, }, - 'network-manager': { - 'installed': False, - }, 'resolvconf': { 'installed': False, }, diff --git a/bundles/systemd-timers/files/template.service b/bundles/systemd-timers/files/template.service index 271b756..6f7c444 100644 --- a/bundles/systemd-timers/files/template.service +++ b/bundles/systemd-timers/files/template.service @@ -1,17 +1,8 @@ -<% - if config.get('exclude_from_monitoring', False): - monitored = '' - else: - monitored = f'/usr/local/sbin/systemd-timer-monitored {timer} ' -%>\ [Unit] Description=Service for Timer ${timer} After=network.target -% if config.get('requires', set()): -Requires=${' '.join(sorted(config['requires']))} -% endif -% if config.get('requisite', set()): -Requisite=${' '.join(sorted(config['requisite']))} +% if config.get('requires', ''): +Requires=${config['requires']} % endif [Service] @@ -24,8 +15,8 @@ WorkingDirectory=${config.get('pwd', '/')} Type=oneshot % if isinstance(config['command'], list): % for command in config['command']: -ExecStart=${monitored}${command} +ExecStart=/usr/local/sbin/systemd-timer-monitored ${timer} ${command} % endfor % else: -ExecStart=${monitored}${config['command']} +ExecStart=/usr/local/sbin/systemd-timer-monitored ${timer} ${config['command']} % endif diff --git a/bundles/systemd-timers/metadata.py b/bundles/systemd-timers/metadata.py index 9aaf573..23f87ff 100644 --- a/bundles/systemd-timers/metadata.py +++ b/bundles/systemd-timers/metadata.py @@ -5,10 +5,7 @@ def monitoring(metadata): services = {} for timer, config in node.metadata.get('systemd-timers/timers', {}).items(): - if ( - config.get('delete', False) - or config.get('exclude_from_monitoring', False) - ): + if config.get('delete', False): continue services[f'SYSTEMD-TIMER {timer}'] = { diff --git a/bundles/systemd/files/journald.conf b/bundles/systemd/files/journald.conf index 1ccdb9c..a062649 100644 --- a/bundles/systemd/files/journald.conf +++ b/bundles/systemd/files/journald.conf @@ -15,10 +15,5 @@ RuntimeKeepFree=${journal.get('keepfree', '2G')} RuntimeMaxFileSize=100M MaxFileSec=1d -ForwardToSyslog=no -ForwardToKMsg=no -ForwardToConsole=no -ForwardToWall=yes - # Disable auditing Audit=no diff --git a/bundles/systemd/items.py b/bundles/systemd/items.py index 005696e..c8ecbd9 100644 --- a/bundles/systemd/items.py +++ b/bundles/systemd/items.py @@ -1,4 +1,4 @@ -timezone = node.metadata.get('timezone') +timezone = node.metadata.get('timezone', 'UTC') actions['systemd-reload'] = { 'command': 'systemctl daemon-reload', diff --git a/bundles/systemd/metadata.py b/bundles/systemd/metadata.py index 76f2016..f8a8ba4 100644 --- a/bundles/systemd/metadata.py +++ b/bundles/systemd/metadata.py @@ -21,14 +21,8 @@ defaults = { }, }, }, - 'timezone': 'UTC', } -if not node.has_bundle('rsyslogd'): - defaults['apt']['packages']['rsyslog'] = { - 'installed': False, - } - if node.has_bundle('apt') and node.os_version[0] > 10: defaults['apt']['packages']['systemd-timesyncd'] = { 'after': { @@ -37,6 +31,5 @@ if node.has_bundle('apt') and node.os_version[0] > 10: }, 'needed_by': { 'action:systemd-enable-ntp', - 'svc_systemd:systemd-timesyncd', }, } diff --git a/bundles/telegraf-monitors-mikrotik/files/telegraf-plugin-snmp-mikrotik b/bundles/telegraf-monitors-mikrotik/files/telegraf-plugin-snmp-mikrotik index dbcefd8..322e9db 100644 --- a/bundles/telegraf-monitors-mikrotik/files/telegraf-plugin-snmp-mikrotik +++ b/bundles/telegraf-monitors-mikrotik/files/telegraf-plugin-snmp-mikrotik @@ -3,6 +3,7 @@ from sys import argv from hnmp import SNMP + snmp = SNMP(argv[2], community=argv[3]) single_value_metrics_int_oids = { diff --git a/bundles/telegraf/files/telegraf.conf b/bundles/telegraf/files/telegraf.conf new file mode 100644 index 0000000..12dcdb7 --- /dev/null +++ b/bundles/telegraf/files/telegraf.conf @@ -0,0 +1,4 @@ +<% + from tomlkit import dumps as toml_dumps + from bundlewrap.utils.text import toml_clean +%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(config), sort_keys=True))} diff --git a/bundles/telegraf/items.py b/bundles/telegraf/items.py index 4ee5ef2..8577cbb 100644 --- a/bundles/telegraf/items.py +++ b/bundles/telegraf/items.py @@ -11,19 +11,7 @@ telegraf_config = { 'quiet': False, 'round_interval': False, }, - 'outputs': { - 'influxdb_v2': [{ - 'urls': [node.metadata.get('telegraf/influxdb_url', repo.libs.defaults.influxdb_url)], - 'token': node.metadata.get('telegraf/influxdb_token', repo.vault.decrypt(repo.libs.defaults.influxdb_token)), - 'organization': node.metadata.get('telegraf/influxdb_org', repo.vault.decrypt(repo.libs.defaults.influxdb_org)), - 'bucket': node.metadata.get('telegraf/influxdb_bucket', repo.vault.decrypt(repo.libs.defaults.influxdb_bucket)), - }], - }, - 'inputs': {}, -} - -if node.metadata.get('telegraf/collect_default_metrics', True): - telegraf_config['inputs'] = { + 'inputs': { 'cpu': [{ 'percpu': False, 'totalcpu': True, @@ -55,9 +43,17 @@ if node.metadata.get('telegraf/collect_default_metrics', True): 'nstat': [{}], 'processes': [{}], 'system': [{}], - } - -telegraf_config['inputs'].update(node.metadata.get('telegraf/input_plugins/builtin', {})) + **node.metadata.get('telegraf/input_plugins/builtin', {}), + }, + 'outputs': { + 'influxdb_v2': [{ + 'urls': [node.metadata.get('telegraf/influxdb_url', repo.libs.defaults.influxdb_url)], + 'token': node.metadata.get('telegraf/influxdb_token', repo.vault.decrypt(repo.libs.defaults.influxdb_token)), + 'organization': node.metadata.get('telegraf/influxdb_org', repo.vault.decrypt(repo.libs.defaults.influxdb_org)), + 'bucket': node.metadata.get('telegraf/influxdb_bucket', repo.vault.decrypt(repo.libs.defaults.influxdb_bucket)), + }], + }, +} # Bundlewrap can't merge lists. To work around this, telegraf/input_plugins/exec(d) # is a dict, of which we only use the value of it. This also allows us @@ -97,7 +93,10 @@ for name, config in sorted(node.metadata.get('telegraf/input_plugins/prometheus' files = { '/etc/telegraf/telegraf.conf': { - 'content': repo.libs.faults.dict_as_toml(telegraf_config), + 'content_type': 'mako', + 'context': { + 'config': telegraf_config, + }, 'triggers': { 'svc_systemd:telegraf:restart', }, diff --git a/bundles/telegraf/metadata.py b/bundles/telegraf/metadata.py index 4af8190..50a588e 100644 --- a/bundles/telegraf/metadata.py +++ b/bundles/telegraf/metadata.py @@ -11,7 +11,7 @@ defaults = { 'repos': { 'influxdb': { 'items': { - 'deb https://repos.influxdata.com/{os} stable main', + 'deb https://repos.influxdata.com/{os} {os_release} stable', }, }, }, @@ -25,4 +25,14 @@ defaults = { }, }, }, + 'pacman': { + 'packages': { + 'telegraf-bin': { + 'needed_by': { + 'svc_systemd:telegraf', + 'user:telegraf', + }, + }, + }, + }, } diff --git a/bundles/telegraf_airgradient/files/airgradient_telegraf b/bundles/telegraf_airgradient/files/airgradient_telegraf deleted file mode 100644 index 3ada3e8..0000000 --- a/bundles/telegraf_airgradient/files/airgradient_telegraf +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/python3 - -from logging import basicConfig, getLogger -from sys import argv - -from requests import get - -basicConfig(level="INFO") -L = getLogger(__name__) - - -def out(keys, values): - print( - "airgradient,{} {}".format( - ",".join([f"{k}={v}" for k, v in keys.items()]), - ",".join([f"{k}={v}" for k, v in values.items()]), - ), - flush=True, - ) - - -try: - r = get( - f"https://api.airgradient.com/public/api/v1/locations/measures/current?token={argv[2]}" - ) - L.debug(r.status_code) - L.info(r.text) - r.raise_for_status() - for location in r.json(): - L.debug(location) - out( - { - "place": argv[1], - "location": location["locationName"], - }, - { - k: location[k] - for k in ( - "atmp", - "noxIndex", - "pm003Count", - "pm01", - "pm02", - "pm10", - "rco2", - "rhum", - "tvoc", - "tvocIndex", - "wifi", - ) - }, - ) -except Exception: - L.exception("fail!") diff --git a/bundles/telegraf_airgradient/items.py b/bundles/telegraf_airgradient/items.py deleted file mode 100644 index 702d22f..0000000 --- a/bundles/telegraf_airgradient/items.py +++ /dev/null @@ -1,3 +0,0 @@ -files['/usr/local/bin/airgradient_telegraf'] = { - 'mode': '0755', -} diff --git a/bundles/telegraf_airgradient/metadata.py b/bundles/telegraf_airgradient/metadata.py deleted file mode 100644 index f64fb28..0000000 --- a/bundles/telegraf_airgradient/metadata.py +++ /dev/null @@ -1,19 +0,0 @@ -@metadata_reactor.provides( - 'telegraf/input_plugins/exec', -) -def telegraf(metadata): - result = {} - for location, api_key in metadata.get('telegraf_airgradient', {}).items(): - result[f'airgradient_{location}'] = { - 'commands': [f'/usr/local/bin/airgradient_telegraf {location} {api_key}'], - 'data_format': 'influx', - 'timeout': '10s', - } - - return { - 'telegraf': { - 'input_plugins': { - 'exec': result, - }, - }, - } diff --git a/bundles/transmission/metadata.py b/bundles/transmission/metadata.py index da2a09e..5f5c682 100644 --- a/bundles/transmission/metadata.py +++ b/bundles/transmission/metadata.py @@ -4,6 +4,7 @@ defaults = { 'apt': { 'packages': { 'transmission-daemon': {}, + 'transmission-remote-cli': {}, }, }, 'icinga2_api': { @@ -55,9 +56,9 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - f"{metadata.get('transmission/config/peer-port')}/tcp": atomic({'*'}), - f"{metadata.get('transmission/config/peer-port')}/udp": atomic({'*'}), - f"{metadata.get('transmission/config/rpc-port')}/tcp": atomic(metadata.get('transmission/restrict-to', {'*'})), + str(metadata.get('transmission/config/peer-port')): atomic({'*'}), + str(metadata.get('transmission/config/peer-port')) + '/udp': atomic({'*'}), + str(metadata.get('transmission/config/rpc-port')): atomic(metadata.get('transmission/restrict-to', {'*'})), }, }, } diff --git a/bundles/travelynx/files/travelynx.conf b/bundles/travelynx/files/travelynx.conf index f73e85f..7787d8b 100644 --- a/bundles/travelynx/files/travelynx.conf +++ b/bundles/travelynx/files/travelynx.conf @@ -33,12 +33,6 @@ from => '${mail_from}', }, -% if not enable_registration: - registration => { - disabled => 1, - }, -% endif - ref => { issues => 'https://github.com/derf/travelynx/issues', source => 'https://github.com/derf/travelynx', @@ -46,9 +40,6 @@ secrets => [ '${cookie_secret}', -% for i in sorted(additional_cookie_secrets): - '${i}', -% endfor ], version => '${version}', diff --git a/bundles/travelynx/files/travelynx.service b/bundles/travelynx/files/travelynx.service index 53aec53..6c7b4f2 100644 --- a/bundles/travelynx/files/travelynx.service +++ b/bundles/travelynx/files/travelynx.service @@ -8,9 +8,9 @@ Type=simple RemainAfterExit=yes PIDFile=/var/cache/travelynx/travelynx.pid -ExecStart=/usr/bin/hypnotoad -f index.pl -ExecStop=/usr/bin/hypnotoad -s index.pl -ExecReload=/usr/bin/hypnotoad index.pl +ExecStart=/usr/local/bin/hypnotoad -f index.pl +ExecStop=/usr/local/bin/hypnotoad -s index.pl +ExecReload=/usr/local/bin/hypnotoad index.pl User=travelynx WorkingDirectory=/opt/travelynx diff --git a/bundles/travelynx/items.py b/bundles/travelynx/items.py index 9a03785..5463a1b 100644 --- a/bundles/travelynx/items.py +++ b/bundles/travelynx/items.py @@ -20,14 +20,14 @@ directories = { } files = { - '/usr/local/lib/systemd/system/travelynx.service': { + '/etc/systemd/system/travelynx.service': { 'triggers': { 'action:systemd-reload', 'svc_systemd:travelynx:restart', 'svc_systemd:travelynx-worker:restart', }, }, - '/usr/local/lib/systemd/system/travelynx-worker.service': { + '/etc/systemd/system/travelynx-worker.service': { 'triggers': { 'action:systemd-reload', 'svc_systemd:travelynx:restart', @@ -102,15 +102,14 @@ actions = { svc_systemd = { 'travelynx': { 'needs': { - 'file:/usr/local/lib/systemd/system/travelynx.service', + 'file:/etc/systemd/system/travelynx.service', 'action:travelynx_database_migrate', 'directory:/var/cache/travelynx', - 'pkg_apt:libmojolicious-perl', }, }, 'travelynx-worker': { 'needs': { - 'file:/usr/local/lib/systemd/system/travelynx-worker.service', + 'file:/etc/systemd/system/travelynx-worker.service', 'svc_systemd:travelynx', }, }, diff --git a/bundles/travelynx/metadata.py b/bundles/travelynx/metadata.py index 630fd27..969b0cd 100644 --- a/bundles/travelynx/metadata.py +++ b/bundles/travelynx/metadata.py @@ -1,21 +1,14 @@ defaults = { - 'apt': { - 'packages': { - 'libmojolicious-perl': {}, - }, - }, 'travelynx': { 'database': { 'username': 'travelynx', 'password': repo.vault.password_for('{} postgresql travelynx'.format(node.name)), 'database': 'travelynx', }, - 'additional_cookie_secrets': set(), - 'cookie_secret': repo.vault.password_for('{} travelynx cookie_secret'.format(node.name)), - 'enable_registration': False, - 'mail_from': 'travelynx@{}'.format(node.hostname), - 'spare_workers': 2, 'workers': 4, + 'spare_workers': 2, + 'mail_from': 'travelynx@{}'.format(node.hostname), + 'cookie_secret': repo.vault.password_for('{} travelynx cookie_secret'.format(node.name)), }, 'postgresql': { 'roles': { diff --git a/bundles/unbound/files/unbound.conf b/bundles/unbound/files/unbound.conf index c25e0a3..247768a 100644 --- a/bundles/unbound/files/unbound.conf +++ b/bundles/unbound/files/unbound.conf @@ -1,11 +1,6 @@ server: # provided by pkg_apt:unbound-anchor auto-trust-anchor-file: "/var/lib/unbound/root.key" -% if node.metadata.get('unbound/dns64', node.has_bundle('jool')): - module-config: "dns64 validator iterator" -% else: - module-config: "validator iterator" -% endif verbosity: 0 @@ -28,6 +23,10 @@ server: access-control: ::1 allow % endif +% if node.has_bundle('pppd'): + prefer-ip4: yes +% endif + msg-cache-size: ${cache_size} msg-cache-slabs: ${cache_slabs} rrset-cache-size: ${cache_size} diff --git a/bundles/unbound/items.py b/bundles/unbound/items.py index 89bce8a..519b811 100644 --- a/bundles/unbound/items.py +++ b/bundles/unbound/items.py @@ -41,13 +41,6 @@ svc_systemd = { }, } -directories['/usr/share/dns'] = { - 'before': { - 'pkg_apt:unbound', - 'pkg_apt:unbound-anchor', - }, -} - if node.has_bundle('systemd-networkd'): svc_systemd['unbound']['needed_by'] = { 'file:/etc/resolv.conf', diff --git a/bundles/unbound/metadata.py b/bundles/unbound/metadata.py index 70a3511..b08df0b 100644 --- a/bundles/unbound/metadata.py +++ b/bundles/unbound/metadata.py @@ -70,7 +70,7 @@ def firewall(metadata): return { 'firewall': { 'port_rules': { - '53/tcp': atomic(metadata.get('unbound/restrict-to', set())), + '53': atomic(metadata.get('unbound/restrict-to', set())), '53/udp': atomic(metadata.get('unbound/restrict-to', set())), }, }, diff --git a/bundles/users/files/bashrc b/bundles/users/files/bashrc index 02a9c02..2b2729d 100644 --- a/bundles/users/files/bashrc +++ b/bundles/users/files/bashrc @@ -19,9 +19,7 @@ then fi uptime -echo -last | head -n5 -echo +last | grep 'still logged in' export HISTCONTROL=ignoredups export HISTSIZE=50000 @@ -64,8 +62,3 @@ ${k}() { ${v} } % endfor - -if [[ -f "/etc/bashrc_bundlewrap/$(logname)" ]] -then - source "/etc/bashrc_bundlewrap/$(logname)" -fi diff --git a/bundles/users/items.py b/bundles/users/items.py index 79590dc..d6df3cd 100644 --- a/bundles/users/items.py +++ b/bundles/users/items.py @@ -1,9 +1,5 @@ from os.path import exists, join -directories['/etc/bashrc_bundlewrap'] = { - 'purge': True, -} - files = { '/etc/bash.bashrc': { 'source': 'bashrc', @@ -68,13 +64,14 @@ for username, attrs in node.metadata['users'].items(): } if exists(join(repo.path, 'data', 'users', 'files', 'bash', '{}.bashrc'.format(username))): - files[f'/etc/bashrc_bundlewrap/{username}'] = { + files[home + '/.bashrc'] = { 'content_type': 'mako', 'source': 'bash/{}.bashrc'.format(username), } - files[f"{home}/.bashrc"] = { - 'delete': True, - } + else: + files[home + '/.bashrc'] = { + 'delete': True, + } if attrs.get('enable_linger', False): linger_test = '' diff --git a/bundles/users/metadata.py b/bundles/users/metadata.py index e6f3498..fc3cb0c 100644 --- a/bundles/users/metadata.py +++ b/bundles/users/metadata.py @@ -7,6 +7,11 @@ defaults = { 'kitty-terminfo': {}, }, }, + 'pacman': { + 'packages': { + 'kitty-terminfo': {}, + }, + }, 'users': { 'root': { 'home': '/root', @@ -31,7 +36,7 @@ def add_users_from_json(metadata): if config.get('is_admin', False) or uname in metadata_users: users[uname] = { 'ssh_pubkey': set(config['ssh_pubkey']), - 'sudo_commands': ['ALL'], + 'is_admin': config.get('is_admin', False), } # Then, run again to get all 'to be deleted' users diff --git a/bundles/vmhost/items.py b/bundles/vmhost/items.py index 402e8ec..e432a40 100644 --- a/bundles/vmhost/items.py +++ b/bundles/vmhost/items.py @@ -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 + } diff --git a/bundles/vmhost/metadata.py b/bundles/vmhost/metadata.py index 79f9d8a..36eb53b 100644 --- a/bundles/vmhost/metadata.py +++ b/bundles/vmhost/metadata.py @@ -21,6 +21,13 @@ defaults = { }, }, }, + 'pacman': { + 'packages': { + 'edk2-ovmf': {}, + 'libvirt': {}, + 'qemu-headless': {}, + }, + }, } if node.os == 'debian' and node.os_version[0] < 11: @@ -36,6 +43,9 @@ if node.has_bundle('nftables'): }, } +if node.has_bundle('arch-with-gui'): + defaults['pacman']['packages']['virt-manager'] = {} + @metadata_reactor.provides( 'users', @@ -43,7 +53,7 @@ if node.has_bundle('nftables'): def libvirt_group_for_admins(metadata): result = {} for user, config in metadata.get('users', {}).items(): - if 'ALL' in config.get('sudo_commands', set()): + if config.get('is_admin', False): result[user] = { 'groups': { 'libvirt', diff --git a/bundles/voc-tracker-worker/files/crs-runner.service b/bundles/voc-tracker-worker/files/crs-runner.service new file mode 100644 index 0000000..72665cb --- /dev/null +++ b/bundles/voc-tracker-worker/files/crs-runner.service @@ -0,0 +1,15 @@ +[Unit] +Description=CRS runner for ${script} +After=network.target + +[Service] +User=voc +Group=voc +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 diff --git a/bundles/voc-tracker-worker/files/environment b/bundles/voc-tracker-worker/files/environment new file mode 100644 index 0000000..87e4333 --- /dev/null +++ b/bundles/voc-tracker-worker/files/environment @@ -0,0 +1,6 @@ +export CRS_TRACKER="${url}" +export CRS_TOKEN="${token}" +export CRS_SECRET="${secret}" +% if use_vaapi: +export CRS_USE_VAAPI="yes" +% endif diff --git a/bundles/voc-tracker-worker/items.py b/bundles/voc-tracker-worker/items.py new file mode 100644 index 0000000..6f28a8b --- /dev/null +++ b/bundles/voc-tracker-worker/items.py @@ -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', + }, + } diff --git a/bundles/voc-tracker-worker/metadata.py b/bundles/voc-tracker-worker/metadata.py new file mode 100644 index 0000000..3a741a8 --- /dev/null +++ b/bundles/voc-tracker-worker/metadata.py @@ -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 diff --git a/bundles/weechat/metadata.py b/bundles/weechat/metadata.py deleted file mode 100644 index 034ecfb..0000000 --- a/bundles/weechat/metadata.py +++ /dev/null @@ -1,102 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'libpod-parser-perl': {}, - 'mosh': {}, - 'weechat': {}, - 'weechat-core': {}, - 'weechat-curses': {}, - 'weechat-perl': {}, - 'weechat-plugins': {}, - 'weechat-python': {}, - 'weechat-ruby': {}, - }, - 'repos': { - 'weechat': { - 'items': { - 'deb https://weechat.org/{os} {os_release} main', - }, - }, - }, - }, - 'nftables': { - 'input': { - '10-weechat': { - 'udp dport { 60000-61000 } accept', - }, - }, - }, -} - - -@metadata_reactor.provides( - 'backup-client/pre-hooks', - 'backups/paths', - 'users', - 'zfs/datasets', -) -def paths(metadata): - user = metadata.get('weechat/user') - - return { - 'backup-client': { - 'pre-hooks': { - 'weechat': f""" - echo 'core.weechat */layout store' >> /home/{user}/.weechat/weechat_fifo - echo 'core.weechat */save' >> /home/{user}/.weechat/weechat_fifo - """, - }, - }, - 'backups': { - 'paths': { - f'/home/{user}/.weechat', - }, - }, - 'users': { - user: { - 'enable_linger': True, - }, - }, - 'zfs': { - 'datasets': { - f'tank/{user}': {}, - f'tank/{user}/weechat': { - 'mountpoint': f'/home/{user}/.weechat', - 'compression': 'on', - }, - }, - }, - } - - -@metadata_reactor.provides( - 'nginx/vhosts', -) -def relay_vhost(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - relay_domain = metadata.get('weechat/relay_domain', None) - if relay_domain is None: - return {} - - return { - 'nginx': { - 'vhosts': { - 'weechat': { - 'domain': relay_domain, - # This only does websockets connections, which stay - # open for a very long time. This only generates - # useless metrics. - 'timing_log': False, - 'locations': { - '/weechat': { - 'proxy_read_timeout': '12h', - 'target': 'http://[::1]:9000', - 'websockets': True, - }, - }, - }, - }, - }, - } diff --git a/bundles/wide-dhcp6c/files/ip-down b/bundles/wide-dhcp6c/files/ip-down index edc84de..ec060ee 100644 --- a/bundles/wide-dhcp6c/files/ip-down +++ b/bundles/wide-dhcp6c/files/ip-down @@ -3,5 +3,8 @@ systemctl stop wide-dhcpv6-client % for interface, subnet_id in sorted(targets.items()): -ip -6 addr flush dev ${interface} scope global +for IP in $(ip -6 addr show dev ${interface} | grep inet6 | awk '{print $2}' | grep -vF 'fe80::') +do + ip -6 addr del $IP dev ${interface} +done % endfor diff --git a/bundles/wide-dhcp6c/files/ip-up b/bundles/wide-dhcp6c/files/ip-up index da0ac8d..d6624a8 100644 --- a/bundles/wide-dhcp6c/files/ip-up +++ b/bundles/wide-dhcp6c/files/ip-up @@ -12,7 +12,7 @@ if systemctl is-active wide-dhcpv6-client; then systemctl stop wide-dhcpv6-client sleep 1 - systemctl start wide-dhcpv6-client + systemctl sart wide-dhcpv6-client else systemctl start wide-dhcpv6-client fi diff --git a/bundles/wide-dhcp6c/items.py b/bundles/wide-dhcp6c/items.py index 53fc656..fb04b49 100644 --- a/bundles/wide-dhcp6c/items.py +++ b/bundles/wide-dhcp6c/items.py @@ -2,21 +2,18 @@ if node.has_bundle('pppd'): files['/etc/ppp/ip-up.d/wide-dhcp6c'] = { 'source': 'ip-up', 'content_type': 'mako', - 'context': node.metadata.get('wide-dhcp6c'), - 'mode': '0755', - 'triggers': { - 'svc_systemd:wide-dhcpv6-client:restart', + 'context': { + 'source': node.metadata['wide-dhcp6c']['source'], }, + 'mode': '0755', } - files['/etc/ppp/ip-down.d/wide-dhcp6c'] = { 'source': 'ip-down', 'content_type': 'mako', - 'context': node.metadata.get('wide-dhcp6c'), - 'mode': '0755', - 'triggers': { - 'svc_systemd:wide-dhcpv6-client:restart', + 'context': { + 'targets': node.metadata['wide-dhcp6c']['targets'], }, + 'mode': '0755', } # Will be started and stopped by pppd. @@ -28,7 +25,11 @@ else: files['/etc/wide-dhcpv6/dhcp6c.conf'] = { 'content_type': 'mako', - 'context': node.metadata.get('wide-dhcp6c'), + 'context': { + 'source': node.metadata['wide-dhcp6c']['source'], + 'targets': node.metadata['wide-dhcp6c']['targets'], + 'subnet_len': node.metadata['wide-dhcp6c']['subnet_len'], + }, 'triggers': { 'svc_systemd:wide-dhcpv6-client:restart', }, @@ -36,7 +37,9 @@ files['/etc/wide-dhcpv6/dhcp6c.conf'] = { files['/etc/systemd/system/wide-dhcpv6-client.service'] = { 'content_type': 'mako', - 'context': node.metadata.get('wide-dhcp6c'), + 'context': { + 'source': node.metadata['wide-dhcp6c']['source'], + }, 'triggers': { 'action:systemd-reload', 'svc_systemd:wide-dhcpv6-client:restart', diff --git a/bundles/wide-dhcp6c/metadata.py b/bundles/wide-dhcp6c/metadata.py index 050e690..7ac556b 100644 --- a/bundles/wide-dhcp6c/metadata.py +++ b/bundles/wide-dhcp6c/metadata.py @@ -5,10 +5,10 @@ defaults = { }, }, 'nftables': { - 'input': { + 'rules': { '10-wide-dhcp6c': [ - 'udp dport { 546, 547 } ip6 saddr ff00::/12 accept', - 'udp dport { 546, 547 } ip6 saddr fe80::/10 accept', + 'inet filter input udp dport { 546, 547 } ip6 saddr ff00::/12 accept', + 'inet filter input udp dport { 546, 547 } ip6 saddr fe80::/10 accept', ], }, }, diff --git a/bundles/wireguard/files/pppd-ip-up b/bundles/wireguard/files/pppd-ip-up new file mode 100644 index 0000000..5e5d200 --- /dev/null +++ b/bundles/wireguard/files/pppd-ip-up @@ -0,0 +1,10 @@ +#!/bin/bash + +# We need to send some traffic over the wireguard tunnel to make sure +# it gets connected. Easiest way is to simply send some pings to the +# other side. + +% for peer, config in sorted(node.metadata.get('wireguard/peers', {}).items()): +# refresh connection to ${peer} +/usr/bin/ping -c 4 ${config['their_ip']} +% endfor diff --git a/bundles/wireguard/files/wg.netdev b/bundles/wireguard/files/wg.netdev index c6abf78..de9af7f 100644 --- a/bundles/wireguard/files/wg.netdev +++ b/bundles/wireguard/files/wg.netdev @@ -1,5 +1,5 @@ [NetDev] -Name=wg_${iface} +Name=wg${number} Kind=wireguard Description=WireGuard connection to ${peer} @@ -10,12 +10,8 @@ ListenPort=${port} [WireGuardPeer] PublicKey=${pubkey} AllowedIPs=0.0.0.0/0 -% if psk: PresharedKey=${psk} -% endif % if endpoint: Endpoint=${endpoint} % endif -% if specials.get('persistent_keepalive', True): PersistentKeepalive=30 -% endif diff --git a/bundles/wireguard/files/wg_health_check b/bundles/wireguard/files/wg_health_check new file mode 100644 index 0000000..976e112 --- /dev/null +++ b/bundles/wireguard/files/wg_health_check @@ -0,0 +1,46 @@ +#!/bin/bash + +if [[ -e "/var/lib/bundlewrap/hard-${node.name}/info" ]] +then + # make sure we're not restarting during bw apply + echo "bw apply running" + exit 0 +fi + +now="$(date +%s)" + +everything_up=1 + +% for peer, ip in sorted(peers.items()): +# ${peer} +if ! /usr/bin/ping -c 4 ${ip} >/dev/null 2>&1 +then + echo "${peer} was not reachable!" + everything_up=0 +fi + +% endfor +if [[ "$everything_up" -eq 1 ]] +then + echo "Everything is up as expected" + echo "$now" > /var/tmp/wg_all_reached + exit 0 +fi + +five_min_ago="$(expr $now - 300)" +last_reached="$(cat /var/tmp/wg_all_reached)" + +if [[ "$last_reached" -lt "$five_min_ago" ]] +then + echo "RESTART" + + systemctl restart systemd-networkd + + # only restart once an hour + echo "$(expr $now + 3300)" > /var/tmp/wg_all_reached +elif [[ "$last_reached" -gt "$now" ]] +then + echo "Something's broken, but we have recently restarted" +else + echo "Something's broken, but still in grace time" +fi diff --git a/bundles/wireguard/items.py b/bundles/wireguard/items.py index 0d8d13d..37d018b 100644 --- a/bundles/wireguard/items.py +++ b/bundles/wireguard/items.py @@ -13,24 +13,46 @@ deps = set() if node.has_bundle('apt'): deps.add('pkg_apt:wireguard') -for peer, config in sorted(node.metadata.get('wireguard/peers', {}).items()): - files[f'/etc/systemd/network/wg_{config["iface"]}.netdev'] = { +health_checks = {} +for number, (peer, config) in enumerate(sorted(node.metadata.get('wireguard/peers', {}).items())): + files[f'/etc/systemd/network/wg{number}.netdev'] = { 'content_type': 'mako', 'source': 'wg.netdev', 'owner': 'systemd-network', 'mode': '0600', 'context': { 'endpoint': config.get('endpoint'), - 'iface': config['iface'], + 'number': number, 'peer': peer, 'port': config['my_port'], 'privatekey': node.metadata.get('wireguard/privatekey'), - 'psk': config.get('psk'), + 'psk': config['psk'], 'pubkey': config['pubkey'], - 'specials': repo.libs.s2s.WG_AUTOGEN_SETTINGS.get(peer, {}), }, 'needs': deps, 'triggers': { 'svc_systemd:systemd-networkd:restart', }, } + + if config.get('health_check', False): + health_checks[peer] = config['their_ip'] + +if health_checks: + files['/usr/local/bin/wg_health_check'] = { + 'content_type': 'mako', + 'context': { + 'peers': health_checks, + }, + 'mode': '0755', + } + files['/etc/cron.d/wg_health_check'] = { + 'content': '* * * * * root /usr/local/bin/wg_health_check | logger -t wg_health_check\n', + } + +if node.has_bundle('pppd'): + files['/etc/ppp/ip-up.d/reconnect-wireguard'] = { + 'source': 'pppd-ip-up', + 'content_type': 'mako', + 'mode': '0755', + } diff --git a/bundles/wireguard/metadata.py b/bundles/wireguard/metadata.py index 267be6a..b19ca8c 100644 --- a/bundles/wireguard/metadata.py +++ b/bundles/wireguard/metadata.py @@ -1,5 +1,4 @@ from ipaddress import ip_network -from re import sub from bundlewrap.exceptions import NoSuchNode from bundlewrap.metadata import atomic @@ -9,26 +8,20 @@ defaults = { 'packages': { 'wireguard': {}, }, + 'repos': { + 'backports': { + 'install_gpg_key': False, # default debian signing key + 'items': { + 'deb http://deb.debian.org/debian {os_release}-backports main', + }, + }, + }, }, 'wireguard': { 'privatekey': repo.libs.keys.gen_privkey(repo, f'{node.name} wireguard privatekey'), }, } -if node.os_version <= (11,): - defaults['apt']['repos'] = { - 'backports': { - 'install_gpg_key': False, # default debian signing key - 'items': { - 'deb http://deb.debian.org/debian {os_release}-backports main', - }, - }, - } -else: - defaults['apt']['packages']['wireguard-dkms'] = { - 'installed': False, - } - if node.has_bundle('telegraf'): defaults['telegraf'] = { 'input_plugins': { @@ -42,35 +35,6 @@ if node.has_bundle('telegraf'): } -@metadata_reactor.provides( - 'wireguard/peers', -) -def peers_auto_full_mesh(metadata): - peers = {} - - if node.name not in repo.libs.s2s.WG_AUTOGEN_NODES: - return {} - - for rnode in repo.libs.s2s.WG_AUTOGEN_NODES: - if rnode is None or rnode == node.name: - continue - - try: - rnode = repo.get_node(rnode) - except NoSuchNode: - continue - - if rnode.dummy: - continue - - peers[rnode.name] = {} - - return { - 'wireguard': { - 'peers': peers, - }, - } - @metadata_reactor.provides( 'wireguard/peers', @@ -79,19 +43,16 @@ def peer_psks(metadata): peers = {} for peer_name in metadata.get('wireguard/peers', {}): - peers[peer_name] = { - 'iface': sub('[^a-z0-9-_]+', '_', peer_name)[:12], - } + peers[peer_name] = {} - try: - repo.get_node(peer_name) - - if node.name < peer_name: - peers[peer_name]['psk'] = repo.vault.random_bytes_as_base64_for(f'{node.name} wireguard {peer_name}') - else: - peers[peer_name]['psk'] = repo.vault.random_bytes_as_base64_for(f'{peer_name} wireguard {node.name}') - except NoSuchNode: - pass + if node.name < peer_name: + peers[peer_name] = { + 'psk': repo.vault.random_bytes_as_base64_for(f'{node.name} wireguard {peer_name}'), + } + else: + peers[peer_name] = { + 'psk': repo.vault.random_bytes_as_base64_for(f'{peer_name} wireguard {node.name}'), + } return { 'wireguard': { @@ -131,9 +92,6 @@ def peer_pubkeys(metadata): 'wireguard/peers', ) def peer_ips_and_ports(metadata): - if node.name not in repo.libs.s2s.WG_AUTOGEN_NODES: - raise DoNotRunAgain - peers = {} base_port = 51820 @@ -143,9 +101,6 @@ def peer_ips_and_ports(metadata): except NoSuchNode: continue - if rnode.name not in repo.libs.s2s.WG_AUTOGEN_NODES: - continue - ip_a, ip_b = repo.libs.s2s.get_subnet_for_connection(repo, *sorted({node.name, peer_name})) if peer_name < node.name: @@ -157,7 +112,7 @@ def peer_ips_and_ports(metadata): peers[rnode.name] = { 'my_ip': str(my_ip), - 'my_port': base_port + repo.libs.s2s.WG_AUTOGEN_NODES.index(rnode.name), + 'my_port': base_port + number, 'their_ip': str(their_ip) } @@ -180,13 +135,11 @@ def peer_endpoints(metadata): except NoSuchNode: continue - if repo.libs.s2s.WG_AUTOGEN_SETTINGS.get(name, {}).get('no_autoconnect'): - continue peers[rnode.name] = { 'endpoint': '{}:{}'.format( - rnode.hostname, - rnode.metadata.get(f'wireguard/peers/{node.name}/my_port'), + rnode.metadata.get('wireguard/external_hostname', rnode.hostname), + rnode.metadata.get(f'wireguard/peers/{node.name}/my_port', 51820), ), } @@ -203,12 +156,12 @@ def peer_endpoints(metadata): def icinga2(metadata): services = {} - for peer, config in sorted(metadata.get('wireguard/peers', {}).items()): + for number, (peer, config) in enumerate(sorted(metadata.get('wireguard/peers', {}).items())): if config.get('exclude_from_monitoring', False): continue services[f'WIREGUARD CONNECTION {peer}'] = { - 'command_on_monitored_host': config['pubkey'].format_into(f'sudo /usr/local/share/icinga/plugins/check_wireguard_connected wg_{config["iface"]} {{}}'), + 'command_on_monitored_host': config['pubkey'].format_into(f'sudo /usr/local/share/icinga/plugins/check_wireguard_connected wg{number} {{}}'), } return { @@ -231,9 +184,7 @@ def firewall(metadata): except NoSuchNode: # roadwarrior ports['{}/udp'.format(config['my_port'])] = atomic(set(metadata.get('wireguard/restrict-to', set()))) else: - ports['{}/udp'.format(config['my_port'])] = atomic( - set(repo.libs.s2s.WG_AUTOGEN_SETTINGS.get(name, {}).get('firewall', set())) | {name} - ) + ports['{}/udp'.format(config['my_port'])] = atomic({name}) return { 'firewall': { @@ -247,31 +198,15 @@ def firewall(metadata): ) def interface_ips(metadata): interfaces = {} - snat_ip = metadata.get('wireguard/snat_ip', None) - - for peer, config in sorted(metadata.get('wireguard/peers', {}).items()): - routes = {} - + for number, (peer, config) in enumerate(sorted(metadata.get('wireguard/peers', {}).items())): if '/' in config['my_ip']: my_ip = config['my_ip'] else: my_ip = '{}/31'.format(config['my_ip']) - - ips = {my_ip} - if snat_ip and peer in repo.libs.s2s.WG_AUTOGEN_NODES: - ips.add(snat_ip) - - their_ip = config['their_ip'] - if '/' in their_ip: - their_ip = their_ip.split('/')[0] - - for route in config.get('routes', set()): - routes[route] = {'via': their_ip} - - interfaces[f'wg_{config["iface"]}'] = { - 'activation_policy': 'up' if config.get('auto_connection', True) else 'manual', - 'ips': ips, - 'routes': routes, + interfaces[f'wg{number}'] = { + 'ips': { + my_ip, + }, } return { 'interfaces': interfaces, @@ -279,37 +214,28 @@ def interface_ips(metadata): @metadata_reactor.provides( - 'nftables/forward/10-wireguard', - 'nftables/postrouting/10-wireguard', + 'nftables/rules/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) + rules = set() + for number, (peer, config) in enumerate(sorted(metadata.get('wireguard/peers', {}).items())): + rules.add(f'inet filter forward iifname wg{number} accept') + rules.add(f'inet filter forward oifname wg{number} accept') - forward = set() - postrouting = set() - for peer, config in sorted(metadata.get('wireguard/peers', {}).items()): - forward.add(f'iifname wg_{config["iface"]} accept') - forward.add(f'oifname wg_{config["iface"]} accept') - - if snat_ip and peer in repo.libs.s2s.WG_AUTOGEN_NODES: - postrouting.add('ip saddr {} ip daddr != {} snat to {}'.format( + if 'snat_to' in config: + rules.add('nat postrouting ip saddr {} ip daddr != {} snat to {}'.format( config['my_ip'], config['their_ip'], - snat_ip, + config['snat_to'], )) - elif config.get('masquerade', False): - postrouting.add(f'oifname wg_{peer} masquerade') return { 'nftables': { - 'forward': { - '10-wireguard': sorted(forward), - }, - 'postrouting': { - '10-wireguard': sorted(postrouting), + 'rules': { + '10-wireguard': sorted(rules), }, }, } diff --git a/bundles/zfs/files/check_zpool_online b/bundles/zfs/files/check_zpool_online index 0e7c16c..9fb0cae 100644 --- a/bundles/zfs/files/check_zpool_online +++ b/bundles/zfs/files/check_zpool_online @@ -5,14 +5,11 @@ if [ $# -eq 0 ] ; then exit 3 fi -status="$(zpool status "$1")" - -if [ "$(echo "$status" | grep '^ state:')" = ' state: ONLINE' ] +if [ "$(zpool status "$1" | grep '^ state:')" = ' state: ONLINE' ] then echo "OK - Pool '$1' is online" exit 0 else echo "CRITICAL - Pool '$1' is FAULTY or NOT ONLINE" - echo "$status" exit 2 fi diff --git a/bundles/zfs/files/zfs-import-scan-override.service b/bundles/zfs/files/zfs-import-scan-override.service index 9004ee2..3853425 100644 --- a/bundles/zfs/files/zfs-import-scan-override.service +++ b/bundles/zfs/files/zfs-import-scan-override.service @@ -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 diff --git a/bundles/zfs/items.py b/bundles/zfs/items.py index 530d27f..85ffdd7 100644 --- a/bundles/zfs/items.py +++ b/bundles/zfs/items.py @@ -2,6 +2,27 @@ from json import dumps from bundlewrap.metadata import MetadataJSONEncoder +if node.os == 'debian': + actions = { + # For some reason, this module doesn't get auto-loaded on debian, + # even if installation of zfsutils-linux tries to start + # zfs-mount.service. We have no choice but to do it manually. + 'modprobe_zfs': { + 'command': 'modprobe zfs', + 'unless': 'lsmod | grep ^zfs', + 'needs': { + 'pkg_apt:zfs-dkms', + }, + 'needed_by': { + 'pkg_apt:zfs-zed', + 'pkg_apt:zfsutils-linux', + 'zfs_dataset:', + 'zfs_pool:', + }, + 'comment': 'If this fails, do a dist-upgrade, reinstall zfs-dkms, reboot', + }, + } + files = { '/etc/modprobe.d/zfs.conf': { 'source': 'zfs-modprobe.conf', @@ -66,10 +87,6 @@ svc_systemd = { 'needs': { 'file:/etc/systemd/system/zfs-import-scan.service.d/bundlewrap.conf', }, - 'after': { - 'bundle:dm-crypt', # might unlock disks - 'pkg_apt:', - }, 'before': { 'svc_systemd:zfs-import-cache.service', }, @@ -78,32 +95,14 @@ svc_systemd = { 'running': None, 'enabled': False, 'masked': True, - 'after': { - 'pkg_apt:', - }, - }, - 'zfs-mount.service': { - 'after': { - 'bundle:dm-crypt', # might unlock disks - 'pkg_apt:', - }, - }, - 'zfs-zed': { - 'after': { - 'pkg_apt:', - }, }, + 'zfs-mount.service': {}, + 'zfs-zed': {}, 'zfs.target': { 'running': None, - 'after': { - 'pkg_apt:', - }, }, 'zfs-import.target': { 'running': None, - 'after': { - 'pkg_apt:', - }, }, } diff --git a/bundles/zfs/metadata.py b/bundles/zfs/metadata.py index 3b63e0b..624e2a6 100644 --- a/bundles/zfs/metadata.py +++ b/bundles/zfs/metadata.py @@ -3,6 +3,11 @@ defaults = { 'apt': { 'packages': { + 'linux-headers-amd64': { + 'needed_by': { + 'pkg_apt:zfs-dkms', + }, + }, 'zfs-dkms': { 'needed_by': { 'pkg_apt:zfs-zed', @@ -43,6 +48,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': { @@ -110,17 +127,20 @@ if node.has_bundle('telegraf'): @metadata_reactor.provides( - 'apt/packages', + 'pacman/packages', ) -def linux_headers(metadata): - cpu_arch = metadata.get('cpu_arch', 'amd64') - +def packages(metadata): + if node.metadata.get('pacman/linux-lts', False): + pkgname = 'zfs-linux-lts' + else: + pkgname = 'zfs-linux' return { - 'apt': { + 'pacman': { 'packages': { - f'linux-headers-{cpu_arch}': { + pkgname: { 'needed_by': { - 'pkg_apt:zfs-dkms', + 'zfs_dataset:', + 'zfs_pool:', }, }, }, @@ -137,7 +157,7 @@ def scrub_timer(metadata): 'systemd-timers': { 'timers': { 'zfs-scrub': { - 'when': metadata.get('zfs/scrub_when', 'Sun 02:00:00 UTC'), + 'when': 'Sun 02:00:00 UTC', 'command': scrubs, }, }, diff --git a/configs/as3320.txt b/configs/as3320.txt index 0ac3052..4eb09e7 100644 --- a/configs/as3320.txt +++ b/configs/as3320.txt @@ -1,8 +1,10 @@ -109.203.176.0/21 +109.160.36.0/24 +109.160.37.0/24 +109.160.38.0/24 +109.160.39.0/24 +109.160.40.0/24 +109.160.41.0/24 109.237.176.0/20 -109.72.116.0/24 -116.50.16.0/21 -128.65.164.0/22 129.181.208.0/21 129.181.216.0/22 137.170.112.0/24 @@ -16,13 +18,22 @@ 139.12.255.0/24 139.12.3.0/24 139.12.4.0/24 +141.11.17.0/24 +141.11.18.0/24 +141.11.247.0/24 141.169.240.0/20 141.77.0.0/16 -143.99.213.0/24 +141.98.44.0/24 +145.225.1.0/24 +145.225.148.0/22 +145.225.152.0/24 145.225.16.0/23 +145.225.2.0/24 +147.136.68.0/22 +147.136.76.0/22 +147.136.84.0/22 147.161.22.0/24 147.78.17.0/24 -147.79.8.0/21 149.208.250.0/23 149.208.252.0/24 149.208.253.0/24 @@ -31,14 +42,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 153.17.251.0/24 @@ -48,15 +55,8 @@ 153.17.255.0/24 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 -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 +160.211.126.0/24 164.133.10.0/24 164.133.11.0/24 164.133.150.0/24 @@ -65,42 +65,46 @@ 164.133.91.0/24 164.133.98.0/24 164.133.99.0/24 -168.199.128.0/22 -168.199.160.0/22 -168.199.192.0/22 -168.199.212.0/22 +164.18.96.0/21 170.237.92.0/23 +171.25.178.0/24 +176.221.24.0/24 +176.221.25.0/24 176.53.136.0/24 176.53.137.0/24 -176.57.59.0/24 +179.61.160.0/22 185.100.160.0/22 -185.101.244.0/23 -185.101.246.0/23 185.101.4.0/22 185.109.108.0/22 +185.112.249.0/24 185.114.200.0/22 185.124.48.0/24 185.126.168.0/22 185.131.239.0/24 185.133.12.0/22 185.136.115.0/24 +185.149.25.0/24 +185.149.26.0/24 +185.149.27.0/24 185.149.52.0/24 185.157.101.0/24 185.161.176.0/22 +185.162.72.0/23 185.163.76.0/24 185.163.77.0/24 185.163.78.0/24 185.163.79.0/24 +185.172.38.0/24 +185.172.39.0/24 185.180.224.0/24 -185.183.212.0/23 -185.183.214.0/23 185.188.64.0/24 -185.195.239.0/24 185.198.13.0/24 185.202.32.0/21 +185.203.148.0/22 +185.206.69.0/24 185.207.46.0/24 -185.21.247.0/24 -185.224.0.0/24 +185.215.183.0/24 +185.230.136.0/24 185.237.0.0/24 185.237.1.0/24 185.237.2.0/24 @@ -113,16 +117,14 @@ 185.28.208.0/22 185.39.12.0/22 185.48.0.0/22 -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 +185.91.204.0/22 +185.95.156.0/24 +185.95.157.0/24 +185.95.158.0/24 +185.95.159.0/24 +188.208.103.0/24 +192.109.121.0/24 192.109.122.0/24 192.109.124.0/24 192.109.129.0/24 @@ -139,8 +141,10 @@ 192.109.209.0/24 192.109.54.0/24 192.109.96.0/24 +192.124.252.0/24 192.129.58.0/24 192.145.8.0/22 +192.166.146.0/23 192.166.253.0/24 192.166.49.0/24 192.166.52.0/24 @@ -148,6 +152,7 @@ 192.31.102.0/24 192.54.39.0/24 192.54.48.0/24 +192.54.66.0/24 192.54.73.0/24 192.54.79.0/24 192.67.167.0/24 @@ -163,6 +168,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 @@ -187,15 +193,14 @@ 193.141.180.0/23 193.141.91.0/24 193.143.24.0/22 -193.151.248.0/22 193.158.0.0/15 193.16.184.0/23 193.16.235.0/24 -193.163.15.0/24 193.168.0.0/24 193.168.232.0/22 193.168.234.0/23 193.169.204.0/23 +193.178.226.0/23 193.188.196.0/24 193.201.170.0/24 193.201.206.0/24 @@ -203,7 +208,6 @@ 193.22.110.0/24 193.22.111.0/24 193.22.16.0/22 -193.22.164.0/24 193.22.174.0/24 193.22.205.0/24 193.22.29.0/24 @@ -229,10 +233,12 @@ 193.28.34.0/23 193.28.48.0/23 193.28.50.0/24 +193.28.64.0/21 193.29.112.0/24 193.29.115.0/24 193.29.116.0/24 193.29.126.0/24 +193.29.152.0/21 193.29.158.0/24 193.3.240.0/24 193.30.136.0/22 @@ -250,14 +256,12 @@ 193.53.93.0/24 193.58.253.0/24 193.84.136.0/22 -193.96.230.0/24 193.96.232.0/23 193.97.238.0/24 193.98.181.0/24 193.98.224.0/24 193.99.96.0/20 194.0.151.0/24 -194.0.232.0/24 194.110.133.0/24 194.113.160.0/22 194.113.20.0/23 @@ -268,8 +272,6 @@ 194.115.120.0/24 194.115.163.0/24 194.115.182.0/23 -194.115.182.0/24 -194.115.183.0/24 194.115.52.0/24 194.115.66.0/24 194.115.88.0/21 @@ -291,23 +293,13 @@ 194.127.182.0/24 194.127.195.0/24 194.127.208.0/22 -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 194.15.64.0/21 194.15.72.0/22 -194.150.228.0/23 -194.152.128.0/24 -194.152.129.0/24 -194.152.132.0/24 -194.152.141.0/24 -194.152.142.0/24 -194.152.154.0/24 -194.152.155.0/24 194.153.86.0/24 194.156.128.0/22 194.156.148.0/24 @@ -329,7 +321,7 @@ 194.180.64.0/20 194.25.0.0/16 194.25.1.5/32 -194.31.142.0/24 +194.26.191.0/24 194.31.208.0/24 194.31.209.0/24 194.31.210.0/24 @@ -339,29 +331,27 @@ 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 194.39.48.0/21 194.39.56.0/21 -194.39.61.0/24 194.39.62.0/24 194.39.63.0/24 194.39.88.0/21 194.39.97.0/24 +194.45.144.0/21 +194.49.110.0/24 194.49.117.0/24 194.49.118.0/23 194.49.125.0/24 194.49.48.0/24 194.49.54.0/24 +194.49.72.0/24 194.49.73.0/24 194.49.74.0/23 194.49.85.0/24 +194.55.158.0/24 194.55.180.0/24 194.55.183.0/24 194.55.192.0/19 @@ -402,17 +392,17 @@ 194.99.76.0/23 194.99.83.0/24 194.99.92.0/22 -195.133.7.0/24 195.137.216.0/23 195.138.223.0/24 195.144.15.0/24 195.145.0.0/16 195.149.79.0/24 195.160.248.0/22 +195.178.132.0/22 195.190.2.0/24 195.192.254.0/24 +195.20.114.0/23 195.200.207.0/24 -195.226.200.0/24 195.230.116.0/24 195.234.133.0/24 195.243.0.0/16 @@ -421,13 +411,13 @@ 195.248.140.0/23 195.248.144.0/23 195.248.89.0/24 +195.250.48.0/24 195.250.50.0/24 195.250.57.0/24 195.36.64.0/18 195.36.81.0/24 195.36.90.0/24 195.36.91.0/24 -195.66.83.0/24 195.68.204.0/23 195.74.94.0/24 195.78.249.0/24 @@ -435,26 +425,14 @@ 198.40.90.0/24 198.57.10.0/24 2.160.0.0/12 -2.58.100.0/24 -2.58.102.0/24 -204.52.120.0/24 -204.52.121.0/24 204.69.32.0/24 205.142.63.0/24 +212.102.107.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 -213.209.136.0/24 -213.209.149.0/24 -213.209.156.0/24 217.0.0.0/13 217.117.96.0/24 -217.177.33.0/24 217.224.0.0/11 217.24.32.0/20 217.24.33.0/24 @@ -462,49 +440,42 @@ 217.80.0.0/12 31.212.0.0/15 31.224.0.0/11 -31.6.56.0/23 -37.143.0.0/22 -37.230.61.0/24 +31.6.52.0/22 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.10.157.0/24 +45.128.158.0/23 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 +45.140.8.0/23 +45.141.232.0/24 +45.141.62.0/23 +45.151.112.0/23 +45.151.114.0/23 +45.154.238.0/23 +45.157.202.0/23 +45.157.32.0/23 +45.90.184.0/22 46.78.0.0/15 46.80.0.0/12 +5.10.208.0/24 +5.10.209.0/24 +5.10.220.0/24 5.133.112.0/24 -5.249.188.0/22 -5.35.192.0/21 62.153.0.0/16 62.154.0.0/15 62.155.0.0/16 62.156.0.0/14 62.156.153.0/24 62.156.168.0/24 +62.192.152.0/24 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 +62.76.229.0/24 77.47.152.0/22 77.83.136.0/23 77.83.138.0/23 -77.90.156.0/24 -77.90.184.0/24 +78.159.131.0/24 79.192.0.0/10 80.128.0.0/11 80.128.0.0/12 @@ -516,97 +487,43 @@ 80.157.8.0/21 80.187.0.0/16 80.187.160.0/20 -80.244.13.0/24 80.64.240.0/22 -80.71.231.0/24 -80.71.233.0/24 -80.71.235.0/24 -80.71.236.0/24 -80.71.238.0/24 -80.83.80.0/21 81.201.32.0/20 -81.31.210.0/23 -82.163.104.0/21 -82.163.60.0/22 -82.206.32.0/21 -82.206.40.0/21 -82.206.48.0/21 -82.215.70.0/24 +81.30.96.0/20 +83.136.208.0/22 +83.147.40.0/22 83.243.48.0/21 +83.243.55.0/24 84.128.0.0/10 84.246.108.0/24 -84.32.108.0/22 +84.32.20.0/22 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 -84.55.6.0/24 -84.55.7.0/24 -85.116.28.0/24 -85.116.29.0/24 -85.116.30.0/24 -85.116.31.0/24 +84.32.56.0/22 +84.46.240.0/20 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 +85.239.148.0/24 +85.239.149.0/24 +85.239.150.0/24 +85.239.151.0/24 +86.38.156.0/24 86.38.248.0/21 86.38.37.0/24 87.128.0.0/10 87.128.0.0/11 87.237.240.0/21 88.128.0.0/16 -88.135.96.0/20 -88.216.60.0/22 +88.216.208.0/24 +89.116.248.0/24 89.116.64.0/22 -89.213.186.0/23 -89.39.97.0/24 +89.117.172.0/22 +89.35.127.0/24 +89.35.72.0/24 91.0.0.0/10 91.103.240.0/21 -91.124.135.0/24 -91.124.19.0/24 -91.124.20.0/24 -91.124.21.0/24 -91.124.22.0/24 -91.124.23.0/24 -91.124.24.0/24 -91.124.26.0/24 -91.124.27.0/24 -91.124.28.0/24 -91.124.31.0/24 -91.124.33.0/24 -91.124.34.0/24 -91.124.36.0/24 -91.124.37.0/24 -91.124.38.0/24 -91.124.39.0/24 -91.124.40.0/24 -91.124.41.0/24 -91.124.42.0/24 -91.124.43.0/24 -91.124.44.0/24 -91.124.45.0/24 -91.124.46.0/24 -91.124.47.0/24 -91.124.50.0/24 -91.124.51.0/24 -91.124.6.0/24 -91.124.7.0/24 91.189.192.0/21 91.194.232.0/23 91.198.113.0/24 @@ -626,52 +543,44 @@ 91.212.130.0/24 91.212.243.0/24 91.213.116.0/24 -91.214.10.0/24 91.215.116.0/22 91.216.242.0/24 91.216.45.0/24 91.217.214.0/24 -91.221.12.0/23 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.16.0/22 -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.114.44.0/22 -92.119.164.0/22 +91.92.33.0/24 +91.92.34.0/24 +91.92.35.0/24 +91.92.49.0/24 +92.118.161.0/24 92.119.208.0/24 92.119.209.0/24 92.119.210.0/24 92.119.211.0/24 -93.113.70.0/24 -93.119.201.0/24 -93.119.232.0/24 +93.152.205.0/24 +93.152.207.0/24 +93.152.209.0/24 +93.152.215.0/24 +93.152.219.0/24 +93.152.221.0/24 +93.152.223.0/24 +93.152.224.0/24 +93.152.225.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 +94.26.90.0/24 2001:650:cc02::/48 2001:678:184::/48 2001:678:36c::/48 2001:678:480::/48 -2001:678:5b0::/48 2001:678:5d4::/48 2001:678:a04::/48 2001:678:adc::/48 2001:678:b38::/48 -2001:678:bdc::/48 2001:678:d4c::/48 +2001:678:e9c::/48 2001:678:ff0::/48 2001:67c:11a4::/48 2001:67c:14c4::/48 @@ -689,34 +598,13 @@ 2001:67c:764::/48 2001:67c:94c::/48 2001:67c:a34::/48 -2001:67c:b80::/48 -2001:67c:c84::/48 -2001:67c:c9c::/48 -2001:67c:ec0::/48 2003:3c0::/28 2003:3e0::/28 2003:8:1800::/48 2003:8:1803::/48 -2003:8:f400::/48 -2003:8:f401::/48 -2003:8:f402::/48 -2003:8:f403::/48 -2003:8:f404::/48 -2003:8:f405::/48 -2003:8:f406::/48 -2003:8:f407::/48 -2003:8:f408::/48 -2003:8:f409::/48 -2003:8:f40a::/48 -2003:8:f40b::/48 -2003:8:f40c::/48 -2003:8:f40d::/48 -2003:8:f40e::/48 2003::/19 2003::/20 2003::/23 -2a00:5c60:3::/48 -2a00:5c60:a::/48 2a00:6680::/46 2a01:598::/29 2a01:8fa0::/32 @@ -730,10 +618,12 @@ 2a06:1800::/29 2a06:1a80::/29 2a06:7180::/29 +2a07:b982:c000::/48 2a09:6f80::/29 2a09:8180::/30 2a0a:5340:ffff::/48 2a0a:a3c0:b0::/44 +2a0b:3c41:1::/48 2a0b:3c41:2::/48 2a0c:9e02:1000::/40 2a0c:9e02:100::/40 @@ -748,12 +638,6 @@ 2a0d:480::/29 2a0d:480::/30 2a0d:484::/30 -2a0e:cbc4::/32 -2a0e:cbc5::/32 -2a0e:cbc6::/32 -2a0e:cbc7::/32 2a0e:eb40::/32 2a10:cd80::/29 2a11:7400:d1::/48 -2a12:6900:1000::/40 -2a13:9500:2::/48 diff --git a/configs/as8881.txt b/configs/as8881.txt index aa354f9..9420d5f 100644 --- a/configs/as8881.txt +++ b/configs/as8881.txt @@ -1,14 +1,20 @@ 104.151.0.0/17 109.250.0.0/16 -109.250.0.0/18 +109.250.0.0/20 109.250.128.0/19 +109.250.16.0/20 109.250.160.0/19 109.250.192.0/19 109.250.224.0/19 -109.250.64.0/18 -109.72.113.0/24 +109.250.32.0/20 +109.250.48.0/20 +109.250.64.0/19 +109.250.80.0/22 +109.250.84.0/22 +109.250.88.0/22 +109.250.92.0/22 +109.250.96.0/19 134.101.0.0/21 -14.102.90.0/24 143.58.64.0/18 149.233.32.0/19 153.94.0.0/20 @@ -30,7 +36,6 @@ 185.151.201.0/24 185.151.203.0/24 185.158.48.0/22 -185.187.122.0/24 185.199.205.0/24 185.235.232.0/22 185.8.230.0/23 @@ -41,13 +46,13 @@ 192.166.84.0/22 192.166.87.0/24 192.166.88.0/21 -192.189.14.0/24 193.101.4.0/23 -193.102.10.0/24 +193.101.5.0/24 193.111.212.0/22 193.111.212.0/24 193.163.13.0/24 -193.17.225.0/24 +193.163.13.0/25 +193.163.13.128/25 193.219.15.0/24 193.22.120.0/21 193.22.120.0/24 @@ -62,22 +67,16 @@ 193.22.3.0/24 193.28.72.0/21 193.29.240.0/24 -193.29.241.0/24 -193.29.242.0/24 193.29.243.0/24 -193.29.244.0/24 -193.29.245.0/24 193.29.246.0/24 -193.29.247.0/24 193.30.132.0/24 193.30.140.0/24 193.96.238.0/24 193.98.229.0/24 193.98.40.0/22 193.99.160.0/21 -194.115.182.0/23 -194.115.182.0/24 -194.115.183.0/24 +194.113.252.0/23 +194.113.253.0/24 194.115.26.0/24 194.120.182.0/23 194.120.182.0/24 @@ -88,16 +87,14 @@ 194.127.144.0/21 194.127.203.0/24 194.139.55.0/24 -194.145.218.0/23 +194.145.230.0/24 194.156.216.0/21 194.156.232.0/23 194.156.233.0/24 194.174.168.0/22 -194.180.18.0/24 194.180.53.0/24 194.180.64.0/20 194.187.112.0/24 -194.30.180.0/24 194.31.92.0/24 194.39.185.0/24 194.39.87.0/24 @@ -109,26 +106,27 @@ 194.88.25.0/24 194.9.190.0/24 194.99.0.0/21 +194.99.113.0/24 195.149.80.0/23 195.167.208.0/20 +195.191.20.0/23 195.202.32.0/19 195.226.160.0/19 195.226.96.0/19 195.234.139.0/24 195.238.233.0/24 -195.238.238.0/24 +195.244.10.0/23 195.64.176.0/23 195.93.158.0/23 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 +212.80.224.0/20 +212.80.240.0/20 212.93.0.0/19 213.138.32.0/19 -213.138.35.0/24 213.139.128.0/19 213.182.128.0/19 213.30.192.0/18 @@ -145,161 +143,322 @@ 45.13.15.0/24 46.142.0.0/16 46.142.0.0/19 +46.142.112.0/20 46.142.128.0/19 46.142.160.0/19 +46.142.194.0/24 46.142.214.0/24 46.142.224.0/19 -46.142.32.0/19 +46.142.32.0/20 +46.142.48.0/20 46.142.64.0/19 -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 +46.189.116.0/24 61.8.128.0/19 -61.8.128.0/22 -61.8.132.0/22 -61.8.136.0/22 -61.8.144.0/22 -61.8.152.0/22 -61.8.156.0/24 -61.8.157.0/24 62.214.0.0/16 +62.214.213.0/24 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 +62.72.88.0/22 +62.72.92.0/23 +62.72.94.0/24 77.74.136.0/21 77.87.190.0/24 -80.241.192.0/20 80.242.160.0/19 82.119.160.0/19 82.140.0.0/18 -82.140.48.0/20 +82.140.2.0/23 +82.140.2.0/24 +82.140.3.0/24 +82.140.48.0/21 82.144.32.0/19 +82.144.34.0/24 +82.144.35.0/24 +82.144.36.0/24 +82.144.37.0/24 82.145.0.0/19 82.194.96.0/19 82.207.128.0/17 82.207.192.0/19 +82.207.224.0/21 +82.207.232.0/22 +82.207.236.0/24 +82.207.240.0/20 +82.207.244.0/24 +82.207.245.0/24 +82.207.246.0/24 +82.207.247.0/24 +82.207.248.0/24 +82.207.249.0/24 +82.207.250.0/24 +82.207.251.0/24 +82.207.252.0/24 +82.207.253.0/24 +82.207.254.0/24 +82.207.255.0/24 83.135.0.0/16 -83.135.0.0/20 +83.135.0.0/22 83.135.112.0/20 -83.135.128.0/19 +83.135.128.0/20 +83.135.144.0/20 +83.135.16.0/22 83.135.160.0/21 +83.135.164.0/22 83.135.168.0/21 83.135.176.0/22 +83.135.180.0/22 83.135.184.0/21 83.135.192.0/20 +83.135.20.0/24 83.135.208.0/20 +83.135.21.0/24 +83.135.22.0/24 83.135.224.0/22 +83.135.23.0/24 +83.135.230.0/23 83.135.232.0/21 +83.135.24.0/24 83.135.240.0/22 +83.135.244.0/24 +83.135.245.0/24 +83.135.248.0/24 +83.135.249.0/24 +83.135.25.0/24 +83.135.250.0/24 +83.135.251.0/24 +83.135.252.0/24 +83.135.253.0/24 +83.135.254.0/24 +83.135.255.0/24 +83.135.26.0/24 +83.135.27.0/24 +83.135.28.0/24 +83.135.29.0/24 +83.135.30.0/24 +83.135.31.0/24 +83.135.32.0/19 +83.135.4.0/22 83.135.64.0/19 +83.135.8.0/21 83.135.96.0/20 +83.243.48.0/21 +83.243.48.0/22 +83.243.52.0/22 84.19.192.0/19 +84.19.192.0/20 +84.19.208.0/20 87.122.0.0/15 +87.122.0.0/16 87.122.0.0/20 87.122.128.0/21 +87.122.136.0/22 87.122.144.0/20 -87.122.16.0/20 +87.122.16.0/22 87.122.160.0/20 87.122.176.0/21 -87.122.192.0/19 +87.122.184.0/24 +87.122.185.0/24 +87.122.186.0/24 +87.122.187.0/24 +87.122.188.0/24 +87.122.189.0/24 +87.122.190.0/24 +87.122.191.0/24 +87.122.192.0/20 +87.122.20.0/22 +87.122.208.0/20 87.122.224.0/19 +87.122.24.0/21 87.122.32.0/19 -87.122.64.0/19 +87.122.64.0/20 +87.122.80.0/20 87.122.96.0/19 -87.123.0.0/19 -87.123.128.0/19 +87.123.0.0/16 +87.123.0.0/20 +87.123.112.0/20 +87.123.128.0/20 +87.123.144.0/20 +87.123.16.0/20 87.123.160.0/20 87.123.176.0/20 -87.123.194.0/24 -87.123.196.0/24 -87.123.203.0/24 +87.123.192.0/20 +87.123.208.0/22 87.123.216.0/21 87.123.224.0/20 -87.123.240.0/21 -87.123.32.0/19 +87.123.240.0/22 +87.123.244.0/22 +87.123.248.0/22 +87.123.252.0/24 +87.123.253.0/24 +87.123.254.0/24 +87.123.255.0/24 +87.123.48.0/20 87.123.64.0/20 87.123.80.0/20 -87.123.96.0/19 +87.123.96.0/20 88.130.0.0/16 +88.130.0.0/19 +88.130.112.0/20 +88.130.130.0/23 +88.130.132.0/22 88.130.136.0/21 -88.130.144.0/20 +88.130.144.0/21 +88.130.152.0/24 +88.130.153.0/24 +88.130.154.0/24 +88.130.155.0/24 +88.130.156.0/22 +88.130.156.0/24 +88.130.157.0/24 +88.130.158.0/24 +88.130.159.0/24 +88.130.160.0/21 88.130.172.0/22 88.130.176.0/21 -88.130.192.0/23 -88.130.194.0/23 +88.130.180.0/24 +88.130.181.0/24 +88.130.182.0/24 +88.130.183.0/24 +88.130.184.0/24 +88.130.185.0/24 +88.130.186.0/24 +88.130.187.0/24 +88.130.188.0/24 +88.130.189.0/24 +88.130.190.0/24 +88.130.191.0/24 +88.130.192.0/21 +88.130.200.0/21 +88.130.208.0/21 88.130.216.0/21 +88.130.216.0/22 +88.130.220.0/24 +88.130.221.0/24 +88.130.222.0/24 +88.130.223.0/24 +88.130.32.0/20 88.130.48.0/24 88.130.49.0/24 88.130.50.0/24 +88.130.51.0/24 88.130.52.0/24 88.130.53.0/24 -88.130.54.0/23 +88.130.54.0/24 +88.130.55.0/24 88.130.56.0/24 88.130.57.0/24 88.130.58.0/24 88.130.59.0/24 +88.130.60.0/24 88.130.61.0/24 +88.130.62.0/24 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 +88.130.96.0/20 89.244.0.0/14 +89.244.0.0/16 +89.244.112.0/21 89.244.120.0/21 -89.244.160.0/21 +89.244.120.0/22 +89.244.124.0/24 +89.244.125.0/24 +89.244.126.0/24 +89.244.127.0/24 +89.244.160.0/20 +89.244.164.0/22 +89.244.168.0/21 89.244.176.0/20 89.244.192.0/19 -89.244.224.0/19 +89.244.224.0/20 +89.244.240.0/20 +89.244.64.0/21 +89.244.72.0/22 89.244.76.0/22 -89.244.78.0/23 89.244.80.0/20 -89.244.96.0/22 +89.244.96.0/20 +89.245.0.0/16 89.245.0.0/20 -89.245.112.0/20 -89.245.158.0/24 -89.245.159.0/24 89.245.16.0/20 89.245.160.0/20 89.245.176.0/21 +89.245.184.0/24 +89.245.185.0/24 +89.245.186.0/24 +89.245.187.0/24 +89.245.188.0/24 +89.245.189.0/24 +89.245.190.0/24 +89.245.191.0/24 89.245.192.0/19 89.245.224.0/19 -89.245.32.0/19 -89.245.64.0/19 +89.245.32.0/20 +89.245.48.0/20 +89.245.64.0/20 +89.245.80.0/20 89.245.96.0/20 -89.246.0.0/19 +89.246.0.0/16 +89.246.0.0/20 +89.246.104.0/23 +89.246.106.0/24 +89.246.107.0/24 +89.246.108.0/24 +89.246.109.0/24 +89.246.110.0/24 +89.246.111.0/24 +89.246.112.0/22 +89.246.116.0/22 +89.246.120.0/24 +89.246.121.0/24 89.246.122.0/24 +89.246.123.0/24 89.246.124.0/22 -89.246.160.0/21 +89.246.16.0/20 +89.246.160.0/20 +89.246.176.0/22 +89.246.180.0/22 89.246.184.0/21 89.246.192.0/19 -89.246.32.0/19 +89.246.32.0/20 +89.246.48.0/21 +89.246.56.0/21 89.246.96.0/21 -89.247.0.0/19 +89.247.0.0/16 +89.247.0.0/20 89.247.112.0/21 -89.247.112.0/22 89.247.120.0/22 -89.247.144.0/20 +89.247.124.0/24 +89.247.125.0/24 +89.247.126.0/24 +89.247.127.0/24 +89.247.144.0/22 +89.247.152.0/21 +89.247.16.0/20 89.247.160.0/20 -89.247.179.0/24 89.247.192.0/20 +89.247.208.0/21 89.247.216.0/22 -89.247.228.0/22 -89.247.232.0/21 +89.247.224.0/21 +89.247.232.0/22 89.247.236.0/22 -89.247.252.0/22 -89.247.32.0/19 +89.247.240.0/21 +89.247.240.0/22 +89.247.252.0/24 +89.247.253.0/24 +89.247.254.0/24 +89.247.255.0/24 89.247.32.0/20 +89.247.48.0/20 89.247.64.0/20 89.247.80.0/20 +89.247.96.0/20 89.27.128.0/17 +89.27.153.0/24 91.194.180.0/23 +91.195.104.0/23 91.198.67.0/24 91.199.158.0/24 91.201.128.0/22 @@ -310,6 +469,8 @@ 91.208.212.0/24 91.217.145.0/24 91.220.125.0/24 +91.223.2.0/24 +91.223.41.0/24 91.229.3.0/24 92.116.0.0/15 92.116.0.0/20 @@ -317,8 +478,11 @@ 92.116.120.0/21 92.116.128.0/18 92.116.16.0/20 -92.116.192.0/18 -92.116.32.0/19 +92.116.192.0/19 +92.116.224.0/20 +92.116.240.0/20 +92.116.32.0/20 +92.116.48.0/20 92.116.64.0/18 92.116.96.0/19 92.117.0.0/19 @@ -331,44 +495,75 @@ 92.117.240.0/21 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 -94.134.144.0/20 +94.134.100.0/22 +94.134.104.0/21 +94.134.112.0/21 +94.134.120.0/24 +94.134.121.0/24 +94.134.122.0/24 +94.134.123.0/24 +94.134.124.0/24 +94.134.125.0/24 +94.134.126.0/24 +94.134.127.0/24 +94.134.128.0/20 +94.134.144.0/22 +94.134.148.0/22 +94.134.152.0/21 94.134.160.0/21 94.134.168.0/22 94.134.172.0/22 +94.134.176.0/20 94.134.176.0/21 -94.134.192.0/22 +94.134.192.0/20 +94.134.208.0/21 94.134.216.0/21 -94.134.64.0/22 -94.134.68.0/22 +94.134.224.0/19 +94.134.64.0/20 94.134.80.0/22 -94.134.88.0/22 -94.134.94.0/23 -94.134.96.0/20 +94.134.84.0/24 +94.134.85.0/24 +94.134.86.0/24 +94.134.87.0/24 +94.134.88.0/24 +94.134.89.0/24 +94.134.90.0/24 +94.134.91.0/24 +94.134.92.0/24 +94.134.93.0/24 +94.134.94.0/24 +94.134.95.0/24 +94.134.96.0/22 2001:1438:1000::/36 -2001:1438:1:100::/56 -2001:1438:1:200::/56 -2001:1438:1:300::/56 -2001:1438:1:400::/56 -2001:1438:1:900::/56 -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:1438:f000::/36 +2001:1438:fff:10::/64 +2001:1438:fff:11::/64 +2001:1438:fff:12::/64 +2001:1438:fff:3::/64 +2001:1438:fff:4::/64 +2001:1438:fff:5::/64 +2001:1438:fff:6::/64 +2001:1438:fff:7::/64 +2001:1438:fff:8::/64 +2001:1438:fff:9::/64 +2001:1438:fff:a::/64 +2001:1438:fff:b::/64 +2001:1438:fff:c::/64 +2001:1438:fff:d::/64 +2001:1438:fff:e::/64 +2001:1438:fff:f::/64 2001:16b8:1000::/40 2001:16b8:100::/40 2001:16b8:1100::/40 2001:16b8:1200::/40 2001:16b8:1300::/40 2001:16b8:1400::/40 -2001:16b8:2000::/35 2001:16b8:2000::/40 2001:16b8:200::/40 2001:16b8:2100::/40 @@ -386,10 +581,14 @@ 2001:16b8:2d00::/40 2001:16b8:2e00::/40 2001:16b8:300::/40 -2001:16b8:4000::/35 +2001:16b8:4000::/40 2001:16b8:400::/40 +2001:16b8:4100::/40 +2001:16b8:4200::/40 +2001:16b8:4300::/40 +2001:16b8:4500::/40 +2001:16b8:4600::/40 2001:16b8:500::/40 -2001:16b8:6000::/35 2001:16b8:6000::/40 2001:16b8:600::/40 2001:16b8:6100::/40 @@ -401,24 +600,19 @@ 2001:16b8:6700::/40 2001:16b8:6800::/40 2001:16b8:700::/40 -2001:16b8:8000::/36 2001:16b8:800::/40 -2001:16b8:9000::/36 2001:16b8:900::/40 2001:16b8::/32 -2001:16b8::/35 2001:16b8::/40 -2001:16b8:a000::/35 2001:16b8:a00::/40 2001:16b8:b00::/40 -2001:16b8:c000::/35 +2001:678:274::/48 2001:678:c74::/48 2001:67c:27ac::/48 2001:67c:2878::/48 2001:67c:2e8c::/48 2001:67c:660::/48 2001:67c:888::/48 -2001:67c:ed8::/48 2001:7b0::/32 2001:9e8:2000::/35 2001:9e8:4000::/35 @@ -435,11 +629,10 @@ 2a00:fb8:4000::/35 2a00:fb8:6000::/35 2a00:fb8::/29 +2a00:fb8::/32 2a00:fb8::/35 2a03:3fc0:2000::/48 2a07:9400::/29 2a0a:ed40::/29 -2a0b:9e80:1000::/36 2a0d:240::/29 2a0d:ad00::/29 -2a11:d00::/32 diff --git a/configs/netbox/home.switch-rack.json b/configs/netbox_device_home.switch-rack.json similarity index 69% rename from configs/netbox/home.switch-rack.json rename to configs/netbox_device_home.switch-rack.json index 4843e1f..09d3775 100644 --- a/configs/netbox/home.switch-rack.json +++ b/configs/netbox_device_home.switch-rack.json @@ -4,225 +4,220 @@ "description": "home.router (enp1s0)", "enabled": true, "ips": [], - "mode": "tagged-all", + "mode": "TAGGED_ALL", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": null }, "ether10": { "description": "home.mitel-rfp35 (LAN)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether11": { "description": "home.usv01 (LAN)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether12": { - "description": "", + "description": "home.rechenmonster (IPMI)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether13": { "description": "", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether14": { - "description": "", + "description": "home.rechenmonster (LAN)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether15": { "description": "", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether16": { "description": "", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether17": { "description": "", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether18": { "description": "", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether19": { - "description": "home.lgtv-wohnzimmer", + "description": "home.kodi-wohnzimmer", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether2": { "description": "Fritz!Box (LAN1)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.wan" }, "ether20": { "description": "Franzi Laptop", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether21": { - "description": "", + "description": "Sophie Laptop", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether22": { - "description": "Arbeitsplatz Regal", + "description": "Sophie Desktop", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether23": { "description": "Wohnzimmer Kabel", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether24": { "description": "home.snom-wohnzimmer", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether3": { - "description": "home.aruba325-schlafzimmer", + "description": "home.winkeeinhorn-1 (LAN)", "enabled": true, "ips": [], - "mode": "tagged", + "mode": "TAGGED", "tagged_vlans": [ - "ffwi.client", - "home.v6only" + "ffwi.mesh" ], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether4": { - "description": "home.aruba325-wohnzimmer", + "description": "home.winkeeinhorn-2 (LAN)", "enabled": true, "ips": [], - "mode": "tagged", + "mode": "TAGGED", "tagged_vlans": [ - "ffwi.client", - "home.v6only" + "ffwi.mesh" ], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether5": { "description": "home.nas (eno1)", "enabled": true, "ips": [], - "mode": "tagged-all", + "mode": "TAGGED_ALL", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": null }, "ether6": { - "description": "home.aruba325-office", + "description": "isanet", "enabled": true, "ips": [], - "mode": "tagged", - "tagged_vlans": [ - "ffwi.client", - "home.v6only" - ], - "type": "1000base-t", - "untagged_vlan": "home.clients" + "mode": "ACCESS", + "tagged_vlans": [], + "type": "A_1000BASE_T", + "untagged_vlan": "home.dmz" }, "ether7": { "description": "RIPE-Probe #28280 (LAN)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.dmz" }, "ether8": { - "description": "home.drucker-franzi", + "description": "home.drucker-sophie", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "ether9": { "description": "info-beamer 12199 (LAN)", "enabled": true, "ips": [], - "mode": "access", + "mode": "ACCESS", "tagged_vlans": [], - "type": "1000base-t", + "type": "A_1000BASE_T", "untagged_vlan": "home.clients" }, "home.clients": { @@ -233,7 +228,7 @@ ], "mode": null, "tagged_vlans": [], - "type": "virtual", + "type": "VIRTUAL", "untagged_vlan": null }, "sfp-sfpplus1": { @@ -242,7 +237,7 @@ "ips": [], "mode": null, "tagged_vlans": [], - "type": "10gbase-x-sfpp", + "type": "A_10GBASE_X_SFPP", "untagged_vlan": null }, "sfp-sfpplus2": { @@ -251,7 +246,7 @@ "ips": [], "mode": null, "tagged_vlans": [], - "type": "10gbase-x-sfpp", + "type": "A_10GBASE_X_SFPP", "untagged_vlan": null } }, @@ -268,10 +263,6 @@ "name": "home.dmz", "vid": 1139 }, - { - "name": "home.v6only", - "vid": 2000 - }, { "name": "ffwi.mesh", "vid": 3000 diff --git a/data/apt/files/gpg-keys/docker.asc b/data/apt/files/gpg-keys/docker.asc deleted file mode 100644 index ee7872e..0000000 --- a/data/apt/files/gpg-keys/docker.asc +++ /dev/null @@ -1,62 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFit2ioBEADhWpZ8/wvZ6hUTiXOwQHXMAlaFHcPH9hAtr4F1y2+OYdbtMuth -lqqwp028AqyY+PRfVMtSYMbjuQuu5byyKR01BbqYhuS3jtqQmljZ/bJvXqnmiVXh -38UuLa+z077PxyxQhu5BbqntTPQMfiyqEiU+BKbq2WmANUKQf+1AmZY/IruOXbnq -L4C1+gJ8vfmXQt99npCaxEjaNRVYfOS8QcixNzHUYnb6emjlANyEVlZzeqo7XKl7 -UrwV5inawTSzWNvtjEjj4nJL8NsLwscpLPQUhTQ+7BbQXAwAmeHCUTQIvvWXqw0N -cmhh4HgeQscQHYgOJjjDVfoY5MucvglbIgCqfzAHW9jxmRL4qbMZj+b1XoePEtht -ku4bIQN1X5P07fNWzlgaRL5Z4POXDDZTlIQ/El58j9kp4bnWRCJW0lya+f8ocodo -vZZ+Doi+fy4D5ZGrL4XEcIQP/Lv5uFyf+kQtl/94VFYVJOleAv8W92KdgDkhTcTD -G7c0tIkVEKNUq48b3aQ64NOZQW7fVjfoKwEZdOqPE72Pa45jrZzvUFxSpdiNk2tZ -XYukHjlxxEgBdC/J3cMMNRE1F4NCA3ApfV1Y7/hTeOnmDuDYwr9/obA8t016Yljj -q5rdkywPf4JF8mXUW5eCN1vAFHxeg9ZWemhBtQmGxXnw9M+z6hWwc6ahmwARAQAB -tCtEb2NrZXIgUmVsZWFzZSAoQ0UgZGViKSA8ZG9ja2VyQGRvY2tlci5jb20+iQI3 -BBMBCgAhBQJYrefAAhsvBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEI2BgDwO -v82IsskP/iQZo68flDQmNvn8X5XTd6RRaUH33kXYXquT6NkHJciS7E2gTJmqvMqd -tI4mNYHCSEYxI5qrcYV5YqX9P6+Ko+vozo4nseUQLPH/ATQ4qL0Zok+1jkag3Lgk -jonyUf9bwtWxFp05HC3GMHPhhcUSexCxQLQvnFWXD2sWLKivHp2fT8QbRGeZ+d3m -6fqcd5Fu7pxsqm0EUDK5NL+nPIgYhN+auTrhgzhK1CShfGccM/wfRlei9Utz6p9P -XRKIlWnXtT4qNGZNTN0tR+NLG/6Bqd8OYBaFAUcue/w1VW6JQ2VGYZHnZu9S8LMc -FYBa5Ig9PxwGQOgq6RDKDbV+PqTQT5EFMeR1mrjckk4DQJjbxeMZbiNMG5kGECA8 -g383P3elhn03WGbEEa4MNc3Z4+7c236QI3xWJfNPdUbXRaAwhy/6rTSFbzwKB0Jm -ebwzQfwjQY6f55MiI/RqDCyuPj3r3jyVRkK86pQKBAJwFHyqj9KaKXMZjfVnowLh -9svIGfNbGHpucATqREvUHuQbNnqkCx8VVhtYkhDb9fEP2xBu5VvHbR+3nfVhMut5 -G34Ct5RS7Jt6LIfFdtcn8CaSas/l1HbiGeRgc70X/9aYx/V/CEJv0lIe8gP6uDoW -FPIZ7d6vH+Vro6xuWEGiuMaiznap2KhZmpkgfupyFmplh0s6knymuQINBFit2ioB -EADneL9S9m4vhU3blaRjVUUyJ7b/qTjcSylvCH5XUE6R2k+ckEZjfAMZPLpO+/tF -M2JIJMD4SifKuS3xck9KtZGCufGmcwiLQRzeHF7vJUKrLD5RTkNi23ydvWZgPjtx -Q+DTT1Zcn7BrQFY6FgnRoUVIxwtdw1bMY/89rsFgS5wwuMESd3Q2RYgb7EOFOpnu -w6da7WakWf4IhnF5nsNYGDVaIHzpiqCl+uTbf1epCjrOlIzkZ3Z3Yk5CM/TiFzPk -z2lLz89cpD8U+NtCsfagWWfjd2U3jDapgH+7nQnCEWpROtzaKHG6lA3pXdix5zG8 -eRc6/0IbUSWvfjKxLLPfNeCS2pCL3IeEI5nothEEYdQH6szpLog79xB9dVnJyKJb -VfxXnseoYqVrRz2VVbUI5Blwm6B40E3eGVfUQWiux54DspyVMMk41Mx7QJ3iynIa -1N4ZAqVMAEruyXTRTxc9XW0tYhDMA/1GYvz0EmFpm8LzTHA6sFVtPm/ZlNCX6P1X -zJwrv7DSQKD6GGlBQUX+OeEJ8tTkkf8QTJSPUdh8P8YxDFS5EOGAvhhpMBYD42kQ -pqXjEC+XcycTvGI7impgv9PDY1RCC1zkBjKPa120rNhv/hkVk/YhuGoajoHyy4h7 -ZQopdcMtpN2dgmhEegny9JCSwxfQmQ0zK0g7m6SHiKMwjwARAQABiQQ+BBgBCAAJ -BQJYrdoqAhsCAikJEI2BgDwOv82IwV0gBBkBCAAGBQJYrdoqAAoJEH6gqcPyc/zY -1WAP/2wJ+R0gE6qsce3rjaIz58PJmc8goKrir5hnElWhPgbq7cYIsW5qiFyLhkdp -YcMmhD9mRiPpQn6Ya2w3e3B8zfIVKipbMBnke/ytZ9M7qHmDCcjoiSmwEXN3wKYI -mD9VHONsl/CG1rU9Isw1jtB5g1YxuBA7M/m36XN6x2u+NtNMDB9P56yc4gfsZVES -KA9v+yY2/l45L8d/WUkUi0YXomn6hyBGI7JrBLq0CX37GEYP6O9rrKipfz73XfO7 -JIGzOKZlljb/D9RX/g7nRbCn+3EtH7xnk+TK/50euEKw8SMUg147sJTcpQmv6UzZ -cM4JgL0HbHVCojV4C/plELwMddALOFeYQzTif6sMRPf+3DSj8frbInjChC3yOLy0 -6br92KFom17EIj2CAcoeq7UPhi2oouYBwPxh5ytdehJkoo+sN7RIWua6P2WSmon5 -U888cSylXC0+ADFdgLX9K2zrDVYUG1vo8CX0vzxFBaHwN6Px26fhIT1/hYUHQR1z -VfNDcyQmXqkOnZvvoMfz/Q0s9BhFJ/zU6AgQbIZE/hm1spsfgvtsD1frZfygXJ9f -irP+MSAI80xHSf91qSRZOj4Pl3ZJNbq4yYxv0b1pkMqeGdjdCYhLU+LZ4wbQmpCk -SVe2prlLureigXtmZfkqevRz7FrIZiu9ky8wnCAPwC7/zmS18rgP/17bOtL4/iIz -QhxAAoAMWVrGyJivSkjhSGx1uCojsWfsTAm11P7jsruIL61ZzMUVE2aM3Pmj5G+W -9AcZ58Em+1WsVnAXdUR//bMmhyr8wL/G1YO1V3JEJTRdxsSxdYa4deGBBY/Adpsw -24jxhOJR+lsJpqIUeb999+R8euDhRHG9eFO7DRu6weatUJ6suupoDTRWtr/4yGqe -dKxV3qQhNLSnaAzqW/1nA3iUB4k7kCaKZxhdhDbClf9P37qaRW467BLCVO/coL3y -Vm50dwdrNtKpMBh3ZpbB1uJvgi9mXtyBOMJ3v8RZeDzFiG8HdCtg9RvIt/AIFoHR -H3S+U79NT6i0KPzLImDfs8T7RlpyuMc4Ufs8ggyg9v3Ae6cN3eQyxcK3w0cbBwsh -/nQNfsA6uu+9H7NhbehBMhYnpNZyrHzCmzyXkauwRAqoCbGCNykTRwsur9gS41TQ -M8ssD1jFheOJf3hODnkKU+HKjvMROl1DK7zdmLdNzA1cvtZH/nCC9KPj1z8QC47S -xx+dTZSx4ONAhwbS/LN3PoKtn8LPjY9NP9uDWI+TWYquS2U+KHDrBDlsgozDbs/O -jCxcpDzNmXpWQHEtHU7649OXHP7UeNST1mCUCH5qdank0V1iejF6/CfTFU4MfcrG -YT90qFF93M3v01BbxP+EIY2/9tiIPbrd -=0YYh ------END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/grafana.asc b/data/apt/files/gpg-keys/grafana.asc index 074cc78..c74f292 100644 --- a/data/apt/files/gpg-keys/grafana.asc +++ b/data/apt/files/gpg-keys/grafana.asc @@ -28,112 +28,3 @@ ymdQ1sqe5nKvwG5GvcncPc3O7LMevDBWnpNNkgERnVxCqpm90TuE3ONbirnU4+/S tUsVU1DERc1fjOCnAm4pKIlNYphISIE7OQ== =0pMC -----END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: This is a revocation certificate - -iQE2BCABCgAgFiEETkDd9tduKEpKZ4DkjIw0xSQJjLYFAmO9q0cCHQIACgkQjIw0 -xSQJjLarJAf+JJU0CHTMSSs5WH6ohVy54HN+ev7p7vfcgvvFBAWZLTLrG5+eFUH0 -w0m9KegxAs+H/H/68ld1jY/P62fvkOR7WCWQ7HH+8ClKLwuWS4DpOHK9IOkHDK0w -0pVJ6NBiwhv8/B7EmiBf9zndjMtYa/wf8JZYVOXb0XE0L+Ec0WZSRZH+/WGA1E1s -MSgPwqDF7RKXDCJ65elYxi9CPZvXhj6RVldn/aRuHf5/SCDE/HmnDB9+v6ReEsWV -r/Xis2J0pWphpF/xtYxGf+Iy5fAHwDd4z9uKs9mBHSR0aDisuAW/eHF6KvBzQ7y0 -Yf3KxEyDvLwuAA5NBi7Xsd2wSKdfBGUGcQ== -=KTb+ ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=lSMJ ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: This is a revocation certificate - -iQG2BCABCAAgFiEEDiLriOOeEid6d2CunkObECzzwMYFAmO4amECHQAACgkQnkOb -ECzzwMYiDQv/bbRnEhrFhr5XyA2vnu6nTZezbMwArC/ZwtFxtnj2iAwGZYY/pbPx -L8cHTpvK99I6J02SBHpmzthwHSindddPjuuQENdqH/TDlGvPH/mECJVTN9/kpjlg -HtO0MVKAKyXGbij7fR8prfPMRqOFbo4Rn9nQZZ/eY9KwkKVKxKHymppNbUbvv1qQ -NGfOi2QWkF+T8dbihbJHJgYpPb7uEmJ2EOX0KHu9nlYGX4jxtql+M3yeOi3juaXH -hLFWqVn3FkQW7N4IV+bVTkYcxQg01rWqY/h7BvL88AiMoiUXhOvE5iAS4sJe+EVB -bDfRaLr1Ju1CXYm5B+Q9b2pU0SWAbBNlVxYGs+NOeBh9YzwdGTFW2l/S/VLLv0bE -hBYuLwOIs0BqrL4TWwlB1ucEikg+r3O7OZL8Dnw0mnBVBmQxKhl1p8dLcYtylG3B -aEIbN6wHQe03xYvAmaHDdG0kjPiwhOlpZ+YU3ux8F2YnENXm9J+25GMyTXqybKQl -ltTE4hHgRH2v -=n71X ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=J9CI ------END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/icinga2.asc b/data/apt/files/gpg-keys/icinga2.asc index 165344f..901c78c 100644 --- a/data/apt/files/gpg-keys/icinga2.asc +++ b/data/apt/files/gpg-keys/icinga2.asc @@ -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----- diff --git a/data/apt/files/gpg-keys/jellyfin.asc b/data/apt/files/gpg-keys/jellyfin.asc deleted file mode 100644 index 618b517..0000000 --- a/data/apt/files/gpg-keys/jellyfin.asc +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -oqYC5A== -=OWPs ------END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/matrix.asc b/data/apt/files/gpg-keys/matrix.asc index 41274cb..4e8d81b 100644 --- a/data/apt/files/gpg-keys/matrix.asc +++ b/data/apt/files/gpg-keys/matrix.asc @@ -12,19 +12,19 @@ s0UuBxwDV/x4AiFTbvYEncYwlXME4scNoeQkESj6bT/EAK50WduMyG7XHULeAD86 i4cSG9mbhDLGaOB084gRb+Jhk6mNUbXiy7TwsNmDaanrP4CO1g8vIRwSCl0l6ayz uFGv3BRVuC+6yN1gvh82DgQm6iWeWdHxkIkNdO3lP5JDZy2Y3LpahsWTfwARAQAB tCltYXRyaXgub3JnIHBhY2thZ2VzIDxwYWNrYWdlc0BtYXRyaXgub3JnPokCVAQT -AQoAPgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBKr5roQ6dYS1o+TNK89F -pRLeLaBYBQJkE1uZBQkaKk5sAAoJEM9FpRLeLaBYpZsQAJp+ZbE1J/AWaUCrmsMp -8pS3TOrTyAqZFw48Ew1UHFBbadjX2T6C97dJz+nDjF/0NpKOsOJokbzq1QA3j3wu -sgZsqub4XGKolTr4DzRg2whYflWygeYmbOz+fQNBGDksT+C37ezu7SmkWykQHUQp -CqmYVUpFTc9ZwIISB0KR/N+V07sc0gJ/6CcokBSE0rHlAolMtV6c7Iy+EauUuvlm -wmRDyN+8TZAtnteO2LBrr4+6/Sl2I1z2Fb9AvY4JMaqrmxYJv+1FTrUc6ilXmuWr -S7eaNUm+lvZQQdInnjWO9UnulBd88HP2j8ltGr5ySOHdpC19mps0V9upG8CsdiHm -UAftNKjleCnhR2vOhHqjapZLBLBW5FYZerSRYRaqKVQ/GHzYa1OAjWf0s/1Mc3cx -MT/11OWdhbRn5zxpg28KRhKcfTKOfeiObbDq5idDbAyhbzvKxyxTX6204q8fmUhh -mq5EiRcBeKF5hQv9eyOyBcBsDnMJsV2+zEP8hVZleOncx8pn1uNNd1nWPX10/R5j -BfgnlUSNNJWZ+YnPH1f71kduhn2iee58jbA1CXnVbFjPMI4c4p2yZsfBm74LziC1 -PVrFtSd7WijWyP2rC3JoL7KQPvqyXJ53Yn4jGQx6brXFPY53lXicLoYTTByg7WK5 -nMfe+URZO54gAkGN7JLo+BhXuQGNBFy1EV4BDADIlwWsfB4tQIErRVHabD1NU6uB +AQoAPhYhBKr5roQ6dYS1o+TNK89FpRLeLaBYBQJctRAtAhsDBQkJZgGABQsJCAcC +BhUKCQgLAgQWAgMBAh4BAheAAAoJEM9FpRLeLaBYWwAP/3dNMHj+hu6Nn583H5Wu +UuTGKbxb7LlWpGtYVd5qt0to/fkYEms3koYJ5X+K71bv8weto+TKyhXM1yoaVHT+ +yvAhQGA8X/jpXUgQpmF48cw1vKFf4guw+hXMhr9Tuiald+7qEi6neLxXt6kh+k7c ++MeZAJ1jsKbPeehGrzJJCjSrQHeYiK9+krw5jfpwCpL3Aqo6wrizWlzBScHmxckP +XPXVc6xsKtQ/EsD8dM7c5LuJA1Na21HzGfFoMUODEg6bjp7rvs4GrY4MGx7jJG6E +xYYArVh4rzy82GJaV6SOKHLqoTMyVdSw3gwL4LoKdfUiv92vszY7un3466eruLcv +fHEA6jRYl7Da8Csb9odFWFrua1Jo9TrT9dZZUFxkSNDSwSHYT8qjCDoPemi9/5T1 +7EY8htVjEv+pE7l33SP1GURvQhWvg8rdJLHILVTzwOz33y30OGOGqWV9P1wqcfbf +ZLcwZIX8HQCBmxPf4+i8augXnBEzVIfUBHh4SJ+md9UNK5Sx1rYRvb/Epd1GenQr +On5NJlNkthyUBCvKDfrFquW5UDTW6TOyhXcmycWcL2lSFueS1psBtiJNeBWnhxc0 +c8OHGV5x3CqigVya5kFL4/47Ay7ldiGXQzLl1RxCBxCaw+0sDbKQlJx2b3/f45V9 +ukVK4rmFVlUeO1ULo/dpOo1ZuQGNBFy1EV4BDADIlwWsfB4tQIErRVHabD1NU6uB XHNoXG3z1ackyByCLSZzD5r4HbAcdgeAjYPZdBnxrtAhXjc4J5Z2ITZkq4riFfYV UsuastrrFXKO8XwA7f8IPhoKVDRbJiRj0S4hEnwwT8yH/bOwJrJEW97OuMeKQ4kW 0fzjg/ifNV4C0gYzo7suOLE4lcOGg+czmyOXrVMMluBqsHihdNgEU84Ht/3pPFJ7 @@ -33,7 +33,7 @@ FUV32+oHTkATADF5OnnnCuAgLG3WNBIKOyA1Ov+e0SmFk1So1hU+mE6349v0rp3R LpV2QRDrIAcn6wUHLsEqyQBArvWP+cg5JuPALYR3ZBEgah52tSgnOGnvVWyPPHNo 0bhAFZ9YGToDuE3qPV+ud8qNe4nT7qsZo4NdfFd3JgBHV6CaVwdRMtkut8Xjjmt9 DiVaHS1hgi+METEMFXdhyXMSwFLH6DDF6Uny9LsAEQEAAYkD8gQYAQoAJgIbAhYh -BKr5roQ6dYS1o+TNK89FpRLeLaBYBQJnxeuFBQkO4xMnAcDA9CAEGQEKAB0WIQRV +BKr5roQ6dYS1o+TNK89FpRLeLaBYBQJgd9nFBQkHhS9nAcDA9CAEGQEKAB0WIQRV hszAy7vvx6JYEa30c91EczZd4QUCXLURXgAKCRD0c91EczZd4U5qC/wLYGzvpT+M I7SNg1of/1ekeRXzvXc8m8JC/cHAhrBzUaI8z9LJ7xna2DGt27eqeTtu/Shtknn+ /8VaX9+7wm7UaGHWVmPFkSt1Rs1x5Opxo6kabLc4HxGSc5buNx+awybFEt9VQdSU @@ -43,16 +43,16 @@ uVJPAFF86z39hiGNnYJcikyVXogjwQPs5Od+3PdGQ19heZp8n+2rVkhl+9yZaCHk RRb3hyRWTRtLQhhaMw3zSwekA8VjKSinTyOxnRPa3rc7/rOqb5b8ZUAIzpTLd7al 7+E0fmOfie93KYh+BV6FuL0KJ0RNHm7zrgaVZbjDoqNIgkHK73+3a9NnSefsgbmC VxOxNM3lY7Jun1E/f/KE6dTY7VGPP6aTtQrcq49Zj1MwPc0SG7VlZkwJEM9FpRLe -LaBY9+YQAKXMKKOY7D+cJVKjVDbVuhknB+vLLRIN7Yx6GxRxM0Q6wPo42WmstDui -ex6u5MN0UjoA7+bPrC/vGBGOIr56sIMiaHkCqhoQoz7vwKayTJHa8McO/x8oRMr1 -aPtDgvUU78N7cdSv01wMW7zF/anCESEtbpfOzd5SM5V+XuYJoVzm3KtAdKQIxH0X -khOPvDa9Nn2bCsEvkp0pds0c5STKPWBeMSYSYuJzf48lcmoDilruPl2PaXPY1oxN -ciOGVuiCoT/XAdYuw2iynU5eC6h7W6b9EQZ1XPatFhkfGSucWtypObgCe+UGojOP -xZvqujcKnZBzECzawFu45Gp7TjPXnbsLmH5tv4GvJ9R0AeBnnHzTTpkduq7C7lO/ -X8VyxPpisJZII6s8pymSuw0/0CCNodf4wd1ar7ATCixcmJutWCJi8HLzvfoXEe8J -hE/ZjUEkVpWwxYIsM/U4ImWmrus81dMqBDVHowxwXoeJHsHNeUGTa8fKkPFo7i54 -Y/GhsNRDIk9nOHNqucV6xx3+WPs5p8eEcNFLalqjONcugfOB6Sfo/NaR3Jus7p+7 -kmwJ4YNxXYnogj4I24PT1/+BTFrrjYMXgbVs8s0yL68AHDlEo5MxHk3C82+ukeI6 -97uC8U9NZEpwVDk2mNb3ngwHWzp7InGGi3bwozHPj8bGIPuBaAlF -=3XJ/ +LaBYVA4QALCPlSk7P4e8BySAex3BEoDEhTTZtl89/bqRJpcK8Pvi04Qnqa1fcqYF +gM9LB4OzGst54ipixIQbMuKxdMT3aaqAsAUQvhtrNC5763SjxCWE/J4wDo5ICj8s +WJDMJeyJ7HgBhaTLVSRGE3ADamXI/NxIRxZ3czuS1NIojNcLlVptOzBnYl7dVH7O +cRsp7Qj6L4mNYMLMl70xXXEaI3WHK3OjQ+Qn7x5gv5NhdP/tVjMT0a5p24yw9KwM +FkDn9LYTzu7IskkPlAFl5kirfOHJGie+NuhK/XW3stoIVc3D3qHZhkRx+/y/wfVW +MavMZTMTs2pXtoFA3yIwm8bIwcMPZWU6KoQTQBxGc3vTj4LKlib0f28xYSX+YMsB +X3JZipPUdzR6ApvJA/9Da/u8LQ6K8ji2bvU1vnRKu8/ot4eABX+1+DY8oAlQWPLJ +6G+PpsHCDtOJf76x+JcFHzIBlLyihCjhZbDkcJj59Jm+7TsKHOaQ1ySEkKnUpog8 +R2Xi6A7nF11n2OlW3T5e7K0qpHoUwvecXA854yQocW6GK9N/HPSbC/qDi/lLKZ5J +jsA55fwysSXtnIqaHyvMN2wVCRQFGx3u4NcI2lwR+cqmJlwS93ZYnK33sGPDYQ6D +UiCsvX1EBMQT1Q6GxDcTXBHfW+M4JciUofUpTXO9exBzHHyJd8cN +=FEYi -----END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/nginx.asc b/data/apt/files/gpg-keys/nginx.asc index 656d40c..d2258b8 100644 --- a/data/apt/files/gpg-keys/nginx.asc +++ b/data/apt/files/gpg-keys/nginx.asc @@ -1,66 +1,5 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- - -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 -vcV0wl+DODz9hw== -=oWlI ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) mQENBE5OMmIBCAD+FPYKGriGGf7NqwKfWC83cBV01gabgVWQmZbMcFzeW+hMsgxH W6iimD0RsfZ9oEbfJCPG0CRSZ7ppq5pKamYs2+EJ8Q2ysOFHHwpGrA2C8zyNAs4I @@ -68,125 +7,22 @@ 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 -ozw9yNdOZmnk2Prj7+mBuchbT3BJOQ== -=AgHy ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -UYda9m8fOnaIew== -=TEOn +a2V5IDxzaWduaW5nLWtleUBuZ2lueC5jb20+iQE+BBMBAgAoAhsDBgsJCAcDAgYV +CAIJCgsEFgIDAQIeAQIXgAUCV2K1+AUJGB4fQQAKCRCr9b2Ce9m/YloaB/9XGrol +kocm7l/tsVjaBQCteXKuwsm4XhCuAQ6YAwA1L1UheGOG/aa2xJvrXE8X32tgcTjr +KoYoXWcdxaFjlXGTt6jV85qRguUzvMOxxSEM2Dn115etN9piPl0Zz+4rkx8+2vJG +F+eMlruPXg/zd88NvyLq5gGHEsFRBMVufYmHtNfcp4okC1klWiRIRSdp4QY1wdrN +1O+/oCTl8Bzy6hcHjLIq3aoumcLxMjtBoclc/5OTioLDwSDfVx7rWyfRhcBzVbwD +oe/PD08AoAA6fxXvWjSxy+dGhEaXoTHjkCbz/l6NxrK3JFyauDgU4K4MytsZ1HDi +MgMW8hZXxszoICTTiQEcBBABAgAGBQJOTkelAAoJEKZP1bF62zmo79oH/1XDb29S +YtWp+MTJTPFEwlWRiyRuDXy3wBd/BpwBRIWfWzMs1gnCjNjk0EVBVGa2grvy9Jtx +JKMd6l/PWXVucSt+U/+GO8rBkw14SdhqxaS2l14v6gyMeUrSbY3XfToGfwHC4sa/ +Thn8X4jFaQ2XN5dAIzJGU1s5JA0tjEzUwCnmrKmyMlXZaoQVrmORGjCuH0I0aAFk +RS0UtnB9HPpxhGVbs24xXZQnZDNbUQeulFxS4uP3OLDBAeCHl+v4t/uotIad8v6J +SO93vc1evIje6lguE81HHmJn9noxPItvOvSMb2yPsE8mH4cJHRTFNSEhPW6ghmlf +Wa9ZwiVX5igxcvaIRgQQEQIABgUCTk5b0gAKCRDs8OkLLBcgg1G+AKCnacLb/+W6 +cflirUIExgZdUJqoogCeNPVwXiHEIVqithAM1pdY/gcaQZmIRgQQEQIABgUCTk5f +YQAKCRCpN2E5pSTFPnNWAJ9gUozyiS+9jf2rJvqmJSeWuCgVRwCcCUFhXRCpQO2Y +Va3l3WuB+rgKjsQ= +=EWWI -----END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/nodejs.asc b/data/apt/files/gpg-keys/nodejs.asc index b7637b8..1dc1d10 100644 --- a/data/apt/files/gpg-keys/nodejs.asc +++ b/data/apt/files/gpg-keys/nodejs.asc @@ -1,29 +1,52 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 +Comment: GPGTools - https://gpgtools.org -mQENBFdDN1ABCADaNd/I3j3tn40deQNgz7hB2NvT+syXe6k4ZmdiEcOfBvFrkS8B -hNS67t93etHsxEy7E0qwsZH32bKazMqe9zDwoa3aVImryjh6SHC9lMtW27JPHFeM -Srkt9YmH1WMwWcRO6eSY9B3PpazquhnvbammLuUojXRIxkDroy6Fw4UKmUNSRr32 -9Ej87jRoR1B2/57Kfp2Y4+vFGGzSvh3AFQpBHq51qsNHALU6+8PjLfIt+5TPvaWR -TB+kAZnQZkaIQM2nr1n3oj6ak2RATY/+kjLizgFWzgEfbCrbsyq68UoY5FPBnu4Z -E3iDZpaIqwKr0seUC7iA1xM5eHi5kty1oB7HABEBAAG0Ik5Tb2xpZCA8bnNvbGlk -LWdwZ0Bub2Rlc291cmNlLmNvbT6JATgEEwECACIFAldDN1ACGwMGCwkIBwMCBhUI -AgkKCwQWAgMBAh4BAheAAAoJEC9ZtfmbG+C0y7wH/i4xnab36dtrYW7RZwL8i6Sc -NjMx4j9+U1kr/F6YtqWd+JwCbBdar5zRghxPcYEq/qf7MbgAYcs1eSOuTOb7n7+o -xUwdH2iCtHhKh3Jr2mRw1ks7BbFZPB5KmkxHaEBfLT4d+I91ZuUdPXJ+0SXs9gzk -Dbz65Uhoz3W03aiF8HeL5JNARZFMbHHNVL05U1sTGTCOtu+1c/33f3TulQ/XZ3Y4 -hwGCpLe0Tv7g7Lp3iLMZMWYPEa0a7S4u8he5IEJQLd8bE8jltcQvrdr3Fm8kI2Jg -BJmUmX4PSfhuTCFaR/yeCt3UoW883bs9LfbTzIx9DJGpRIu8Y0IL3b4sj/GoZVq5 -AQ0EV0M3UAEIAKrTaC62ayzqOIPa7nS90BHHck4Z33a2tZF/uof38xNOiyWGhT8u -JeFoTTHn5SQq5Ftyu4K3K2fbbpuu/APQF05AaljzVkDGNMW4pSkgOasdysj831cu -ssrHX2RYS22wg80k6C/Hwmh5F45faEuNxsV+bPx7oPUrt5n6GMx84vEP3i1+FDBi -0pt/B/QnDFBXki1BGvJ35f5NwDefK8VaInxXP3ZN/WIbtn5dqxppkV/YkO7GiJlp -Jlju9rf3kKUIQzKQWxFsbCAPIHoWv7rH9RSxgDithXtG6Yg5R1aeBbJaPNXL9wpJ -YBJbiMjkAFaz4B95FOqZm3r7oHugiCGsHX0AEQEAAYkBHwQYAQIACQUCV0M3UAIb -DAAKCRAvWbX5mxvgtE/OB/0VN88DR3Y3fuqy7lq/dthkn7Dqm9YXdorZl3L152eE -IF882aG8FE3qZdaLGjQO4oShAyNWmRfSGuoH0XERXAI9n0r8m4mDMxE6rtP7tHet -y/5M8x3CTyuMgx5GLDaEUvBusnTD+/v/fBMwRK/cZ9du5PSG4R50rtst+oYyC2ao -x4I2SgjtF/cY7bECsZDplzatN3gv34PkcdIg8SLHAVlL4N5tzumDeizRspcSyoy2 -K2+hwKU4C4+dekLLTg8rjnRROvplV2KtaEk6rxKtIRFDCoQng8wfJuIMrDNKvqZw -FRGt7cbvW5MCnuH8MhItOl9Uxp1wHp6gtav/h8Gp6MBa -=MARt +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 +=CLGF -----END PGP PUBLIC KEY BLOCK----- diff --git a/data/apt/files/gpg-keys/php.asc b/data/apt/files/gpg-keys/php.asc new file mode 100644 index 0000000..ba04e3c --- /dev/null +++ b/data/apt/files/gpg-keys/php.asc @@ -0,0 +1,42 @@ +-----BEGIN PGP ARMORED FILE----- +Comment: Use "gpg --dearmor" for unpacking + +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 +=gNGr +-----END PGP ARMORED FILE----- diff --git a/data/apt/files/gpg-keys/tailscale.asc b/data/apt/files/gpg-keys/tailscale.asc deleted file mode 100644 index 8a8d36d..0000000 --- a/data/apt/files/gpg-keys/tailscale.asc +++ /dev/null @@ -1,7003 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFyOLUgBEACvIkPeEBZLADHykk4riTVNU8HCYRjiUeeaDLHL1LirlkUsGLJO -xGp8gzf625jZKRXdwhoZrVWXKBX3lPsc5jDG5BO19H7lrwt2Xu0rmrDM0X3fITWf -MYFQ99dUvPKLDgqgzLN5vpyvkaYzhrt2yvDzSA9Vti3WghHns4W2eExyfb29kYYY -aYT78LdL53lpYBzfEb5hlW7GCoR0ZoevUmMVXxEP9681H8k/dQZUOmXeDO6sRoZ8 -zGEVaq0Ic1XKzJnS5c69P3B/lCanzumHXfq0VV/qKiHVcsiJT8JGrlh33FzVIM2A -3osVyT9WIrCrTsFqsqA1gPhSoTW0oypdpk8bYsx1gQzn3GclyQK1uBwaWgfXBkVw -6aH/D5sje352iU3SpK5UhhxsJiwCqJ+ua9U0I2HboIUdX6nnrzE1IuZal1etFDnn -o5AvS7no/rUbOiyzqbF6jzUuD08cHJfL8KYoCUR4TqlTInS9AUEWn2Bygwbrbqlg -ntxxEBaiokqOsKYPEKOvdgP1CkmJOP23E6znHIzIBbEYi0sXdjYxDs6iwLeB2vgq -taqfZV6J1EmZn7+Ubrfl+d2ELRhGqHu6/geoDAShqKctCP0ujKbpDKqDj646xsml -5fRxNYQBBOi8W0PX4ph908fKeLSLbb0Vd/VBHr2kZHBzn1Zj5TeJh3mrowARAQAB -tCpGcmFuemlza2EgTGVvbmllIEt1bnNtYW5uIDxoaUBrdW5zbWFubi5ldT6JAlQE -EwEIAD4CGwEFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AWIQRf43/zyYGpFGw4BTJC -Be9T7ODSvAUCZ9gItAUJDwxCbAAKCRBCBe9T7ODSvHpZEAClYGCrKINJkv/c7MuD -bS00vrqtbXVBUltOFACpyBn9g1lbp5VL3l+7lfry+/QtJEo3N8dLDppCayUsPwqg -gX9VYD4jWjkiRyFA3PHpAcasBAEKJZUbzXLf0FjWUD/9AXdYz3heaVwdzhGExkwm -FdLd0cmr5oFrQ5WFiv/WPi6QGIGQHIzzfog6vdCecOEIAhD4X2YP4U+5sPOyFnSa -gw8lGRUEtF/YGkwjJCZPshCEY422Ju1P2MRBgwBc+Asc1s6HPC5Ld8AMaRLV802v -Lu3F6hN+k9nbBEgOZ1oJOWnu8e5ebL5sStYI0NawyzV0BT6a0LSWg7rA13YtS22u -uABxDLOQ1jgVmetYLA1UsCziOLWlvh9/+3ma6fF9uSzOK+x40VMFSY75sdpKAXzq -clHMYQSStUUxp4MXdIYCkjz/afOAeMZoamErKvWtimovm3U3PxBHUFtOC2v/b9oS -TlQz93PvmAk/Q8waWDy9Qjy0qZ0ZeU6UN0j4bR14ZOhg8sc5at4jjGf7mRLm3QUd -RVVyyz7MXYkc0Qj12aCL0spOBZsvwfVUkZoMNbOojGBYkAeJV/KZUnrtjH3bcaY3 -GUdwWByiYPdeSbBNAD4zFds86dha/wHOa6UUVOU5iiNPpZxf5Cb6i0lMSdHZfW9V -9YwXBZUN8FC1oB9VOMQFwyiwL4kCVAQTAQgAPhYhBF/jf/PJgakUbDgFMkIF71Ps -4NK8BQJcji1IAhsBBQkDwmcABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEEIF -71Ps4NK8xJAP/RHFuZ5mQJN3gcEyzuC6cOQyEzM8oktNphINQUnS4aVuu4szYch+ -i358bM5gRyVXIeajVE0BKGTVlr0DYifJUHvxAJzZkozmogtgVRybeS3DrtHFH8GE -OWnzH6li/7aJE5S8Kd26g74+c71FY/Iuulc5M4OJRfWIm/xo8WMoRQ9c4GjtRg2A -4kEN2U/i3GNE+sHfUeSzlvG2KVvTODZM7ff4nEikkAq0IE1C2VT17o/LorhZbMxy -6+QhKchbV6k+8Bbhm/JbeIjNgCtxcZ5PASqYQ1WUytbKBwaDd1pVOgeohYFRI3O6 -xm+1zlcJpjDG5zF0RF3Z8+qOzuG6/OypDzf4ZagpD7uGdRyt0dEyior6fu5OHmRa -iBKGvW0inzphtuOMIufEYKJYxQ8xaBGA4Hq3eQCGvl5n7lSYilCtTNM9u825rdVP -BoKTKA5pYSlbPxnr3BPzBF+kEfTzC9qBwzSUjF7MzRbH29XtHhwp/TxT58sbZ48v -mMqm+NaTIqcnamPcK0hNWaAYIV5N4xOWHwZacjVtgWbLwgNo9pc1FhL/4LXG1YKN -T5whfLNyhaU8Jr9b/WxYy4dQTsuDdxS7coGwcO6DOTyuITzBhBUPVVo2y9uG4Tmj -jG5by5qQ/fnKAaovMuphX/Hks9ChkCBrwvGnbnTZF6xvjHp7ioHuYT3fuQINBFyO -Lu4BEAC8a4rX2UNcvG2Qo49dYEW5DnSb0xY0PTePVWeZlYY8IszTHyyTbhxjvO9a -nGC6+WB8bEsUku283Z4oTNyH29Al9nt9WGK2BTCfDPzAbCngt4BGuI+tnQBXTELx -NkpvAtpvgWftcyMimoyS2eyQVAS5at1czjZ0U1bq1RPJq98nxAndQQmjsN175fVx -whByJIn9jAyZp3CHT8R0ETq+++e83VW0R/0fcP9WAf+E57wlImgd+Z4YYkTZoNZt -yIXGUWwR4kfxhRC+4+dOet3qOzbh9IUxrzyPuwdohOtodZfFMtUmfp+PT8mamlLw -RgTLWRh/bhTpIxEYyt2Ml5MYlGbU3LjlmMdR3FZCRnWd/zKkAz8HJou0/+0edqhl -dXZPoo7f90n18RZdBwr7NK1ynrQcSYeLAxucYbBPWknXdAo5boWuZeEpVwQu+QBO -zUlzeI3++bm2ME9Nmxs3RKYC/7VeMLLyLxrWFw+3hBv3mOJ6MEUvLxDU6JAAVSbS -vMkVvY3BOeADzZQVh55w8hSaBylv29Sr8/C7kDhl5nsdoVRJ8gRAtEWh+Wwr3PGl -p9aDrdsxrxg5EUvS0muRoBirfyaSdglSpnHBKUO9gWMzovA3uURVjwvmNeT1DVlb -vICvBqLj1yP3vfJnTrlx/t3E8Zusa1Dki596kTTXVmFRUbDiyQARAQABiQRyBBgB -CAAmAhsCFiEEX+N/88mBqRRsOAUyQgXvU+zg0rwFAmfYCNsFCQ0rDW0CQMF0IAQZ -AQgAHRYhBC0k7yyacFikuaY5EhLj0hNrgYNQBQJcji7uAAoJEBLj0hNrgYNQc5IP -/AtWY/7hqrZEePyd5LUTm2d5mqZXolxI8VpQUcra0xXFFMrJQozn9G8gRjKsjH2i -2je6ltUDSZv0RIEXFJV+Iblv+j71Bn1tM/qex8lLP/7DN3yM+6XMD1cbTEDHsh8w -MQxdurbJjuoHMLOBAlWcPpY3V6Eeo6OvqIA7ylvLTKTd0ViOic5Wxq8HyihhBuig -Mpi5ZtlMfbzASiEhbx8B32vGELIE6FbypIDFwJ3+V7CToS6XVl6o27dp5VvJd5aA -iCFMJ+P3sFXFQkVoCao6zwJ1R5Wp1n6HOw+FR0zsdrDTjL67Fkag4tVkvP7fVwXn -8gBTROFxAQr3tw1hLjqJbZbaMTBEWooUvvL9/fp65MBWn1r5NcarhxNWzz0mpwQW -uklGWAwtdXP0dKjNtHZo+r3rUg4yz9IckP+mYacLWjA62ITyM38mtsGm4Nj5fgcU -DNXyDhe6PLZzeSUZGjSpAPEeVzQ39DwmExDBANGOFZzxzXH0062SclaIE19LXGoE -B3tBMRcixTHWos0lTy3LFC84CJlXHEhZ+6DvitI5rYFrL1Fbsqu9iAg7RPqmYDKB -b7sVxQ+nk0DOpAjBZU+UIstYrg50qTIh+E2sfKrnbhLzbGLX9vdl62pi07HW31vk -MMSLZv6kt9melr5n7ykNuymi1IQFJHe5qvdFAUcpQPC6CRBCBe9T7ODSvEoUEACc -Pfv060349Wss+w0KeWu44NI4VgZvrPnfJ1Jc1HoDNQG8Vp+4wpVa52l1T5wb6LCF -OAleGjUp5OscM6UPtvr1wVlvYsG3lxPac07wnHzjWvLlngKu5+ZoUifo/L+p2qnx -gjbmJudR5g/UTYfcFKs3WsfLveZ8KbP7oDBpXsWOK7xMkK85FeNOL1MR2aybQIXd -NY0IYmV/1+PuNRHiw4GAmLXy7lvfNz6EKuJ9bmqvrmB4eoGJMPXhz1+0ALNRiN4u -fbfGR/gvOxsuZI+dPu5zbbkjjOK8t5mh4kDvHABtncwQECmnH59o8bpbtT2x3eRZ -fWKnvLY4ku/Hb3Eu6dMr88Uvk6AyvPMSDztFU6HVbHsh8muypIG/aVugQchY7htD -FQylcJRQZOWEyRetIYTep14NvqTUwyzRXP6P+UAt9a910emLxBV2b7i7pbFjMCZ1 -s9hX63HHg3VugrEoDJPmGvYn3Z50ooXhCfTpKS0k4WI7bBFivTDg4XtEUvVZpqrn -KcP0LEp9hZIXU7mFFfuGo/Ndr9axPOqC3J/IOH9DG/vvzxnf3UKv8mc1zr0BKUqH -EOHXlSysd4Vt2NwgqhZVVMY559rsExiSkqSIBt9SsiCfXX8jOaest1E1xItuYI96 -EcJpi/Hvl4pCHw7X5RNfrskaC3mIh1idCFFFrsbQgbkCDQRcji+eARAApHcgdCET -zzEMsJ7uv5eo18H0vYu4vuAZ4dDPDd8098bdHjtgY5tNEWd7mA8DOI4exjtZyjVi -tEIrvUYs+muQ7TBJ3eizZbrS/RL2focCnmYzoQQiLbg8b3RaNgVHubECiaDa8tWc -rQ9RHkRSSjs6uRSLLr0IJeR3K3gBpVpP7NYtrJyOV9eD3Le8ICJ8N8CO/VTXtpMc -6IcVGu2v3Se2TasVZefhRFf5d9IRpT2HR/oNuZbdOe9wBo18ggv3rDt0pnKInVlk -6oMebTkp7D3UtVKvUMNsCCJ75d0/jOHhwOxV/oHFuEcMUyZAYUeH9+CuKfG0KwRZ -W0uJFsc+yjuotKU4XZ3fFFuRwVW7uilS15eKgjT0q+DgPwYRm3/DZrrpoMLMsb2D -TAoo8wRPNaj1Myq9NZWaAVQPgK5roEkjSlgsEkt3Jji3v2PVkwTJRc0O1NUXsymz -AciG4gqo0E389kk3sg/eBxlrB+7LlkqZsTGI4YvlSMoO5vtSrWoOqlwG0lj145OG -llKIurEMFpAezlljk6Z8NlCaS38/MicbLKqt7RpxtXsHwylpq6hA9AixVz0LdkSe -8qhD7uqzq2KJ42T3I1Bcf6xO9QVdsqgsWhU12ukZG1e5JsqlGkBjZGALGC/VWh02 -B/RdHjEV+WjuyZhcocnwN+RxkoCdMJdIgikAEQEAAYkCPAQYAQgAJgIbDBYhBF/j -f/PJgakUbDgFMkIF71Ps4NK8BQJn2AjeBQkNKwy9AAoJEEIF71Ps4NK8vA8P/0qI -4CLTXvyh51tLr8f/oY/dROoZQouhcgkw+L0RZfj4YHKrf/bVk4M+1EynvidylUUl -3+wxay+yJ+oWzrkwiBqiNUryl7FzYIQl5cp5K7SferaDDIsR0LZFW6E3LzfnylWR -DkyvyBVJcCZ/4M+I6NGPr+C/m8vB3Pq8XjSrLFM9xzqzg8qWu6RZlmp+JC3ksd5B -8pp0vOQH1KBVqps9dRastfVpOVgQO1Heh0rVX7kY4E3gBjly7bBE+8L6qwAi3+K9 -NMMwJu0woFIHchW96NM5q+Exqh8L37PX1S62Px1TFCKwzUJPNl1eegbsXqgKR7m4 -P4b8NK9q0GvyHJzh87PausprJtfJIdCWQm/ljoeHkQvdpuWFUW/GHe+bvj734lgl -l6LlZauMsLLuaTzmr0YMHKKko2NILUPMhnzz0Yh8rX/cqijn2HV2TRaI32BtajjJ -t96xlvfZfGbLiUGHTaspLJmAtPyxYb3FQ5Zv+iDr+/O+p+nzR8Sy2Od1O00xBI4h -3Wo39EyjD4I/bgELJZ0wnPpFYA17aoFfFoHs5LuG5GUJB+bmDPaLa1Nw4I6oa6Wa -UpfWPrvxFr3tVyDRJFND1oS+2RKPpsKgu2Ftqa8Z4xuAgE83WOO/ikYM9c3kKrWu -xo5duj1mxXkP/uPq4qE7OkyB8/7evTy95RczEAteuQINBFyOMUoBEAC+ja1z5VRQ -zaKCCePsUM14qMr9QR94qlWc7Je5Poki9UmC1t/TyxRVzcCBL1ZdIfBGx6QKtfkE -bvhgb3nxVt3PvXjoJrc6wwGLmNrVsU6B88y35g7nzupQiPKYJwkNzJ9j6Dmkgj1F -5Q+aY2SitDaX6vqICLJ4Al/ZFw2IQxVJfC7JXRJ9jRMG5o9gWoE3gWDYEAmw+HU2 -mNzyeuaD12qJw9DHUimAlgkOWzll3gh9WclsYnnXGrCCn5fyHFUCJl+XXAIy519z -7YTpKih02rsIOw5dnaGClBZD/YQu2ZKVFZiwIVH7aBiqHOmtgRyWTQgjbh/fMpIN -0ar2f/iZsWYUjd6et48TOmXZYIPCQ5FivXNvxt9oo1XZfq76UHBwlmypLJIWROMb -z375n2M6hr3hECuxuPjKEUXAv05KiC1aJ4xc6pFoVhqwAR99hvHw5U4o7/ko2NVj -NpTu6Jr5DT5VaQLIdDDjC/93kUjMpdD/8P72bEn7454+WexU6OE6uvNiHj1fetrp -tr2UAuzVfnCoaV8pBqY7X95gk+lnSENdpr8ltJYMg8s0Z7Pzz0OxsZtzzDY5VmWf -C9TCdJkN5lT8IbnaixsYlWdjQl1lMmZGElmelfU3K7YQLAbZiHmHKe4hTl9ZoCcW -dTQ3d4y2t1DBos+N2HZNdtFCyOS8esDdMwARAQABiQI8BBgBCAAmAhsgFiEEX+N/ -88mBqRRsOAUyQgXvU+zg0rwFAmfYCOEFCQ0rCxEACgkQQgXvU+zg0rxozBAAoXRf -NjUmdtsgnGadjs6c2IbaXunB0pMGCTwzPV5XXV8tV/Qo8jVhPL6OIbzH/84X7iqw -qC/cmlDffwaKEc9UiAq4Mp3yK+m9lHVcrR3RNQr7CzUHJgK+pYT6RszxcnryQpEr -batpxitLs9PjCTz4pAW0d1B2nYMlgxNCu3q9cTcanrBb4ehsNBEl3dR+N7unvdLG -sHXTc3UjREgSgVCPKapHzyf0pE4CkAHtFyHDkRroStJNvRKhHeCrZ/hIGXfoJPad -fmNtWonJfPnkXL6yGn2jj8tt0od+n5Qv4CNfRRxiMUOmljxvCxZp8zj5Va66HQzb -DLpF3gmBr8TMps2MlVritfuF93KyNb3oP8D5Te8qHNVepMgk9oqyCu3l9EXeIK2b -AsOPpPEf8q4uZXC2p9004KljCFz3FyjeR90YwiYwHUWm0nC89bzhe0Y7MABMRIoG -k7qU2+damGsDFeZk52MyealCY9N4k1CGAP7qNcbVKz/ikBoOvNJJeRaDkiPMp2IO -ySNsP1J/nFYC35l1N1WiaVFQdkKyQUx8uxbe7u3/pKohaC5LXi2mglSG9uUhoJe1 -QHK/vw9syuZym07NS03/p6fklnk9/EoDuliHW/uW2SQ2nXpkP1vNr8KncZnuetrc -ThkOuIpbFOve6z+Rm2IkGUzYsE6rdJPDSJw4MbOZAg0EUVGPGAEQAOhZ4MZaEk14 -ukIn/8IEuVyW74t+sBHdxoKpVcj7xRh5jLS/6gNfdzhqKfhpmEySHoN49tnnpwnn -qV58ihMQEfBMXqjRggZzUBnaVGaOy2gZhjs2VF3ZyPeaXQZEtPWf81MTfODgLiDH -1TbdgWltpwBGtFuRMyDSWVGWyWmlInPEPSfSszxXklKMXkd8yx3wETA17LKwkqwS -onLbRtS2pybWUrWXcrst3lW2adEETswXjlHVJctx4AK5R16YX979TW+4wnUimS4P -jS8ivZ/oPOzt6K9cqU5HnTDN0EIxgK/CLq/5oT4hSggrHO8GPWNoiwdBZPFPLWWu -+a2Y3J6Z9X+Gilo1/Fg+xMu+GnMdC4dFMYpsR2FfwDbFJJd5N6aKayYF/yF09AE0 -45lGSsbztbEbqgP/zQQPiQ44756xbVnr2WZ5mRYeOil0tfCwp9sgQ2K1dsrQedRi -K1iGtCKCzXba0lA3v4W8EWOnA0jsZT42+993qN6VXw2Y0rRPzY1DSKQn/8aooNpv -0utjVHZ+mdk+CAFREkEADDcmwYdmL2viTIkHe4e6uRE4PhMGfvjs93qU0Hsh70q4 -X3QsdgZS2Wi2oaOtMdtkrmJ6xG62dl6d/LvmOf4+4YB2eDlsvAgUEhoqKTUWLKPQ -dWk1YKbu4r8yUkpLB/R+4xdd3KFsEbQ9ABEBAAG0F0FuZGlfIDxhbmRpQG11Yy5j -Y2MuZGU+iQI+BBMBAgAoBQJTPfAeAhsvBQkHhh+ABgsJCAcDAgYVCAIJCgsEFgID -AQIeAQIXgAAKCRDqZmQ//+oOztJWD/95GI7NiIfJDg7c7j6R6KUktgD130teXKbb -dms0QeHPaDZIDoTWi7cOw0PjMN4uughX2a8i7yAjBViZznVtyd20bTUUDEeUm2jM -KV+cy8hjZaIifq4rFuJVcTjSkQ/7RortLwtqgLtW8l31rYWQriQ17YIDEU7E/66d -3PG4UkQ0RvTZO8CHRvkCb4t9RQYDWBSb+GMcZuhPhn0X3HJavKOb0Y6WxKfjWlUd -k2967rjUbBO54JZLlWoBdCpAAZYvtB5yP0sC8th6qkHLKFzviRBoASiIaEYFaMQl -cBOQIVkY8M1EiFXkPxhwqHa/TZximw6FlscKITuwVwpqUwT+8t4YaHjpgIqb+u38 -xMXySEMbqsYEpjBAlZPlVLJPbwRS93LK+84s7JmPhplWT9Yuy6R4R5mD/O1QVueP -ZsnLIvyWpIgNTO/VW+ue5LwzkGFQeM/kOGSbzvuE0ZRKqsUHnxRF09I20cooURzF -NUtjaFX4El3t73r23+p/bVnPsnAO+TU+bwsIQleYl9mMH9oQoTKHNLmaOJLnzN9B -RdU8SpC6duiL6CB4BVU5XyV7Ct0zIP9vvwD8JcE8Kyfzi1yl8RmViM5a9mNoQdGc -xdl+0dNfUh3HKtqC/fiICxXuWJ8PzbL6wkQTMcbPqo1iijoEsEBrpSYEXHTvV5j3 -FvEg5pe87IkCHAQQAQIABgUCVM53IwAKCRAfx4ZSEjTx9aSoEADUWdrOjfaeTdWA -Rf3tFaj7WErVOBbSFcpoXzMQHoFjXDewUoxFxzX6yEI3/bENQtvnEBw8fm4VcEit -Ka1pTR0i9fOMofhWwJQQ8+w21m+AsRPHSQQwKy8RZganln/Mqeh8P+w6n7AIzBk2 -QFPPVZ88s1ylZ9UdYEU32/54tC06m069o64KU6frtuakSR3kNX/n66BWb48QQfi5 -I/r7LqLXGm/MLVBgsDGKpbGVeZzI7d5P/jfeilEhjtVXICYSYXUbIARq05mrLPeA -PsNyiqIfP2hwpgJJ5wEkK91q22RO3B86Tjgb1xnXt6knWt7F21tDGjtyzV5IqoLi -5Tgkpj3R6lvV3/Q3gB8PXdRj9DomsiCwhAHm/R6dbz/UwOPsp4+kj2fErYzLFOYV -c6rNhX8+fzDS1FArOqzVBoP5pUey+eGKVaiu8R6w97lTJmqdfUOz4bGIqdGZj3x1 -rWIp3uNSS1r6L7hKvmFYHPoU9h5iW0SrWYXgilOUsfS10a+1T9UJWhFuJgXoGO23 -EEIadOWDxe7fB95dbppVX0vgNA0Hpc9mZY9hlLJAOPisXL1BDF8J21ejkqcuR/Fo -hzp4O2kruvKKjUyyCJqu6ij4IMe/7qunYlZHmX3w5p1tVIHHDLfOuaqM/MveoY1G -2oYze73M3CCdZvbb4DPEcu/vA1cq2IkCHAQQAQgABgUCVxytLQAKCRCT5E+sZJW0 -Ty6dD/4k3B69AVbRE6zTsPgtO0Hda0ITmRC4vZKuqsullutkEUh4AoCcttR4ECWH -oQZNYdesRUd+w+ik37cSAXPJ6zGIfCsc/o7agm7Dl/ejrCLO1ZPAaQmfLW+u2DlK -NhOm/MLlVtPd0yVOaZzmDaWUUHZSt+AxJs5Xw1722HfDye9T5rpcAhbo7qcH+xPy -sKGjaiwzCQgJan8FcNwzux2cBJybesPFTav08trJSCZjoeZwEaQkMeo5WzOi9vJ2 -SIUT7K11RUVkQcOFNE/JNjEULvO6dajFm6ORWfJTK3mk33KbUh3/mb+Sa+A/qF3V -PH6i4778HScgyl7MKbvIKSkvD25igMl19IfiVTOt5JKmAw+1ASmzDTZHDywgLkhk -SNhFkI9tYKGdvla7uNif9Z4Jttwj4S9isihBOc7lk6Hk4HjSIyFCLcwkEw1nPmhv -nLo3q1jnxmt+4xgWGr4SeZdsc2gDNQ/4+wZ0BSJqSkgdz1Tv5UR6KstwSHPTvP6t -0xSS2oc6fAvz2QqjSXiVFXMbfVho1P8oM+22olfAAQrX8BQKddTqiT4jiLFsUDUT -4UvB8uXdVGzSffXnsBKTXc4b59umGQ4w+9r7RgyxwHgVLMK9gF19iI0L3MTK3S2h -oLpcTDK4R4ohtdzj8bmhh30UaRCwGpP6UiRUMeGaP1JYmZEBS4kBHAQSAQgABgUC -VxytFQAKCRAqspY3EIltsMU7CACOmZWwNIi6DDmUH9mbMeCUErz4LrKWkc8xgfBa -7Ve8/AF52C/sOpmaIkK47OQyZu+JTr0dm4jPXPH9AaKClS7DbbOPDTlOVlQ/jj95 -4oLEfD1HRdvY6Y+thu+Jg8Z8euFGiCkrxMMM21wkJmOLGzXi6J17nwKEAc8EoRiU -BF+AXO5iobM40CQtlMaFEptiGOWQDtVR4xog3ZT/haL5ewmhxpdMjpBP180+buZi -ETQkLaS1Mc/k2m8RUVk3hhea5Y2z+xDyj/zwbjucACoTaErXFG/K7CMIDQof5edz -Vs4fIDTKjed5PMpg2wZ3mdaAGvoA+rKgGw7ZtxNqO+PUeJVDiQIcBBABAgAGBQJX -HKqYAAoJEGVQ2gM5q8/4GZAP/3vqzJ7x4OBHTQsyQtpbMqWUqWip1fvfrZ01/wEv -bBt93ciVC+zfCuuYRAuzLRc5Esqi2q1qd4EnY4trP9O9f7ctq6xqI/54mOfqhFD4 -HoqbIv1/wQILodZpj+WKB/06TASjLYi5m4QdvnD6gdcMujLc+7urV9CiOBH5LGgn -dIkWU2gbxueDZjgm5y6Zd+OBcKQCgDuaDQqlz7Ewq1lI1FDTdChiTy8KkhIuXkJF -Fos3rHP7vbX/CXB0TGZYVTSK+XHWU+eErh4f4g012JPW2NiDnkNc/rQHV//l1tRl -G+vUIC1ea/D/E0bes29dpqJOyChJhlIF02hz7rdIuu8UDvuXIOz8RWJC+2MWuSAX -5LHgCTiY1k6UVwW/GAxqul4KZ2oEjt+HpInA4ds8XA9SgyRHx3JHG8SxQeO3rUZI -VgFlrmuIhYEoKC7DLBz1QID6CRzRuF2JupTNqAUJIaCYNf54YcXfMydy42lDciO9 -E+K5UFx9MiqnMiXk6AWZVZU6O/QWACbtkwWnoO6fn1LiIogEtrmjTpzf5FJVwyrw -6oA8Xhr3sEOQYITkk/wKIHfyhtvBcpzf6YPW+Dpm3x7uRoZADadOFU6Jbr7DBWUX -9DyslrySRlxCSAZBfm2908ugQzlI/f6zweghJX25E5CSvUtl0KykiAFTV6/3UI7f -lRZxiQIcBBIBCAAGBQJXHKr2AAoJEKCPJD6tMZHipQUQAIL+VWT2TfmPEyiqsVF4 -hD6jbAmm+WWcSeGI2SRmBVObD6kwsyWQ1EPnN0+GT2c4Zav6b79YGLSpY5+onI6s -MZERqj4rfkZ+Qzf+ZAb53F4ZUMAV3gVOUdat3p2goOaccz8ntsoQONKwrJ+tYYxu -pfl1deY2vQ+JEEy5RZ8Pxc4LqAP8lAFa+0HoD8rGoWNpUZVEK+9N3ibpk/T0diyu -xZUGXhiCtsIadBUNXtvOvEjTGfskU9wKu79IwPd5uP83xnFbD4hNgDGDjjPnnZJ2 -NJCAhQlyLzjfSuYCBTVQM8wSXDrGkPLXL87pQqF7RoF+xyj2RkVPdWkd6W6MSKZQ -BWm6P9G15nd/GJkyA2+C06T9ptYR/stvkxiXfca8o3jfh8NHgRmvXtUuChpQ6XHW -VH7jmNVrkqOF7d8PY+20e22KeuQikz6NWKfwqoibriSw2Mws/F0UXcErvr8U0mFC -9ItSnnumkvo6yCEFSupGaU7SU6w3cBbh21kHW2Ja+9DbOEiHl87FK/XU+qriUFSm -1eUQJTsny7lXoBR643qytma1Ng2qXtJhwCtDF1pqowDL78j1hZLXGmovo+yd+RPI -NH+KCSX2GGRSWhvy8Tf/O10ah9rkV/kGJIBLw0bGb1Jyf01PcqOF8TT55Hnmkjsq -LuIKPiX2I9NX6e8tMnmUxtVhiQI+BBMBAgAoAhsvBgsJCAcDAgYVCAIJCgsEFgID -AQIeAQIXgAUCWRXmDwUJDWqUdwAKCRDqZmQ//+oOzqYLD/9GDPtkrvr6l8OLO2CH -ZrvKPxPG4ZE4kmx/eeXZjYIHoZgG9FY0jAEDJ+b2TJI4h7RgFydtq4deRxFuxWjK -LuzAOtjVuobGh+BjtdZXYuvXaVt6NWYMXLcBqglvg++VIAjHb7r6e3PlgQVcsyrk -eSbYpl3baZN/ZAK5Esekc2yoi0DwrDT+Sl28/rsbvIrAPpOThcG3RQ6sHxBFe9Wm -N8nFiOohyYMPIIv3wbda28hoYro+udw3z8tYOS4abHWnTjOKHNQEVbXxEUz1JhL0 -KccRz67abqAuz/mF9pz2eb72Xy9Ku4CwPvALo+fpBCgiYxk0wC3g6jPTmornle+U -UjQO2P7MsGhUxTDYEPHX+IdFGChcAmPS8DxSfwmAE/ey7etocZzVUq2ZqkIIexMj -HT50kjkQfmAO+FsyMSPptzyvm4rpnN6FtiwgKzMeAt2ZnBq8nb/DiSNiJi0yooRd -/9qGnF8fTuZQO5ydQJMUYyxLOFPG1cIeyIw4sWN13dIYxH1gW1GoMErAkZrww2yj -xOVTeQzgOH8jKHrxGRhteism02u+CENdVw7gxh2kOOi7Qgs02ApCoRoPKfqIgcI0 -M8hJNU4i4ub4vYgXsf5woa0RV0GtXYzZhy5gbaxO9rjcm3rzzQDv+sr9NvrwB6Ox -AKyONfGHQDiQO0VossNy98J3LIkCVQQTAQgAPwIbLwYLCQgHAwIGFQgCCQoLBBYC -AwECHgECF4AWIQQFLqFWSAoz2Xx6eAbqZmQ//+oOzgUCZdZ2kQUJGEdOeQAKCRDq -ZmQ//+oOznS4EACp6SGNJvQj1juYJMpFEoeoypx5qJi2LywA+NAymQV7fUHMWAWY -dFW4P6JU/zMbPWMe9aVJI1zPuEHaLeaXj1zHBuFpqTROkQyddP+2TuJLvndXa8Rq -cbIOdQRigSzQWaAXRarnekVgAON08C0vIRb77HB/T3HNm1Trv+9QAIZ49Ilf8iJf -hTGE9iGlaq/nt3/u7d7s012XvcUMPpfCav+b9JTHY91zKyZuQ/vZGpEliGcmZDKJ -81cOE4Jw/4BdL5Ru6S0UpcrNfGSjVgafnBNtJGbCuq3OH9XiwKJsiuIdK5DYT4FE -klNiBKb+T+DtwrFdMbMYeyJT4ERy/EQhz95In9AuJqfQWsdAq07+V+TC+5JT6Hwi -WcsB7EllMQ1xjupDWoqoQY5mtIQ8vrXM6f4+rHHtKdznxwegWaDdoH+3As64VhSt -7+0OO4BcD2+vMQiDtKj+/Dge2H9RdzIgUaaFhe7CWt6pvb3RYy4yi3t5mB+Vd+OB -xu8h8KWpBll5zcd8E2VfZVbDgvzYT9at77S9Ty1qpxkYYihbR0zsPIAxH7fOrh8I -MC7GmSOLFeszf0rQqtG16qegIc9VHnnGYffPCRFmzqx+CfkscYQ1l9HcoEGpMe8k -anKifRtr5rrI5ObWnKGduBMtfk+thABM7M3YuaUHUfqs+s3VtezJIEsxIbQfQW5k -cmVhcyBIdWJlbCA8YW5kaUBtdWMuY2NjLmRlPokCHAQQAQIABgUCUo6LPAAKCRAI -nZGsgksOa10lD/4tamMc1AQybIiOzCcts+oxJQ8TRKm9ndKUsNcUFC4n7ydoQZuo -xkGsZIUh8dnjTKTtDhYSaMjR/Ql6f+4Azna4cV/T2Lnng9jC6PD/RK8i/VaIybe7 -foEawVtMy46Q3wfW/a1BGrBg5DNoOL63RQWQxAqpQaABMd+7OtF58AOZZU1XG9wJ -o57vHteJUDWRg0vkY+fgzBxY8l7MdYAYxZVORdsgA4PhAhiUFB02eqVHLelMBEe6 -B4/0nTiSPPaeqBGTlVa39asQGZfRDAS6CBaicXQBQ427cTgXk3rsCRTmGr35pPgF -544J7WihJzS3xT/N/FcXGtsNUcaM4PND9H6ywoSAeaZmuN2dBdcViEIwFqkhW9zz -/kvPGCE/SDZhKScHb88Y77Brg5pZUw/RzYnYNtBeZub528uJFTVyGxVo2vdSm0XZ -sO4Nn6mfcZJZJlFUoLuqo1I8xEw+Kih7dFT5vBHN/HiMy2UDyOhGbi8oprki+6b3 -7uFl11+/VUQfj1GM2M2bgquramRr471V+9qPte+ylUIpLtgpWaG79YeqJyh9Pve4 -02ZetNob0e1BWKFWG4AdjwxNAS1iuBWbtNS7tj2l9yBtr5GCJvBjdQdcaba2zT3h -CZE2V97NvPdu7F+lWxu4WiINAxlloedUyC8MMyjSRLatioW8HohifQ+9J4kCPwQT -AQIAKQUCUVGPGAIbLwUJB4YfgAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJ -EOpmZD//6g7OjNMP/iuZdL23nrpp/cMFY9oi3793diy1M8BgJkABB7Jut6x8bCQX -MEx9gVj8rd2QrsDz4h+hMExFrtIIki+EJ3/ALHGDvVyVLgj2wabhHR8TmcfOWc1F -dWwXVSfyfGjZg0hYybkIRyMpAhYzptE/84TwzK9zlCfpLGPAf2kZI47fu6X1mscc -+6gGL3SS0/nkKwjdVvImNUUuD8DlpjnW/ZaS81oirdPWLVeP1Cog8kH3PmMXvKDB -PahPm0UZNtkoUyoKm5/0PzCovWQ5Xm+CrUt48z/7bR2HaWkAMG3lU/xsmeEc9TH2 -j0bk+Hd+JHz8HJRzc2Mb9KKyQW5/DUWa3TGYLGNkVjDIFEdxGlFZ51T52cG7OeaN -XfLMR+wADVzz2IXNgzluAlOh6jarcWfkPsjAOFFkOQWAnRwlk/5wRxrr24bgIFcW -X8T7tjtGnz9FW7oh9d9KIzT6JYfAUonR2M82GuQlQ5AJZsZdnxG4Ox29V06P8qs1 -WFQvfcV6zW1Dufl3aKbL6CO/UbwP3evUx2svLcVewwp6FH/edqMQ7Hq1MEK6N63v -LGlsq6g/tFukCnNzowdLlXiPRQxo3yf1/rtBnYN7jpNI0Vp3S3E0oWkrkvha9vWP -ZjwGtgcHvbvDvjYVtgx64tCPiqJl32+tXIPKoVMgzJrsTWyLdRpBy7J6SjIyiQIc -BBABAgAGBQJUzncjAAoJEB/HhlISNPH1dh0QAIjHrmW9ZwMSyI/d6YS+AIp9XO+W -zOLZM7jkEhX/ZtMMb6qabsEHiNTctN7PdfHFFrWrWWCk2xN3Ktuxl2KVWFFgSTxz -cRMonGyY1n5fD62cV0kKTFP19BpgXgBOOmY3KJ4vX7NOCHMOjzGqQzMQS86MYgQI -0WmgPD0XHCQfwBmg/ozDDnWJO4J1xueFQQ5attS1ua9qPoFtE2GV2s63Py9qSosR -rTNuis3Q0hPWWerzQxTPh2G6sLVZkLzY67ycnGd3iJIRkDSQXN20s8yUX8bCXJy1 -DbIpErsY/pkGQ2oXDye4U4WEUyVtJpkR1GtkkpTHzNIhKwXj12ShlUDPgQ+WMeH7 -TTK6Wyd6/xynaHHQbbuX5s+r0hracqn6Yhcs/xuc5kDfsDOwG8j+6T49CTlbblM2 -4sZUVgSRUgDXo8I9y3Ua3YCWSOVSVpdgW9/6LUTxFDg9tYFOu5Hpjn+cat/q746F -mXBg7vcyRhOgYWFL6YZiDTBjU1ZDgy6VV/ZaNrA5KzJZM0/EZH9X52hkerKncQym -z0Fbcqc32NekU+eLG5V53Sn6AyGh3oZf8HC0Xt9hISNb5kXrNcLyPxILAWfxrqVH -uGzyTx5tUsYN089R+h19/1eUjuNwtfZbfH+o0NMbGnUo91vv17h1IAK5fQSF82H5 -d964WtVnXcLLJj/ziQIfBDABAgAJBQJU1MH9Ah0AAAoJEOpmZD//6g7O3+MP/3h/ -NsQd7U9Q/sL7AEr5a0rVMc5du+VEHR+wY6ZxGWF6VBAqRdOATW7Lc0ipoWs8fePq -CxMuUK+FH1ffsZMa74i7M28UVYuCjRfAsDuVp/zaIa5bPZfT74XNOoK/DFhlZJ+H -ng+Lz/8IZzsU+ctbbyLbACnJ8CBolW88SBPYptEoR4uxpFKOE2hvQBnQP1R8ELX2 -LbdnQgDBDVEuMEtdwn2FgcxKvlukK+AHfTpNAhuZU8ryyv2pDq5GoFNltRlGG0qR -qCi6NlnRW54r3HCQ7oe1LszptkvQ1OAVPXnULEa+FznNDSOg1cgM5TcDpcD/f12E -z8vy398yNBbD3uNpeLG43UpGx6/ofCEZe2j+lb1vaYo1F/O4GJghSeWgX7RKEiLO -Ge/vlXlOgA0SAI7tAB6TTNt5mGS0G9PSMz4DSzD8h+YENc41njgIGc56JyQRcFy7 -xvm3gUAx6MmsrqLk7KEVz5jlGXdis3Exbq9U3ndMRtOAkSvRn0i8l4hT5Dtm6inL -GAoAPEzgCeeRe7mccfWDXeWQXHyghcmGexASwhzHFRPpIsDAt3+PM4zcAXpTqv7g -wNM3w05KNOWVdg7o8wXrGfx4p8iYJEDEfqwIReYqtSiVe1nU4oTmjKz4QrqpkuqO -xBi9hMO949reo8b8LBwaFKg9f9kpE9OsvTZsW5LMiQEcBBIBCAAGBQJXHK0VAAoJ -ECqyljcQiW2wPMIH/RkNFZQVsrfO6eKiyf2sUuYGoURJUo3a1M0dXFAc4qYOHa98 -AkowluqY1hGvv8nLWpG5p6PPn0HXzbmlgHwIfYnKr9Lgs4Zj7pWYSbJLuqB3oRCo -Un4KTRE0i+ehxnDu1SgCKo1kuGIw5s/zDqMNN6vDeUFkq/ILIsumolgh39e4xXAv -PEOHHDe841yvU9DMnrwszdNH1DnHKxi4zWw34Ba34GqiIuEn/+TyQbRNgKRU9bSF -+9HSActVciHWcOVOpBUonm8RrUu6HQJaaEuDjXVEDwcozpc1aKRmF4YRPbTKsN1G -zQIOtbTE3Xo6nXCtvcFSP2NPDcBT8B535wxz77O5Ag0EUVGPGAEQANPLIUWKUzCL -T3j8a53otgoy6pgbE7BRusexigTZt64p6BW1CJlaF5tRP3z8FR5Gh1F3cvlR6/cA -lyEVRvqAxM9aK18EXru3sdK1kDvXYHdla4bGC9zdttmVmTB/gW4ifjbE7CQDHskd -TU/LIjxbBIB0b3slq1sgkIiES/U4wqmZiY9kJnn1DI09RA4bdv0+8D6IDNrUxYaw -No7GZe9b2s7y9RK9968dYfcjLqWUXgj4YHgqjB93lUhvpJZsdMfG46xX9G+v9tl0 -Ys7ZnVpOn/ytBBJpF1Djh04GDJCE8st5vSlmC/ZG25vRIyQA9MwVd2hwe66TTBUi -wv408U2rDKsOY42sJ6saI63mfAU3WHzMrPypX2lPbWUiIv9Qb8UN5VSAdtMmxI3B -ESIt7FQu7IXI5nQxqLkK+fwfgys1//l7hpsooQr6dZDNey5+wB/T2eoRqcuW80eE -NDZKn3zYn35PQh8hl7SUMxqvbcSWy83mAgYkm1JeM1LPo9DI1C2ziFsyBSbYwzxS -VMzLxcMVKMXWEF0Az0JORPN76Jxga1VaNhrHQd5K0SaLqNLDPiBLS/8CN10KG6sl -1xFl2xLwZ6gON02dlHzXY34cEYRqD89B7hMIedTIIymxa7n6uaEsuXML0fJG0i5V -073ZB+rNMJJ5bcaNZxXUZ0cE9fh0cnFHABEBAAGJBEQEGAECAA8FAlFRjxgCGy4F -CQeGH4ACKQkQ6mZkP//qDs7BXSAEGQECAAYFAlFRjxgACgkQ9GMElmEpr7087A/9 -HPgM/5+M920nmTidYtXBJ+esQgol04A0XDxcyba8NOfXRy7q1J8K0vT4Gpg8K1h2 -6a9JoHeXHSfR/L6qcvryJr+9xuXAhO70lALmoIC0kqyGzciP5JVG37VyEPq5klp9 -Ja0FuXMqwYu5KxFI3liJPVN9Qrvgq8J9mSdHjgYFoP8OvDf731jbZKk9OG+EjQWo -kdK6/tM9wGLh6j8b5kV4bM9f4Kw/tZTtPRK4/caxoH53oBNNuF8WQZZDlsuV+HNd -lyk30jMJe1nUNi/wGyMDef52vVxRfN5noWfkU12J1Ez3744LAGEAtXjE8GkXBFBM -3Ikr7aHTSTqFYbWF2MZn9SNbIA/sL6BT7/KaCiKFIwd5L6jG1tzqLS3AJYvSyrbE -H7b+BLq723M5FzEdFFUJ17GvWzqXSfUXMjsUr6XMCIzlD7acJNSwOkLiRxSRErYl -pTrXeROPQ4Y12HAhKF2K/XA/kPzbSStQIVYkPNlOJhezO3nCdx4X37AnpkAq2fgI -vmgpo6v3khGSPmxn+6mD1Av9H9bZDR8YSFoTpS7NNZeiCzFfYqFP3x1wlsNuwSNG -NkFT6c9hPhX1qhPlJeA1irlL2BJDiwRqPqG/cb3Ka8nMoGPcwwYIhQEAxHyuc5Ba -3TIau7EC0G+BI1i8QXas9TA96b1YATRN+euaTj2KY8rRkhAAjdvG8W5bghRe4KqM -FZojJRh3GJOawcVeRgQwIJL7srI1DldynmNG+oQ1zqxB2oWEBoOBuY//Dp6kBTzz -1jk0WG/UfbNWRjKY2mDCeMm/+NqtcMX37fnZ7IAJmfYKeGP+05/Jgnt7rx1kCzQy -Gm66tnufYg92u2I4GaDmCVRKjC3RGrjpy2iUKZhltwVuaSThlPujJqjAOaU6Qwzx -FE+OdxKOkBzUvvfJBarZZJ0qaSsiGsGw9XbAz453ptfachvxNjJc5M/N3CY+0KSJ -wLufJZNrLvd+HsrW5Ny2iqBT8ba2w7jXKk4r8N+rOg1VcfCc3vY4ygJ1tLex6mBc -X/EGwcc3OY8BMEZS87ZxEF8aPQm1g1xzaKqybFmUA4dqu6VGNP/QbzMr9wmGNBMg -boLk3NoSoLNHrcZU2f0tdfbiUOnQem8JhjsQnTSwf2+7FQ45zzTCCaIXNyxjIh2Z -GnlN0z4SrU5HOkEaCM5f8CCebUaNJbUpjq61J3MyXywCm27DqVy0sll9wMJUJgn9 -w0ep9Nk4qFVH1MmwuS5jw+nBkxPruX8qQO2HcjbN3HZV7n5FNL1Px4OJzUITA6cn -C2RcDEm/nIMRM9dsfwcEEigt3ozdzwsHPbWesn8ImA4KTNSOZ0aEgau8VEej0GsG -4+AecYklNftJvTmBs+LIxGFsrfmJBFsEGAECACYCGy4WIQQFLqFWSAoz2Xx6eAbq -ZmQ//+oOzgUCWgOE8AUJDlgzWAIpwV0gBBkBAgAGBQJRUY8YAAoJEPRjBJZhKa+9 -POwP/Rz4DP+fjPdtJ5k4nWLVwSfnrEIKJdOANFw8XMm2vDTn10cu6tSfCtL0+BqY -PCtYdumvSaB3lx0n0fy+qnL68ia/vcblwITu9JQC5qCAtJKshs3Ij+SVRt+1chD6 -uZJafSWtBblzKsGLuSsRSN5YiT1TfUK74KvCfZknR44GBaD/Drw3+99Y22SpPThv -hI0FqJHSuv7TPcBi4eo/G+ZFeGzPX+CsP7WU7T0SuP3GsaB+d6ATTbhfFkGWQ5bL -lfhzXZcpN9IzCXtZ1DYv8BsjA3n+dr1cUXzeZ6Fn5FNdidRM9++OCwBhALV4xPBp -FwRQTNyJK+2h00k6hWG1hdjGZ/UjWyAP7C+gU+/ymgoihSMHeS+oxtbc6i0twCWL -0sq2xB+2/gS6u9tzORcxHRRVCdexr1s6l0n1FzI7FK+lzAiM5Q+2nCTUsDpC4kcU -kRK2JaU613kTj0OGNdhwIShdiv1wP5D820krUCFWJDzZTiYXszt5wnceF9+wJ6ZA -Ktn4CL5oKaOr95IRkj5sZ/upg9QL/R/W2Q0fGEhaE6UuzTWXogsxX2KhT98dcJbD -bsEjRjZBU+nPYT4V9aoT5SXgNYq5S9gSQ4sEaj6hv3G9ymvJzKBj3MMGCIUBAMR8 -rnOQWt0yGruxAtBvgSNYvEF2rPUwPem9WAE0Tfnrmk49imPKCRDqZmQ//+oOzmFm -EACKTjfYX+axtFtMgITma7XAtU9e02uFF9HAmK/Idb8/UIRW2ucpP7TFn6HEapIT -aMaFjmNfnCFlxWKp2yNshquBESXzKaVNrEM4fElLDnpn98dL/Vao2ZtbavWvMF4e -tcDqcgeI3htF/w9J6Zo/phx6MFF0p/3aGec5+rNa6qKtsr23KvTevKUuWCBTAseM -vmeCwAYadecRYgh3EO/I1M/NNz9NQJgWp5wBKL7ptZUHPm52jpF+aDufJcf8am5/ -ATNWXz8R1cTzWL/pZyAn6wY5Gt7E+lj/xge7SvVVMBF3rrWiTcHQA7HAQTw0Z2E0 -Oon5yq8KocLyfXGM+V6ZTY7/+vKvYdrpyLKNsaVM7aNr6XF8QtToiTWc6t8UpsRH -9YIIGztMjE1Vdo1g5GaRHuhRno3omXlMQmciENptmyqClnfZFrihzJPIsVv5CvYh -2cF5mDmIRxKFpU+cPiuBCFZ+TjAKc0u4pyQvAT7j+c9R/fDtoBp+6+iFfUH4kIBV -UZFroDUS6dOCSQSAX+iJz8Tfrrx/9H3Z40Kt30r5XOleH7spi4Bvim90gedxA/58 -5jMH80Nnm1EUbLfKrplcT9+ZXSKmAcCyBy4b7ozbdNxa12Nk1RIjf//cHE0YYQcf -rR6k9MFow8WOGiq4E7o6hrMZ6mFfKVOvTfihINcK6HGggIkEWwQYAQgAJgIbLhYh -BAUuoVZICjPZfHp4BupmZD//6g7OBQJjSRysBQkVufSUAikJEOpmZD//6g7OwV0g -BBkBAgAGBQJRUY8YAAoJEPRjBJZhKa+9POwP/Rz4DP+fjPdtJ5k4nWLVwSfnrEIK -JdOANFw8XMm2vDTn10cu6tSfCtL0+BqYPCtYdumvSaB3lx0n0fy+qnL68ia/vcbl -wITu9JQC5qCAtJKshs3Ij+SVRt+1chD6uZJafSWtBblzKsGLuSsRSN5YiT1TfUK7 -4KvCfZknR44GBaD/Drw3+99Y22SpPThvhI0FqJHSuv7TPcBi4eo/G+ZFeGzPX+Cs -P7WU7T0SuP3GsaB+d6ATTbhfFkGWQ5bLlfhzXZcpN9IzCXtZ1DYv8BsjA3n+dr1c -UXzeZ6Fn5FNdidRM9++OCwBhALV4xPBpFwRQTNyJK+2h00k6hWG1hdjGZ/UjWyAP -7C+gU+/ymgoihSMHeS+oxtbc6i0twCWL0sq2xB+2/gS6u9tzORcxHRRVCdexr1s6 -l0n1FzI7FK+lzAiM5Q+2nCTUsDpC4kcUkRK2JaU613kTj0OGNdhwIShdiv1wP5D8 -20krUCFWJDzZTiYXszt5wnceF9+wJ6ZAKtn4CL5oKaOr95IRkj5sZ/upg9QL/R/W -2Q0fGEhaE6UuzTWXogsxX2KhT98dcJbDbsEjRjZBU+nPYT4V9aoT5SXgNYq5S9gS -Q4sEaj6hv3G9ymvJzKBj3MMGCIUBAMR8rnOQWt0yGruxAtBvgSNYvEF2rPUwPem9 -WAE0Tfnrmk49imPKbjwP/RNsF/7bkKaYAhqufP1JYHf9eGx8N9XZ8AOO0upQOuN3 -Fq+N0sKaz3DorVxcvfSfmTQ4YZe7paF99nIXyWV65I1SUAtOdVPNJw/nTgzp6PZP -uI7IPRHCA1SIjb6DIQk6bj/5ohCj+F2ZL8//Dz3RWPDGNIijHhYqJzBYxqbXKHzk -oLIa7monTefu0Fbrc1Rj5QqnYtFhR1SCW50edRmVbrBot2jBZ66sZO6suacYfNjX -ol2lRiMPuEvzwVuyk1nRRjhT/fovY/tOIe3pN6VfoNaol65nyrBs/D7RynKttPDW -cF2O1u3CGVDnmYgZx61jDyz49XRJy6jvREAvleKY3QO3gLDvm9acuVPQmroSlL+T -7j3X49TOFVrst5mr//sOVU4i9fGuS5gE+5BjipAPgK5FtdPAAlr56vzFwjGSXV4l -FuCjB6vtyYx7QZm0pzMvIgxmJtnPFom5XD7o8l1G4TRZbInRdWnufm2On3ZhCqes -Gf+5RcLk4Llmcu8fzxOnjW7Zn5ssrRNneWCSoHELiFCYC+lrR4G6OcgtNARINWD/ -mxRnfrPXF2wJuYD2lodtw1VL/uuic5LY4d8+QjV1ym/GppyHVjZdNpqR446O8AVC -Vc/+2XrZvcOV3yS7wfTwL7EVnTmL7h1NY6Xdf5xlAN1DA/rkgCtwtOEeUbWIvP3u -mQINBFag5jABEADEZTMS8qM/uhOSGyl6Vy/Odr+sZh5oqb7OEfHe3J/BDDcLnPY3 -73e5xmEdW4lNJB4BaR73z/kQ+AuxOp76A6C7PtQNDnTWOtvWkrn56eneFozZVE18 -FVbk1znQ34MMkptWtMEW8H1fIf2KouhvZ4TeyKJW9b2ol8eqyKAN8agLBAk5GNQJ -VMTH1WEnOuqKOZ+nmHwpLw9lffM8lQxvlIhiw+RkN7G/3wogRDtPdE5+WcSPFW6P -Xs7a01qmQn6s9jNFZHsVFfiHOuKPBwhaHjKccDFxd+ZDdeSghAbcTx5nhnw+I+7n -1GF+mymSoKPI5UnRnl7Vqva6sb9ykp5+4IFj2LjUZiJkXStF5HGNRr49CUuTvrG8 -vw4Ka3w0owzd3JyXLggmmYc//OlzLSIDCkoXrvcg9vkiOqtLXUH4Xb32nBtaFAEl -wO5AOuzhDS7s7E91gr9XmWg8Od83x0whOe8Z31IqMj6Kxq55KNidn2bhxcE9GV9J -glU5dTbDN2VDuKgABDPu/fR5LUKNHVLRtT7SIPTZvuuRyJ8QbBBeiMUCpaV/G1d7 -wZM2VNktoEUQIHwKoAxxtdLyKZi9YoPg5zymL90VIaUnc2tYcPhqoPkjI30kHzMp -J+KIjlxDs2V5HSt6jBHvK+jHtZZgtDRn/w2j6cOMTyPlMObXxPjNjXbJjQARAQAB -tCZNYXR0aGlhcyBIdW5zdG9jayA8bWF0emVAYW5uYWJlcmc2LmRlPohGBBMRAgAG -BQJWoOdIAAoJEER1sN9YNP6Yo6YAoJxasYACO7qpfUIXRW3BbPEZM+++AKCnXNB4 -xOzSA3J3nk/fa1hBYoTQoIkCOQQTAQIAIwUCVqDnGgIbIwcLCQgHAwIBBhUIAgkK -CwQWAgMBAh4BAheAAAoJENa97orcqSpLRscP/icImXRvccn3xz5TClPHcl/lkunD -cbagbrA0ezTi0SW8t3HoCXyBag1y8mJSfHbjXnMUR369nDPHd9lGRmA0F7hyIe/c -RIRWyhlAK88XuJGI9QzsDo7+CQsik+c0jkhvCWwfKzctcchKvQ6bJrltZ9EYZa+a -89XwydYw5sHgoF/teHm399AvjnP2wJrOSsYzszNuGgllrJkBMSEBiv6R8yLEav+T -l0pS2au7TC+W3viJvvzciLCzQ52cM/qxKNaEZ1+9o0L0Pd6jcIw0nDoJ9qhsLve/ -vqOUJZSXfxlQSrRdFvri/S+FJ9QMo0JVM2Md1hSinoLrxD6u5jKggylD+sxcLNOQ -fLJJLjU4SGkyzq+ZSfQwaK6Gil5ZaZQBSPxLCSx2fEpHtbp8LWR6pAX3kYPt3vCi -QeDtTiglRQ/IhqHTeEh5D83Bpot+UkmS9MxTuw0OdBp1YinzyEwGE7kryp0i90kj -SHT8Z4QAf5T/zoYWHRsUCJJLn8BC2/n1CSD09kQ8zdMiW32j9HmiWthbqgntXtjI -2uiNdj5oYEJkrB2utI5YPWS4SDshxLWiGQPK9UaYGHBMcdgXViAavtRPCz1SV4Pr -4I2GCAgT3rMKzPR8kVJpgQvYsCpv8PylPKR5heUn14LZNZCQcoDn/7bC1darKoum -TUQ+N6yuWL5BMHG9iQI8BBMBAgAmAhsjBwsJCAcDAgEGFQgCCQoLBBYCAwECHgEC -F4AFAlag530CGQEACgkQ1r3uitypKktNXRAAiCH3gmHgYGuG3bHjefwW0kzLgtL1 -f3pcPMrojuCG9EryDwmPh3T79532b3hOflktfdvqkh7IlX70ZKB+Dq3qJLRM58Re -lh0Dk21Amtn5SnNq8C7Qom2iZrYAh2hLqaBmSWkmONHb37N6ndgwN0IDaebj3xZg -sWhlWG3wsGrivKeWYbaZrQ1Iy4ou7biig7bidtsG1MGS7DmbPORZopeMX8cGJHha -GBEVspUAZyJgvoH2368KLhhM5oysHxifGaCh7SWlHHY5uZR6029uEwyhVt8T0OJu -PRpkEUI7SY2m+tnkod2DVlR4F0WjuBxlXeMNGXlWxmF8EXyrRyrbQ9HDBQjkHC5C -6T/Eft6n2FDFX2ug6wDM7Go0UHuj0BsBbobnR0wOH5rysJs4bWBQjXSJt33YuOhb -y3T2LgNWmsdyGSIZzacNkJls8gJBKPrpdTbkSyw/HOD4817xdRfQEHJgubyd1UqL -IHPSzm5Jm9GbrJZwPLdZ1yEaxKBlCy8M3TrbXjN0gmA8xyTguyVDmz7Xkq3BxuId -C8Z/pPtigAJ0D9M2FZQi2Ny507ubYKMvQs9cfthCcLVX8yTjROJb5CR94vpZfvcW -6AgiHeZklxrOTEUkNh44Sal/01fkqKI663HKIkN+LJL0HLaONM2E3LJe5gevqcrd -16Q5NhA101pl2gG0KHJlcGxhY2VzIDB4NTgzNGZlOTggPG1hdHplQGFubmFiZXJn -Ni5kZT6IRgQTEQIABgUCVqDnSAAKCRBEdbDfWDT+mBXhAKCGTH5zEvVdC5DcrrfB -uSxP/djBEgCgq/YR7352t78SaPr+O7PNhszrutuJAjkEEwECACMFAlag5wACGyMH -CwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRDWve6K3KkqS+/SEACBOhJIceuo -al3pZQhO58bCCkursJo5O/CuwpAQIVNgQr6n2kp95g0MIbZIf6MgcBj8QMIAGRpI -okjWUS12xS7GjM8R1H446tBb2Q8mih0wuAliCKBMFJJrH9wARWZMYUwHJkteNxdr -QkRG0n4lC8WiJBVgqqr3TvljxB+MBnRxXbQVnwiO2/3rzBp8c6xVneVlxAuUlgJH -5ryZy8LrB3ZzPTUBjVZXxxhtSA1qgLzn2mySoxi9izvw3V7uYDYMl3gO+gt/Jrgz -68yMUexpPN7ll6O4aUl5Sw5uMq2ihH/mZmYLsOxte3Z0f++DZ2QUsJg67jAuI2LV -GXyFfazQWUddnPa1ugaslDnDXMCt+s1EJIj9YE5SKP8IZ/4osgigJ6djpxoLuWXw -cZD2h1St/Rb/tgYPvd+a2vteXYEEbfZdl2JJgSLNYKBz9BFV7k+nJtEK+L7wAuwk -kPEBO04E0kgyF3mSJJSkVJ9eJxMWtF/rl5m0j8b83w/Md1/SIN+Ip0Rbqde8q9Ea -ymPBAr9QxBoCP3rEML/Jp0mhKAvmY5+tzLx6YhATu+NjEin1JzQN/wekVk3xhvCQ -/zmREs96XzW+d8e3YDql/2YEQo0ECs0fR0CvwE6U8wZCz3wkF4A/xjwUc32fQsdd -F8XWoRsd88m1wigjGt6KD1xEI4Wot51A5rQqTWF0dGhpYXMgSHVuc3RvY2sgPGF0 -emVAZmVtLnR1LWlsbWVuYXUuZGU+iQI5BBMBAgAjBQJWoOd4AhsjBwsJCAcDAgEG -FQgCCQoLBBYCAwECHgECF4AACgkQ1r3uitypKkvvmQ/+OllDn06FKE+swuqmUeb+ -PaCA/AVy0+SD/j+nrHgUe51voFMWNfnBMqMMFVQR9ipnC4BI2w/CfqPFSHRYwE3d -/GjZ2epRvWPh2bWkTqeAaYo4/3dbhqbVq0hKkjWGhqIQzEbHXlxH0SbAG+B+mCe2 -vCPVR3b7zEtFbUd7lbPxWcGGOcEfkQt5Y0BoI33vTX+qBPLl3Ru7xPcC/xk3LK9v -GM52SUCwwVLuYEJcimpvtcf/vv/jtwQAI9OdFCxUnVpoRi8W5MHVAt+PB+aJwz9O -wSIqR4o7mUFyXR44hir5bvALxhvk9WGyvoxTH7BmRZLxeCOwzNqgyValVIssYd0U -ZHlu6MS4/PaupWgE8pESYKukKOuKTA3o2JbMrHjLnicYLZ2LwCpGY4EYEUQTg6vf -DRpGi2pqEkqs+Fovz0O722pg9mAK3CInTfW8uqIUf+/op/cDNi8FVeMsjKe6OZZR -tu9DNZWUbo0JM0HCSiBirJCCjhqVyM96yazQk3G+ZnZ/fOtxxmoN6usl+BZBgHSv -iHMWIuYhLaJK+P/5XReHF+JmGoecO3TZO1As+gpxB9sS3rgtH7RoS3bMa6az+1UL -8wNMAiF7paNtzrWNKpY6G/RVwR5iWMThEoPvBVtGPqWrKCOh/oem4NLCqpdWa+N4 -sJe5yfQLRvoXwswtbDiGP1m0M01hdHRoaWFzIEh1bnN0b2NrIDxtYXR0aGlhcy5o -dW5zdG9ja0B0dS1pbG1lbmF1LmRlPohGBBMRAgAGBQJWoOdIAAoJEER1sN9YNP6Y -C4kAoIZL8BvzFYgYPy/UgI+q+tg1VjWFAJ4l//A8yBPU62A7XvuZlgOVTrlXJ4kC -OQQTAQIAIwUCVqDmMAIbIwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJENa9 -7orcqSpLxIQQAMKBmU8V/6cpHTUEESpc6wixCJepxdJOMZvjGC75/V0/8gJ0A1cY -5qM+bogKSSApYAtEt5XvYI5/7+8k3DjKq9VPktpv3Q/Go8daLUnjXiKWfZ1+nx01 -41q4O6Um2nrt4afyxQJTqdKO2dvwuFIdTZVE+h1mcJq09299dGW7dQhHwBuNR0VA -p45lBja5SgaH/oQcgfhjG92TtGItVORVGOGH52GH5/FcYnjLyDR7pxwguIQKhsh5 -DWDEwz9+PueQzf57O4o75ilJURAS9SYcoPT2aVVE9qdUu1lBAt9Dj5Ao2+UHwmmn -4W8UnpuLVFrCt68SpC8yoHHA06EdAmtk4kjsEjijZjnUMAVcva7l8xNzT8154BjS -aH7J8FYVK6NUABaNmNYGTKDMJFfczQnBvlpwWs5knF0IynhikDSr6OZ8DQsQFTbz -VMKCZlHIw5eI5PX/swBYPi7oQvXapnvjTRimc7qQzX9SyG+gwqrFVVRaYEpBN/bV -yOR6xfzO3mjC3nfGiHvBx+VwkXLRjtd9Vzwdh5EnZ0q13nynyu9qIDXNljlHu3vD -cUOcMM7iYjMyzweitYoKTJEVUUDFQiGAK6zHy8c1Y+vji7tmWPVKwkENILUz54Vi -ra8ysFi7/nYgFF24geaxwvsTGmyyVGAHcqSEurEJwkis6zQeORbiqNHuuQINBFag -5jABEADqkoc6EMcZGiwY6nEhrI3E8WpnOZKJxPkskBxfJy10EomuHD5dP4+tS2/4 -J+QA6WzssLzIjYOh1Qffqxb7QAk7lle2XupInkQxwkV6fTMRC/njA9BRTngvbIqb -RyoZuQtAgT/aBB42qSb+HOwiMWL3OSJ0yGl0uZ4JtIcfY6B62HYdnT0V1tAqaDdF -xKo/MjOaR/tXWd2IdcpXl5yDPY7rrbS11VT6rtAK68WwdFf3o8aJZxgvU/L+HUpO -MmjF1piKkiY5qEG75AiQeLcOeBnEG44rKTIjpewDAhuyegFsp20t8fu27kPA2VvI -EIbVDezE94zJzQ2bPHDi3KkpMeHAsqZScSnK1oMF6pELyYcbAcpueR0ANA+TmHlu -nRpxR5sbXiPrYWuRWYEWD8MRNzUIToW7X0TgshzX/61+pCj5dyYICu9YVbsGop8/ -PGWlsC+G6r71aK31tpRSdZzPi4ttmqxxrndhkBVZ3h+jamQJaDs4qM+7aeOcKaLN -qBNbuqCTprc1Hre8TY16eBu+++ibf17aiYKnGlVc93ssUtM0V5KPb8k2U0U8+4uw -HeZenfp3EVFUGjOQluEAr8unBcMm9EYpY4a4n8/kZ0oEji77k0yZ+NoYhcGKJ/UP -ezCEMTytzqGLDu/E6mnSRekfZEpPX04be/OAvxDXKAX7cS23kQARAQABiQIfBBgB -AgAJBQJWoOYwAhsMAAoJENa97orcqSpLq5wQALTLwaeu546bEHd6pLyc9FHuqL2F -XsaC4/ivWGdJhuNCbZTDoa/+OjaN+2vZQWqOPEmBL1uBY40QEQA51lZU6FmABsj2 -Myg/gAQYGMDAoEHq1Oe3BBjJq3X3UCj5TWGnFO7w7+v2NqS8FxN5uLOrutQ6dopO -2uDCzvf9cXFarDD15evffAsqb8eXU2/ujIrTpa5p3s2ARBdjEj08xfDodMEtPs/+ -q5BXFUBXj9cwGx3taf+ofb0or8e4UC90T2o8NRmeNXVu+aJfwtUNcnx8MRxPM3nE -EWn00uHuKK0Cyzgd8n9zGA3sbWEUF9iXAzRyAXsBTFTU/KHOvXRfWK3oTc92Hd1U -eBd6vJ5YpenavN2eh/Q4gBGHmk9C7n/e6oUq+MQ1JyVN+IMR6SBbOnERcn6+n/9T -pIDr/AMwiU7Xv98vqPL+PKjYH84UDYRBvgx3gaVProaQiVnDM3gj1R4Yr84Jk894 -ctOKF6mUCvE71qDhOp2bhq2pbyM6MGCrDsNz7K6Ui+hdDIcWitJZ3OQd5I32mktq -neLmv7R5t0MuXh/ddUc1/1PhsHOSEi2s/nhTxkrm6khDXc1+aIwzi2AyQeDV72rN -WYsR+249JHsoj5sXxeeCDXUFvLOeTQdMP+rKq9ZaKnxSgadMWo46zpX/EsaHe9w/ -scs+I2vrlWkIVnM5mQMuBFTBYAARCADZjsIR7JlenTDW7illkJ5gfaibl901eQ91 -mBYnNdtiD9o+XS1OJO2C89gbj2vwLyLd2KmoxRIhA9wibsm7riGIoYn5+CoCMzCg -pvJTzhfz5Sc4ZURudMJKGuZlUl+eS0OpYLVnKawl/s4J6ynoYnPXEwocQJDkiCtn -X5LJFuXbUmOd0yZjYK4uE3J2AAZ7683OOJO+qCRRUrwYzeZis4riG7TMQawS5MjK -LNXyq/SNO0HuuEnpuhKBevDOxE7Ls/r8QQfxRrWURnn32fGCiusCYUZXT2K27kKI -YEhC37dYacxBvFv7qJEzy+jp2F8LG/HoghSJ56Diuk4M/gMJyM7zAQDW4f7ceefq -/s3i9j21bFE8lwHgGGC23PvSezFCcK79/wgAiOIrHeiV6fhQBfusDeUMXnoD30V/ -YHjJs8sV071ZH1atnXIJsPd5L2ruxdMIM6HfCcHhHtLBEKpnaiiOSXZeHOBZ4Dgu -TQgzDPXXVSzyszylEW3bbfOLygpCjjwN6TGIYplb5AmkhyFUEDxkvQ63TvMRGQ21 -XC9BvUv1SghUIPMz6VQ+DMLP33R6f9D78+BmuVGaCPUJtfPPRcNH/Ic1iVEuoTlt -ugVCWohIQMp79u3d0UZtj/agDVbM+biFRTGmnagLl93ebiQJ6ShRi1ApjwUhV5Dk -tVKn/2/3m7fHM7DTAVdQx5hVePliR8w56WzO+lDtBh7cIX8bVWHiv2GvOQgAtqN5 -/TPGP1diCliHKSA4UHd/zJWP7QirwriXGJgtzu8LSRaPaegyoK1eCDyGV1HYsHqV -33/0g0YNZh40EwXEbN6mnEVMXDq3fvdaeBQJpZ5mBk0fAZsp8zVmkx5+oq8NBhNl -DdD9crGLnIrwVZ1JrfBqIEfPaQZshxB6pkHaY/ziSWjgOZejcU+0xzk4oMLI+FEP -a+lHplp5wZ8dCJnu4CJ6ELCF+5znCa4fjkRov6rxtFoqQZHkrwOf39sjUUeKUaAQ -FIMEpSCIlxatRo3/EdC13X0w7BuRtfg+sDs/fzhWHP+3eRFwl6xjG5Cj2vohqkc/ -aVpqJyPue+Lu90y3FrQ0YmpvZXJuIChrZXkgZm9yIFZPQyBjb21tdW5pY2F0aW9u -KSA8YzN2b2NAbml4ZGEuYml6PoiZBBMRCgBBAhsDBQsJCAcDBRUKCQgLBRYCAwEA -Ah4BAheAAhkBFiEE4TOiABurBXtkAm4vNjlgbKrUPcEFAmRSCrAFCRS8gLAACgkQ -NjlgbKrUPcHZngD+IHvh7zi+l6OOWsCQ5QmTkPiq8Ugq6/uoteh+ALroikwA/RmQ -b10Im5peBVgNH4my4kgx8xP2DkEEuD2kP0zqbEg9iH8EExEKACcFAlTBYAACGwMF -CQeGH4AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQNjlgbKrUPcEFeAEAi2a1 -5tITa1Q1XO43XrUaX6jnwftPUr8E1wY9ewC6q1sA/RwyGdL/1OIpOwWnuT9NBMw8 -mTE/vHh41NesV9jmaUnEiIIEExEKACoCGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgID -AQACHgECF4AFAlTBYKECGQEACgkQNjlgbKrUPcGorwD/cYMCxViql9FNc5Inb/61 -o/rQ9mhnCqCfIHVAHuj3AyYA/30dyKcr4GqzSVsCD5atXcjtPfneVRU7RL4vrpVc -VDfgtBdiam9lcm4gPDMwYzNAbml4ZGEuYml6PoiWBBMRCgA+AhsDBQsJCAcDBRUK -CQgLBRYCAwEAAh4BAheAFiEE4TOiABurBXtkAm4vNjlgbKrUPcEFAmRSCr4FCRS8 -gLAACgkQNjlgbKrUPcGgvQD/U7lIxcx11wgnDDcBy2MwCo4pVbOESDWa29rBSYCy -JsgA/A9iEAEOIEUjbeHtTEmO6wk9jaqNGYwSErOMXo5obP+HiH8EExEKACcFAlTB -YG4CGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQNjlgbKrUPcHJ -TwD9Frvd8y3DhGwc8qWDjnX+k8z5Zva4vnpOZqACPWCvXjIBAINgl4lxytv29Lzj -isbSqAIygpfI75AA4R8pVrmkH1k1tB9iam9lcm4gPGJqb2Vybi5jM3ZvY0BuaXhk -YS5iaXo+iH8EExEKACcFAlTDoPICGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQAC -HgECF4AACgkQNjlgbKrUPcEgbQEAw1O/aw5++aOVg4njLNLiG8ju9ktGj8/LrLdH -kFd7BdUBAI9yCxIZkJ9oroxO1QvsZIBoca5D8ZOXnACcBrg0Gs0kuQINBFTBYAAQ -CADjZdffmSzTMGFzrpVLtKZmtVqn8EPo32R6rIUdemGfnJqjdlikFLf7ddLnQRCp -KKL0whOkyrylYv9Dcc53EJ/9JFNLKQ/ve82civFiSNfxVLcdO55iCCdCzd3nfU7S -S6UVkmoTYvOgqG7EAVZ8eaazDCKtU/LYk0VPNMKDz220RkL2s0YnTLhaiMrhXqhU -Cn7SoEZmOJTNh2w0z4ju2gNffJ9/QdImPlfgwQ2y9e6KTM5TaXl55AFcK6XYxbel -4Kv88/O9gLHwa6vMBHIdhyHbtzSEdmN+MimLuItXDZ73B37pXFWkvr7v2h73AUOs -nN7boqMJWHV4Cztsl+sqSKYbAAMFCADFXdCqDrkFozHy0bErvTEYkYHgGqT36txW -yPQf31cQG3GqXBH2nUJRB0LycdhE282uBwzkwg8j/NVwwcB0EVGheibDLhXWY3B2 -dnaOaEJJI/akTIMECC3jS2I+Tsh01VGKpCp3/m+RgqB5y5G9tVF90PWmnqCfdn8H -c15MQLWuMknwuWOdjbpJOBMusnPrY1+0Zp185cpmmg3eGwkLI0yf7ugD6kJ4ntE3 -iNuxX67M55veyhOcFs6NIk5695Uv/J4VUhzHAAwIXRi7ad7msE2u9KUxkEXpNoL/ -nQB/HUYXxtBP4xeKRunvILVXApqXEC1qU//30248CT6L0Tc294pAiH4EGBEKACYC -GwwWIQThM6IAG6sFe2QCbi82OWBsqtQ9wQUCZFIK2gUJFLyAsAAKCRA2OWBsqtQ9 -wYQ0AP9Nm3VLQqaEasikc9ypYlbHqxqS/yyHO7LWNb8OPCThVgEAmlqEsaLEVPPk -LDpqCRTNPACLadv7uSThv3d2tIMMjHWZAg0EUvqV9gEQALSIw7apeujDVdngMYzw -t0lve37XPMkU4HiQH3is9kV2deyuW5n3Jruc0eRcR1tFWZ7n6uL+U7F8YdsIi3ci -MInIisSvYK+SD9zdNDyh+i6ZzoDcmTcqOmPh20PXDeXOup8v5wQyWvVfwDtTGreH -q+O7njmbY6g3YN+3Ef+5W+Qxj2sArxetpy/efuwB/IDVzKs94CwRfPrONiNvxnkA -KHU7MgW7hHDxygbIJ6jyMvCny57kv1FOnZw6S0dHsUdI0n9JWLMVB/e/RPuM+jxh -ZD2p0wgvQYV2/TkkNKMTTSmEBzLswdtZER8Cy78XL7V4dyi5bOTrYIPjiOqKYXmT -VPTI1/MMbvrpWtxmPWIdVHElxM3r79rV7+0u8b16bqb1XeOkUYQiNzHI3dkLk/wM -MoBdKJQyB6mnckuxCD4PyZZJaMRmP7AwLB2i9jxgJU1cRecByv1E0X0U7HLdPy/C -OT76nd1WkmqkVRJG9xr+IJXVUtinYf2W7XGW1OD12n2PzTWYSwhpV40lrKWHj3Ld -3tmTmG2x8X0D8IfLyDLpYlYUW+8vuyXPiGgSGcBpVcJDeuWj1onini1493Wte1Y3 -zWf338fjheCCpAGaZ8v+tDVDt6L2IlHbgAxItSj4APGyUcPKsAjQOY+nFNPa1gEJ -xqyR3Bzm8/TszEeKEyVGR0kjABEBAAG0J0RhbmllbCBNb2xrZW50aW4gPGRhbmll -bEBtb2xrZW50aW4ubmV0PohGBBARAgAGBQJS+ptAAAoJELtVpH/JAcM+nBgAn0gT -Q30u8l5Sw2RxJi/fKE6YyPCtAKCtWSRDAtw23IsLyppGmyFJMz2cGokCHAQQAQgA -BgUCVxpinAAKCRAfx4ZSEjTx9aMqEADYfY0/Bu/PVc3mMz5NXVUAL5ef5kljWKfk -PVtnFnUJoaoCmq2mStx9+H3jXOQLiMdeH3eFkvUGZCN+cr+YOh/qpkD2nfSFWyEl -Vr+BqpHA7Jt4HNlJGzZMFtEZZ+8/n6bxZamqgQ+73HaArBuJoZGdN9XT9VpAGgQe -uroZtKu8DCLLzrWQLuABNVsbytgeg3H9dRP4aD7jfcXdov0npvT6+JxFTgvl+eYs -LldIrv8wf71YjUcUnrdNp2JmnM5VYoFwuuFIVhctJnnepxs3A4IkUfKwiJoB6J8c -0bSwu3K8h+My1ohGkg7tn1uYwQGn6ug9nJ2Fm2EVNpMzKSrI7VLtDj/bkY0atz6w -HjFdvp9tHGS/YL969tt5Lw/BZUlSXW94MojU9D/5lUETgiJ0axcuIM1etLm+4AWb -rzz7zHjjGTG4ve7SStR1T4FfRyRQrZUkAlQ/vJeeCjbrMF19qzxpH4BA0KzShr75 -UkWj5pu30YU0Ezsdl0jW4JaXrApYQ3EydR0XAq4BCLW3hlMOzGHEXogFTrU/+cd1 -JHWCuWnoTSAkcJubGwIrfr4lfhls+Hh7O5vMFZMIv5YwtU60lMGxOcgHqPi+DB28 -fkfim3+bvw/dU5FUCqFvMdnhoPxM/lzgHPbfRh42ZHLSYbTtH5o0BpzcL70cXXXC -ym+PDNoxaIkCHAQTAQgABgUCVQibzgAKCRBdtuy6f7Wxsl0sD/0cfixqFcd0XX3E -DETeR5E3iMxDBxkf4ZYxO+hlYgp9uFQqn1eQoxf1JOSSLgLmZp0vTL+ZsvzShjfY -jgTReAeDVrPVXNfvt3Qcuu+pDywI0apqpFv5o+vniaBtRMRaev1t2Zh2UqNaeeZv -DLJdZNPV5JCs6Gdj8suv+MOfErhOeItA1yNSnc8U8YGjjZn7sWh1xs/Nf6P6zwlj -BQF83nOiJmzTVCtpBDm/6merjWIXR2nm2u5EiLJjxOU8eefg8bd3PeyRKY4+cI+y -glaZEECpheAgoUn/OV+z3aNJv2OyBHAQF9knfwYoTCSSrbRUstqMqvuNnVGzmyF+ -EyGxWJ2iGJ5t0KrH9rFHQYw3tjyC99ezXFygPGFTVI3A1Nb1Q+je6/FQiieXPOSs -QdsNDiZuNNBXmIm16zXyj1Fhz4OjQYacujsA84YDAQXlrlILhjQDBT+8GDajHJSi -Y5Mq1u9ihKP7FYflwcOQUNqXXrT8Q9ESOIHdZ6UCrDNM3Yj1S9JHyD0GCDvm0zYb -ZwQR3uDr3WzI2BPp63Wz3Tlu9qPwORTi3gdF6NNPAdQ0IK1nGywP8dx9UoGWYK1W -v1dZXeA5QciHwXCOz6u9DacmJhBqm9nznf3kE0U7/mVjkfqzA0K9/PHbT2X9BlcH -TXsjFLQ/3bOeYfTmcaxAG9wppMC6dokCPgQTAQIAKAUCUvqXngIbAwUJBaOv+gYL -CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQcOHFhj9zCLkhzg/7BbUrqA/gVrII -mciMPqzQCU0rwZlK2NuMaWlw3P+xvsXvXlYayGrz4O+MqedS6Og0BWaEYGi2JKmk -NfVe+gPHrKkacQ4ZZERzfrXIZWV74SJqGC25i+CrGscoXqj2t0acD6ey1dx9gaiP -8RQu8ckeWriEKMNuDTAUPlrZ5F7OmO7MM09aVX/oAK9SCmWr7IKle+oVpftZmW7D -BX0fhhYw5Xr/PVJEjvES6X4Ip+UQjnBpLgbXPuLCwLBvTSp9B3S9nZa8IH4LdvkV -Uzuwf09qEftlUjtRDKUkw8kJBd8ol5cMJXTAlRnmWq4NjMWCVX3ZdVtMEvt0/n4h -6zqWq72/petbVb43GCwKCPUpS+XsBhUClNzgtBRV7/v9aClp8lLvLNGghDyAYLw4 -1LRVfbOoaZTvfbkle8kdk/oKjZon8+bqJ3Z+pC/nEBFwEm/0UZUzo5CQGY0yA3Ci -vGDYJMkWQCAdIKhHripo+YvRZZZwudlcAlN1nK/20k3dhJC1P0EL3qsL4uIsxiJn -xoeZ93pOcmOG2aUnIWLMAL/MJGx3dZFDeXBJsnmjvJKKrYLrKBYECFpN6ZZvyEU9 -oJoWDVR7StcaA+xfOZ3pJ0MhjMz1LSHjnZZf7Rz+Oeak/8Q+O/EWpOqWMYUnLPce -oTsff9wfzr25D7IRzcY69HZN5PMvBB2JAhwEEAEIAAYFAlccra4ACgkQk+RPrGSV -tE+uTxAAhwMBJxu3NaAvCwdQAyj/4NEij2RrEh8eT3YNUvLlg6ryjAVeL6Abi7tO -Ovmfz6VbG0SlCu/laM0iOAk/ke4fu/uUdUWhAiKc9NskNQ3JkAKRjglIhxNWx+Dg -gpXVU/WzCOpIxZxPidKpqZA8kUkmK1aiNPsrYXW31m6FD55+WC02aYmm5b45yAVV -6U18fA0OnfJSAJYDfkuefr58A5YbGw6mKShPQ0FZbudf2AHAVxEAEtSKKUMFboFU -69i3LdAWFGfmWhwIytqL1ZNSue9Txufke2Xt7nbzI1BwGFG0zbv4mM71qqcD9z35 -Yv3Kq5BysKbobARHBYpDTHsEhFc6UZfISrYXEAHxlrRFRZJjCaoW7QqVmKuJh5A6 -Uz25/Vj4wl1rWkuwVQJFnX8yKfOoVpaImETTxVliSKwzA08OyN4I52lJdzH57na8 -cpO/we6/4ZS5HSVhOI8G/IRJ6KR9E6zWjKOFMmhgk6LSVRrvcaDxSb3En3GTGj03 -QdErc7wL2VghuQmtLKShZBKu/fQVoKOwB40b78yWu5hlTdmtZ3/3Ei5UAsG3icqz -6k5KpqBfMqpW6/pv4jq1hQfGaxS2EZWwVEe3LB1Xc1/00/8hw5GlJOYwSHJpG6VJ -AbpUoszff+LThNGVN3iF9sU7zmHU75aUQ/nB6PaEzjzfDxZ0AJeJAlUEEwEKAD8C -GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEE3V0+U+mGx30t8WeDcOHFhj9z -CLkFAmCBzmIFCRKWs7oACgkQcOHFhj9zCLlH6w//Y1ZLFi1fg5yjSUubLzykL4ng -K1/bMADLw8wDKDIsLeRKN4PM/5JTD7JdW+JqGEYWRVwIAsO4ufsdva8Id/kCtmYU -6VtvjkIiawGVXIxC3KV7FrPab7ogl7Mz8P/KqxQ1LijiZBeqYZn4NoCVdMEgwnck -hCfJpmduC8BvuKadpb81/FE32rggE2ul7p+zH745E/dBTHvrqd00S3azq3FtrxYd -ICLHvNhvLr/VIT7RkA8iFrwTwqOxN4xcdvUKmofxnAtA3ad3Av4L9m7pYY++3cFa -ZaiyWgHol91ayR1svQ6RMp1dYa+LNG13rcRyJcdisc4wtu8WR6CTOHY4LWf2hkav -weUJ61IiVVrAjTD7SXD6OZSD5ugsoI4yxFYHZp6fDJNGL+JPW1dWRdx2n4ZpjiSQ -YEzFmvq+0vVpoBO4k6RwCbqCZMVrDtgnOGf6JAE6vPrp4OPnR1s8Qd/DytReQn9p -FkwJyzf/mtsfz61B6ODxoGOE7oMVV6csQrUNqEkajyZHvMPLgc6q1tnD4dJsQCWM -3BPqJvHC7uyXDY5y4Una1dRC/zQTPt0+WI5BzpaWEl15L1ez4vaPY63sdTOnLx2n -Vx+AUel8W5ISDQZU5dDKxnNUdkq5g7R71LqPmNN2kR9XhrtD4hMwuyMvPAUffvNs -D5yJcw2bhRNwlGX32FqJAlUEEwECAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B -AheAFiEE3V0+U+mGx30t8WeDcOHFhj9zCLkFAlyRTVcFCQ1kejoACgkQcOHFhj9z -CLmnpw//YRK7Zqdv+2XtcDfvu+nO7jI8ZSUWigHTN/Tbj2oG5ya94bFPCDSv3HzZ -fcgMQZHiUcX1oYL0Arb5VyI7kSbH1roPNzR7QUKDlhEaR7eTJNiGuD53rorCZxXA -jee/H3yMlEnCYJApekicyYXR/cMlyHam/KmKh96Xpzx+xpty1AxxsjETwB5ojP5j -t2snPub8QBfvVx8y/z8A0H01OtzxQSI/XYzxAvZ294kT247jl5dIJWkRDXi10gvI -Z7C5CKhQoi1ec9t3fgKgrd+sW672UjW2GycRRaykyC54eZkp2Mgi03JLHZtKPkud -KnWdIh30G9FcT+F2IoG7loA5GECVzeIOmwCxh27kPS3rKI+kJsCburaE3h/143U4 -SAeqQf7G6k1Yu3CR50n9zoGiF0/X7LQE7DQuaWBLYZMbKQnsqeQR4SBz8lYW+0P7 -RmTY+LDPYzX02u0JISD8jT1Icbnq3Kp68V8tYEfxxNU7zR/mn93hRAgiVzP+Q0kj -4vslFIBowCTEFYejhtVE/NcTuqHxzWPpIay1H7RWWNPIzFgs8iTzyYzWMpfTULYy -jgNOukzNm/lscgaOnUoIRonEUkGYP33wEBmWjgMf/1XvAv2ZTfkRxiDmbUMoOro0 -ED7J+Bv1B9dqwPOFLyu2eTDuZjxqsRId+pcA+Bmpoh1KBNcvDpeJAlUEEwECACgC -GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJYntYHBQkJZW46ACEJEHDhxYY/ -cwi5FiEE3V0+U+mGx30t8WeDcOHFhj9zCLmdNg/8DT3no2lySIBPW/IwJhCV4Mn/ -Qzbi0RfvPhKWiM7MCpdPE6+vg1DemDN3UxqMqDo5+SEFD2pGORoB19nJc4qDU9/8 -B+k4MHOywfvqYNw8qKu9ojAqKzUblghRuEgA88gPfsKIRR5RKwBCGhy2j3BYHyop -E44eE8vV62sDsIdkVpFiJRPNH6I6d5+EptL+6e32BN4Lh1OzLtbacTwS8lPQ0DID -UAt+XF2ZO9wUs2Xv6tLUi8EpkBQcxyYUD66liKbJqLDYjyNeONHFKQ1fjMhleRWc -GAzLYf2FzMyVeW+F0HEEYUQLXiyPVhiIcKzOhZ0T1Nobohx7x4i8YXFd/w9gzTYo -igZWcLNEdJ0iGiC7fd63xFyBSw3KLMO93+QGjTZTCSinwPJFO8OIj14iRi5o18uj -ZphH+PyhfM3cr8QK0zJbtWEFG+m7PKPKl9xzXz6vqj03AyYU/b9pWnoTtwNknv7z -Awxe7qQ5cvPo4S5Orb1n7CyH3rbvVobccwWWarpbfMLtDr+s0GMGU3uiQfUJZxjM -M4sjHjHYFcgLSoDh/OwrhdlRSWGujzaLb363kZqTFvT+7ubs4i5/7TKgcF6OxrDm -X1FrXA88+vlXWlLpl4kv5gsBPfeOsc8CTBgLJYzU05eitrXX65RiU2p9ah0Ex0b4 -2fDfUXSzwI+4JkRbFwmJAlUEEwEKAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B -AheAFiEE3V0+U+mGx30t8WeDcOHFhj9zCLkFAmV+F34FCRZF6IgACgkQcOHFhj9z -CLmBrw/+NCRzpTAgaemYY8+1dvQINxOcI6LK5/2v5lRQEIDM4b/nUkH2o4C5UoF3 -C0dsc14aUAlRsXq2itTTe0Q2E8rczfg9etoymu3kujNW5ekvHhENGmHSuuA7erWm -hO80j8O27eutW4N8uRCxEKd3lk8BReLPV3NzEQImTX82B9naedezVY6G7535om5n -nc0T/aC4qBukhD/OjDTjulVzOgz0akb4hDA1ovwjARN+31MQhYx1EtFweflEUbtd -RdoWVZFM+DF8g6otbc/hhHbkiioVa14djAV1j0QTD29m/DhZX+RZudOX7pCFVoeO -8tXcpMQQim3++HcVzUqBuErTCJL3hfwJO0r7pwZFBXyuC6wnkyUAj9kYHEqaBKsz -mL0eYNAO/nd+DUzXc/zal5bNOuQqAV1CbnjXOzg1RmsWx++pBx3MD1mgQGBTQNI7 -S0V0DraeNbv4fgiMM97RQ3Ie51BBgnUiDAadlMvvLlPSujPTgoxkmoiLU5EGA9L5 -hjFG9gEH82zamG3IdQ2NGJuorrwIEHcywPthDloBD9L3VGSPrmY7uQFDPHoanDV3 -oaoiSWr3HJnROHU5TVsna+q0hwsG5RCluJ9P8ljGuBI4LmMEnsk8z7rO14zGbUVn -EpIVM3gbiuvUJdy1NryVYmAuB5mlNFejZG+jLV4YDT/NkGV/gO6JAj4EEwECACgC -GwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJaulYFBQkJoPOPAAoJEHDhxYY/ -cwi5r9EP/jK/+88Qlpknx1mqPnNqNn/3crz0tPRXf+kz8YZPFIIbtd4aRoYALiw5 -Ap1kX7kVSI1zsNXb/Zi7c6dcRsULcBA2b89z8+pxCbzlvieIKj0U+Zk8ppSIh8Jq -z0xzuiOeWdDC/YCTKibZhxumEzt+ouggEW/mycZrIX0ooFJlazEUNSRm52JOXgdq -QY3E3cU7MZlgjAdxwWXGnQt+NtWT+vdhss+YavLvnsP8xoO0ahRNelUig+/awvZX -2F0yTHcfLTXiWpr+EZfa/bCWT0m1QBthXkOCZE9ii1Bwxg91BUws4BY4cG+5Uc6q -NJaMP+JpaYJu4U68E+lTeFE4SuuBSjz2xabyxY9S8+Xau14IopZbJ/qn0dEiwiou -1XB4EHurt93K/6mfxC67xyPviRrVP4WdoweeUmTMinotTKO4kFc2FTmvcuf1+3y6 -+n2ceF7j/cObFDt+C+lQdm+RaSUgVwfH6FbDoWjWdw/5isRKIfshg4yQ/wuOIIJG -fR3s+aXVl79AEGSRDLMlZ+CkTjrCLlPU3TRm5HoWTW3J/N+iU+Lk9BO3Ysk5pb2W -RbvKy9BzmKjstnfE9b0nH32d5cRHro1xs5VOn8WfV08yCRsomMmfn/AKXgGYKK8c -7DxGdPn2e2UQt0OFSJ1+5uSUykF3A1s/zk5rhcSpqMHVThLoSUKctCZEYW5pZWwg -TW9sa2VudGluIDxkYW5pZWxAbW9sa2VudGluLmRlPohGBBARAgAGBQJS+ptcAAoJ -ELtVpH/JAcM+v+cAniDLwCDkhIvgXnCPa2uOhx2/Nk/vAKC0UV68wb78OFYhSykp -OtA1U7r/NYkCHAQQAQgABgUCVxpiowAKCRAfx4ZSEjTx9cpxEACKssaLYx9z3CcA -l59UAXUub+UQ/3UWWOAjVZFWk/er965UYOhNsIhuDfkwOKkQ4nb9hHoEUpyF2Eh0 -eiultrepDBftFdRbi3duteZMIluOCTS+RM23MLsVMxQu+RH9elVDoZ0nKtjDBCwW -RomLBUP88GyaSOOKOwx+tFqcN/owNOSJNqa7Cs7Qq3bTHv5kpYJlSjiwX5G6YNKm -HoHNE3slyAZ8VSMBvdDVqEiy6v19sMbBFHuPLK8O0YBrgYYO3KjGJRq8ZUYNZl21 -NlL8btgoX455Yln1ys72TxBRDi4AjqkjWvKvWWnCMV2DipJQScoAIuyqXhxcJozc -nJ355Z6KxzCWsNE9iJ05qX1XZyT8ucKUkhjX5GNYCIkOUFHPSAyL4OPxopwx4U0u -gzdo8XDSezzQFLXPHhD4ONh14LCQcntZBJzj9KpcqfGQbmtD5uA2LYlCdRp3YMHr -PliE1hLSZ6/QZk0yYOSbmuG18FNXvW7YdpcjxrP6pkXkNPc2d8iyGNzgfAzPFaMl -p4IFqB9lqf8ULDAvpKOp4VXgJLObDUBL4X014e5ai4uzTlm858NU8bS6nJOJbAVJ -hZUl9+Yc4RijfM2aK5Vx8G3XIF2OTjfO86n20utO+Q/a4kEyGSSeAPb7Etr2rFph -dUxTqvfIHs5KpBhaPtoH7SmyxTBLKYkCHAQTAQgABgUCVQibzgAKCRBdtuy6f7Wx -sn25D/9GJbBBYg1ggS3lAKIYUs8XT5KEK9oA3JVrZdRrrZL1BJCHhrYkgaBOPgQa -FfaqWT/6P55zYi+h2Pn5Y3eHulExgRcJ6R03VbgjlWl+xUhQQiPq0+O9cJnGz7me -ikvEmnXwsAVdG5o6iZhmj3aHcHR4GypaO3ykewB8JzofZ0guMTJiSqFxpE9ljRDO -3vJUYkunAklfT1iQO6vH6MCA0Pz/FA4zwrCAAY7w5+E/m+b+uY9VDVDG3l78ZkTD -HJLvJcQ50whRrcjRfUa7uuoiLLYC03fA+kgSGbOJxXS29BH9WlU0csGZeb2DBleK -eH6+5gTrZzcYOESWrd+mIq28fEYIBhwUJTuoo75v4SQLM7K08RKQjOMiITyik/94 -ZMaWpopbhdRMK8vEvh1rbEz5IuNkDu/UYtwLoqWbn9mBOjQZG0XthQjzze5RQ5u2 -PaTbWL15lEi01qu8VK1nMsEXJ08UEPpiMmO/EyjTRTbqbCRcrW/vRBKux9njEcVl -zfOxPO3C4WSVAmUpHHtv8XXjhoWwqk/6bR0skWZ+oie1yzUMrCoLmqQervVJfc5v -TjW+wsCyHAetbRAGT0qiIllze0z77NHqCEpfL6du9kNP/bHgXTa2lNhubNfyt8u4 -nkkZ8LDPYTVw2b481IQ6biDj6YI5nK0zatkC1Gcotakk27yox4kCPgQTAQIAKAUC -UvqV9gIbAwUJBaOv+gYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQcOHFhj9z -CLln3BAAil2T3YFtoUDpUKX2Ilc0FAKGM4yXx7qZXe0wEa1dg8NW2rCw0U+ZPbrc -vfZfITzYmnQUp04eSjuahGpjPulywbrheCoU64WTGb+IzjHimsnzKaD0rL2xbiZv -0TEJoeSc8aCMxs8DT5E0jX+6RZo9RDfjEHZSHEDWtgpJgLOJhOaAd57OKkWQOKaY -ZncdfXHWyNIeVI8Khb7Pye/n1L32Boez+a0XXgyyTRRSmG82Y+CuJZHQxk6j4XoV -bJ/ee5pb1fpHouTHrtyQyVzoWN5BpyJSflEY0Y5/SiGEu/igUJENuv5D0kSSGCfA -qJLQOchrQ4jgwlcMBbWzm41PRsP4qYDePL4uNOVrPb8eIRsqWIGS4k0FUQpF1MI/ -aepDOClbAz7BzDjdv1neY8QShVQ9CukFdRxLz+aZsFZNl/4Cn+AVrTULxis2n1rz -ttlF44DzYztRZy3Mj2giVF+qlUunpiNkGDGnjxpYlJh8Um6brbuOBf85DbXJPjAz -NyowriL1MhuaqeN4iyWBKBl0mad+s3TQL5NvqL3y8ZtOFWH/NxDikEH1jjxtpepi -IlItq1ds9qzxe7oTDO6qfMFtITQWwiOcEF4Amo+xRPevfutxXRPRK310cvunykWn -KLXFXWGlABpJzPPU26iRnAkIFue2CmYZAfCyez9AMCy1c3A5QaCJAhwEEAEIAAYF -Alccra4ACgkQk+RPrGSVtE8EMw/9E89t50T4T6Qcg35R8u/mz3BUbpIAafnVLrmD -TCesB5B6HO/5PV5gQx3DUnB2Dumlw/ESg9tzNzO3oHsiSvp3of5FtHnZz3pRwKLl -GNPRj+b62VdQRkhVRowKevPTmqyVrL04IDEqiw946ykeIV9r5fRugXKKmYefqdA3 -HgItoX2ZzSz38iMABuPZsSiaYC4+Y1Ivqe6Fj3sZ7Sg9VXQiYlY6Z94rXvdcEOHt -oqAcDQvYf9gLty2P8FRuvJAcLlY73yuF/FNx3wEYtJQKmNdcYtxMoBelIFN9XvWw -/dMW12g7B3DE1AWHrUYXXjZGKIscMIfkkbxwZlyaDhw03Xp8fp/OP5/NV7VfOhwx -GKfKrAKufO9sRHkPqze4+PV5KvcH9dQkKmouHYcfCRYy5SEjFA5mxSjTG9csla6P -UmC4LBVipVbVbnumBiEOrtPsj+WsczHJs86ThgREw4VokxrnO8odDjb7XQW9+2RS -EbY2GPVkAVgoS8L6qcvSZggSzc9njHd6fEbrrw5WaGr91xGaIZiyEp/dMdNsrYdR -Z/J1pIjlCKplQJbHgvwZZZ/k21r8wuenjlmMafjAdhye/GX8coslRxQgpsQN7Gux -8epDNyu3CDXvwFhSD17Y7dP3U0AZHQnWgkY0EKi0X2mLEhfnUqsRWgA/ZPsQqEa1 -8V1JMFiJAlUEEwEKAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEE3V0+ -U+mGx30t8WeDcOHFhj9zCLkFAmV+F5oFCRZF6IgACgkQcOHFhj9zCLnOPA//Rs6Y -ngEjQdHxd7vS1AsY3LabvmEBA+la0Nat92YQx9E/40UDbSaSxvCE02AoJNA9fPaz -dMlowF5lnR5ew1gNaEhBi69jrMnnC+5pJ/XcbK33LLbIjI16K/ZOKUzUwUYEukOD -efXroRkhXLvHYi7JIhchit+7MlRcMh+vWP1B1aSNQgf1Z/YfDj5H4vUwPBL9Umis -Vd5r4iugoBJ0ULDjiqnt+iWzDfAoQpVKIzOw3z4ti5wMFHxg0Ctqvhl2/rRcwY6I -j2Nv20ndtwL0CgUT+4pGUUXfCSvttWv4AOjz2oGf4IXH7mMZiXWCHIscGUPV0HWN -MreNnESbMr2cI+lNOTfroaHGHwshceIit/uflbqKaibbSJ5XYrtn1RSv8xnpPuMP -Qfhvz4l2t/sgDuVuReiNCI7mM7g885y2o+6WOKiGxwERWg3J2kIvYFR2Aq0OfZRi -EYFb5O+W/9txT1+GIlPR60LMlrfXgrBG69WleSSwLD+eQHYuc7iT9/lWpst3nnm5 -DvE48VM8pdPfk027rsOzxiYU6p/hTSyf4AX/NsVAqWS2NQSFocBUS9/1nyfYo+WT -K7mSYIA+3Qfjv6wypbckEUjozfNkgp2pYihn71RsT+ylvwq/Va6KCtgscaqigzPN -M7uCCiHl5GBlHHFO8PR/1sZvynC70hbeGajrnhuJAlUEEwEKAD8CGwMGCwkIBwMC -BhUIAgkKCwQWAgMBAh4BAheAFiEE3V0+U+mGx30t8WeDcOHFhj9zCLkFAmCBzmIF -CRKWs7oACgkQcOHFhj9zCLneDg/+IJ7yeMAqrzR2+sj96HWfbjRK+r6SK/2pVn37 -OfjApg/Hn6KvFPp0IRfvIAGOwT+1vYK3XkXrIaIJp6BedDxYA7zCO7n+uTTVyuW2 -tR+mrFQIkUcBiMNxwSm9OAjJP6E7rC3EWYCoGGFXjN/ZfqZfxqfzJtmTuT8IsB/d -Hq4agEiCsFh17Pp3pWl2+nyGAfn/5rueo54va23JKGanF4/J4p/ZRVLc2CacjqqU -pf9+6mDwVHIt0W8aVF4EzZ0dLfQWAr1xpRO9Vfw6DFumSJV1LKb5D7/42QplEBxd -Zl2mGu6u8QSfT+mZMFUWlJXyjbH2lX3KAiZfOgPhaIx9jZeDeMprFKMXhu4Rf8Tf -Ras5Usqf3o5WPnRpNrurGs5cBcuybqqdE3RyT9QkVv1YAha1EcA7KkRUOpnbueN2 -N9tbetOu8OXIvj6+eup1VvbzgE1XQUc/ujsM497KTcxmGdtaxZEjxljtKrQ6apDh -abp7oIQ211kR343O+cuniIsWb98zBsUZLTu1QQT1rEsTCEvywqBVqIk9Yo/on4ic -ghaiphr32voLG7GvI8CmQ47bBgg2NqH/iJbTrlS2kywE1Ayic6jUBnYXQxHL7bMq -0OG49ju/3Skv231Xj9TjY/TBPMlQrELnGKUuDrfPCUWTwcpUrDFe0gBNGsRewU29 -/QbaWbWJAlUEEwECAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEE3V0+ -U+mGx30t8WeDcOHFhj9zCLkFAlyRTVcFCQ1kejoACgkQcOHFhj9zCLkMuRAApqnh -izoPE/Q8c1nAcTli3r5C6vyWEL+OtK5xikpWuBZXI1S05nRcG9T4LHAGHq7Q5LzL -EAdjXuw8LIG8IVX1JckWp0TG12pbXCDJMgV/Ia4AtPMeG1Bb0YPzRfJ58cvepaGe -ZdLiTquhRUgsWRtcVxFzJiAooPeOdVtzFlVdnYGgohx33KnbUH/LLvp9pLVUn7WE -BsmoXf3/ISga4272BNtl6jAV3Zv3w8DiBFm95/rYSLhWJz5p8NzP/7LkRKF/pc91 -MHcsgy1hz9CGz4S6/KRM/8Fxqw/j/psCjNI+148ZAMcI8UoVTxj1EJwbPYWhaOLS -vJUt0ny2rlQpbsOA/9CXLEddR58Gttk4VQtIhqed7qodLq0U6ufe+hjwwkr/NYvS -tuHfSi177AdimyrZKwSZOMHHg8UBSlNG+Ng/Q9CLgsNUmZ/0iXojBQwYoCpFCtf6 -gtDBmXaaFRZxd2QPs2hL+l0W9wNATSMKT0bMCzdoxgbRWnvAS20fGD0JWG9aDoJD -C4PHMmBb0RMXhR5TCn2NLtzK4cUdKWMagU/WrrhhQKzrir03D3Dfopjtz0xzuCuz -fzJcz9RsJoVQbL0QuBctFKgWzm2jKJWLmG0+IbYnxssoosILl+iN/g8/sdFp+u0k -5ks42Kstn8bBF5tBqZtI8yT65EeKaFV90Hd9m/KJAj4EEwECACgCGwMGCwkIBwMC -BhUIAgkKCwQWAgMBAh4BAheABQJaulYFBQkJoPOPAAoJEHDhxYY/cwi50fcP/RZb -4FEhaBowjszq9pBJ5B02f0p0R6IMr+TkHpmGPA4MANcN4qPt6D2JBiKYz2sg+P3m -gNEmN5+peUwfcBRsbQgI6nMRwmXD20Pwq7/tzRm9DvHMKLKaeG+o0RAf/LQ5UpGT -WqsdO1Kgy+X3LZ5DwyaQZZLAyoZ/iUq0+OjLMlzbVOKknnvO6nxni0Jp9UDwsVfE -pu7vGcD8hpkfxOHg71VQebH8SNbVqa34wpHC2yii2aYJUqhiukvIBDqTU0GBpY5l -fW7BKUI5ZKSS1f50P92lm4+RutvZ2mjiI25PqtqDiQgjKejIho6kwGM4QBYjPxPC -vU1/qKMOMj7dInBtahew9GJxfsW9bJUkUc7OZyZug/Yo88yEF50+LEfu8fXPG/P7 -y+cCmRQQ2rpX1I5WlA1U/kMWIwygXYSsGi5hCxcoUlrTl25t+9pTEUM84LBabmA5 -BZN9GP65awBbt8li6u+ApiMzY4v/Iex9twcpQKvbdTpb756H+PmODn04ABtCfkKP -XdSacKgaRnBWYARtS1SXEEYlZZgRJ+Pz047lc4Co2X+TnRMZFMia/0iiSMgVYTh5 -iipnHiOAZ1VFErlub0fT3DAn1rg50YJBQVvrqYpWgUoaoTSVDRI3SB2XrRfvvgfq -piQZOGJ+5D/n3lnHxYilOePm9wq9Lz4sPHvEcTQniQI+BBMBAgAoAhsDBgsJCAcD -AgYVCAIJCgsEFgIDAQIeAQIXgAUCWJ7WBwUJCWVuOgAKCRBw4cWGP3MIuaixD/0X -PlFnMbrLxiH0CAUSXCkWFGJzxD5GXxYM5mV8H/Zklkij+T3qQZlcYCv2Pdlr8fBo -R8K8BlBzA2TZ1TO8tKfoXHQHJY3YEPEcY/PqDhrycAuQnAiSFnFDRqltKSV0E5fB -RXSdVZFFCoEJUgTtIlvSvTyXJnRPSXGyXFcETfCGQZ1SFydk2eIuE72pLduDzqZs -coQ3KAPMKINqS/QgIUf1rQo3M1x+7JkAUER4QwS/IYC3/GfJrw5OkqCnb4Lxdr7p -Ew/5ZAYVRK4JGvgNRSpa/MKypXmnpr/ioWWWNWKc7uCX9wGX1UiSRZeGDBQ0mOO1 -VWpuqRRcv3U021naXs6KXiRpdRAxizrA18A9HtElhTXgtkbslO2lkEZfOU4s6Dj5 -317imsKac5zOU/RDlnIjq+OaQ9sY5QJmt7VfRuRXQDJ+iQB74837cyacowoVPlsn -C6l98f3iO7v8l9dXLIpBEAjd0NjxfK6+4txDEB1l9evALVvCZgRXqavDIeAS9lkI -me9jD8GLvIST2d17t17n5wCajlixbT8Zq3dr0QugXQFJjb1VvGoX5e7YbVPFojjX -0t/HSZZORNelmjnvA/ur1d7Rp87vVSCUZCJ00/YAILfWbaWW8TcirSc3hfvDk3At -kLvpXv4434JnnWtuE+i/WSU+RltQkWWJQ9Rt8s9+PLkCDQRS+pX2ARAAuKqZEUEl -8t+tNe4lw4FbW4TPJ1axmaVb1QTkv8qweI90ej8AZFYXmAY/JZmbHhTBFdnTdufP -3DbVduFwPlppkGhLDXQ2LsBJ3jBkKAphjwEc2QJXwRI18/bd5mf5+iu1hhvosYZ3 -ZqZR3+yNdXLUy93b0MWZappibfit+llp476KAhyxVfQrteiibWAblAhpO8bDc2sm -rdcXldUsgNuvIVJdBaa/oiceGLk2cRLCmfGgjPIteA9zM0bpv3mO20jVVjahxXxz -lVsd1FCpfj6wOiB087kdnT6OMfNub9o83t3Ds59ZJAUUzkuXO81aDk2loKpXwPXj -wfY7dX7MfESrP7kS/KEVgA4oDIAYpfkpqHUh2vFC9I2H3FtLPE68Kc1DbYT0Hvqs -U8k5498KqsquUc6ZLlDbh0skrVgzqYdtLUATFnDGJorGyqTPpGbimueHoonsPAAL -EAEeHR51vqbF/qiN2bd9p8/a+90OQbUUZ/9pr+FyKNDZrZYKMOaTOjMJBT5Qfsh/ -yqLVGdmKJhoob/FvSbKUzpAfZ8YDesl5kxuqvV2mkr+nWQY2rRzmCW8r+m2Iugs0 -zIqH5emxtFn5d+gayEoeos9cfSS3TkGxbIW5DZZMRGA5BuYYEA12uNiuXWMWJFNj -xeUIg0P6n0iRt3h1yyy+PydLQadjr42qLs8AEQEAAYkCJQQYAQIADwUCUvqV9gIb -DAUJBaOv+gAKCRBw4cWGP3MIuc/KD/sHKwPO+A+KDgsuedjS0KtPO5ctOnhWmnaj -b8+MUhfWbNbly96ptXDLts9E44XiqvyQjkXR3TWID8qJQ+fwUHB9TSa7fNML4TLy -yvKiuGOp5QwKKPIM2m+WA0poDAs8c52MDtrB001Nj4wf0ruYPKCbHG4/plMSEOTK -CTPAmp7GopnhiAZj8pvYsGdjMOOZZVdquw3WheFTFL2dFOe0bbGH5VuZbbuJXxod -ybgEO6FdEQOJnoLh1NwE5QOBDqsj3zfg1qpavOKdL1fJemeKqgrGf3c+Y7Mt+LmT -SVZG94G7/VaTo4SAq4PM8VFVmWkkzY4QgHx7695ZFyVg1nV5Yt1wtywMdlaYwJDY -myAkw9MJmLgD/tjGIregPIH1lC4szxc3uy0D+YntibakzkGfvXVIa/INpvs1u4Uk -vcEaXkLIyAnLYSGL+qjfVH5tMZ3KgtDGDy+F9zyGpUpneyHgP/HLlaRK0Ye/LfjC -xJMTT1OhCZ/BTsXkOlOBvyavFHRk/rUubXtgqUD0QvriLR2+a+GKspBGw/0LJe3H -XwNdzX3sDBjmyAOcoEeL/MnbmzyfBji1L9ea25qh/NJv39l4ORdCVGIrVH8uzs5G -folw+1KeaQEd0LlCg5nd+TAJ3YoXeLiGq+oGppemNB3oUewwS0Nh5xgbML+Vl4AM -RA2GoLofIIkCPAQYAQoAJgIbDBYhBN1dPlPphsd9LfFng3DhxYY/cwi5BQJkJUey -BQkU7Ri8AAoJEHDhxYY/cwi5joYP/0aXq2rJIqyGo+9xEvalcLDU7OnECL9kLaMy -S0iC3r5JBzXTX+MgJols5AxQE8Bw8OZFw8lxTVIDPpXirhstBoRu+s0salGkwR56 -lDZYwglrZAdLObluvmnx2gXSrm0lA6gBwT/N1dURVI+69rZaeb15OlXxYrfNO44Y -0PJfFmXg/p3lGTXUwc2R2hRLXQpgwWlyNdJeOhfNaAIlZAa2YJ/rwRyIzDmOAs3/ -PSNEh9Ar4OA7fbjq1887xHCOfg6l6wkX2MTys4nSbgWQOCxS0/sMxcY2dwOG9CnY -cqmopU3qHZ6ddCoqcUD6FYj8Plo1b2yr8PB2sw3m301DWY08T528ZSwKdxPwrK6G -vy1d5K32WLbN1MC+kZrQsYMf2q2OVgKRJbdIAy4IfqAQojnB1ibNnOUBjhUnS0oj -3ki5r4fVMA84/M5hcAPBuf7iOlj3EFnxgfu2dq47jg5+qjCYOpFpbcVeZHBxTTou -PPY5MCjHArFitNwJDPwZXakMIGA+lpsUXPFXfNmT7+VqeolgWTA0LTx33w1aUnr6 -dunvy6cij4dH9U8xPhrT/wXRv6XlrmIFO6taprOfFwDGV0uOlnolKhCZktZcZpUl -eFSzzgKJ1K5q4V9646hZlucDjTIYQzpUSghYceF/fOT3BPoNM5k4F8uPD4lLxXoT -3VYGAWRRiQI8BBgBCgAmAhsMFiEE3V0+U+mGx30t8WeDcOHFhj9zCLkFAmfpbhQF -CRixPx4ACgkQcOHFhj9zCLmeERAAovb7RdcjQKeC6ng8Iognh6tfSTqQRU6eOG4K -Xyh1HPwzcUSkImTyH97vV85OFs32Ym+qfRu1vhBYNL4mZNsrOvx0chz1D/vxapE2 -cX99w92q7g1+3xq4hsmU589pwKL8tyMBUGw6etPF0/6A2gk4SwdMNpC+kwyJcK4d -GqOQsKQPaz4E4JluBz9vmloizKPhcYHd0R4Uw87nS0Z7pWBQ98L9htEmr8OkDXxO -kF+5e8eOTSCEendzSGYXvWYZaq4arb9oVc79/id/SD/J4DXzpiAM4XDIa6+FuGyb -DBmQn5kXbOeS+B71ebP/ZiMchO4jkvU4Tj0Eujxwd873OrRlGPs6DS9XprcwW/SB -Nk6pQf2+FnhR4SPs3o/EFqEsI2MErh6x7evy9Y2y3QOqaQy2csD00DKbjPQ0rUn8 -EL44vQpyVeckXAMACZJxAOfAAFWtkWLdZVx/JARs2ryUUwV8UAhv3SE4b2NKaSqU -xG8QVtar1c4gnCJh1RA+UuBuO96hIk0XQ0gJQRfG54ByPGF3ngNmcllrVh/8OyyK -GTLHXMBCDf/DK3CZqvSFB0Vd+YP4YVVOYQHCsL5KiqcdWX85z8x+6+ZfJtNrlAE8 -WeGdch8w1RL861IbtOlwP9GwApMIVuHXBeesApNchURttVqrDk0vH31WKLnJF8Ss -1N1AwX2ZAg0EUsTbuwEQANLNSYxSqa2nU8ghgs2HQ3EL9LZxx+DDrPSc6BOA8AfF -twTquuDsLZu/TzTI/RSi/0os1R0WWjXHwMD0Hsa8v016EE2CUymNvZ/djf/hmbYA -0/HbGIMO3gLmR84E4hN+lntLajJh6+SF6avD/nrPBe7mfVZgAqoL0rR2Q1YKCp0r -SuEgdrbuwz056WsOYKc1vuSUWXB4RraRLAnNCdFLbs5Oi6oK10FQu5i36gO1SDrx -HroRwRIhQvFkUBNdpkVlu9RsOl4p75E7mN5voDyf5DxttpH1CS9h+or8HdOS3r2S -QD+d8xRP47N3xC3vAHViR6fstDxaWHsu0eSmGOpRU+ZFc8wu7c6L5ryF3VTZZOu/ -q8gPF6aeYqiMCRvODw/PU/Lx0BYQjTz+MDW/rzGr4rPr953fLQ1NuJ+sp9g1bFyL -uNhAudBF++6BJGUw5zhoJpJTwwwO5QhHJhnb3Qt6Pz2UgiZp941TugzrKW9bJTd9 -haTYrJkxrunNsqinoSyQx9qn1dgWFekVY6Jf5U7HqZLdn+UewLUvapCTgdr+QmD8 -9UUm30BsvE6vGNdbBqTHZhacmMhl4XF/mruWoz76p6FhA63rYP/gIKX6XFa/JWKH -s6asM4vCzetF0JPLeeSARtA15cJikuxbhEvt5ifcVALDYSkachYZ2rri43oPidyT -ABEBAAG0JUNocmlzdGlhbiBHZXJicmFuZHQgPGRlcmNocmlzQG1lLmNvbT6JAlcE -EwEKAEECGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4ACGQEWIQRoydWWDr6VpqzC -/IUYdvQ24aSlnAUCZE9o+QUJF/iqowAKCRAYdvQ24aSlnAEyEACBP1ais5+ZqjKH -UA2LspmUG0/uEdXUa3WdQluqLD5IyOObnwdEH1yjuWMuCmdd+Rmh86UkMr8agO65 -dlWoMGmIe3MB9orrcF0qylrPnRv4I6PVaMLe+4fD7C1b6nVW9QS5M/Ea87Y32kVO -uibP++/sRutUKgZpbHg+f8vwsJBP1Ddzinhcigicjl1OTesNCbnUXO6m2/cdP22B -1Un4Urx8vAUqpTaRg0HWgSys3gkbkabo/jT+6Fn12LbEE9cThWGQqipaEFTd7s89 -Ygl0NYwBuFEhfEld8Er8vf2Z+5XmGCP/Wwm/zgGUIC9/oMWhNdm4IwwCP+FcMJHn -5Oxgxi5SUdws4Z2xAQD4ZOnJ18qnZnWOPnUS9wbzETAVPFsPuS2FSqKEU/jLINiz -qXcJcPrsgZ+ywf67FFHmI5FpoYi5Pd2T9miUkwgxBOTcx9+37Uts4KspboBVuayX -VifM0QPbTtrqt/lGjZUSAgWATmGnNIbs6ZXTiYRrkivJmkFemb619EIhyM4DU9ZC -t0o/cbGxzL75ZZVOsk+bmc+igMJk09tmJBbPkz27NN7H9eO0PcwJ+Cp1auhz/B+S -/dkFJjEVF4Bpc0oJpH6sCeOlmV+NQTXZa2ffWzMivUn45aV9SndBQ5OXgv98LXUw -763EtO7bWeg+QBSC6fi1RxNQD2bZEYkCVwQTAQoAQQIbAwULCQgHAwUVCgkICwUW -AgMBAAIeAQIXgAIZARYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJeuS+MBQkPtrrR -AAoJEBh29DbhpKWcbCoQAJdCTfj6MfDKrb8Uccp/vEcKrg4S1w4ds5y7y3HjdLj8 -aEjk6XzNXVzTrYD81KSzuK4qb4Yih1ZB3FhiLhuYUe5ShM8SEOW2loZjRMWrWkl9 -7y0Sp5lBdnE6WEw0Fh73kjLohk5Ya3wYxwcbMMCkgrUH8oGgnEpYKJXLK1rg8o/3 -oFZ7bMJTYUSYkNzzEZ7fIwce6C10Jc3ZnDWaCEvohYCcTlYDMje9Pjc4+m75QvyX -k1tuTq0qZCFmtbRHZuuyddwrMTCgT7KVrz+jB0XiSPv4xn1rXVk3WZRmzADYpC/F -yIzgMadRV5naj4zSUzeGqWLJHKewyLYV/FTNl5jClTYoouQEvKFY2UWk4LSt44fp -va4Lgi1Mv7QJdtS1rV0C5DpuYyVop8hI6floLXmaSyrKV5QGozqMPGVSqOjQNmcR -phOTFGNSGo5wtOvId4iYsilOJfQvwx4bUynvEh4B4JziDShXwoecDZgbnuDzTCbc -u4by4isCRfKx/r3ixY+Tpio1IDyfgGjTifqjqmi+rWWl8BXOWHwcS6uNAOqKbX0P -wbL38HJggaANczmeNBX78ACAmLKAfKtEvfjlejL0xLaxM4Jwzp7JynKqgBBglEvg -By0WOzI6qUnES83YpGQ6y8Flz54JNT7c6Q1ONFOYzLN/Xi4QiDgS6+VRUhXVTIcF -iQJXBBMBCgBBAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEEaMnVlg6+ -laaswvyFGHb0NuGkpZwFAlo/pFsFCQtJDSAACgkQGHb0NuGkpZw+lxAAlyW93TfJ -opu8ucqrWKqYvjgJsKbmw/nGm+OAvThLUKi4nzqeya9q1868DvPvGkRHC/wOytoR -2ypdGzm54z7QRWUxACF2vLx/CpKcog/aicGk6prXmThtV25isc6RJF3e0VZ+jLt5 -TF4KsvMCgGOPwCsPFeLwwdWqiuCxzh60VN4tFeZyPWMrKug9nX7qQDnh1mbklLqe -bCUGWLsrmLex2vPuELETZFK2IyiVouoj1uQHKoWqBkIk7DBnCzsr3I0Oa4FX40Z9 -4r4VRA6Qe/XvvtaW0vu/DO9ZQO65Fhlx5S/5r9+z49RqMZv4Ene94gkKOgQUpNlD -uWcaN0mqEc/KWprtXiyjQs2Kkeofdr/zLyLAX/bthpnMtUq85j5fWOSdSrhUSy6H -RwKC1W9V1Ctdtk9T71AjL+chjDQ2km7x4ZYOcfxocyKywnmPL2MQFQmJOJ7fR//9 -vaVqtkqCewpFulxtqyKL4hbeaUa7lv7G9jAZ1v2L+uhbQ3a/MFOEp8im2jVTY7I/ -52r8bq1FZ21L2eecKhqBInAApKAiO5vF/rQ82DR+kxheLFbVGtODhALMMN1FbgNL -1O/c+Ll8mpCBg15rnV5PJXjlWINjLTbk0Gtj/TCM5Scr15T2ozNV7KVuawc4EX/u -YS9/vjMChLCpb5JA4sHmSu8xSqNPsIA7mDaJAkAEEwEKACoCGwMFCQeGH4AFCwkI -BwMFFQoJCAsFFgIDAQACHgECF4AFAlLE3HUCGQEACgkQGHb0NuGkpZwe3RAAgOZP -7H8jQywVzS+MMRsjYTuLJ20EGpyhcWTzU+QLF1idzOrvAHRGYrZloGw22ivQqv3D -6DN2A5E4x1hpjqLla1q7c2ka2SoAGXbd+zhLxINTT4qUeKXGv+DwxQxF+vhK7GqF -qQcrBXNG9LqHLbkws1ED6W/gajj5Odf7fr2o68wPK28iU1KxcKvy4hXL5IXsrJRv -55V31m8C+cokefIMELG8Glx+jsHBz6eN+tkNBPXj1GFf/stbECKH7Z+XhXge8XPt -zRJfkpNKgEjzcokDagOUGf9cprtm4AYb1kNvUFn4gZ8mLZG2pduHfCeArR0mhyo6 -/CkHIroZ9AEqCIyDKA6+gnVdIS8smwcj+p7oj3RL/uMEXwwqcekOROD1Ac7V121j -v+CFoiVgrLq7b7x7722WdcGgPHNMKgsc6HzTe5/hnTfDdkc73fDMy1AhPxXata7I -/L9VuzJya/YQ9tW5LktGjSmb7Y76DbawNf/rVmO7g8J07i0BNpYkjn2d6SZzWzKp -MQU/ps6K9XPzl+ENlbPs3uVHffazcxPorcSQekF8IEe9OHg5/YTdYfWWpGiUiwHW -8jMTiufzdG46K0iCw/nnISM0vsw80Yu+agupCGI5Eab21kVc87HX8R9JGQVbah+U -L/OW27ymlf1/HWiYJx3E5WCBftMlRSJo3eu6UqqJAj0EEwEKACcFAlLE27sCGwMF -CQeGH4AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQGHb0NuGkpZyW7w//Wr6q -v22dYaohT3LtSqJRfHEm9ejiQetROuYPa39V/w0hyZcSwCcjQNUDOYPFGCt44y2O -8EGQCo7+Abd16/I44CGcKccHtGYu8iDpRpQ44FzIrA+uamxikv+FE5q2SrBadDuc -iCiAqppn7ws8fJx25X03xtjUpD2xZDZAd7og6J/kimjbMB+JIf6GAXm5oyX1j147 -7lnJoX20pH75p0rvX9/skj//kv0xGtMWgdzlMBGzmp40PmKNO4NTXpbPTmlHYmv0 -S6ncpsSLt6NZvLjnJpC+KnOKjV3/2Mc+sJkAjT39S8Yvyo4bK/C/+KInLGqHk2FD -hU/ueElvs63qkJYnWDx0ulYmdwm+J2+suHVLjSi6aRCjcIDqa4Sn4A0PlZPalD63 -KuAkiRuJo1fYRPszhl3Dh1sbT/bl8mvdCfQ6QNt51uD661s+8QwOdHkYsv36Ofb/ -JhI5iKPUXuIJLBgS5Rf9ZiwUA1j/RZ+bCxPaJ23f80hc0cCzVQsdLQt1cjvVuSLK -I6VNPB8quqv2MkQeaYcOt5IIGP0JvXpCVDtnY/JNj+EljLPIRTM69QPAvDebX1A9 -l9WDA9PiHdgmZok4fQmYJJ95vGJtlh9GepidCTqlH7ltP8aXv4WOcIKn1iuLqWEY -i+lkOfTsHTcLUaiggsNuxacxfT9fzz7nJ0iqZtq0HmRlcmNocmlzIDxkZXJjaHJp -c0BtdWMuY2NjLmRlPokCVAQTAQoAPgIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIX -gBYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJkT2kaBQkX+KqjAAoJEBh29DbhpKWc -HdgQAK8hQJMcJYAx0NuhhQfOy/weuCDP6bQIFJaxohGF9ukx2HIzcPxxaHclp06v -aD9MNRNLS/6Ck0skSbXv2/5jOjExoBjzMJc4iojBTt/cwyjxAHdoPezOV1UW7SmV -jFbYoOzSREOUJJYPL9Hux0g7zl0J3bTvemj6famgoVc9K4C56owIUp+gtw3Rb0qV -fK0M7YdQxfNVsRM/eU/4nJXJgH5t+u3APckRCqRojLdsoVaQP09EW1Lo0KEcitsP -x+1eo0Ex7cEfmSNNQFuuY9znvnON/w57pqZPau/+txpRKzFsz5UQSn2ikckjGzpT -tljipHB7T4fmHsjog4lEOEcusUDCxfCbfiUfuI96h8l3xub+AZqinIM8HXxRdz7Y -+4sJVrOZUYfkRKg+ydhaqsZlMI0QpQKTcJZuI9JWyLb5WirSsaf5TU8Z+qGYSBma -r79znmvse7fZlXIhnbUH42kLAATOIjgLTsyXFxeU1JjE/EuImg6ZRxq6Qy7CAyjm -+IHay3eSPUSD60LUHoW8M4sNgjNDnL2SJAqxTLtUYGF9psA4yW/fj/VWTKI2hJ0W -QU/ahP5YCkuPOF6SJhvCUd5W58UDmfSTjzuZiLhv2j76HeISVm+hlRyNUgfl7y2h -DQt0JHFtF738UlfySaNC6lJ9I7IcCsJTFIVMOvvzw+abRHuFiQJUBBMBCgA+AhsD -BQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEEaMnVlg6+laaswvyFGHb0NuGkpZwF -Al65L4wFCQ+2utEACgkQGHb0NuGkpZwBJRAApPQSmpg3xyMwPV6Ae3EpSgxSghne -n5ag84pZAywCCZS0jfmhDDrrHT/aokjmIQ31W/bOVuYFQVJBQabUwyrvI+8FZGzf -xOEZ9jfdBc9vCVtlR3s7UxMkoVhBQpVlCm4AJYUe2kU0XAGyNlyA2V3exCGgXngg -HaYoj7nraKcWyK8M/9Nwlp7BNiUcQOqIpwoVx10CN+pVgJpHNcHlxyP9FuZOisso -3f1paJyrm63XZSwokcrW3SQDMMRiq4+vJy5Q+AV/Bjv7DpsfW7lbCnq1rxKQtXdN -wL9I8TfuUhrOS1UoT++V7PVoOrk8lXpXmRiu4W5DiJ6RVtRYtNfBHa8sO7HWLOhh -tbtn97NaEf8dUa4LV3kyPMYhFS1wGf1n6BNutZiUoDAsKbgcgKYrrYPTSPDdt65V -j1dtAt+MjgsxhFnC1Abtj0IIFKxyovWayk5WS2F4orrKavmtI2ZoikrKK2Z+kEk7 -e5++bZmZ0t16zFOiktz9aO3rKMb/yAzwdS+ZQbA6ojlq8k1E4EmAg6v2JYgXkGwg -N+XH6fFNu/XQduSjnBla1YQgXT7wLKRjLS9RVPOAWuu95CGCWDEv3LvHs1yz1/cd -TKVvr8ug+bxNj6Zqr+YKWVqVB8mO068wIhStAlpED6fv+mESUAH29i/qEv165MnO -RWk+uu0aEtQdIgqJAlQEEwEKAD4CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AW -IQRoydWWDr6VpqzC/IUYdvQ24aSlnAUCWj+kXAUJC0kNIAAKCRAYdvQ24aSlnPDe -D/911O87aur4tGbdJQ8q+SfR9aPOrvRScwdR4YEqrlB5gngee7cxxe2qkWA0kQRv -Aaj0k0PuVsTZ7mYASJ5s7jTK/gWwrItEe9KHx4LHWrrximelhVmzBfM4BX8w5HON -aO4nmCFcZYNGPokt8px/pHWTJtqO28Hg13fgY0bWTBN0sEbQnvFJ01USHCgCFuvs -d2hu95gJTEzKin5N/WdomtAGw2R+w24JKCk1zJ2M39mjItZM0cZOCDLX1TnkVoYT -8uBCULsyl/5YjMUZvysgejQhw8InGGrS3sdAenH5GqkZbMyphPIwhFr3oppfDSlj -Rq4NsHsSb8pmJwCCxzEl0xRoU1ejFrA6gs0vScYf8VdlU4B1VFwdriXpbRcnduTc -JztnvYP3Q7TqvoYenXZtP7n5x78pk4DMRxjQv591G6EPQ+tGVIJZFrNq1iKcYRS5 -lcV2c4zysEKbK1TL2tJhDEjU7hnCTRraVBcNtJWPmUf4jLl1hZwWVxlg+LF2uk94 -aZa1lafZwzD7YFCbkQxJdHG3WytazgOdyyk9Fylpb5oClyPDeE8ql5IA7fzgtmfk -5aLwujl4PcQVKoWZSnzq0fCQ1POyWeH149KSLEzPnowSwR6NI995HOCQTQhy0v9j -ymFGW87apUwQtou8CiqjuurAbUJOEu9JDJXYMDY3ZJ2AG4kCPQQTAQoAJwUCVvx1 -NAIbAwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRAYdvQ24aSlnJ5o -D/9wzXbaX1pHyyUQitlxHpfqtZbok17UVYh1lXyWKPLa+EqMM1LoXf7Vv2/ZPj6a -suF7jY1z5QIKPD+TdRA5eB8Xdmm/A0dakQ3Wp+WzbhVNl0v3bRMUgJCbMJPkMTAP -bQIwcw1W6TbuXZyzbtTWMdFZ7d8Hk7hARHZTwBOcpkY+ADdgJbzwKHa0dWXLVzba -spQKy+3H+JL1a715r54lVKu56QI1JU5HpRPncEyriUaDwzfZTorjCK0joAamMGeo -3X6NMcLxuPULk4yfaaP57RB8StUpqMvMcKxyHpTcuAjm5usbuq2MOpG6M2CIVXE0 -IV6KWE2RSudNILMzyXjoHFrL7SaCRUaAMke0iIqGknSMybwcv8ZPxTY5QPHlpH/Z -70R0lrVZMYMXMlWLqGbcv4u9eXpTM589TVf4OTjlVrl50FbJq0SYzKAPl3/h67Al -tTepd9o76fsUbU5Fyu45nbEqwLtU6LQYXM7FWiNSnzMNJC7x+1VJLtd+rNdoURwM -kQDiNjSqjVZd0GdPwWrEWQdGGvkM54UDeB53FprxIFO3omM//DSSjbDeMWU/SEeo -k9RPVRce5i+DiiP7pmr+vgQNFOBhj4Ub6kVxNhzH2znuNu2KUP1xfnlAoFNTRD8J -Wj/McoV9/zk5zo8cEylzXmlebwlNbXGKOjXCLEoyTwy0drQqQ2hyaXN0aWFuIEdl -cmJyYW5kdCA8ZGVyY2hyaXNAc2hhMjAxNy5vcmc+iQJUBBMBCgA+AhsDBQsJCAcD -BRUKCQgLBRYCAwEAAh4BAheAFiEEaMnVlg6+laaswvyFGHb0NuGkpZwFAmRPaRoF -CRf4qqMACgkQGHb0NuGkpZyt6Q/+O7Qk45kGBYyky5VVNBG1z73Nofv/1vdU4t4L -5uyFdbDPTWC1VvJbBFpV5shKciPMj32nZLHvMBsxiXmYEBviZkJ14TG8/pezfr1s -aj3btGaqz7eV+neI7xr203Jz2qoBJ57ZnwoYFSf3srRW08JbuvFXyEbmERYbiFIH -LL4/C5ixw50ERmRaOxQfuNHIkAwdL5lRJteDGZB9l6G9do2Wc0dqOyL/ltTirVXA -1nGnbdaj896YjF9MYTto0q1W5N3XpKcyT1R5ra41lJSxWbjf6xLvyA7JB7CV5FuS -1WDlXGqCsNrlObIMwdcEITLRLYXAHKfivOh05N08RL4i71uqNWLITDpLOXI54TeA -rqSm37Q3O9LROM9FEDwdrZE1Wr58whysbhePrQZZVX63MG4FzhWP7SWlfh4FC0SB -+7vcwpZN7mpAKkBkRO+qoyQuweT310nQd3rPkXua+GtS4H4901y+tAFswI7ci5ux -xBU98Ns+AUuB3gSQQOh93812HkV5iL0XqLYHpBRpq6sf21Fu1VA6A1+1InAtd6Ar -+GJq+ekW1J5ni9xc9Hsx97J/01Bc2iTD3azh8e7QwFMziKZIFYsE/VE+XRCEgELq -Rxt4yDRvI4sPjV/ooIilpP9pnlyjqPMl9r11qwn+xaDi5X9umwQ0uCBUOOsfoNGv -DneNX4mJAlQEEwEKAD4CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AWIQRoydWW -Dr6VpqzC/IUYdvQ24aSlnAUCXrkvjAUJD7a60QAKCRAYdvQ24aSlnGS6EACMZMi6 -BLnqWPacOyujeE9bEkO3cszoj/QaHHavyZQt4GBl5FC7LErMqWVMPXH+YmcgXcY7 -9YlIWSbBEPUxAKYxRhHO9DI+2XEBr7CQbFZtK6wnHvYKmsz+Ai8uxvr5ouuZHhr4 -qr/K95VLFU3kCqFgauG+2dkZ0K1UYlaqL3ET3y6jXMOGSBdBTbh9xaeCZ6jw5NjX -cdgv4ZLQ5PeUeWJUVKyJNUvorRGhOcUwL52li0z2R4cXQVh3zyI22H/DDClvNGtm -nEzGfYEoACDcvOiCUQkQjccgq705ap89wGrKn09prg7z+KvGeFI7Xa4LCXu0d9Rl -nl4fPf/yfALg8bnuBydSo0NKcQTTPwJ/gBaq+a3dSathMexVxcR7VJJ664JqU61O -wfR8uaI6LL2403Jq3ioq/JV/n64nvMGrs5ngnqm4L21zQyaOP9FiytHlwekwgV1v -szUpsBTpwMO1N1o9y9nLr3j8T4qy1cmtx67NPWC5McvJyksPbCG6K/uqNB4muHyv -JyKyGpGhgI/oWqbUCUSBsNHO7ovN3WfslXlfD55oXNpU4FfxDhE64JWk+/jiKWvm -q59rLlbrIS9Svr371Yv6rPhW5r9wauZizw39HgnnMzzA0HKVtb2gXjrs0xBs/lFd -TBSl796rOqyP9Ni4RNtrPPtK6a1A1ZIe6W6LzIkCVAQTAQoAPgIbAwULCQgHAwUV -CgkICwUWAgMBAAIeAQIXgBYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJaP6RcBQkL -SQ0gAAoJEBh29DbhpKWcnH4P/Ajm0GHQ5OY9TLh8eVZAAbKRNYFpzoHzGOst2e0z -M7s/ZpkxXBjITBo8vWw/0f7v5Q28eSPD21vcoS3rfnIK95lon+AkCd7rpJpep1kM -s9ZtvwktNoPgSi6scAW2V9YBWu8znXtch1E7QUcAOVC9cYSPwiYbQW9aHb3Fw+Q7 -NIIf1Ww+FZb5HKKU14RoNmtwgz/D8FehzGonvMs98tYcMdV4k6icA/c8mX5eILLU -LtwE1WeD2tROfvE4TUTR/n1L7vEC9ZrazC+AXDHuL7UKuj+ZM9DmLqPlSW69TuKw -fr+EMSAS/cpYneNdjYcZ7EZDP0OEpYsx+nv+kuSjpBZsEd2lLt+7WJF9rAeL3z10 -uhqOGTKOmVL0mOBc7K8LNxhu3fPPWq3Rv6hJHyCurztgKACDekCbI2dTow60ukuy -WtmGqAnj6aW1CzpV70y/CpB9V/yNO0azpQRbiTht9PGnDFZzfzImk6I0PA69b0B5 -5TVtAGxWRpseukK7IbVqiet4w1rQynnTHwH/peTHC1uraV0mVqCwrv8jUsDk/qHV -oXkPF9HDpoafvc0x6lgO0AqLfQEBJG19RryPpDGjVf7knOodF0J3eIKANoyVieEr -tjWKxYoAPyFv0dgFQ0NXH1ivh6up6fsbPQWrtnmulKpsBRmFv2ZpYS66vqmnUS4V -uet4tCpDaHJpc3RpYW4gR2VyYnJhbmR0IDxkZXJjaHJpc3VrQGdtYWlsLmNvbT6J -AlQEEwEKAD4CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AWIQRoydWWDr6VpqzC -/IUYdvQ24aSlnAUCZE9pGgUJF/iqowAKCRAYdvQ24aSlnPpbD/4xpKpQkKFEGJzc -guvWZcUhK3LO/AgJncZHScrIDIr/ZqWA8BRZ/unaNby9MpdpVzSHNo6izaYx4p8g -TyHygg8IaVfwJvoSP+/sEKB/n4MxxARCmdGuiB2w08yThCJaFjclqSGAyUDG5Tv9 -eUL8+kXwJ17sflN3VolaD4MREUvgqgDcKcxEppbzW914hWahJJCRCWLKEwZ3bpHE -US8pH5fNBi3ttzGpLvdDaiw4n8fhWQkT5TUN4jOjM3UxKl4fwVVDpCsF9sthFMtf -OZVHKZqK471VwILCy/SCy4Gc2xuUCFq/w/VyhYHAxhE4F2VkOul/BLPw4SOv//JU -x/1ajxr4oxJW8HRvnTPPsGFmxlr9fDD6JycgjhqgaUJ+dx1zNNj0xwobz5yse3aD -0HsFUc4LyrOoTR4Gkxz/2RzB4lmd/gujSaNVYll0XIL5mix8qp2geQzJ3ByC7k4E -gWgxSUn6RkqRH5ZD2VvkoUmICUlhmR61SlPvAeq27OSDYjLjPehO8kxaBOThsM6u -cEc37nYGVFdgcCLZF8VQb2+J7I3CIXtiTHGdhTvDtGMbWGdPLCMYrJyvHaYbf6EG -Q/wSmPeDXTkdPk9CpoOZZJLC+kyBV2dgE6Ako7Y5DMDiywOqIufBry4PysqfdXhm -Mpi9roaa9gWwYDrmJym/GEGDj9/O04kCVAQTAQoAPgIbAwULCQgHAwUVCgkICwUW -AgMBAAIeAQIXgBYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJeuS+MBQkPtrrRAAoJ -EBh29DbhpKWcCqAQAM3SLFxgUFwonAFzRviG1tkYZ88pa6q3/cXhvoFcOVknk/05 -Qg3IqZvlkOX3RMRcogKRKYpIcbI/Nfn5FQXSMnFL8vAkND5Cx3DdgzuO8S+G/x+n -nr5SDH2KAJlfwX9kUAGKfECGWRpCKHKYyW/4eLN2G1sb/XBp+P0cTcDtjCrYyy2G -oNwMObvMdMdXqpX0NLUoNPJUUsldfCFHlM24wX7UhyUiyGmhZgymWgn0NgSIKT6L -4YXNtqwoSU1vWKfLKPQ+RL+4eD0UmZSmV33vISUljNZnJlF50Ib2g2N0BqrC2TSJ -LoDVxstCPC/TpSmYjJ1MN3iLMmG6CsKDPPn/G5uX+YXjycVhv5KOdERwMlT16KDr -DJlTifEYHQLNqd0n1a9xWTRQNaM1IhTJN1pEca60C1DgYaii/B3Rr2l6+vpXMLx1 -snh9ecpMHMSHNk62xdpyb7evAFiHmGye34cqjgKNhP4h1vh/HwW2yQAvaSn+N2mh -Zwxk+tA+VIsOCjNuJ6t0e62iQBnMirYrzIYkYLHdpje0bXQMZJ7cROaEdkJJwQgA -UlI/g7tsKo4ZjE4Lz/KBoUg79NKyi7SzjKl3pdmb+nzuu4q75EUQbVpvsY2loury -DxpUV6/XpqZrPvRcepB1V4iwRxBFmF6h57drUFa8BN2jjJT38LDBys3IUx9ZiQJU -BBMBCgA+AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEEaMnVlg6+laaswvyF -GHb0NuGkpZwFAlo/pFsFCQtJDSAACgkQGHb0NuGkpZzL2hAArK1zlBlFDCyaAKfD -nodm+5e8684DmDwvg5h20oa3MO/FjORvm2Gt3IkcAkhyqh70iGG+NiGG6nrY/LXZ -FRPDZ+0OrRLR5Fg9Ocny7lWezDUnJji3x//rp2bjaBpL6nnE9bG19ka44rrPQeKD -JsxRPQOwtcc6WVcBtWAHKO2VMKqqiiBzVZk0WVT6WVEkc/JFioxo93qdmx3AmD7e -EwiWWzcCQZxXDhky0atY635m4cSn/4+E8Eq869JwyQjFuBkIwSuUTbh+KS5+eCsv -qymKPzvyeVGD460w5TCNo2dMcWseiP2hVoCdZ/reOX5RlHnTHHehDus9r9sy+fNZ -dmtEq1Nf81m/Q3nKeRzBCSSjk2gUuA9Wy5XjRHkQRB9XDeMCKI5sJRCaXh0aq7/Y -OWX910J+fPJ0aT41+27edNARH59Sty9Zep+kEdHYKtqLiyUfwC/POoxvFxXWswKp -svLxnxjRZKaWM5Ft+dScuG2ss0CsAijTrHQt3VRyOGlI4+Mf3pNO66WukGiClSTf -fkSn0I2IGQX/lSSZtFhYLTa7k5iH2gjxkoWpFrLPvtmqcJIrYHCBsT4pqzFVs2AN -6UOER6Xamrb9Cxz5OgKmUV2B2gnzffl2wEXZPz1+PzXUCkUf/WHz5UYbpgoSNleB -QhrsyYMAiNXRoEpsRKSGYVDu6I+JAj0EEwEKACcFAlLE3F0CGwMFCQeGH4AFCwkI -BwMFFQoJCAsFFgIDAQACHgECF4AACgkQGHb0NuGkpZzo0g/8DlP+MwjBGeYoL+Ts -RSNcHo+YZ53MMFEWTXuclXMcYdH9MUaYtpbg5j86ZoAkwvYB+eyd9zsjZiB2oZbU -GctveGcy9vOo4iHGehwXLmcOXcIAGvnvXWMFUUG4qhkvUMCS51DAMTY18h8ptwtm -TJcWx8WsXgbSNif+K2EC5xIOHD9DPP/TQe3rqRBcJMVvToaz+jSLj69a1od6bmMc -X4I/WxvUP0zPypV64/UrBiE964bJJuTHMmt+GGikQxNtpBfbTaKlG0z87tplA87K -IrJxB2N1q62uXCZNXR396wk56t7Oa1kSVY31IlQAUJ6S0knDlDmT/OyVAHDub7f0 -6GRi9PzGIoFTrXUokbVLL+qP1eN+xBMU1FBpVFx1iO5lPbggfkznUuCnMkqKKysA -kVCb8ZQF/H02zJXwaQ0ziPXg1O7RJwjWSHQQjG5socQfg97uZ4+f7QeYHshUirJt -luDSeOGV/2U6fwYU3g276KEQqlYRJpIa3em4xZg7ObaubmQznXvTgL9zwl1z3PwK -7pwRO5y7zm8CDaj2nj4/9TowYRp3LEUR58OJCtffNoPhofBBIH7SHPCrB4lXju7y -0UEuDBoM0fHM6i6DtL0O/fZmVl8V1ZSPVWienjREEvXjdN2um8FIKrEVTmFaFa4f -o0SVIsqdiD/znpWujEzJpA2OUIW0KkNocmlzdGlhbiBHZXJicmFuZHQgPGdlcmJy -YUBnb3RhZHNsLmNvLnVrPokCVAQTAQoAPgIbAwULCQgHAwUVCgkICwUWAgMBAAIe -AQIXgBYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJkT2kaBQkX+KqjAAoJEBh29Dbh -pKWclmsP/iAyIzLkC2YZuQ+BoJGMC4gnUsBaI37PjBmedYdZy1PwVJeXUKGUsHuj -vhfqzW8ifgZ6osSgxD/q4P/wSEZQCjIYtdsvanmlUKpm3uFiXrvDjWRVOj4cFNcd -qLzyunMQfT2EI9yxc5Uk/fuE5BIH6d0apacj8jAfmkmLwlZgTGLc4p5WEfH4eM5z -x/ggZrywXBZ8sJUkSO7ocX+oHY6B/u0rYyR1GUnF46cUNiPHgliqc/VaP/m6nYXs -I0AyK9mPCL58W0SIJpti71Sj2LBs6+h5cTIFBdEy7Dgy/6Hd+s6le8Brj4c8YBUp -8B+ocg8cP6jaHE2bzts0OkJw3crDnoTV3VMUiXxAPu2qRmPHNTMmjxvuybGMsyzw -o84gtyGH/uMrwz/Cay1ML9VqxvZuYYoIS1PwTznFqG+4ygjVVqp76EavCww8jYQU -GJNzPnhbimuLuaSVojFTst9rZ1GcQHg6QHPbb9lZ4pmWf6s9rXNIwNguZlLTS8NA -fpi849NPxD7ExGFjafo0Q/K9wRgoYU4weRTvYOwn4mijNsgXgcJH1KtYFUK5qHcI -c3nJ83s6d1T2IvO8vE0QhoU9K15Unmb2g/xfCzP5ncNw8h7VKOXVLhVkZcpau8ij -glpthRqlrKzxY8l3lazFNSd3Q+bNFQ3ykQ1/JF+Oap1jhWvxUu/jiQJUBBMBCgA+ -AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEEaMnVlg6+laaswvyFGHb0NuGk -pZwFAl65L4wFCQ+2utEACgkQGHb0NuGkpZwsQQ//U4xyCKefIhJFfd8kC2E9OcMr -5hLL71UJDGfoaVD320VbF9NSPXI6XRBuoy7hI0+SfAge4uSjKnqnLqHv7Q9GdAyO -zDkh/F/s84Cx9QEnhA15z6Pu2X3tJdcvVH2WGJVNpGG/ZYcENFCXOSruDChEYWAJ -pNAkwMyaVErwsaGesCabs4Lu3Tc3on+M8dIScxDyUc4/SUcUs+Nnb75QViZ0Afn7 -UCvIjHEqBHpLdsrymJVU90ev0p78Xcc5DnXxw4ItvaWINVZfG2uR1kkccvsL+x/E -fXNksIJOR06Va6hvJS6/7CccEdxB7tN6dL2SWGmhvvXLnhZsnI7fMWtTFP4Ozjam -v7uHAwcGkmP5kZNhL3b3AGDLyzlzOODabZQp9m39NKBo8svPZyqMSiRf7ihDqnPv -PoUvbg2XXhSqXLOGCUesiguPpi9Rj/tkzMIMNHfcu4i30+5SWcn50bYTmSNd6/Z7 -sZ6YlqUcDe7nNx01D0T8RV7L0DKMkt2zpsxtE9IqK3XiKG5WHYeWaCPQiXSlJHF4 -QiYVt63es/NRGKh2VjtoCisEthdAyfnfOmnbx9gBz0e0jIxQOm6tiVdA40oMXTOQ -20Ug3q+vf5AkN00ZM2DE5hgBx7ZGIesL17iQzM6dfmldkD47t8Q3qWpwb5SZv3Fn -c/iFd2s26pm/eCgh6vKJAlQEEwEKAD4CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgEC -F4AWIQRoydWWDr6VpqzC/IUYdvQ24aSlnAUCWj+kWwUJC0kNIAAKCRAYdvQ24aSl -nN1SD/oCcS/V2B72y/hH6jtovTzfkvkcYACDuZyRVakiZj9yOpTKEQ5Ml/baEmG/ -mKQtFu8JIbFBVgnZ5IFmWdosAINf0Byf4Tm19a3pJhiktMQmuSvzgEDMBiO/3K2d -AA7QceB9LcVSc1v5p0GERwgfxEFw9gY6JzFRuP3G1AdgQ+uPzoM8ZGC4NqCocCAK -iRwFxuIcHWa14XhearzqST28lrsvzfmC6TnOdkDicduXxY4w3heE+ENTEpW7Oy4c -9jgXopBE40Ex2DpLltJL8okDeGkhvquiUSP2H2cS4ziSC1UZQdYyoCzHcDkV9tHv -NqnXIqsbj5aCfBfI0TV532DnOybsuO8rzgLU7Um8dyEBxTYrXvt4rK7D6EnvMyYP -Ha1R1cfe+Z+rWxWzsZW8zgb+hGs9z//NikgHiD/SteL6YLc+4Iu1/VO64V1hf6AS -nnQFzClJLhaqX0J8ap8HCmbeIYjNrLOjgMVSEH5IXNQELMWgC757wwVLIiY4Sgng -5p5zLo720yWZ+OzyC40Ing0jv2qdKOnWvh5QKbAs2yWj/iMmOzVPYPE3GamPIfwj -siA3HXp3Dvgrcaarj5hvaLCibw380bsn0q6XCEvfg2zzHUinGD88XotjDzPpXfjS -hPJd5cTwBDLhRQbL0SV44bwsP0/Y9WofqswYFi+Ky2lYFLbZTokCPQQTAQoAJwUC -UsTcRgIbAwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRAYdvQ24aSl -nA5SD/9LFZPUA8MDvnipQOqsl5VPmScLObTEpcM/UMtIG7kt34nGp97JpGn8bZX4 -4v+MZGy3xc6u68BxVpl/raWs9FqMJ1sgJJ0lKBRJVc94psFAicZwujDbcxthy/bN -6xoFm6DyAjaBjjnCnTe3KskCAaXksCCkEics+sc9Qjp/LaAPSkM8TAArG5g01oC2 -43DQ1lc31rWUozfqSgDSKLNhDOkjuWhUPFU0raBGGbhtI/NjJOfv0uUfna8kDS4l -F0xuKer2tsepOlcjj9xxUczW+naHYF1QXlR3ZinWfz+XNMTrouv0AUdk/71cxaP8 -r8n6B47ANHrCkL2rRewwl0ibVhoTUhu31hNvcO5VMq4HCehVVgCufJ/yxz3yLCug -FCSEDP4bMHnN8Y9oLLB8sAb+lhtAATZnpa6IYYa4/r/1MBAzXTe0fQGjXZVtzhAi -6D5pPucOd4HFkKxggTd84XqcfeKuKVX4Ggq/Ib+XswZ6eE2thAMiUDC7fBj92WZ1 -+3iADVOLdq4v3E4T7b5900G+xnU2bGTXpL26fEuO6MowEjBPAYGOlHn2GP6E7RCi -Tt16IPjIXJiiSolX4KFUqvJi3mXm9Aq7LHFwv8dts5LkZKeq2qqotZIKj7nnnLgJ -HWAcT8ERWpNeWd2sBMctj1LP2nRmw3hbsYQb6eQ3jcBS3SI5JLQZZGVyY2hyaXMg -PG1lQGRlcmNocmlzLmV1PokCVAQTAQgAPgIbAwULCQgHAgYVCgkICwIEFgIDAQIe -AQIXgBYhBGjJ1ZYOvpWmrML8hRh29DbhpKWcBQJkT2kaBQkX+KqjAAoJEBh29Dbh -pKWcrYcQAMbRQ0swmmoOjjPapSX8PbzdTEgylokPMikoYCuah8nCZCmsl2fme0Vp -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 -ZgGABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAfx4ZSEjTx9R14D/9mLZWb -59GyzS7gKSS8V47vfF8TjzB7Okk3ELGg/yg29ODYrOxN+JmSbLojq4/UX5EPIVDt -mugAFHKrlEtsGg42b43ItCZwbh3CtwMvOebp8fyDd4MP/hifrtdM1/1g85I2p3bw -Nu/UDEBHBSOkWLpR8oZYkrKG8w4JhO+cn8L2uB/QZ7J7z9tsQ4XtcAetUxkJ0upJ -ZlbPxAY7Tr5x8PDoxB5pCFeyWT3Hl5Vh4L1fH/RsXqWMe/Vqya1jRRJcXp8qvwxK -thi16IaSkOwHtE+jo4+n5crTXgy/RuYbiWDRfPPaqgmAwJlrjwEbqJ3nXFHJuAFk -W5PTgFXUxwk0uSLJ89fFyPcSWnkFJcqjFfEV9Oyqk1tE1c2C2hMGVbmfS1GopxU9 -ukmboDjz+CdSxePDeQ8hXmcXswHaTyL9u41SNDfcgkKv+bUYoGXGBLdbp+Eg6arN -IWsFI/htf38Ux6sBLpcL11FQMBeSmTFUc5ZBe4hrfnDpwQJ39L2LbYPCSZliufTR -l93XDZfIDGU8QY60bpjLUZfK5LYVVGA3H2HEuILZbkaeFYo95UeiYroJ2hxtWMwE -cP/dsVaCA1hS0EM1iByL5FZiI/4RchyQdBF4ARDPWEWjA6GoHl33L9EYQmlH26oD -PIKYHvJMCwnCPE60v04/uDO/faiVkwgfMZW69IkCQQQTAQIAKwIbIwUJCWYBgAYL -CQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAlHNcYwCGQEACgkQH8eGUhI08fXpRQ// -X27ISR7Shja4h6TJt3vY44qoLe+0rz0NFCKXW8mVe9rmHbimn6VImBpThh94rk4Z -zWmgl7E9Mn/7H1UTkP6FrUEJfqMtAMfh4r7tBSlM1OtCfpaKl8idjVGm/JEJvOVZ -tDemn/Em2b9XWIvI+pdZq23jgV39JZAlzGmRbq+owKOeE/CO+TFK6F6Hwn8K+e8M -toCHQ8kJSsFjdNzokQ2flLFtmsLAoRPVrqZF2WH80BXcQtpZOhkgh6IL+jhpQzk6 -HIvn7Jw+Sc9NrYjYRE6OEFtbBqL2hCwXmS8PLX9B25o+NfeLEsKsftxSMCRUrdK3 -ebOkdxYAReUb+yR2pJRRFwCYhHBkB8kghCH2oS1WUFZysWX3MvyYPKDztQZFo2v6 -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 -G3tTVIQy/V8s1vlqZeElBnFFaP6HEU3VyTrKCSIoUooCnqNfvm39T+p8FXG2U2QZ -c4Iob9EuaOFhxiGyP67MleiNIj+3bNaJAhwEEAEIAAYFAlccqW0ACgkQH8eGUhI0 -8fXo2A/8DHkLsrxgOiglyt+OGtg39F316Cykys5bHRCcPFqgOOciY2UpspiO8djt -/nobS03Rlpu6pUZwsJop8sswTnEXZyNrKurEm91NzuGBbVP9jfC3H4ynV9WOWkYE -nopYIBadsTrpnNeGuekTUsPjAZG4S3DdbOA2CycPxg36Oo7YzwewR50hR9D+bqBT -02WMPe4l+2jHEz8iGyR80PVET08evjhXZcw8b8sG3tLCQN0eXM+oBO+sYGcFiwBm -2+2GOHFTw2al28wj/bTQJyeAMQ1fvdvk8dgOZ/4aEcedpsBI3WYAH9UWJuW1BlNA -/xSQ1feu68DtkG9YFwR0bsLE1uac5bZs8252unpwuqzLGNMOT+1jO2jj+AvbY4Sz -ZWnBqDoM4TOEtASwzom5pp5g/Y+jjFz4UPoGbsUVWrosIzUPfByhCDSML4kZexco -/o4nIkP8i9XRF2co0vSn7uk+EGUKsVinVPxdMNA4uWbUCcA9hmJJsSpsNeb/+wIf -o2wkcwkcW971RnJOOUIjvmz8kDmp/NGY73IyYwEKFikznwKRqIRh3AIy9K5qqt0T -28Ure18wEenGLEw8s7kfDimeYHl5VIgLc8qlEVjgrH4cb1zrvoVTUNud92nJGipE -FNxYW010aZ0b2I5hvWdtgE9orBkdKliFQ05d5xO97IPNMXpIxJ6JAhwEEgEIAAYF -Alccq1sACgkQoI8kPq0xkeIdRw//Wttq/Oebykswa0U3zE3Wqed9gE7tCoZeNwc/ -vV2u8zWRQPby8xnVV9Ttegt427PCdk8q2ScKhmHlCnYSExeRY2yhrYZLM14W+F6i -MtcQz4VQc2ZEqZpNS8f6prF9Ruko5NIjlbMjyVLdzN0/R9vx0sAgQEIYwSAxnsEs -kVLuQbpAkoevM277yZZ41W1k77u48PX38IHRWTkn+63WKFWDnDe3ANRWKqXYSibS -dRQFrv2TO7h4xRyN+UcLkqlTFpTZLvUEOnNeFjQySiRShCnWlg/dRluDbJJbjR+u -+vCW70dyiqhgjgIRrfB7Bu63tqCOKTvHUmXf0BYlaXixUmi6iK7WAoH9otTyYYpY -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 -9UASR9IP+EVCvBzwnKogj0tuItN0ANsQ6hrwjTB0+qSOJHeiNEyir29vF2ff0XBO -BB+azFyUkaCf+SCXpIpYHQ7bn5SFDcdngtHD1xohkOLvsG4lBv6W5b8Z9j/7SRYz -j35cpBv7L16OrG1q7qJ6tRaOXhV6C9U1ivQQAToJEJNN9vbkWjBqFNce09SP/ihz -WaVcaT1YzR5G3e48MXcPgreMqKurrlekC/g9wG1S96WCWmncvX87f8hkHpFSClkS -pQr/aPcOqT2mw+Pmipk3pTEkIMUZPHf4gnYgldgz1JR6TzZJgmZw/Q5oAz6gGd43 -hO46m/HoPuK6HOfnn3M0sE9EzGsejQdZOl5fw9ynG6Av7fAxsOlrVN4DQ0Q2mON6 -SIqCDnRYa2znBWj/joJewFgZHF0MlSszvccct8nnJr9yYM7i57SxW2BjWqoY+S6h -zmSBpdxmquLQUe8+jMgnS8OIJOEWcrEMjKNb3T3v3r81Zu48QbrkhMQ0iC3EXWHs -/MBxgI6ddNm9/VGhxgtp04/U8/nx6nRajizfAoKobbOl1RLQnSpWnYfgCrC2/VyF -pUVO+Yc8UW5Ic3kw+v8wsKkPYFBXtC5BbGV4YW5kZXIgVm90dGVsZXIgPGFsZXhA -YWxleGFuZGVydm90dGVsZXIuZGU+iQI9BBMBCgAnBQJUpcmfAhsDBQkHhh+ABQsJ -CAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEBoPJ987fXhp+zYQAJZPdxlm/d+dgvk6 -RtxSBMy7yv1ObTa3JqOpVysOUUMzQVKhvexbFJL6dHQgZ05oDU0Nkp1RTFZs7juG -nDbufY1gkY7EiNoqQ8885oc7K8xi3umZlMu+vIlsa9jnv0fBcu1ORoPnVyex9HuP -Zp42g7c5tSbogQ1e24ah7eVAf0viw+b2DDX47zSDom5DfTtI1TpC/1MxKradRHNV -8KLKug2syDWoGHFGnSG+nU3xXw2w1c1dZex7V12F0LQ7jOO2AiOkYElM1Lz8zUVP -L3rp2HUGvwkY0QJXVSB74Z0RfJKSUyXvWx0e3HUHwKrm2pkMPZG5KAsGLV26IGN4 -bDf7BJQZxJMu81KIGfFOSDzghG+d1Tb23uwj8bNwgjH++SKSWdbUU4TG/TxSImwL -JUlZ+NhItvDv6pLU8O0IZobnQOEfCK7Y1u5K8NIXb30W7zrC9CuELdeXN0t6U6Md -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 -5CnxR9FGRCl0dg63tuEWR4dOuTL2a3Clteu0jmQiRxNsy/is2dQSup1Na/NtG5OS -NtiXxdC6smbIx7DvYoltxj4EB8PviQ8qyHN+HIUZ5yh7r0wdV8blQCsaMUwpoDML -olws41rldeWKDJBF3gJYojExyMUTuLRzb8vonEK2kzBsXBOXFv23jK2MjbQiOgm6 -g5ZWXI+yg5Tr7IMDkNWGxTUnCBqwH+dk3UW3XQr58//oKqxWifLIVRlLHZt6cy/2 -hyo6AsB39V272CuAJQYzSn/wd8fc0csAyv4BEAABAQAAAAAAAAAAAAAAAP/Y/+AA -EEpGSUYAAQEAAAEAAQAA/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0a -Hx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwY -DQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy -MjIyMjIyMjIy/8AAEQgAhwCHAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAA -AAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNR -YQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZH -SElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Sl -pqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX2 -9/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQE -AwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoW -JDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2 -d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJ -ytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A4lTz1p4O -arhgakDYpEFgNTwarhvepFakNE4apAarBqzNU16KxBjj+eb07D60DNxpo413OwUD -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 -=uPzA ------END PGP PUBLIC KEY BLOCK----- diff --git a/data/backup/keys/aurto.key.vault b/data/backup/keys/aurto.key.vault new file mode 100644 index 0000000..8cf9e4d --- /dev/null +++ b/data/backup/keys/aurto.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABg2xbZgDvKN7zvwFWAanfqHpsVJxRzvvPZBN7OzYBYlpjMbr7NCYngOVzMeHrBWoD56QASpBpCXib7GoZhjRbrkA3XLg-xHyC2W0UQrdIm6w3o5RpMji5ll5BdDJJYpCsf_l_lgklBM4k5fb_4X4zjK77J-15B_DdPGzQbAZxw1LT0OV3LrC55MNv_UeVwmDGg07Xy38-GPdFEAzH-lrzfsP7-PBsjaRmdFT_iShrsQgpcecKSBG_zqyxbbZKxG3cRJL791RYVNwGXFWVTZTs0UjbAFd5Q2pHjy10cdio_EnhfCcP2b6pwMjgihvYGwS3j_s90bXf9ko1njxpPXvxauSN6biURa7j7k3EABhywdhV_kcZoWbIK7tLY7ojYi1Al2xx1e-L9jvS66QLnbMrNW_xqVHPple98hYcTawf3yI2n4KSKcsDr71Iu3cOrdJOQkG6QiE2CjTm0J2gySoRvtoqTJjsBPud6LSHrDcbHKenMr9aCSM5MYm_aadyeHh0bphgU5F5ye8UVuAmPmFa12WChxLTWDj7zhgeTJpvbfQUALry8nD6tDOWMOqkXOhJkGV48xBoCKLrtxVgpnKxNu7aTDpJAwxEY9uFyymmD4lXQquQC8eElEl-n2Xz2Z-9fK3uJ \ No newline at end of file diff --git a/data/backup/keys/aurto.pub b/data/backup/keys/aurto.pub new file mode 100644 index 0000000..d590079 --- /dev/null +++ b/data/backup/keys/aurto.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEqhj3JQ+82FCLVg4a+cRU4FRudnifcwrWgZnvrQGkG diff --git a/data/backup/keys/gce.bind01.key.vault b/data/backup/keys/gce.bind01.key.vault new file mode 100644 index 0000000..e08644e --- /dev/null +++ b/data/backup/keys/gce.bind01.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWfFm8-vDqO9So0Ru3QCA_kWvO2bbIcYtnq3VnJfq0QxPKW4TTuUbS8gloq19TbQRTZeZ0-22H-CdIeiXv_SGtKzK7ijbV3pUfNppy5I9c1Kcn--6YnLEBRx9DxhOh3n3i3gxyF8dA9izjp_-XS3XjjPcdw6WAp1z55a6p6ggTDEyXn1MGEUl8405ri8kpe9AtPIBZV7GND8GmH8jG8jrMJGTta_TJlrW_FcsYqcEKf5f1N1ShOCWCxUijlTwLVZzufZCR3-IJpcdKR8L2ifTggT04meHRzd_4HkC3X-3wdfqnoNCo7ln63SeerseN0Gnz_Psk0L9CnwQwWlfTbCMVdn2oiRUc8wLZ06R-GVhdIs9C4jGnQJZeStOFYYtHWgqZcToNx_Bq5zIK4aMa5vZ8cmKgCDWBMfjcaWJ8SKK8_zRZwRbsPOzuzSfvGoAmcnhQbnDmmhtSaka4POk-aH-8ZV_1dNq0JK5g7xcC6vUb1GSvfFPqXhx9ypo48NueHC9seJt7Pp05hP91z8yBT9-CHtMH91G4iBkyJf-DfG65YfDFVmXTU4ikV5UV6leXFkzmIzGshKAwuDuRVWA5tXEHAyoluTaX2nZXziz_wNszj2Fc= \ No newline at end of file diff --git a/data/backup/keys/gce.bind01.pub b/data/backup/keys/gce.bind01.pub new file mode 100644 index 0000000..9db75f4 --- /dev/null +++ b/data/backup/keys/gce.bind01.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF4wrVPICvYitHaR0Qp6K8LzlPaHothuw0BI3XGiyAmN diff --git a/data/backup/keys/home.hass.key.vault b/data/backup/keys/home.hass.key.vault new file mode 100644 index 0000000..44f9b82 --- /dev/null +++ b/data/backup/keys/home.hass.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABhflKcIRszHtJHuBcgaWh7divgjgw72cKDiP7PPk7CQ9xpdSDw3phE7tpVBnaYSjYFcn0lxH5IN7YfgsgQnRFrH4N25-awLwxp6kVsL00Si9F4o8GUBvzobQGJtzEh0nuQ3zmGGfQSLZGKiXkFHLPmnc67Mqtz7zK7Qc5Lp0qqhMJ-2PLEwl5F6WxQU8TcNTlHDgIb23yS2GWfT3DrUvZjgOKkDvS--Huphyklksn3SR3cxHy1wSmlzJxV31t4Rh7YQyj1DcuBy2TIzLAhebtPJbiUZTFsFXDJULiHl1zi5X2jVIc17rpKW_9JMTeBEDZbebyqpOp3bo9zNv4RcC_XEIW7i2hCXNT8RksW5x45-E01jKQpiKgIcJoImcDQAanNh6_xEWEPWiJFVDulkMiJob5EvZjl1j79jOciahq8ycuePWyFAAtDZgpLm9u0JlzOLFL4NbvL8-MypBLpysXTohqDa3SYKlc2-UvsUJD8bagEYsy0Ay_nGQo961AqlWF7vPk2SdYXUjN657PxSbnczOuKv63BmFWEF9Bu8OFOzxIRs1ds7jvK3KChikO91VJMQxsZrSynFBwDm5zpYRsk-k1D2blf2g1yaThd2fijYCe1Lico_nTlyf-dpSrN5szlKW5V \ No newline at end of file diff --git a/data/backup/keys/home.hass.pub b/data/backup/keys/home.hass.pub new file mode 100644 index 0000000..25e2a1b --- /dev/null +++ b/data/backup/keys/home.hass.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKYyrgpO2tCRTP+eEFD127OlRIATw7BxaSgYMnyYAbMS diff --git a/data/backup/keys/home.kodi-wohnzimmer.key.vault b/data/backup/keys/home.kodi-wohnzimmer.key.vault new file mode 100644 index 0000000..1904a4f --- /dev/null +++ b/data/backup/keys/home.kodi-wohnzimmer.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWfJTYZVIlllCPefCyzG16p3-JLyr1vST3xWvkc5rB9jvCNw-7LwP7CSh62YTchvyJBk5NfrDCnZnYhW44rn4I2YWr-LfHkVNIsq_b1Kv7rL_xvgcHt1iww_0Fa0nUmK5gGbbedz0uJtTO_9IS8P7KJUWziW3Ugsajt0NKIAB__-M7d461E6coLKmbkD9EnTGkXGp14U1vA0oyR8xsfHasWtQ8ntNu3it4_SFmu_xMbeEXOV1RZACKkCr-nS7ctjQ4LNgIIdfLWs-KKM1cmCjwDQqPWRIoPD5YJJ8EtBxvUyNc0KT8ySMS7m2TNfw158U2QdO4KQUdbuwPTpDWuhOMRp5nzliEkiw2QHhKbZGbHrliw1AD9naQWUh-R1XtMx3gKRp-vser4RFQk83bhcL63j7dSjzKHpANa3HB0f2GEoek9VOwZIHpXWu1OkJNMVk5a_F8f75Iggmj5xiz_O_nRRhYRA3MzXgfV_QKTvPHEKFvkoh_-esb33qgiJ8tL-5uJ2ADWFbBqy-KoUJDKFeoyDNlJKwFpgFq0Kbd5eJbbVp95D9LCCkdiwQ34_SopMqbVBfauHdloygsgs35ifAvEW1VDyHtz-cpmRDYc0jV-iyI= \ No newline at end of file diff --git a/data/backup/keys/home.kodi-wohnzimmer.pub b/data/backup/keys/home.kodi-wohnzimmer.pub new file mode 100644 index 0000000..b5ff2e9 --- /dev/null +++ b/data/backup/keys/home.kodi-wohnzimmer.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE/WEgalbJUsr2q3DurqR7NkY9RXnuMs7BmmBgVmW3tj diff --git a/data/backup/keys/home.nas.key.vault b/data/backup/keys/home.nas.key.vault new file mode 100644 index 0000000..84683c7 --- /dev/null +++ b/data/backup/keys/home.nas.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABh27wEndfbW4cyz1fgM3e87zCqStsK8upwR56flNhpwAMJQJtjflH76nvw63cZYGWjJaOY29jO4y8DONjRoe3OQxH1bt9qgBgSfdW4k1A2axKevj67wphrb5bipJCg_EKFZumRONCSaaFDFlRp8DJlwj4LWxHONENx6KEYtMMZyGRUnh853kYDxA9E2gq7ScXZMAws002iD1sBONCsXOLEcpX8-Yt1f9qDzhfSGh4z7JdBa_xfmjKYAMBl62pPeZoI2c8LnogtjPEdblPJmjBuIVhGb_wP6nF4jdEim57v0lGezPblddTFvsgNcZO9AWIeM4ivtVd0AZaZXHXxSh7aGTKOKn6BiZtvah5Dhc61GL-Iga3sXISuG7EALWVODtwfUBwD-s8gAXfT0_LYh2tkrkPVm39Uwx8hM1WZUyDvQ3ox3a5RxQgenz4YskdNA-2Yw53zxdaCp_sORJJPpsFntoPXtw0aHXGVTdluRDtBJCqDPUVvO69J3jDMDnNXb3W9BrKK1CABbZkd5hLQH9jH6ZY8SOZzr5-RpEPbR4akIKPJAL0lcCFRwS0TgCfTAKDBbz9y19xkzIAM4cjraMlUDS69zegryOzG9u1-Cjj82kNKT95iA70Hm63idJWR0naCRUCu \ No newline at end of file diff --git a/data/backup/keys/home.nas.pub b/data/backup/keys/home.nas.pub new file mode 100644 index 0000000..b556e97 --- /dev/null +++ b/data/backup/keys/home.nas.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBf2z34n5oovv1PjJrDTNQyrI78oEmazeshLKTwheP4x diff --git a/data/backup/keys/home.octoprint-vielschichtigkeit.key.vault b/data/backup/keys/home.octoprint-vielschichtigkeit.key.vault new file mode 100644 index 0000000..39fa436 --- /dev/null +++ b/data/backup/keys/home.octoprint-vielschichtigkeit.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWgqqfc6tymm4tFnl4qy6rodRU7ZCMsPXw-bLOBoPdxxPdQEVVvWWK6WhqidBtGRGEvyp32W3rltA_lTZFhSEy5y-xOHK7waviQi2wahK4B3zBYPc-nKOREzbSKqOaaNlpOsReAfyZgizeKb_XGump--sOwLn120k9ImMGmVhhQSx0BdJpi2Z23aqV6TvRgDM2utCR2aRFXyFbFG_TR8exI9tQLg80qaotXv9O5I2pnIyTyanXEm4pZBmN88kGSW-ZPTVO2SpWjfGO46XtPirsFAp7pya-0O8EeXApEGjtQiVUw_JrlQmMTJ14j8AV4m_lNsiu_6bKPawaNJCcSfOF9C_49LMj-0mupyss2Py3qtF-KTxU0TvODg2DnLIMlcxtv_zheYFeY90nPBpQ3Dh8L2qAOd_eDu4gFvQLQvWQyB6aAlChC9ufTrhDFNyNI3Am5oWh32iFcv8Ie7UNtIB0Jc2bHfApJl8LJhizpObLgHtuxK127m2D5jEXRYwjLYDGGDwyL-qfKpxQoKaBPBP8JNxT0LbtsecveAyLIknyqtX3fxvZpon1DbJ0UTwvlUeoRcmOThmtx_hlGS7As12Ds60EnDbuhMddFGnZyo4GObqA= \ No newline at end of file diff --git a/data/backup/keys/home.octoprint-vielschichtigkeit.pub b/data/backup/keys/home.octoprint-vielschichtigkeit.pub new file mode 100644 index 0000000..32866d0 --- /dev/null +++ b/data/backup/keys/home.octoprint-vielschichtigkeit.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII6c5QTi50obr8Eh3pCCy+y8E4HXb/5YwRIVD1WZneO9 diff --git a/data/backup/keys/home.paperless.key.vault b/data/backup/keys/home.paperless.key.vault new file mode 100644 index 0000000..364fa26 --- /dev/null +++ b/data/backup/keys/home.paperless.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABgqlxI4OjgrQfSKqCqA8vSbhNpdPwt56Akk73WMcqTs0nf9tiQsGoneptdO-1x5X_-yEI_YE_SywHo4yZ0ABQjUdNpLDojjDqkT2wZPDeSXgoIQFpnf_JZ84aw89_srH6CBEBGDU6bjljiAarrkAyBWaW21DFSuH1SSwuNiy3Rr1GP6HwTgqMVtNc-W4x6pehViOpkiyvvffgYGTY826YXmV4dCapr3Z8l4acOmSucnnc5YxKXSHl5wk9vTDpyhcT6qQJ7d-_cRCDrZtkPYNWNJRjAVmshIg_QRXwgQU_YPqZRrcQIUGMnaIBNjv0LKcSDPDAD2Rv8GHMLF1Vt6brJ_p3ihY_8KrP6QvwKyvSX1CDVxhwYq9WfCqvlqQOIkVLnn_vS-FzqU98cbef-rZsXLVRe7ODrU-Fg5tOVmKp761VGQSF1l4FIZnkQwF5uj-AmJXgaTfkcvoYhWtFEadnrKYmV92GbymiwPB6EG9SRMgcgpMAYCl9If7oEMjuYBs6bfTq0dfA39xWRJQx9zhAMTAAWHewYwEzME5PuTaQCDSRd2qIYik-DemhRp3suuphvjeuJTL5qyHXIH03yCTRxYf28cw0PVC2B696mI-z0I_-FT5Tc9l4pbh3RZlQ7Z8dNewJX \ No newline at end of file diff --git a/data/backup/keys/home.paperless.pub b/data/backup/keys/home.paperless.pub new file mode 100644 index 0000000..db4a767 --- /dev/null +++ b/data/backup/keys/home.paperless.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIbL8JFM5vHyxSf4Ym57K+ssOi7gbk7Ma/+pOoT+1qGy diff --git a/data/backup/keys/htz-cloud.influxdb.key.vault b/data/backup/keys/htz-cloud.influxdb.key.vault new file mode 100644 index 0000000..296f65c --- /dev/null +++ b/data/backup/keys/htz-cloud.influxdb.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABgoBM4n7eEwMxfav4200d5LoGyLsM67Ps9CCPBgjZjdsOpyQulbp2l4LIhWj1kljgrXZ_LnOaRUf3S8q7-drv3yEfG1d-cyK8vP7r8wkTcawaazM5XdhR8VkgxCyBCuOZmM1vvAmOwIMi1JiQcgiJ4G32ThS085onN3T9HvEu2a9sWYuOlk-yVUBpelqP97vbO6r2n3hn-62AC7Ww-Q_EQ_kcdDdJLOawNe1anJOsOeLb1XOlMIJWI74LZXfszsRi9LmxUpzaB4Gd_nzDLO1AZHD_GOf9UOeeab8PujwhQ4UhbEHCdB-uVH88LGCw25-6eiv0yA_kRulj7InA9sKRyBZ1okSF4Xhl-htez6XwBD6BuA_ly6ulSxWuoOV_qsCNiXhJYGTuKPJS0-wpLyeLb_PV1tlYOKZv3VK5a_EpCRa4fCdX7oj9pcA8ZQkQeFAx0P4b3oYkz8YkDiBINFdOLE177lC6Kuk33sLfsZBuoR7MSjHUtZHPOXUHu8pV0o0_YxxF5fBs6hyReXvCbZB18NikeH4Ki-RR5IE4ofTngf6dIQhCxp9u-cNs-mNP0GRKiYIBUInr9Udpr-ymXRq-7OvyTM92950ePm-qoqjbpVFA8HN057WfkW6N6DASRRa2HjqQJ \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.influxdb.pub b/data/backup/keys/htz-cloud.influxdb.pub new file mode 100644 index 0000000..efa9e6d --- /dev/null +++ b/data/backup/keys/htz-cloud.influxdb.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpAUytQ0ncucltODEr3MgcKF5U/6TS4zZG1OYJDIEQp diff --git a/data/backup/keys/htz-cloud.luther.key.vault b/data/backup/keys/htz-cloud.luther.key.vault new file mode 100644 index 0000000..13c5671 --- /dev/null +++ b/data/backup/keys/htz-cloud.luther.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWgO_QYaKznjoFXGPw4PTjv92niiHE_61_Tp7dOnKiqWHJc06MOxmFdZaf9i8wLH1H0R8MNgt5gGuGDk6frQh1cz_EMyQh9Vo9iBbHI6q5OXYHmTX3mEeeoudhGUNaXwaea0SaErcql_jJDRGrbvxGJH2-wmiJaeZ5oyIkedp6F7_Y1SuRw-c2YG8hEBtjALlLhz3bL25_2V8hzrKZ1OtK1TyoWvdbA7yo2PdE1RfxfzJG5MMCNBTb9ngVvCXz6bZuq6EQidBONOvR7mWncMKeuB_pd87DvxIvahhhI4roHp8H7rbH_6eqRQLKiNBvmJxmqtNlb_wJPFtzTGZUNNOzZLuddJsBZggx6R3CsDigQVK6MKBi6qGlZTsn3nBNhEtX9jmRWU2Xx9IaVNuc9a3qlkMN2qTXg4B6ijMYa6emIva5Y-2ByK4dBwZd9nQSqk_QNcaLA_EVGBah1yIXCTRWqF5A3VrIlPnpVxTZZoLqnyjtWRh23L0-K47V3NuvXS7R1sZGGAapadVenRUH-iRs8493v07aJlH2DHNSuINEw15sPWALWpOiGJ6UdVsZ5FYtXcCTBX87PfmCp6OKChmkRqVXS_j3LTH48HzknZvYP-YY= \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.luther.pub b/data/backup/keys/htz-cloud.luther.pub new file mode 100644 index 0000000..bd609da --- /dev/null +++ b/data/backup/keys/htz-cloud.luther.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO6bxLAHdTe9gQIwFhFWRBKq9BSMeds3lyDK9iud4kpL diff --git a/data/backup/keys/htz-cloud.miniserver.key.vault b/data/backup/keys/htz-cloud.miniserver.key.vault new file mode 100644 index 0000000..a7468c7 --- /dev/null +++ b/data/backup/keys/htz-cloud.miniserver.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABgoVlzLgIb2UCbDSztRNaLNDY5AaF3BlosclzZvKQPDvgRLobDusDPGCuxreeZ19PB1vOjyT0unuALoM-3qufCutiv9QxmeDwzKy6D9RFn_PVfL2WhNGOG_oO8W_2Itx8Nza-8ta-eQfnR-1FJnti3gXDh60usWwE9rI3C8BMBDiaGBWNqhi_P2r7YoWBsJ06jE-qr7J51ddO1W2VaP_95ebZu9GmAljQkzUy4EdgH5f0xQBgjHFzA5H_OAUMZ-ey3MFXPAXMSFKomIBy4eSks0ghHS5KcJYD3UTjXEdag022CXfNqQDZL99yZm7re4tvQ1nsaiD8rRPciNZHxb2VYEj-OPHEjJnJ4dv_uqba8IPd8Stc5n3A-vklMsZwQWwaAvu12T6m61HbJeCc7WPst8UTJbJJPMhX1bhnvo8qtmB0kRdQ7GhVno0OZRFbHAEgXj8ifXdEEwWuGmw_191LA_UGKjcUau27CxyfY9CnJoah0DSWoZ8_M6haQB4QisiPdDXUilb1Jva3b13U7wubMCSqdZCc5ySnI5womn-GuXWCOQlfwR3sKop5NPs8oeOcN2k_XZUvHm1udcntEMPqEbEBtlP21nUkxZ2nUl4KCpbQQ6iM= \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.miniserver.pub b/data/backup/keys/htz-cloud.miniserver.pub new file mode 100644 index 0000000..35357fd --- /dev/null +++ b/data/backup/keys/htz-cloud.miniserver.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBkINf6i/nlscFFcvyZUrvYlpKZRMo6Si1LbNlClWksA diff --git a/data/backup/keys/htz-cloud.pirmasens.key.vault b/data/backup/keys/htz-cloud.pirmasens.key.vault new file mode 100644 index 0000000..0990166 --- /dev/null +++ b/data/backup/keys/htz-cloud.pirmasens.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWgKPszezQgjWLwmoRjEF1k_AedpCj3sYAIrzKDfdSEVuYjj_8tbzflMRuCax9FPCwffQdy2Y-79SuIoHgjVDfrV3jRPTegFhSWudIcbSMrlc-3Ypob_BD2pGyz8XbdYXdaPTz8R7wTLpYgqxWPkBAnHj_AsJeXO3qtbFkuMwqiUST9fFDbNfmUxunbmjk-WYYr6pBNy91dydWVR7Th_XxJNPtTucK1qRJgzaA5aA1UsiMXoc07jkDMVJAvs7Qy1ynofz0hh8DEb8SHo2htPQyKEWljU6vdYQ4PgYIWdP746m4fuDvTVKU2EkMmMxTtBF-lSHpg_AxVt3krB3Geo9MHTzodBmKkwHRRD49ZjY6E1QXQqjsrJ9T8eudokyaLuOZz9AwzgBZfWKNMh1D8BqaJVOoGgK0S1nLvRiONqX0sLq6XmQqEHalR1puMwugOBDNmrt2dBH283Jr9p_zbxe8fnNK0hgOeVJCe9tAr68Cn_dcWJgLsL-KUnhORXLjZXP44k8-k8ovj15cbW8fUobf8VyK6XqyUt119hXMCrjDed0RbjRBYjwm0A9Zv_DjsH6dFVKfyC1mu1nWTeOK0km3H6CnzWEPPhD3bA8YvXAoQfFY= \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.pirmasens.pub b/data/backup/keys/htz-cloud.pirmasens.pub new file mode 100644 index 0000000..7cbe538 --- /dev/null +++ b/data/backup/keys/htz-cloud.pirmasens.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIILD1lwc1lNzVWQDxBxs9//5OUioFGOA7qGZjDykSIRa diff --git a/data/backup/keys/htz-cloud.pleroma.key.vault b/data/backup/keys/htz-cloud.pleroma.key.vault new file mode 100644 index 0000000..06e6894 --- /dev/null +++ b/data/backup/keys/htz-cloud.pleroma.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABgMXllIGiB__clFctfOC6T4qRhFDrh_WJZU745-DZef2UpKCy0gz_2FlDAIqrNceL-Ahz1AXZrsdHUKPYAZ5AW4ne0b0G6uHQENYB0xv-ZqA3MZS26gzvNM7ejhyTCM1zO1j6ePgIxfZlaalNcuLIRAphuhu7KkJA8sGaoUMjdTqVWJUjj4Le8KHcS-s7PhB1XjkyHYxb0cKFgPxs1CgHWVjfCviVnl3yFAF1aLvYsbNcpzM_RGGIIA9YsO3yPQ8Mfk4B3truuNg1mdNaunpnhoTImF2cSNoI64f2mVaSNxxRXm1NG2qUJkZN8ZQlW8k7A1w_zUwHw9-JaimZejfPWrhew7krAbPQWEqOz7Km0RkQdbzFzxWECDIOQ_Z87n_yEFLSN3sAHA0eQ-a6oqj5Ybga5p9eeNNdOYAZyU_6KfSl9U6XSKT16brAXnsZevWQHk06ObdOPhJW5SMIQwk0TZXUOMZ11T0o0-2IMGBngOjoOxqt7gjZoiLFt4c8BkFcDkpTj25asyG2iF-2jWZ1cY91F5nDkIE3CSQzD7DYANyTI7ik9qACiY25bBYOwo9HS9TEcE-wDS2_jKolFFmEx5EFdxzIpSXdWB7EznbizgqAtu2eYubASKlBKILpeVZiqKZi8 \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.pleroma.pub b/data/backup/keys/htz-cloud.pleroma.pub new file mode 100644 index 0000000..1795293 --- /dev/null +++ b/data/backup/keys/htz-cloud.pleroma.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7vz3CMmmHmnWZs4b+Ohh4wnUgcME8PvZscjgS+91Qd diff --git a/data/backup/keys/htz-cloud.sewfile.key.vault b/data/backup/keys/htz-cloud.sewfile.key.vault new file mode 100644 index 0000000..ab1b31f --- /dev/null +++ b/data/backup/keys/htz-cloud.sewfile.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWhKNaNm-FvjJIB97rK-RoXRnLHHZ63k8Y-beVmSwuYnXYEjZLSD5yrvE3TtkodVikztjx4Cuck6lTECQR2MwSSlZ76L_uJOCmwyCKbDmjCRAfJsr8ni0WIIDa6GBWeqy1KDqZsaqEJwaH_zF6Ps-JHsUB7NCpqcDLGCTGOQLUrgH_Qzyi4Jme0LAnH2DeY7bSyzOGdLezwGUd2nhv7eKet0NeJwWWTnN3HSd6KGJybZLR2I2FsqiNutqGNLnJgeuTHHsUVUxroJepmE4bC0sK9kd_yWWQDNTVc2MRsJA2XkfgfeWzusmjQyho-9iOucX66E2DnSLOSVfvV1ZQ5iTUx_iYQstDs_V48-Za8OEh0wtMvWJlw4fIZvT2CTbFMjv-Z3ID9O8zu-MOZTKJlvGgQzaCJlvI1xMAd9UcfwKvoejGrZNZdHdadyjB_hbNZk1e2KLYEXsnSzIyTU544K4yWOaKpA70di_rQHfrgUosdRn-CtZkWJolUzKVILNmaaI1gZYI3jr3SYqWWfHjVIlQIt8z5qmR527bvEKhJhDIkJ-RnvTNHeXx9Kqw3VPIWxHaYSS1Fv-M47e2rXsM5eDfPWRsQvYOiQO3g0EbMQhjho8o= \ No newline at end of file diff --git a/data/backup/keys/htz-cloud.sewfile.pub b/data/backup/keys/htz-cloud.sewfile.pub new file mode 100644 index 0000000..4d33a5a --- /dev/null +++ b/data/backup/keys/htz-cloud.sewfile.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9fWj0+jwIxDSvwyP6sOiFeI6huU/kQ+N5nIBAj+2eT diff --git a/data/backup/keys/htz.ex42-1048908.key.vault b/data/backup/keys/htz.ex42-1048908.key.vault new file mode 100644 index 0000000..69129e2 --- /dev/null +++ b/data/backup/keys/htz.ex42-1048908.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWhxrcCNO5KHOsPsxD5ZymUgHG3my4qIJxfr3nJQyBVMRjFjxx2akQubpWWG9UC8xKthSvADXUZxjcGTAvqcELX60W2cdvJ90bY8RGHQ-Dua6-PsThurLVJeWZSmxo3vCneTj0lYEdAwK1aiZsRvxLjWhkyRELXvgPhC3GeNnS0SeC1AHGuRJVnC3ZMbRfSps1_LBxRvIES_acDJSfsRpcLg0oPmdpkDV9wdB0ZBuimngUYCl6jZ-syofI9yRU9q9lpNtZbahKAIBKNHeFzkgC6I5oi8e2-mZqnh_BSLomvRXPdZRvlHQWsSPNX2_25IlZiXyXrBIsN5rXAAwl16PNZjuG703WWiV2RxifGRux7cbJVE-LREBKCADgLduOZPe2voXo3jRq8v4NZfTtk8CKSm4QxS6Q7fRb7_0dAWZadd_dap8HigCUkr_5l-CotSKhiBNTAwyClLSMpDW1oUAaeLgM2YLF7V8TlWAwtxKi1lqmDchoWk221CQ97njVfhUOCNrdiGXOtFeiB-JRsXK8eAgthDzrR2F78s2w9NGZf0SdRxxNNil1f7ikDZfXbsdagaP_HZvjmq8oeTcwibcjsGl7HDVw0xV_7SvOJ3iDhLdQ= \ No newline at end of file diff --git a/data/backup/keys/htz.ex42-1048908.pub b/data/backup/keys/htz.ex42-1048908.pub new file mode 100644 index 0000000..88b121e --- /dev/null +++ b/data/backup/keys/htz.ex42-1048908.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFn5SDyIV+GtSqSDvKPsfkxRgmUKdu8eOOyEWUo5ZtJl diff --git a/data/backup/keys/kunsi-p14s.key.vault b/data/backup/keys/kunsi-p14s.key.vault new file mode 100644 index 0000000..f2ee06a --- /dev/null +++ b/data/backup/keys/kunsi-p14s.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABiB-rPruxytUp5eFUDx-bfXhTHoXbV4E71--i0EFgQxVn0bmgfNrQQL21mAHm9JqSnwtzHxuHW5C_VYXb1vsg6b3lopue3i4XPHZYFe0VU5SDFdKbP2JEQcuMZfYqjN49MxM3bGVkTiErNpf-Ctgf_sop02O_IYNR3fhvD8IST32RUrfqYHPAky9O48pon202bPi10jPMu2dZTevE3ODtBHdiY1Sx7vTzpUiVskXj9H3A3dzywM2w7KpHiUx5sROaOWNZBQ2MASQLfIbAe1mQobCpySKsMNhbxmpTO2Cg75a8tLbtTicrzwU9DB8HOLn5L3ed-K1bPpP57_bWrxl9_Jrvgu6PgDB8b1PTInycej8o7zZKF-UTi1aGcjJAvSRymWDb045WBQs3HIJJuBlKoHwjMUN7Vw9u1JqooTSmJWFql3pdIlhR3YZxTe5wrT1jxHeyxKPk7YlNqcj6nlK8v9QT9w24IdF0yekVl_HVnFgZ4EQ_DH_wdKTnAJWLOMkqYjlFCz0HS_IOF-X3oPr8UcbXzQ6dtcJAh3nR6kJRUIfifzEk0hBkZZ8axiDt2KFFYLqv5SM5TmtRuxeJq38Eqa-uv62w2_lJZiLQ6wFHR7UoGgBexp65vGe3cDnN7j1fPXgGo \ No newline at end of file diff --git a/data/backup/keys/kunsi-p14s.pub b/data/backup/keys/kunsi-p14s.pub new file mode 100644 index 0000000..636ca3f --- /dev/null +++ b/data/backup/keys/kunsi-p14s.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGDTtww1OWI29zxXpUANToHzzBR/Kp0Jqpii0+JUr3MY kunsi@kunsi-p14s.kunbox.net diff --git a/data/backup/keys/kunsi-t470.pub b/data/backup/keys/kunsi-t470.pub new file mode 100644 index 0000000..1d712a5 --- /dev/null +++ b/data/backup/keys/kunsi-t470.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+ja1z5VRQzaKCCePsUM14qMr9QR94qlWc7Je5Poki9UmC1t/TyxRVzcCBL1ZdIfBGx6QKtfkEbvhgb3nxVt3PvXjoJrc6wwGLmNrVsU6B88y35g7nzupQiPKYJwkNzJ9j6Dmkgj1F5Q+aY2SitDaX6vqICLJ4Al/ZFw2IQxVJfC7JXRJ9jRMG5o9gWoE3gWDYEAmw+HU2mNzyeuaD12qJw9DHUimAlgkOWzll3gh9WclsYnnXGrCCn5fyHFUCJl+XXAIy519z7YTpKih02rsIOw5dnaGClBZD/YQu2ZKVFZiwIVH7aBiqHOmtgRyWTQgjbh/fMpIN0ar2f/iZsWYUjd6et48TOmXZYIPCQ5FivXNvxt9oo1XZfq76UHBwlmypLJIWROMbz375n2M6hr3hECuxuPjKEUXAv05KiC1aJ4xc6pFoVhqwAR99hvHw5U4o7/ko2NVjNpTu6Jr5DT5VaQLIdDDjC/93kUjMpdD/8P72bEn7454+WexU6OE6uvNiHj1fetrptr2UAuzVfnCoaV8pBqY7X95gk+lnSENdpr8ltJYMg8s0Z7Pzz0OxsZtzzDY5VmWfC9TCdJkN5lT8IbnaixsYlWdjQl1lMmZGElmelfU3K7YQLAbZiHmHKe4hTl9ZoCcWdTQ3d4y2t1DBos+N2HZNdtFCyOS8esDdMw== diff --git a/data/backup/keys/ns-primary.key.vault b/data/backup/keys/ns-primary.key.vault new file mode 100644 index 0000000..52bb656 --- /dev/null +++ b/data/backup/keys/ns-primary.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABj1jTasX0XOFRWh7F0pxNgMoJIjrblvqOM8ohGVCsvVyMEQDiOmGaJCs9lW-lbeghlzRpiC8P7CNot6OOeNXBYWmxN_HgN3J2p6Q5-XoSJ62NUJWQNRNNENuiN1Yy0g0MREk4gVsNh8-VeoXuKgyLEXJQJI-SYLzl8faZoBnQGTK4FbTAiN6KSB4EbTPwxx-8dYp8kNIj4ipBjkQKNu-mXuVvdnf5fTUwTCQx6rz7yjlp7DOPuSJDASg5bE33dd8gt89grW5vBKeEnQsi7hpJCJF5vNfRay89IKfjf6UqxJHKCmS2tIWQ9Kz4Tv41MnNR0-jvnULq7TWcnqwo_SKb8JRLUA3dH2wLiOUu7aApYSkeSNiul2ILCtBPsjY_eWzqdd3tkpJBErOcFVe2mdjVRSIUOXTM_T3nNWCJgn5TxD4qbHklZoCaM6Ey9P_yQj-sSRGizgcDhGiqY8xJNmwbWz9IH5a_Fs6iRVhAh6VzSa1ZAKxcum87dj-KVA_SjG9hy7Dy28xK0D4NoSpYFOkEz4VHpa1tP0t8QJ2WtQiw-qjHFzokkIINEUKUPIBg6t_5oedJ24YMnyyzBZ2_uQ1HFVFjBx-7Iw73bTPNluVwXkobzEnrYFwDsEXGE6tR0HjbteNxj \ No newline at end of file diff --git a/data/backup/keys/ns-primary.pub b/data/backup/keys/ns-primary.pub new file mode 100644 index 0000000..442d8b9 --- /dev/null +++ b/data/backup/keys/ns-primary.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+FCn1sWP74+lVAyaXDpXxCCauh6LC2KEJmIMhDEYvJ kunsi@kunsi-p14s.kunbox.net diff --git a/data/backup/keys/ovh.icinga2.key.vault b/data/backup/keys/ovh.icinga2.key.vault new file mode 100644 index 0000000..93964c5 --- /dev/null +++ b/data/backup/keys/ovh.icinga2.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABfrlWizt5Lp7t_CRYxVrlPmXFKSKKpNzWIKaM8X6l-7eUD-vDMN9G1tj6nucjQ3sHOll7WXM367HIcqIlOQfUDM2Qat3_4MstsKnEHUvoPh1xyjrui74ZQvLrdedYjtQ_YlsLJnoHkqLThJQ1D3pazifMYouF0CO9MMz4pVxTNiSGYPzVaixUN_LcMm9-u0vWaVh3UqDa3mLxufI36C5lKR6p7jEhB3vTpxtahquDxSjMmCYQv1AiEbPfoh0-8mFlZ5QZ9ZPxno5q_5SnZViv4jDuLLcW1VeK4ocOP2vjh8QuN2uc2-AuQRzykOAHBjprKcjgrp_M9sejy4W5I40wgpMliPtgc8z_tdBhU5uLwKR50l0xjCW9oR7mPQIzrs8Y6b-KPO3Hy9v2iCKYT0XOLiY9fCF_hmIk-hN7ekS2zUlU4TzRC9nDD-YBX28mqXU7n1-0QciDjVkpmcxvBFzBbNt5XXJJ7jLdfj6fx2keErnmSLWAnMv-ztJX93sfxYfnQejqhYIc_H81xF4Nm3P3V7lf8PeR_FsfqvQujR9ECBWQ6vo8-5KnAiYnMSyPapirY8b4FPUjKhEgel5goSZ4DhbmUBKPVecByUTYSBAXP76IyXRE= \ No newline at end of file diff --git a/data/backup/keys/ovh.icinga2.pub b/data/backup/keys/ovh.icinga2.pub new file mode 100644 index 0000000..a0045cc --- /dev/null +++ b/data/backup/keys/ovh.icinga2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE5hLAqBz7Vm6oVv+oye5hQCsRI3cPA9q5B8KCWYCYUw diff --git a/data/backup/keys/rx300.key.vault b/data/backup/keys/rx300.key.vault new file mode 100644 index 0000000..b272d12 --- /dev/null +++ b/data/backup/keys/rx300.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABg2xbjGmqokuwp9mIL5CX0fmGhvxpeYJGam2csaFKM5UqpgpnE9BFSUUkJRPOc0cnXH7xNriDJaY6EXEd959gkCMm0Cwu4H7t8XUeHNPfeqoyp7R1mmddnDp5BglbhkI6VJqCiD4YhmDzAieu6YY9Ho-E0SR-kOB-z9Jfw1P8yUzaF4GzNqKdWlSaTSt_fq2aotIQm13ukrewZChA8xY_1mMVgxcfVfOLFFRNVCrW1oRcH0qaQ_6_7ZsRZat_8tCgjknFLb9suBGBNbwl7yxlayaRfbN36VevSX4iSA4Q_nvSZ40oV5otqljpMyUpbVRbeZb0uAJFbn_8nEWc0FKR5iJy-mXcToBlx0Rc8wPmHuG2Gdf0BJDFK8AIIL9p-ucqYdvfU8oC_dsHlnhIXnf0dc9PdP-9Lnh3Ov1Lkm-i0GLa6K6nPrtRXgDaj_fv1V01-0vYF_t4vs_4VbjMMXGhUXI94lRw59vFB4WJQluir2ut-jDQR0Ek0U3g5-ziRbg4t77JzKjeUymbguT2BAT0er7W0zfKUcQ5VizSJ3j1U7VtbVJ7E3710BQ_1pCoz9HAt_BcxYSJ3bnhRR9V_NdaSdtPeIVqQ0G69hKbwNYZ0CAEAgIhbRgeyDeMev6WhWN6T5We- \ No newline at end of file diff --git a/data/backup/keys/rx300.pub b/data/backup/keys/rx300.pub new file mode 100644 index 0000000..6fff864 --- /dev/null +++ b/data/backup/keys/rx300.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/pOUa5sbFtqzHZF2qnG+MroI8Z65FRnYAiS1CrqCss diff --git a/data/c3voc-addons/files b/data/c3voc-addons/files new file mode 120000 index 0000000..e2f9229 --- /dev/null +++ b/data/c3voc-addons/files @@ -0,0 +1 @@ +../nginx/files \ No newline at end of file diff --git a/data/c3voc-addons/files/error.html b/data/c3voc-addons/files/error.html deleted file mode 120000 index 26606f0..0000000 --- a/data/c3voc-addons/files/error.html +++ /dev/null @@ -1 +0,0 @@ -../../nginx/files/error.html \ No newline at end of file diff --git a/data/c3voc-addons/files/extras b/data/c3voc-addons/files/extras deleted file mode 120000 index afe5648..0000000 --- a/data/c3voc-addons/files/extras +++ /dev/null @@ -1 +0,0 @@ -../../nginx/files/extras \ No newline at end of file diff --git a/data/c3voc-addons/files/gpg-keys b/data/c3voc-addons/files/gpg-keys deleted file mode 120000 index c649d44..0000000 --- a/data/c3voc-addons/files/gpg-keys +++ /dev/null @@ -1 +0,0 @@ -../../apt/files/gpg-keys \ No newline at end of file diff --git a/data/c3voc-addons/files/not_found.html b/data/c3voc-addons/files/not_found.html deleted file mode 120000 index b6964cb..0000000 --- a/data/c3voc-addons/files/not_found.html +++ /dev/null @@ -1 +0,0 @@ -../../nginx/files/not_found.html \ No newline at end of file diff --git a/data/c3voc-addons/files/ssl b/data/c3voc-addons/files/ssl deleted file mode 120000 index 348aeea..0000000 --- a/data/c3voc-addons/files/ssl +++ /dev/null @@ -1 +0,0 @@ -../../ssl \ No newline at end of file diff --git a/data/forgejo/files/ssh-keys/carlene.key.vault b/data/gitea/files/ssh-keys/rx300.key.vault similarity index 100% rename from data/forgejo/files/ssh-keys/carlene.key.vault rename to data/gitea/files/ssh-keys/rx300.key.vault diff --git a/data/forgejo/files/ssh-keys/carlene.pub b/data/gitea/files/ssh-keys/rx300.pub similarity index 100% rename from data/forgejo/files/ssh-keys/carlene.pub rename to data/gitea/files/ssh-keys/rx300.pub diff --git a/data/icinga2/icingaweb2_nginx.conf b/data/icinga2/icingaweb2_nginx.conf deleted file mode 100644 index bd9415e..0000000 --- a/data/icinga2/icingaweb2_nginx.conf +++ /dev/null @@ -1,15 +0,0 @@ - location ~ \.php$ { - include fastcgi.conf; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/run/php/php8.2-fpm.sock; - fastcgi_param SCRIPT_FILENAME /usr/share/icingaweb2/public/index.php; - fastcgi_param ICINGAWEB_CONFIGDIR /etc/icingaweb2; - } - - location = / { - return 301 https://$host/authentication/login; - } - - location / { - try_files $1 $uri $uri/ /index.php$is_args$args; - } diff --git a/data/jenkins-ci/files/ssh-keys/rx300.key.vault b/data/jenkins-ci/files/ssh-keys/rx300.key.vault new file mode 100644 index 0000000..e56190a --- /dev/null +++ b/data/jenkins-ci/files/ssh-keys/rx300.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABg6vNNuCZcmhH52dQDiD4ePsbXhz0kHSjqX3yduJ6E5NylWEdKNtjtrfc9bu1WNnDBO0YpsqxIeax2u1xc6gstohVfbu2MgwGJKpA7J5Py6xiQL82YKJcwV7k0EZ7ilWbqlzXuSDh40KG3GWOTPiw_CbsbDEpCU09x1hUs1_0BTPAU6ln4t7ync7ZjFZf_vRBTlrnZWchzXoSwppzedAZeaptfhMWn_-8oARoYvxJf3pkmTSGjovNMvDak_sscq_M2rldng6_oboR4iTo_6eY6bpCjEGD3xMeSzLhDZsJ4c0l9bZBDef-NRWA7Ewptc4KYKVvzKlgyrByqSV8TCmYn4aBgOusv-VAW3VqKg2rHi3nq5L50zkPwWmHC6_rdtIS-pAlnR5A0HJYdXGyf2eQSq3UkrZA3BIFlqUWrvS8aTWxp9CUL5C9oRGpL8P3fVfExiqhmcLGamHZb1Y2kjxX8EMcSCRLgiVO9DwIpXlEm86HfgVcXaL0wpibM32PD0sspOPILThE5P9WETGhpFAWDkWR0WaYQjZuAVlXTtk8tgdh0vC2auQl2pEVbvvnZaa04Ohp2QgE3AJLg3tdekLciwCQmPm0bpX8xYvJ49vNWG-SCaAlLHzLVIMFXFY53-SBOHYnE \ No newline at end of file diff --git a/data/jenkins-ci/files/ssh-keys/rx300.pub b/data/jenkins-ci/files/ssh-keys/rx300.pub new file mode 100644 index 0000000..55ce7ec --- /dev/null +++ b/data/jenkins-ci/files/ssh-keys/rx300.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHZnYhsdtGUYJiFcvfqTLljGkInnFTOoDF/WZniLtPjH diff --git a/data/matrix-synapse/rx300/homeserver_signing.key.vault b/data/matrix-synapse/rx300/homeserver_signing.key.vault new file mode 100644 index 0000000..120737d --- /dev/null +++ b/data/matrix-synapse/rx300/homeserver_signing.key.vault @@ -0,0 +1 @@ +encrypt$gAAAAABeiaEqyvC5b9qRtL9I760dD51BJ9ZMKjofyORoSedhjqfHM0Pp-x_UECvoZgrtY8dgcq0Ste27YlSofnPwLM6Jr6wXfNX-Ih8WZD7hV6yQdEQ6wmj2FYilmMknGdQ_yVnu5TRe_malgW78n6hRQc7DsdsEfw== \ No newline at end of file diff --git a/data/minecraft/files/rx300 b/data/minecraft/files/rx300 new file mode 100644 index 0000000..19e41fe --- /dev/null +++ b/data/minecraft/files/rx300 @@ -0,0 +1,59 @@ +#Minecraft server properties +#Sun Nov 06 13:56:13 UTC 2022 +allow-flight=true +allow-nether=true +broadcast-console-to-ops=true +broadcast-rcon-to-ops=true +debug=false +difficulty=easy +enable-command-block=false +enable-jmx-monitoring=true +enable-query=false +enable-rcon=true +enable-status=true +enforce-secure-profile=true +enforce-whitelist=true +entity-broadcast-range-percentage=100 +force-gamemode=false +function-permission-level=2 +gamemode=creative +generate-structures=true +generator-settings={} +hardcore=false +hide-online-players=false +level-name=/home/minecraft/world +level-seed= +level-type=minecraft\:normal +max-chained-neighbor-updates=1000000 +max-players=20 +max-tick-time=60000 +max-world-size=29999984 +motd=CutieMC +network-compression-threshold=256 +online-mode=true +op-permission-level=4 +player-idle-timeout=0 +prevent-proxy-connections=false +previews-chat=false +pvp=true +query.port=25565 +rate-limit=0 +rcon.password= +rcon.port=25575 +require-resource-pack=false +resource-pack-prompt= +resource-pack-sha1= +resource-pack= +server-ip= +server-port=25565 +simulation-distance=10 +snooper-enabled=false +spawn-animals=true +spawn-monsters=false +spawn-npcs=true +spawn-protection=16 +sync-chunk-writes=true +text-filtering-config= +use-native-transport=true +view-distance=32 +white-list=true diff --git a/data/nextcloud/nginx.conf b/data/nextcloud/nginx.conf deleted file mode 100644 index 34267ad..0000000 --- a/data/nextcloud/nginx.conf +++ /dev/null @@ -1,41 +0,0 @@ - location ^~ /.well-known { - location = /.well-known/carddav { return 301 /remote.php/dav/; } - location = /.well-known/caldav { return 301 /remote.php/dav/; } - - return 301 /index.php$request_uri; - } - - - location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } - location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } - - location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ { - try_files $uri /index.php$request_uri; - # 182 days, 14 hours, 54 minutes, 23 seconds. I have no clue why - # this exact value, but i copied it from the example config. - add_header Cache-Control "public, max-age=15778463, $asset_immutable"; - - location ~ \.wasm$ { - default_type application/wasm; - } - } - - location ~ \.woff2?$ { - try_files $uri /index.php$request_uri; - expires 7d; - } - - location /remote { - return 301 /remote.php$request_uri; - } - - location / { - try_files $uri $uri/ /index.php$request_uri; - } - - # cursed shit, use like this to have the 'map' feature outside the regular nginx config -} - -map $arg_v $asset_immutable { - "" ""; - default "immutable"; diff --git a/data/nginx/files/extras/htz-cloud.aurto/aurto b/data/nginx/files/extras/aurto/aurto similarity index 100% rename from data/nginx/files/extras/htz-cloud.aurto/aurto rename to data/nginx/files/extras/aurto/aurto diff --git a/data/nginx/files/extras/carlene/nextcloud b/data/nginx/files/extras/carlene/nextcloud deleted file mode 120000 index eaabf9e..0000000 --- a/data/nginx/files/extras/carlene/nextcloud +++ /dev/null @@ -1 +0,0 @@ -../../../../nextcloud/nginx.conf \ No newline at end of file diff --git a/data/nginx/files/extras/home.paperless-sophie/paperless b/data/nginx/files/extras/home.paperless-sophie/paperless new file mode 100644 index 0000000..1aa1b28 --- /dev/null +++ b/data/nginx/files/extras/home.paperless-sophie/paperless @@ -0,0 +1,3 @@ + location /static/ { + alias /opt/paperless/static/; + } diff --git a/data/nginx/files/extras/htz-cloud.luther/luther-ps b/data/nginx/files/extras/htz-cloud.luther/luther-ps new file mode 100644 index 0000000..f5a95e6 --- /dev/null +++ b/data/nginx/files/extras/htz-cloud.luther/luther-ps @@ -0,0 +1,51 @@ + location ~ ^/sites/.*/private/ { + return 403; + } + + location ~ ^/sites/[^/]+/files/.*\.php$ { + deny all; + } + + location ~ (^|/)\. { + return 403; + } + + location / { + try_files $uri /index.php?$query_string; + } + + location /update { + try_files $uri /update.php; + } + + location @rewrite { + rewrite ^ /index.php; + } + + location ~ /vendor/.*\.php$ { + deny all; + return 404; + } + + location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|/(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config)$|/#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ { + deny all; + return 404; + } + + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + try_files $uri @rewrite; + expires max; + log_not_found off; + } + + location ~ ^/sites/.*/files/styles/ { + try_files $uri @rewrite; + } + + location ~ ^(/[a-z\-]+)?/system/files/ { + try_files $uri /index.php?$query_string; + } + + if ($request_uri ~* "^(.*/)index\.php/(.*)") { + return 307 $1$2; + } diff --git a/data/nginx/files/extras/htz-cloud.miniserver/sophies-kitchen.eu b/data/nginx/files/extras/htz-cloud.miniserver/sophies-kitchen.eu index 2f321f7..cc5c4e3 100644 --- a/data/nginx/files/extras/htz-cloud.miniserver/sophies-kitchen.eu +++ b/data/nginx/files/extras/htz-cloud.miniserver/sophies-kitchen.eu @@ -8,13 +8,3 @@ location /.well-known/matrix/server { default_type application/json; add_header Access-Control-Allow-Origin *; } - -location /.well-known/webfinger { - return 302 'https://chaos.social/.well-known/webfinger?resource=acct:sophie@chaos.social'; -} - -location /social { - return 200 'Mastodon'; - default_type text/html; - add_header Access-Control-Allow-Origin *; -} diff --git a/data/nginx/files/extras/htz-cloud.pleroma/pleroma b/data/nginx/files/extras/htz-cloud.pleroma/pleroma new file mode 100644 index 0000000..7e69502 --- /dev/null +++ b/data/nginx/files/extras/htz-cloud.pleroma/pleroma @@ -0,0 +1,2 @@ + access_log /var/log/nginx/pleroma.log gdpr; + error_log /var/log/nginx/error.log; diff --git a/data/nginx/files/extras/htz-cloud.sewfile/sewfile.franzi.business b/data/nginx/files/extras/htz-cloud.sewfile/sewfile.franzi.business new file mode 100644 index 0000000..9312c7e --- /dev/null +++ b/data/nginx/files/extras/htz-cloud.sewfile/sewfile.franzi.business @@ -0,0 +1,23 @@ + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + proxy_read_timeout 1200s; + } + + location /seafhttp { + rewrite ^/seafhttp(.*)$ $1 break; + proxy_pass http://127.0.0.1:8082; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_connect_timeout 36000s; + proxy_read_timeout 36000s; + proxy_send_timeout 36000s; + send_timeout 36000s; + proxy_request_buffering off; + } + + location /media { + alias /opt/seafile/seafile-server-latest/seahub/media; + } diff --git a/data/nginx/files/extras/icinga2/icingaweb2 b/data/nginx/files/extras/icinga2/icingaweb2 deleted file mode 120000 index b6a8498..0000000 --- a/data/nginx/files/extras/icinga2/icingaweb2 +++ /dev/null @@ -1 +0,0 @@ -../../../../icinga2/icingaweb2_nginx.conf \ No newline at end of file diff --git a/data/nginx/files/extras/rottenraptor-server/dokuwiki b/data/nginx/files/extras/rottenraptor-server/dokuwiki deleted file mode 100644 index 2e9b682..0000000 --- a/data/nginx/files/extras/rottenraptor-server/dokuwiki +++ /dev/null @@ -1,33 +0,0 @@ - location ~ ^/lib.*\.(js|css|gif|png|ico|jpg|jpeg|svg)$ { - expires 365d; # browser caching - } - - location ~ /(install.php) { deny all; } - - location ~ /(\.ht|\.git|\.hg|\.svn|\.vs|data|conf|bin|inc|vendor|README|VERSION|SECURITY.md|COPYING|composer.json|composer.lock) { - #return 404; # https://www.dokuwiki.org/install:nginx?rev=1734102057#nginx_particulars - deny all; # Returns 403 - } - - # Support for X-Accel-Redirect - location ~ ^/data/ { - internal; - } - - location / { - try_files $uri $uri/ @dokuwiki; - - # This means; where $uri is 'path', if 'GET /path' doesnt exist, redirect - # client to 'GET /path/' directory. If neither, goto @dokuwiki rules. - } - - location @dokuwiki { - rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last; - rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last; - rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last; -# rewrite ^/tag/(.*) /doku.php?id=tag:$1&do=showtag&tag=tag:$1 last; #untested - rewrite ^/(.*) /doku.php?id=$1&$args last; - - # rewrites "doku.php/" out of the URLs if you set the userewrite - # setting to .htaccess in dokuwiki config page - } diff --git a/data/nginx/files/extras/rottenraptor-server/radio b/data/nginx/files/extras/rottenraptor-server/radio deleted file mode 100644 index 4452701..0000000 --- a/data/nginx/files/extras/rottenraptor-server/radio +++ /dev/null @@ -1,13 +0,0 @@ - location / { - proxy_pass http://172.30.17.52:8000/; - proxy_http_version 1.0; - proxy_buffering off; - proxy_read_timeout 7d; - - auth_basic "Rotten City Eventradio"; - auth_basic_user_file /etc/nginx/radio-htpasswd; - - location /admin/ { - deny all; - } - } diff --git a/data/nginx/files/extras/rx300/franzi.business b/data/nginx/files/extras/rx300/franzi.business new file mode 100644 index 0000000..472d106 --- /dev/null +++ b/data/nginx/files/extras/rx300/franzi.business @@ -0,0 +1,15 @@ + gzip on; + gzip_vary on; + gzip_min_length 10240; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml image/svg+xml; + + location /css/ { + expires 7d; + add_header Cache-Control "public, no-transform"; + } + + location /img/ { + expires 30d; + add_header Cache-Control "public, no-transform"; + } diff --git a/data/nginx/files/extras/rx300/paste.franzi.business b/data/nginx/files/extras/rx300/paste.franzi.business new file mode 100644 index 0000000..93f035d --- /dev/null +++ b/data/nginx/files/extras/rx300/paste.franzi.business @@ -0,0 +1,5 @@ + autoindex on; + + location = / { + autoindex off; + } diff --git a/data/nginx/files/extras/rx300/wiki.franzi.business b/data/nginx/files/extras/rx300/wiki.franzi.business new file mode 100644 index 0000000..cc1fc01 --- /dev/null +++ b/data/nginx/files/extras/rx300/wiki.franzi.business @@ -0,0 +1,12 @@ + location ~ /(data|conf|bin|inc|vendor)/ { + deny all; + } + + location / { try_files $uri $uri/ @dokuwiki; } + + location @dokuwiki { + rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last; + rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last; + rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last; + rewrite ^/(.*) /doku.php?id=$1&$args last; + } diff --git a/data/nginx/files/extras/voc.pretalx/pretalx b/data/nginx/files/extras/voc.pretalx/pretalx index 8c82109..1d1c718 100644 --- a/data/nginx/files/extras/voc.pretalx/pretalx +++ b/data/nginx/files/extras/voc.pretalx/pretalx @@ -25,3 +25,12 @@ expires 365d; add_header Cache-Control "public"; } + + location /Uluagh8Oichai4Uk/ { + alias /var/www/pretalx/; + access_log off; + expires 365d; + add_header Cache-Control "public"; + autoindex on; + } + diff --git a/data/openvpn-client/c3voc.conf.vault b/data/openvpn-client/c3voc.conf.vault new file mode 100644 index 0000000..e18a68e --- /dev/null +++ b/data/openvpn-client/c3voc.conf.vault @@ -0,0 +1 @@ +encrypt$gAAAAABje8PnbzxHl_1Lr3mpXemItAaxmkeKsKtZ1dWVxcK9DJ8MUNKwryWcmcMkpHFFgYrjmyU3pw93vmlPn6wa0Vc5IcY4ZR3xqO9LqhgXtzD_PGXwAhL9vTEVinDdBS_3S9ub9w8LhlLv99eHVbojqCw7xHtwvo4Nc78EZexuHrhitWEP-ailL_UGXpeaQzUZegjzK8lbUqdgEIUFQb7nraZGm3ZwHVt8oQ3Qeipb6joiFo1jChFiIIRXk1M4TqZAHiRCWIuMomXxDio386WcvnEpghVAebU5s2EgSIjoaDW9DQhLNzuUAFjJW_ugBJNZd3wA3m0CdpSWskpi3ppK0YRbIOxepgtoFa_sITu0OdTRKUgbEnNU8zePwf6zHe2ujH_AjHQ_F1Y46KDsk5yi_8yC5Ml8ivyHkUV0CI4eRYd5pwl0HxFh-gaxZoCPfVec2-13gLY_eugtydTux0Ci4DXsc_RnPUvKpMS5eTPSK-YggB_ctjUV4-Au-WQQ3830-gruYePxnuhtSRsxNbf_MsUVKPM6zYdHg6sXX7RN7EvZ-tyATPVTdwDDf-F0xjiRMQd8gNcklELo--OjKV-J2yj6bZNG3TVDk74DVKiogytrvevQYG-cMIIPLFNBIRrhn5Xycy2ypZj3R-qvfksb0aQtTl3NYzWrJZBw8n0HtUxtLZRqH-e4zz0ft6rKdI576NIjNHksMeKt_8W_Rty-huNicrXX2tZYoi3_D5EglFtRuhgygSPoFiPh-BU5bQaconMDuQki5vemSGYL8tC1Oy4VhnMHwGRHBm76a4LsC_lBB97uWlBtZ7ubd8CmXQfijxewWmKliMOlsMgBG8nb25cpxBoklPpq4VG_JKMNGZN1Sa-e4TdLe4Men655qMZ1eUyp0AYiScQplwKDcADlFUmbuj7FBqZ5hqKhgnLZydUk2skZsD_GydNEA9PAkULM34p24T0sND-BmLnE7TAtdEaxpNq9uhsVSEa59EJhCq0Zygs3MTSAWZ8r1rxPVfwvTdEm30whhqEwn53zbFLQWCnKbINUx37MMrgyRAYL_kP6JLlz8ANQYCu5TFGwn2_d6vEahesXAvIB8CuN2CMqx5XMQrI5GE45g0a0vp3tLUuU_4RX5qLBPCig5UvxXA0PXuSsuhvKRMN8Le0h-s4KEX6xWon4rb7adsj9WuyMDolySqW3FB7grf-eqx3S_PfCZEL3w-URzuQbkKUH0BgDkltmTr6ZgoNqWxVIbYDIjzO4TGNOItDWQBrAOlOakTj2X3NyOim1btLw8RlVRRdcUNq2ueLquyrcvGOhFMkAYYgXR34Z7FE4DG70omfETAzc4jhvcggYRjxZLwMcImbs_q6ZhfYY_SQkNP7_ot2lE8UoU13j3mKYdZoMQ0LL_IRMt4g_CYWtHRjKY0m2cmP4avwK469H337LXwijwrSLNP6jUtqbUyhX-HiGtkJ6ZlIzH7JHfO5CEl7Fu_3ljla9CTKcXybORj_ElwHWOufACHbpC8jc6LLnxwYVjBiFuCIn2JiulGygef8LQemXHN6vud1xWtKf_OhJFDGkJX1D-IwYK_5MGkLZZUj6K4NMelWQIecR5qkYcDOc1-URKxUO8-g_pALbTzrVaf6aybQl9xQasyFb84aD0Gp8CgmDQG0yt_KH0TQNr9-mUQhS4baEF4O4TwrgERdl0sJ-521wBCyq2M3hAbcBtP1n8vxjfxkv9PLBaRHldGoPqCWDQmEnT57CZToj_MjVI_mJRPJ900VZk8IRIkmmeiGup0jbJujrAf6sQ5MGIUMVBEA_gc9qFgRruU-2PpA0mwsbomsv0aUSZKXSHMF_KyHoSC73haDNxzifbbJV2PzNVp1ce_j9m3V1SUbAgKUaIBzf52hDfC2Ub373EXE5z0JmvnLNWYe5SLw5iLLOXiriujzNsEdi5_AoOEx5wuLNwhR9mmvB8giUsbp0c-EC_JC3vPt1W-6unsb2CnMrIvqjRLVXhE0ZyzVtAl0JVlQ9bb3Va5HL2aLE3DOQrMl1E0iddmsNrsJrGM80X1RGMwyXrVNoDTjkxVTKg4tqngV4BCYkzD7xkKh5mBatYCSwetb2IRslut5SvJOBzJ-wLNjxcWiBIs2NEEGMfj8WjiXY7JOmaneXjprrsVsmvDAlHEMjtZpXlML72lfYkF64SA9uhz2wQLKuUXCWZPENCytYz52TtEtePmPOKP4CPi_w1QyP7CLhymOWZAQQc3xHDnL3orpUbstpYgdo34D-iuSyd3quQLTJQnPTC1fKxJuNrKBxftqs3ZbE4EBxLjBxhW3hVadS4-VYzdc--nv8hPLQU1k8IpGAJ5U7kmxROKQMJEqr9Ay4zosY8AqnPqD48cJ5o2hDSa9Znve9QIaXKV1dH3WPsF8aEu71E7hH-TXo-56HY_lxfPejaa7Ls3JZ6JJKNh8KncQU1AdARIU9Gw-bCpfQuKTaB7F6OdrqcGd4Qhic0kvIkWzFGLKUsQ_UigcbdW0h1kIU6qZJxV-8KQMhHOUsoXgVExkNU7bBlXxCa8-owQkTY1auTyCDvGIET36UzKyfSyympBIdL3YWNphgErhI4ZMrr3ol6iPAWqlQYxpu9OY1XYq63KvSXirIm3YEW0_FqCm2jgQdYqXoelgpAqmTSCfCaZTRMm__zqf0xqVUTYagVGUHUNpTKwr_YD-F7KtgnGH_KDSt-auNBfAJEMB9-c1AgmkYff4FLhiu_pUJaD7U1qwac8fu1amf9obUNTX_zArJqYwOCFKJcRR7mOH_TABT58VaCcMPaI6cKKoBj_UtfSKH-m_Vq_N6uMbcMFZahhBuLGKTtidCqHENz1IGo8FePAUaFgg7rviyHg4cfZMXkI8YG5S447rj5F52j2nOsWWS2yxUGVbgIUFqCEDk_c4eeEBhzfFVc4gyPssuAOWn-FvIrMOInNyctgqQSmRpYzorsYzTtdJCO1wnz5m-gbrGKkwd10TTf2Wt24xxhPOsAGv_ZFD2jlKtzAseRvR9lKAVr-roApPS1Ikeeq2mDrwrz5qEX9L8U5TCh3GVihQRbOtDphivDmeAEu_OS5yZyDFEtqoea31dtz3dmbLws8_ph_7E9ZDHv8OmAbDVC0hoq65Wl6r2jeJ-nnowy4ntRqw9zUfwJnMb56cXAbsLUnKr_CJ5sk0ip3yRJW7tcMwVOB33QZWfrlr9IJJEKkKS56BuuhZriUQCqT6ZXf0U64GHirSz8C7uG7bPKk9cSO9dKAPMAhhuzf7Z9wTlXtGfja_XbHL0zaSc5xINrdTZiXRidaj0YSHNw3aPokwAmzsDZv8kVwwX7Wdnb_StkClle5EuIVcRfeyz7l5jQC-Bsqe3mVnN3KmPAWzHhT_p3TDk843OEN59b6vv286Z_kEijIu2ujW5isdZLnUgvprTq9LkLaAvSF53ruPiWR7lPg4vrT9Ag8P6No1wDuTKK9M7ZI79a7optNYlJw_dWCjE0VU4cFF74Kxdg9kjnsrkQrNInDFFwCQRfTMr2gPTXdMmWJX1a_U1PGUdoAv7v5pwPoXPO2iaBeqw98GpCPc463mOOpp2_rrKbUIfJ9IjCFN8MBvbvnHxQoLrif-D5xvFaZ1CxtfMSLo4jecJFQ62kRxbkOfNlRGyVX9e9ZN8LJ3Hr5hKx6EJelUktjpYdZZjr9jmQa8E7mmKzw918nbaQEt28xp_yJ2G18EqYw5k1fICvYwbrSwVnJnrFIOc3dNbMz9jt2CLccNx6V1w5bLagGj99zWdpywEqpzrIUFUz0rpQRD9kbHHwaTCPZ0R2tW8XFYN6nPvaTMsJWRXR4Z9jqW6x95vB6O11sCOM_z8fJYjHWTsA0VQbzdglHo7iKDH7qjprC8AtHzYSVknP4WSIOst93Me9KTmZNcNls34vS507SeJpMMQ9JOT4Vd_ZGcvZmhhZ2pbAxyruglTOmdF5Dny5PZfiAACgCY74s7H759o2jPDiY6cJddanH44uCtXVSWsBLbFh9ImWKWfFPH6kffAq1UoLRvAoz3apZGdCU4gLpUYgevudO7y6jL5U5xQC9pyKJuwQ5TpXBpZ3ADVvpttcilAVi4oc-zgigJRxiJAl2SxpN0BfcW43cLM17s26xEEtry_bFv_K4_DjAV2lkVxCebHAvXnSoJu8Ub8_59bZTCov690l48wa0yHf6ANnxFkvV1dmweTdLvplSfVRbRICrljm2fMYJpI2IIJ1JGKHzY2T76oeIzoitwgAetWgz04w8beC8YTv1zwMNOoXslz3XYRHBE2Z6BQ2DGWgFMlfBcea8aUJKJJC1E93iz2GHNysFLYF8gLrM1obE26G1q5i6djJtmF7fSQyterDRIpvQNR8WhMKn5z-oGzOU1ZwTXhuYOV7CITDHfUuAd11hT6hbiDp1m9JfCmZZCkUdPayH57XdNKwsTm1C9m3vwdTVGmySTqvhiRGKnz5jBhnI1qQloIqRNbtUjicpCd_vpUbgPaYxQYZZZS3OjVAcMNqb3EFO2G-E6uS5EY9C8iIzMRDpc4T5PnT3WdvlqPPPWOEAIHRvlIInOyI5g_q6hR9NyJ_-pR-ebz7KUbXZnv4TxS9gSnfBeDPGLZ3TQ0YJJ_ecXWzwuT-TYRDO4WlQxssci_KayBlK6NVeCs6c4JhDiKghID6gBiy3StNDmvNKzb0jwv1vPhuJ6TLFr3NHXx4wqCKu9W8hIGx3d5KceCfubhzF0qW7GmorGWeud5WDMNn9KSBMyIrRT3YwpHzaDEyCcKaIwfZLEWSIV7io3cB1STdKHUJ_6NHTPsTA-4f7nFk5AnNl9MtVCK82si5w0v6-PU8z6Otu4JdoCGUx_ppPPnAYsuiWqQGswEJszgCRjckshMr6LZn804C2urW--JMUcMn8Zb5CCDut6HDk002hKDhprsMJKItp5raIM03u4m75gBA4b0gu_PLCbzAOQRY_gGUsxk3jL1LvLrq0mmlS8w51Ri4i6gDFJ6FviSFjhpMGPqwONX78HnFYlWajdGTbEc_0Q-l_zrhuh3iP2vxvuh1Es75g3X6AxcxTJYn7wfE4whWv_g8NCg6kW7NAM91AmUzf5SG2sEqYa-wy7JYDOIqVj7K6CiagEsKEXEyeu17VrpH5FQCqzfd3pCDECPFbwF28Y7A74VvL45GnmG0Iup5qmcZJWQ60ZYaxxq37jVRGX464-lnygem4leqHBa30_-a6lWywPCiJYSedfxZ1ekrqiAlYAKDS2VpI6fbRmgwQMf4p381iUBIbjpXO7VVneBS4CCY0H1G9TdXVhWsArMzODxw2reTo0oSHyGkXhvImEkBnPeqpJFtT7rc90Aw6BeeZMcVwiM7_1xvfZ6c6N6ldBii4kcJAuQ5qq8Ew-mriYknK1wnX0QzYReO7uu5hgb3jPC5L59MO8LysjBN0JgWRl6z0BU0bPBnClscgkHbkqDtWBToUThpymJSJe9HeH_2PfUWvAUMh-139fUoLsKW27agLYgySuP1vYdNUCxda32R5DlCe-5c_O6cZhokSng9BeFgtldHu1s_phs0w0EYdMuBGzi_n62-77_kGwwHBkwPK4q-ti-dkACMvyQQdbxFOAiQWcLmjAkFelufq_ydYlUst7OzFlJ232onjLV4xRBYvn9aiIoaxCwxFswuWHeQ_SDdOfFcEu12SuOuvH6y9t_s8Tmus_PTbzLoHCX4VOe1hytZV-WCr8M_9RuMseInz1Qb0pIbi6tXgMjLukTVmNu0KOeQrFkEtggpLhYkEE2REajUhlo7gpdWH0nRazsU-cM1WbVChDsf6BXYlaDziOi4DyQViXDWjQ9jM-xUtCaWngVcpnx0wnNd5j04G2oIF1a9T0ZH1_vsgZwvX-KmX-KBY8qcv0zUA3anBKPUeZ0n0JGN7Suj_Upl-IobJM2nv_HbI8CYFFa9SGphxxKSPNA-FMZH0n8cLG50hOWJ7GSn1DtNY3_9uZC4my3nnJ9DDFTS8xhH2-UHHqFy7sAP3GthtDJsydQnZ5lfI47S8J7XC55bWxYrphYOcDhZbn-r2gKIniyncwODrx2yX_4TXHXjxjQScRZliJ-AlmKcFnSXBbL1LPoWSwqtxaB0_f5F9U5CfnPa7kSnmqit6bNvdvzJ3HVWAaUKTkcnLeOAz17MNH9gPuoY2SpXe5siLykWxcwdzYlkCfU9-IbnC_tJqyadfWnVsvOJ6YiPxEOofy-ZFzpq7YRbz3cxLq6Zm3QzKovYPbDEdpimU_pt08HSmQyTqP8WMsoXOF3otqt_Q2nYrRCwljfY-SACU8-zCw0eU_rrV_FLuYgoiwnyFBIWtr35vHs6ZEevpjvBUg-ikkWBgLUV7WpX6V2976orH3oF4hmewllyLDOGaChCcFnOZOj9EEbYJfp6FaqQjzICr1ShXwSp5K_E-BEVax6bsmLkH_AY1B0CIlc_zN_o-sS0vjs4dlQwD7dYciayOFh3nvSwrR-IZiUrPMmnqq-4oo18k7LjNQTQmZh-OWIROBxhfjVIRb0V1MR2SS0INYgtqpycuFjKYgAIxeY_of0BlBwm-4YkuOKzA4gvGY9Cxd4rLx99tU6wR3YQ7VVGX0tLUDPqtyKnjMqxbCRO2ciToXvC6svzG1l0OZdYc-ao_8fha-MHDogUSej4o8dsvd46QZf4dy9teafEtrnJZ3TGVlTOoHjkoFYsXuhKWz6djGIAN6-XSGToaBeBNccgtlr_cCitEW_5QJ3YVjJH7IIZlNJpGC58fq3_KnoX2LnDpdWSbuU-inkNeXMkZA48RbFbvOtjiD4CwsAjKNJ84ay5Tfa-nH0DLdwyXytQk48FWlUMAHdSY7HIAlS2I8bHIcPSaMWk1HcUOrxuxc_J-M8KXmD3OKzNg_p_OeBEjCUne1oiMTiWUSwU3kSbajIu11t6W_wDWx_l0LeGmt1TfNS1cXvq1mbPWZF_0wtUMXGCNrj7040to_mic3SoWwKc6GApePZ9xlktTBRNmdPzxwz1d3Fotrh-ALRrfskXa0quDBI_TerFZs07yboGjhBXbijtXsxw3RLoCPSB6jXDEI7rwz5xoA4D_67B2kL35mM_IPCmu2lqBEJUGKucB4x1E7ru4YungoYLSZynSIFZOtuQ3ZxELtIbNy1rESycClW9D-QmqkoMzUOohvPiVyGdMTP3uChSPCRZ4xiCaSWrQEPRKYm69zBnQtbYAfBsXT0Km-OKANYEDn4KTTZL4nSdkhFKK0dxHBigKJw1YHbw5mUMe1HJ05EfTP3BlClhqDtvQj-ybuPKcJJ-bgqUbf5jg8UrOBoc1s-LsFSCEajvR3Su2xUJM6jlqcRYAFtsGL8weUvlWvrFQ7hnh6WCS099ByIk-lKkMNfbSPD9OBKGAPdXaGPKVSyytzvLgk-Fv-qLCYgIx_-olcGdDGMnNZVrlAysiGK0lAJA0Cxf3qK-5nm4FP-hQ_aVegddt11Kt2zyq5_T8O81sO-DI-Ef4TTEJPr5HfRXVff4I5Mpy5J_-Wso84AdtcCQjU3wjBE0waPP0EIvrBLvxQfG9nQywujk6dte4o2AuT4ysJDD6ff5DP3Ccq0moAKqTXwAA26z3F0qgXV1TaoPoiWXcg8bMIyDvidtXB3yjDWjpgRDkKRnruDwWYeDho0mQqfJeJf8AAjDEYCyYZNm_KFtc8G-6s71hrx8R4OPoO6qn4aCEG06bP8VB24AqoHlIyS7osmWF5SF1pl51otNHVZ-0h5gmLCq58VZJPvFnXwf3Q3ipXUvWVq2jzohlX2T6IPz4NfJjBzu_Veng9HW42sL6qF1aE26lIyG2YD5_1zLRSg0Rsm7BhOQ3ei_Kp-gyseHvVS0L5FxRmtVxMF3OavJg_Y195M0g5k_2ubVVuPzGZq6aGBmTTZedYjdgIJ8QA5Oa70VCwbsNK0ATAsi77I1R1sY15KDblFj4omlu71zzr-PlUecSK3I_VoFzI4g4SFUM3eNm-0lmEqWDKHHhjyhxYIkWGGtfCOB5MOiqEZbnLVNeEvjRaXB6A_LVwtGs-muVB85dp8Xu_-gQF-ctxp7lelY1mnr4lHHJwSL-5_Q5BUn9OScGWIsBG3XSjCOdJMmrwFp4JJs3wNRbJle8WKKb0IVQ65zqBwrUc37ek105KHeU1GiAaJeALGLgTfx62cjGkg98sWemoDGcXiL748ZQvcfbWTNDsk6o4_PLvRfqxttLdZmeiCcmuHBazv_WASwDYwjA2MHHzAOqZCiK84xtJm-SOvoCqmfngwer2e79585hjgsirj8YylH3-C5zu9N9rntDWJtUtGTy71qKV_IY_S-Wp-eEbpIXcD0LR-V1VABfrsF8CLgKnX-Q1x2BGjLywCEUNR7SSP_B8MJ00LNM0uhGF8d6I1t4CO2Njf7gxbCwSXvkXayojvHzvxIElqTBo6H6JFNrD2T7Mhb6arXY0fjmLYfSpAlY07noByxnm2f7qY0Im7oRhM9RiIGmoe0jaaIoH6IRQOc47u_uOh0JbceS2eWMkB1hO-NHy-w5Bdt5g0_wGgyqNjxNKGmpXfUn43rizTk5r3sXvK64fnA6PYXB_zLtF51z-_6kdGMNh3KqWrxldkQUop06wKJ5kjssgLaDnas6tkB6UuBFSpwp5GDWSrD_i5u2aOH-mqWtXu2FQSB_jtj8sDG2gbqDjhz1SWbzZwp-ONgPkgvmpCiUvZ8_lI9BH0JzVjPRMHmACIN3xp4zc-hkK18cTGniYSk2A91uYcgsgsMD6n5iuSzRe1G7zyIRLF3ty177fkDxGsCXYaGUExurD5cLHOtgJU7f6pK4DPcuZs9EbaoIO4vMADEy0rD50D5OxHsGXVdPJHcYZflGFOo3WdU5PbgAGbWeMyi1wsT4VnkzeD2GdQfXH6GmECLL3lyAcnXBml2myeRO-aKqk0QCpd1L054RV-fbr-CuJg9L1k1A8l9dg1t-JvhOaGZT2wBhnt0DrRKJtktXzuKyVUwTffkHlXkASAYiLk8YN6ReHThr540KkF_FZyfADIaPHZ7AaIr6vnKC4jshDYoXTZJRElHlpgLWgo-hBVCmxAYsRHOk2ihwpU8jfLFC_97ZBUZJht6PDiU_fikgiZ_BTE4sLA5ZUs8_GPCN1Tz_hE5FM2YlmyXxEzvorFgItpl8KYQ6cvJvtiXkGakxiJvEqCPHxrn7wwJW6ctPBDFC42X-dVlxueQvuo3yFXJ5w4hapUL6h_bM_KYD365FDnnf-JL2yHsw5mL9y7fydR4eViQemIsj8Iw7_vjOnz21MWsH2h-kS0_BjAd8nPLGNDM7Omi16TXK_9xP8ZysEYnf2JyZeo81tPGg6XmR6fBoKmrBWdwxbxzCR1Gai4umbzlL0vil_nSoOZ9zRl4vR8SDxDpOV7Njp7TsaBy6Cy5bmE7XhxRZKtmZ4upnESY-EcRAch2j1zKlwIhYthrJWG1InsvGa5yotxwY5bhz8VM6TGdiFxC3yn4zwoS0SYf6YlL1C65COj7NiVITkAJQlRcorzyCa-CAPmvJ5BkYV3SvlLtIp2QiKC25pPnZl4U25rWB09LOnLW5ckfcYoCFCL3-QPnwuXdsEAQ-LUDQT8TqiZpnN7-gLSnLVdNgUDoHHkJTndJZFklcMQNCNmGHlTBrz0CDjikVpXmMZZ4Ahy_d0MoUoH1vXGzs-duxFZYXwPNGXGjcYvZ-sFV3R-cNM-SlnAq_XkWA4xxEzDotdYU72u9CeBS8pt1_en1hi7H96FK638PChKZthH7wr6k1M2d-De0QerSiRtAA8egfMnUlAIGBEx40YM-1-UCont-9TiKdkUBxwydb5sBcJZChK0hoIV244-qsByvSM9lAnp8eQV4Q_FqNkTaFJVr0jz9RQE9xIXeHi7KSQkRPRTHCTBxpkiXJf-_pipMZ2r6mWpzLu8ypjycJVFNHT4SjLFN6axjF8iBzSZl5VueIxD7iOmgMT4JSPOTlK3jywOoI2JRgT4eOmWvh-El-M1zwKjvVY6SoVY87CHoSuVtcM6TfVhb9geXjULdXXXtPgzOV9wFkc4W476YY_qtomnMNtU8YU_vBANyRRvlAOoQSnDwh7qW9NvEeAS9aftmlOFfJiWCG9SaLXMP4KIJ9cl-FFLlgREcupLAPb3kqCBF92a8VH1D5f_qPlOzR6HZf6DQjznNkPMZfhbYhr0miB7lYSDn4EaDHxXUbtpfvUpFv7ZjukGP3DvpWrTaNXh2EoNpWmVGJ6ovnYzQlPVtKqcd8XuQxMOm94V9LDLQE_Navc0H2U= \ No newline at end of file diff --git a/data/openvpn-client/smedia-priv.conf.vault b/data/openvpn-client/smedia-priv.conf.vault new file mode 100644 index 0000000..e537847 --- /dev/null +++ b/data/openvpn-client/smedia-priv.conf.vault @@ -0,0 +1 @@ +encrypt$gAAAAABjfQln8FpE4uWbo-nqbkXRv72SVSeQaUKM7H38QT9TfBaXSWHbwMGJLr8wa7LS8IXTy0CiZd6VA3GUi4oWjVAw1qYnuE2Unn4tf99nYqOG1iP9BWMNtR5CKx1tDblaJy9vSvFGQGuSdjHpcRXnfynW3PHJZpHRjqTxMc5wGVNF0Nh1RNADpQ5hcJ66VBpdY1yKVbgMKdrqJqj4a1qm7dqrEemFdVJbR_O3_ZKOM-9rjma18Raje2b9DV-XdcuOs8RsnK_RWzEkBdUnv8AKeW6jV-h9-TEQS4H8A_LDdVOXwh-nF3Um_SCGip2VKo-nJqe3PT38MkBi6VWtReO2AgwE6ZSNxF4c8X8PjDMXnQF8nUhtHLYGNu6qArgT8XeBrRmxESm1bLlkMWsXElTRvtNoVZfwcuapZU2DoMslGmpkf76-ryEPRmmfPtuAgKEY9DsBSnJL1ogp1xqmVucXiePKqfEGhZ1kyTBJFGq3JyLcL8NUoLBbXOwoVLDW_3V1-yg-GolsJ8w_jKMm1f8wKmupSYICOcORuEZy7piKmZRIEYv7Xbi9VVQWd0xY8_3d6VZJKlNSZhv7Sip0maWDA17IAedPSDQmspmqcpgCcBTT1NROFfNYCT3ZiNLsA1A4pSJoER72o_72l1S_NVRc-wwwNoE7eSw77ZftriB8Hx2Ke69phAdT_auwUVP5hR8s99RsS16Gb1W6_TCMj3abwTxM7o4gqpfmlfKf8b1HOu_2NtALy4DITvTTL25c4IbuWDxb7saPR239etoI41BLsANx8Coq2OCm_iHmmeNe8eiz_n_Yu3tE_EIv05eiFxo5GIRIKqbiN-QLdaISeNNUCW01YBMPwnEW9MKqFd7w5eVzdHwdNB0jK_b6bC8G-qura2E6BMOGUfOSqm9P8ylAHvvljEK6wwDDYwt2TUwSi8YpfDThv5xlwAwj6bz8tlBdGDspIRhPth7P9p75ZZQZqDfYnliWl3c5QA4HV6JJ1534CeVpdCJCqfG3Txs43CWkFUxPA7Su1pDVnHBZig1m9Up_KxWSA_nPk2WUzoTIUfwI-e8IE-D0TlZ7Tn73fwpzVR-Bwr6j52D6BAsIx8KFw9yunf_uokDbaGed29SdoITnDthy8SzkVdu04PsaznDZ-D_Dh1uLnZM-F6PKVMh8QmwYsg81D5-fzHqRAYlyBpR4HHtksSDdaWfvYhjR8qedTa0g5X83FcQZ4DuZCnJNa6SNcFpa3DqyLc7iwMckFg2nppKeum2MoP4hQJ_h-CVvd2kgNey9EmrcOXgJs8O5wJEOI-L0oR34XrYhmnGAkjwyng_omt9hTzIGHrbVqktkgkI4ZELFde1TKGbvHVoIC_z2ig_sZZDRqZ5HgNYmAX5mesMWVY4J0Pqr0UL6dUZ_r87__r8eBVGl29uwEw9cEyzbqJh19qOyo0WrVfwr1_8jqBZvhN6Dfss5uJH1Yv7GC4j3Vrsv-fZ-sZTgRSmtid-k1bxTUhlJYYcONc9kqr8ko7EiLQwLO8m-u9AHVoRpIJou3lZ6s3O0pZj6v_P1DAuy6YF8Oa1sC5D3loePdF4V2WV5ElPCBl1GoIxjGo7afM6x4hjzIAxk6anspv7VOL55qq_StfDP7WrVq84Zxn2oUBuc7RV9DvWzTAfZx-Wo7ITwnaUQdsCQ2SVUxOJZpWAxZwPKjFCcNEo5pEmuyBU2OmlyFQo2OAwi7_zhzgMftbpFOUPlAI1MMlSFaxmIRRk3nBKvQQm3uS-bZwy_UcDaWSjZ0QqH1RUIKtrsi_2P3WRz7g2Wojz1paLVcT5GdLXK96aX9N1L2lzS_Q8CYswno5mS9VcUPKylRUMtnNE1QfdBCalg_0q0XVUZaP7Jz5-F0-hbDt0A2uev5YEr0EdZVdhMKnntSo09RB0garHyW2Isw-YqxRAIgVZ69FJ-mNANUgd8n59tsgY9puP-WYd-big5eQM3NoOip5e623rYbOfG3Mtuc-ki6-1-HfJhIEon0vBpTFozgkipEAsn1-yZHWgXTbwbErz5eNNPcdgOUu5SIyJLuwiNv6AO8kRvK8le-TNqbcMF1TAhW09o2IlMPqNxhCBlPc3YtVtj4z3KcrPirUp0m8LCCyykAh3Y3vODbg-H1AOnX5MJUyaHSXrgnRbu2-PsbjwHD9x5VgZTvJgeNYDf8vi6Rqfa8HlKwt-YfmNetMJoiZZ3lT88O1VlaAVuep_TneDixHoqMlLTuWJ_6MnqOjGGap-6tkCYArZVfTufyjrfg6CaU-iLwTWmAPnoqexABc6tfZOHqjWo89uGhVbp_VfsKVfcEIlOKP1ioFCWC01zpCe4hzOJEPWb8DOrg2ZyC4nsHAleL8Ni9CxqNT9J28tnh-7h_K6I0t9wd0eLZTCu0ZY-Atwwb0IICjJmLNN7ac19G6OvSAErw-hw1Aadj-pZtfCYvtFWpu6WzST5pMxejut3Y_4O-CjisN5uGp4zLKsbQ7NGHZUzuSl58Q3I1jc7DyN5xCRa4IDRKZIzf0gr7S9nZ64E3A4NoXo5gemSVnVHlv9luN4-ak_sM36BE05DW-U9UmHtT8Jjj2C97oOq4fgf8dpFZ9bDty0z8pbsvVwkhrDGPw-xzhfu6qlVPLApizYxkxcM6WZYgAM6EjFWeNJu0vP9iUbXCaczXfs3dphmO2NII-DuekHQMjh4sLfWQ3hniN-2yU0S8cHUUl0xRr5_BhsSqC-gbh03UgUeP1d_NSXon0EsBHbl0vOQwJ8XKSyxBRCmNiGhevChiUdhzpVJwmq665KgiL200ldW8uOEIqHA8ZdQmgcxjkuYJtIWrNNTazlNfyFHt1-9Ir-IkAnjEk-l7s3rAqQ-TpFIC7jjYF52rSZ8MTzjxHlftEtkd2ifbqBgvfIlaCn1ff_LMynP1ijq6UX5r7pOlVMIPasJMG08gt7lmLTZIbI0lJKVD9Ar7qBsQzQCD25Y8rlsKFW3YZtGL3RMnPH2BmeszQ4mpNT9MJVe5DhV8IP0YO3ulM5IGiPj9bf9rDb6um8DjG4AfylREez-eZhDvibjJNyK7B4h9FxjhtZQSybXyJxiglUp5UV8oq8XZ4pE2GzE7KJFpjDOBjA7DGFNNSSjUSdtdqHr-4DKv3tBovcGrzQkPkt6omHB_q_cZk3Xi8e0uhMtixDknL5NdHBoXO7LIus1XykUlZLmlMoE8ct0Sqyq7nVGS3966wyBLe3nCgROi210z5sOcCZYzJSrJvlONjV2ltUZ-kJJnjUrcixFaqGcB8w3wxkfFqNrTeMxVqCLpKak4wO8ZS1xF-_46me4RG5cGB-TDU4i7Am5BXX0FrVnAl2TdjRe2qrLJkIZB4HSTJAcmfsj34HOCunTsCgZcLI4y8XbPHoN3PpZMi0o0uy2HMxSE_UUS80hR_pq8gpd1FGyikV9b-UdW0AuDpxYK9MmFNOXUSAl0SXJ77wXWGxFt1kc4WgtLGawRgr8cdE9nYpQr-VKlVvg3j7ruojD7c73tVwkZAi_8F9uiXaxHfszgskAiNOQN2J9jKWwks1XfBXqD-l_4yRBGu0dHCGYI_1xE1CFTUpXsRDoM7EyeR5dXZKWuaAlEetxdlQcyClCFyskAjNCw5ET3_b3wZOaZpGItIEIy0vfdAH9gB9bzDZfjFG13K2Dx5SYVm98ZgbIQMjSXMa-IA99qOPVMpDh6TX6fmH8Q-c-h6W5BeDoO4dR5_36QlADyxEBtvjtb-XaMlbM8ha3V_KpkcT0sOP8fSm6xxkONkVsmms1oYZPcxEu_4pvkJbQNIZKWtbb0BNS5uEen6Sp37nEQN2ERcL8SqxoWVhYs6kiDeVmcycIcGUh0S5NKucw5mwoMnfP9qKK5xG6XKaQtaRgCHb0Ji_W4MmD-jNJayMksi3PD6U_gI3FcEhdZzkgv2YNNWQML4xeKz_VIkzmb8lfmQdoc792YyaWtuEVqR3z-c3L8gUu7VuA6Q6LIqhswK3SB2J9vkUuMLLUvet9vPNsvtLLNJ3kkVGMcTCDNPQGfOF9nh8_gKB7fIJYRLozk9xSP9JoqAtTQlT-lunPNc-52cBkPIo2ziaUc73ICI7eLKJSTfMhTThqvhLGQSv0Lqj87O7gGR9G5U7gxRtz7s5ghEoD-SRv5drvSudPMfKf4KFF9K3KycHdFEGWoL5cGOXetl8y3bmFiT2bjoedmBCboSdr2GZthf9RYcqJwTz54IxkoDp11bgdvo3VWAvEA6Deobsryjb4wq8G1VvlIK9ZaH7gxbKYc4wJ83nIqbO6H_W00rr5uXq9SoArYmKF6eMzI2o_geyPtibmCljDdrx3X78P-8iumHJVqv45pDEo1zkPF0XoXFr0RlIEsiZBOoMGBi9NKZvCAkD4w_cZw82sZQOQv3HkTBfUKrf1K7UsqUXHz5HNyYbmJojUR-ttTY6o3q5ysQ-trToH8KjDBNF6reRdEZh3fuxYt1gnJriCR_RRRI8vOseuJZm8WgoBNSSSyrzCUP_CyCfZrVXxpfPm0ElTalwa6DCyOyKW3MVut_vaneluUZ5Mrfc9mDy0lH3RJ3XREkAOKugqhDQaUh7ExTmPwreEQR8GX0GIxRa6g8QqGljWF8pkkDYXa9CWj2lj3Xwzuj9GYmlY5d-VzFkbWYlsP2k6NrOfzK-2D1ZN9n2TwkMlEj-zQVZtgdt0M9Jvp3tuCku5zxhRXE0JEQPm12wcpuLIJQmb9cgwyTkMMOclkSTeUsepo2xGPNAQ4dK383suQD7TcgFdllyQ1udFUuJTDCDs0rr2OLspxif74qp_x0MF-9dJJfRD6uKPWUzUKhIswzD5nY9EH040DxBnX4n_NNO1xaViNlUiD2NNOL86e3jlxNAqf7Q8DJJ7XHOPpiherB4VbudCad8ddilq3URd-oVRmxR63lVlGdvaDkKBzE13Zpqe2acErEvKfuUgO2oUdXiLBczOSvcGhcELn72jIKkBeR79klJgdNsntCdBzM_o3M-OPzkGpu3u5tIn2al8JwElB_dCdNauJbLo0yYBncXMUs9SZtqdm3Jk_bQYaAJ7Wua9ZJTB5_bT9BTZyj-GEvyAPAS5w3IkwhXE9wA5zlh-LvsK26qWnMiTc3IKCunav8DbEUoSNj_ACTD6zcUqoggiIREjoye-kTlERU09CZZWSmU29zB9gDlYaycGpexcdvdpMBpO1-unw1cdqkBO8bbeb7Jh6eBVYwWbAzKCJutEzJ7jBGNmeRVbqgtLcHrWUD2eW8e_-K-xFJG4Snt0IMIQdetRZVFAio4VR9XEqN6JQ8RjDWX1N5BrWMe5VW1wP7S9Jd_pQpOC4cGRuiIO9ATFamVvmre-CuI789pO8tMVrXQ3GGCI391CVXtQMTyXbRUkU-9r9RVfRX6R-v0TZm4Iq1IY4nDt53QbpACMg1c9KbKZnDoNJ6TCs16oJ0YnAqpCSohXq4d94UsCC61eTPBxRbK8iZ6yCulCxOI9g4-s000KTrS54_cfQ-TBd3OwrKe6aIAfO3w2ZXb-AAnxHlF5ih_0-J2fvFqfkiowa2kecozFwPzcddKRlF2gfGjD3v8LwP0VC7RW3onemwRTVpb7bXXyhKQAoJ33DhVACcU6wC8TpPZpndot8X6B5sZjhbugw2t5yIOHJJLqGNUZPKfN27K5TzeJdVS2t6CcDhhIVtE3O5eOMnUABK6xnDP5SzPbfkWP4yZqbKxbqQuOI9qlyoxZlZIYHqohmF4QgGtCc2SDhQW2qXW88Q7zo_OhUxNLRu7TldSo0qCcMou_vqU8zjhALUtASJQtFlWINGVmxJ0Qci-9OaNWeVBi9Tj9MVFAbcaYKKOxusy3ZQcjfkDueRKP-hZXBUGERj5yN7jEDEGjMKB3ykVRNfWogyX9Jy0TB98UYsb8Fm4-SxGrs8atgnfVZzVQY0vcXEuJPT9MYPZRMIST0-SNcYUlMnnqq6xaSoUwVMyy5VnI_KdilQWJ3Mv42TA23JZcK0kXtsWZY9WQX8ppwimUidvKAWLSKWAN2Po7L_LVOpOl6kI1xqXquD-zFH_XFRr4r3rmm9vYOXL932eSVFKo5S5U7ACSVq6cBXegyf3IxGESxFhb0xTinT7iIjESHh7VwpwWm74F8AtOoPODscL00S6uMevWbYtRSpbf2e8wFJSLImMlE9QKKos2o7HPhpqDLSqA9F3Qtz-ymtmCZADk37ZTwYtpNZzVqSx2iTH_GpgY43gPyollG_LXPVCfj0LKpiylIHZJ75DEqjSvePkGCPQxuqbfVR7PqZ2U1rRSUddhY_VzZvFYjai-GRZDJf1EBSgvnYZolnIcubfggsCYB6iZOgpgxZtPIW1Dz67IhV9-J6rTZMuZ2SSf6zZCxf4JyQ0eTuzu7Bw9scys64R65K1NLe_JCdADQhkW1XqrCfdUIVrxyeYV-W46-LvcGGCfeBmRNfRoPgitnsOHTcHtjd8eGXzGRyXYNKWAfzgZBl0IZS2kMsyj0hOJLoR9b7Cu56vkdAJKKQQb_hu09DQuly9BVG5MG4nxh7UPp6rpwr7b1w58cUcKfEeEeQrzoV5KB_XzycHkYgpbeluBArGkgpgnKUAL47SbyBeFcSSzURxnvnsFFH-s3o1H-BFCHQ4Ciu-vcgxQ7IEywwCRAICLhfFzhoL6N1jw9PMZF-yBaQ6O8cheAzRiP0OFHOk-ygMEuQJu8JzDy0Ux7_Y6lHQGHkmmoVOoRyEFAGsZoPmFwKEF1aNo5_xsOpz5mEyRDeiNh8TvOk9MyW7fwpmDe130YUP6kuzRlkJ7YbChu1WxQspkBn5qFsjrMBav0NfIFO5m3HN4WxuyMlG8ZiXalagGFu8kCKuzvAjf0A8NjBpv8ReOBSDfH1Pa3ABOlShbMCRoFNnuuqje_oflKQ5r1-AboBXjgyJuxa01PeKRazLSvtHR2ETBAgNZTBw8knVWRkvVkNGgVI_AZuZQpirF1iHevGzCl87RsZQoAnoqxwDdkapjXvopi1zKyBu9h3H6z1nv-vYdl6lW-tREjx4eT49spEwq3eOr4rLULTXDcMZBKKDEuFlZDzwVd2diazxMmVYJNEyzmqUs5UeufsAzJeZCGBwA4HxaaxLJu1PzCjeBPKxa7PVaU7SP8dqu8N8MkOOGP4sB6Sjn6e_yoGvx_0tcNRxNhzV7FLsX4cMHKRrXCqphR_k4bea3AqEEbvX9y63p22y1iTVzYtIEXMlzJnusC_5v5ZJxyQRneiYz0z8GIJiZvNBaLkk-zhRndiMoTTiG82bCyL2SuYR8kDFP6naXfXIzH2psP1XHCpmyKGceqBzkuW8BjaYqNM8-DK876sW-xW-zPsacFTYL0iCxHqYILfpCxia1e0JO_-RX4AjGoasftm66wmIOvb_J_lcIDJiDkh9sAH8ZfKF-_Q79Hdi5K97ysEyd7gWU6GZlKh9rdnHTiJbAM9x49EqHM7knzO1i4Jc5ey4DBdx2oLnWOeDoY_bvUyF8qCBJkCOTuBjyeEss8Pg2w8pOyyRZjFPMeatADUPM2UR1cntLHBGkselEkoVMxT_3rzq_lotxAQQERoCoGvnbf4n-nKPE1g2js6tEM6lSg88C-7j83CvwmqqfLe4jE1SwsvQ80q7YsS16c3VKnzH40E7pL_NDl9YlTbrgLDKNKFQIkx-6t0dlMeDb7bB4JiAivEUpJ1RpTdlNOpP-LgfasqI6a1OP7VrXsJEnBIm7xHiqiklJ5WA29511aIfIDrMJPW-U1imBK77jJp_7EenOac5jsgIXayHnh2zBWmzqyddccDtFEwcbyIfxkfoSxkNGjddYkI6ImI2ECRc_ukHVMEIqVH25sOxb-9Lss_aSAi7-qGgAIM7f-KJ3TyMCRMHFPm66xeRTOa8JUi5C0h57nUSG5OvK18uSODYL1BBNM-4JrJGZTVFCot23oLTUmM3M5xNxrJ8VY8JybBraFzgwZ0dJ_tEENSb9x-MZlG42cLhovSOr3vmbwkEN5dVDaK1otC0vgJglyZfXHiBocNPn3Tb1R4wbqEdvXuijUtbKNr3xBWXsKPBrInu4yHkOxNN6eFjtZBcXcIzyQucvrvcFVqjLrZBY7ni5Rrz13b7mDG90BpVF4JBdSuv_5vAw-DbCXYbaXpxo9sUah-68v0EBlILyLqJl5uKLJumCh2r_FYB6yyJrLAmk9Lz8GPhNhC9TyEBTZk2G78_LcMN5y5fJRfElTtXbnTIDjSyN6wAhqFNVoblV_6yZgzXRg1B2PUU0CSzj6aTpXT_2m3fRhKOe9x3Pvd72ZzEj2Ls4Pvn_oFMoPCVTaaNFiX5hu1mbGv67ngJE8egT1xUIJwNC987tIh8c88FnT-D-Z4lyA_PLJ75d-6MwpwNoi3qM-BGt6EUkSlQvFMGFuO2mT8QCY_E8OlKPUmUPiapwzYYj8Gmr7TOxa_H9TJhTvGjWLDc8JkhRb93zjBgwtkxi0ZM4m-EO0RYRkqiz1AtqFPRJKmRQ5C4EURB0bDu89y19YK4YPBhtcCgJ_nvpsG7Bf0IMJsQyH5bVrQSBS2bLZ-ggjjysEO8TaAK79UiBJuW6jbbOANPJVcKC9dSlGkGoft4KJCsP_MyZ28_joWbeamk5Ic4XKxx9ydHCuFPXrk2LfoOrCPyEEOU05dpdCjbBfZhU0q_Lohb4lo3zz8F5wF86V_VZCRfe00gk2DxRyM32zfbhQlf3Ikp5AphpMvqYqKdiwDsAypUJjsbUMOSkjeD6qqgHGfeOR5Mk8s2U21VgXqtHJzhaQud8aiF_8E5vMFOzbY20y5iWMeSK5owu2j5ODmC--iU1HLAX0TnfUKPa48qnYO_s4hG9UTgeOIwZKalnonBIeUPwVk1gUciy4s0-CJ7Nmh2s5s-3Hhqgf8nLaJrnekm_4Yp3iTG9c8UyPYM7JxSM01yFxQreGHBzhpj6Me9hNLqdNGWuNCI3ANnDTFdXb3skQYaFeF8RS0MPEoOfoDeY9nirniZ9bMk69fCUDcUqpKJ6RolFiD_d6raJPnr1FYPpWklmxbh_14VJ6ApJJYbKR9dGcAHGGhISPNsN4arC3RwdTGj24rrwA0zHI-U11MmFwW2fSobW0KKwcnc6-QD-nf5NRowedYCTZxWMwlXzV6Qu3szkTjs_Gn4nWqqBgiJdWAlGNQNIAVqnkDaoGDQccvQNT2mjvFdBL3oKxvTSPVF-xA3ZNBYEzF2YkiIvS8f7GBrfnli6LYecAlEsF6j0kFlUarR8kA1boNpXhbDm8x4TvUk5b4mGhn1dfz77UGmlXhs-bu-XTpY59TsjaIIBGM6CZBM7SRw5vQWEqIXAxhcRBE3sMRj2Da4WnnJVan0l_h8iF4r_XgE5PAmqYL4p_-ENS_thdtDFSnfYWuUU9_U7KCvssJC3FjkIPc-Ix0NmmEiVnyDh9s98sn_KG2k4J2vQ4BPsgkx8chlRd-eBmhyEw4wzBNUII1zis5V_jyJX727r3PEXN-iAOLkWHaVY-kpfQSfVbnb73FPAicZWyKMfnTbDRZBBerKKzZznvC3IEuQowJo2cvfxaKjTKkQyJRyG49QaAxgXl-bv31DOHQRcIvmvRROF-uJjTt0AKrEP5W3wiiznQZxQWZARSpV8MfezoRGdfjUqphJBIE5TdZMhcWW4Yl5tL34QNgqktJRCey3RrN2Q69bv8wiWrXcchotJ64n5xJ6Cawr31H-CajE= \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/_mail_NULL b/data/powerdns/files/bind-zones/_mail_NULL deleted file mode 100644 index 907abc8..0000000 --- a/data/powerdns/files/bind-zones/_mail_NULL +++ /dev/null @@ -1,2 +0,0 @@ -@ IN TXT "v=spf1 -all" -_dmarc IN TXT "v=DMARC1; p=reject" diff --git a/data/powerdns/files/bind-zones/_mail_carlene b/data/powerdns/files/bind-zones/_mail_carlene deleted file mode 100644 index 7a8e210..0000000 --- a/data/powerdns/files/bind-zones/_mail_carlene +++ /dev/null @@ -1,11 +0,0 @@ -@ IN TXT "v=spf1 mx -all" -@ IN MX 10 mail.franzi.business. -_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@kunbox.net; ruf=mailto:dmarc@kunbox.net; fo=0:d:s; adkim=s; aspf=s" -_mta-sts IN TXT "v=STSv1;id=20201111;" -_smtp._tls IN TXT "v=TLSRPTv1;rua=mailto:tlsrpt@kunbox.net" - -mta-sts IN CNAME carlene.kunbox.net. - -2019._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB" - -uo4anejdvvdw8bkne3kjiqavcqmj0416._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnh5Ym9PO7r+wdOIKfopvHzn3KU3qT6IlCG/gvvbmIqoeFQfRbAe3gQmcG6RcLue55cJQGhI6y2r0lm59ZeoHR40aM+VabAOlplekM7xWmoXb/9vG2OZLIqAyF4I+7GQmTN6B9keBHp9SWtDUkI0B0G9neZ5MkXJP705M0duxritqQlb4YvCZwteHiyckKcg9aE9j+GF2EEawBoVDpoveoB3+wgde3lWEUjjwKFtXNXxuN354o6jgXgPNWtIEdPMLfK/o0CaCjZNlzaLTsTegY/+67hdHFqDmm8zXO9s+Xiyfq7CVq21t7wDhQ2W1agj+up6lH82FMh5rZNxJ6XB0yQIDAQAB" diff --git a/data/powerdns/files/bind-zones/_parked b/data/powerdns/files/bind-zones/_parked deleted file mode 100644 index 8331fc4..0000000 --- a/data/powerdns/files/bind-zones/_parked +++ /dev/null @@ -1,3 +0,0 @@ -${HEADER} - -<%include file="bind-zones/_mail_NULL" /> diff --git a/data/powerdns/files/bind-zones/afra.berlin b/data/powerdns/files/bind-zones/afra.berlin deleted file mode 100644 index 93ffc96..0000000 --- a/data/powerdns/files/bind-zones/afra.berlin +++ /dev/null @@ -1,6 +0,0 @@ -${HEADER} - -@ IN AAAA 2a0a:51c0:0:225::2 -@ IN A 193.135.9.29 - -<%include file="bind-zones/_mail_NULL" /> diff --git a/data/powerdns/files/bind-zones/die-brontosaurier-waren-es.org b/data/powerdns/files/bind-zones/die-brontosaurier-waren-es.org deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/die-brontosaurier-waren-es.org +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/emails.sexy b/data/powerdns/files/bind-zones/emails.sexy deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/emails.sexy +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/eskalation.jetzt b/data/powerdns/files/bind-zones/eskalation.jetzt deleted file mode 100644 index 8331fc4..0000000 --- a/data/powerdns/files/bind-zones/eskalation.jetzt +++ /dev/null @@ -1,3 +0,0 @@ -${HEADER} - -<%include file="bind-zones/_mail_NULL" /> diff --git a/data/powerdns/files/bind-zones/felix-kunsmann.de b/data/powerdns/files/bind-zones/felix-kunsmann.de deleted file mode 100644 index 42bac92..0000000 --- a/data/powerdns/files/bind-zones/felix-kunsmann.de +++ /dev/null @@ -1,3 +0,0 @@ -${HEADER} - -<%include file="bind-zones/_mail_carlene" /> diff --git a/data/powerdns/files/bind-zones/flauschehorn.sexy b/data/powerdns/files/bind-zones/flauschehorn.sexy deleted file mode 100644 index 4779fe4..0000000 --- a/data/powerdns/files/bind-zones/flauschehorn.sexy +++ /dev/null @@ -1,8 +0,0 @@ -${HEADER} - -@ IN AAAA 2a03:4000:4d:5e::1 -@ IN A 194.36.145.49 - -<%include file="bind-zones/_mail_carlene" /> - -_acme-challenge IN CNAME 63bc37c61bda3c1f4fa1f270f8890c7f89c24353.acme.ctu.cx. diff --git a/data/powerdns/files/bind-zones/franzi.business b/data/powerdns/files/bind-zones/franzi.business deleted file mode 100644 index ce864a7..0000000 --- a/data/powerdns/files/bind-zones/franzi.business +++ /dev/null @@ -1,29 +0,0 @@ -${HEADER} - -@ IN AAAA 2a0a:51c0:0:225::2 -@ IN A 193.135.9.29 - -<%include file="bind-zones/_mail_carlene" /> - -_atproto IN TXT "did=did:plc:d762mg6wvvmpeu66zojntlof" -_token._dnswl IN TXT "gg3mbwjx9bbuo5osvh7oz6bc881wcmc" -_matrix._tcp IN SRV 10 10 443 matrix.franzi.business. - -; carlene -git IN CNAME carlene.kunbox.net. -irc IN CNAME carlene.kunbox.net. -mail IN CNAME carlene.kunbox.net. -matrix IN CNAME carlene.kunbox.net. -matrix-stickers IN CNAME carlene.kunbox.net. -netbox IN CNAME carlene.kunbox.net. -ntfy IN CNAME carlene.kunbox.net. -postfixadmin IN CNAME carlene.kunbox.net. -rss IN CNAME carlene.kunbox.net. -travelynx IN CNAME carlene.kunbox.net. - -; icinga2 -icinga IN CNAME icinga2.kunbox.net. -status IN CNAME icinga2.kunbox.net. - -; pretix -tickets IN CNAME franzi-business.cname.pretix.eu. diff --git a/data/powerdns/files/bind-zones/kunbox.net b/data/powerdns/files/bind-zones/kunbox.net index 2292b7d..25a0273 100644 --- a/data/powerdns/files/bind-zones/kunbox.net +++ b/data/powerdns/files/bind-zones/kunbox.net @@ -1,37 +1,37 @@ -${HEADER} +$TTL 60 +@ IN SOA ns-primary.kunbox.net. hostmaster.kunbox.net. ( + ${SERIAL} + 3600 + 600 + 86400 + 300 + ) -; ends up on carlene.kunbox.net -@ IN A 193.135.9.29 - IN AAAA 2a0a:51c0:0:225::2 + +${NAMESERVERS} + +$ORIGIN kunbox.net. + +; ends up on rx300.kunbox.net +@ IN A 31.47.232.106 + IN AAAA 2a00:f820:528::2 ; Needs to have a working Mail address, otherwise Telekom goes mimimi - IN MX 10 mail.franzi.business. - IN TXT "v=spf1 mx a:mail.kunsmann.info ~all" + IN MX 10 rx300 + IN TXT "v=spf1 mx ~all" ; delegate acme stuff to psql-managed zone _acme-challenge IN CNAME _acme-challenge.kunbox.net.le.kunbox.net. _acme-challenge.home IN CNAME _acme-challenge.home.kunbox.net.le.kunbox.net. -; aurto, keep old name -aurto IN CNAME aurto.htz-cloud - -; stuff running at home -jellyfin.home IN CNAME nas.home - ; Mail servers -mta-sts IN CNAME carlene +mta-sts IN CNAME rx300 -; legacy Nameservers +; Nameservers ns-1 IN A 34.89.208.78 ns-2 IN A 35.187.109.249 ns-3 IN A 35.228.143.71 -; temp, while updating names -; XXX remove 2023-07-01 -ns-primary IN CNAME ns-mephisto -ns-ionos IN CNAME ns-mephisto -ns-digitalocean IN CNAME ns-ghirahim - % for record in sorted(metadata_records): ${record} % endfor @@ -41,7 +41,7 @@ ${record} ; record here to avoid creating loops. ; We're still publishing DKIM keys and have enabled TLSRPT, though. _mta-sts IN TXT "v=STSv1;id=20201111;" -_smtp._tls IN TXT "v=TLSRPTv1;rua=mailto:tlsrpt@kunbox.net" +_smtp._tls IN TXT "v=TLSRPTv1;rua=mailto:hostmaster@kunbox.net" _token._dnswl IN TXT "6akc10htbgmg56e072w0w2n0wql4oezu" 2019._domainkey IN TXT ( "v=DKIM1; k=rsa; " diff --git a/data/powerdns/files/bind-zones/kunsi.scot b/data/powerdns/files/bind-zones/kunsi.scot deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/kunsi.scot +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/kunsitracker.de b/data/powerdns/files/bind-zones/kunsitracker.de deleted file mode 100644 index 9c641b6..0000000 --- a/data/powerdns/files/bind-zones/kunsitracker.de +++ /dev/null @@ -1,6 +0,0 @@ -${HEADER} - -@ IN AAAA 2a0a:51c0:0:225::2 -@ IN A 193.135.9.29 - -<%include file="bind-zones/_mail_carlene" /> diff --git a/data/powerdns/files/bind-zones/kunsmann.eu b/data/powerdns/files/bind-zones/kunsmann.eu deleted file mode 100644 index f5b8acf..0000000 --- a/data/powerdns/files/bind-zones/kunsmann.eu +++ /dev/null @@ -1,14 +0,0 @@ -${HEADER} - -@ IN AAAA 2a0a:51c0:0:225::2 -@ IN A 193.135.9.29 - -<%include file="bind-zones/_mail_carlene" /> - -@ IN TXT "google-site-verification=Xl-OBZpTL1maD2Qr8QmQ2aKRXZLnCmvddpFdrTT8L34" - -_token._dnswl IN TXT "5mx0rv9ru8s1zz4tf4xlt48osh09czmg" - -git IN CNAME git.franzi.business. -grafana IN CNAME influxdb.htz-cloud.kunbox.net. -influxdb IN CNAME influxdb.htz-cloud.kunbox.net. diff --git a/data/powerdns/files/bind-zones/raptor.events b/data/powerdns/files/bind-zones/raptor.events deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/raptor.events +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/trans-agenda.de b/data/powerdns/files/bind-zones/trans-agenda.de deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/trans-agenda.de +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/trans-agenda.eu b/data/powerdns/files/bind-zones/trans-agenda.eu deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/trans-agenda.eu +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/powerdns/files/bind-zones/warnochwas.de b/data/powerdns/files/bind-zones/warnochwas.de deleted file mode 100644 index 9c641b6..0000000 --- a/data/powerdns/files/bind-zones/warnochwas.de +++ /dev/null @@ -1,6 +0,0 @@ -${HEADER} - -@ IN AAAA 2a0a:51c0:0:225::2 -@ IN A 193.135.9.29 - -<%include file="bind-zones/_mail_carlene" /> diff --git a/data/powerdns/files/bind-zones/winkeeinhorn.de b/data/powerdns/files/bind-zones/winkeeinhorn.de deleted file mode 120000 index e0f69f8..0000000 --- a/data/powerdns/files/bind-zones/winkeeinhorn.de +++ /dev/null @@ -1 +0,0 @@ -_parked \ No newline at end of file diff --git a/data/proftpd/files/home.paperless.conf b/data/proftpd/files/home.paperless.conf deleted file mode 100644 index 49a9c5b..0000000 --- a/data/proftpd/files/home.paperless.conf +++ /dev/null @@ -1,67 +0,0 @@ -Include /etc/proftpd/modules.conf - -UseIPv6 on - - IdentLookups off - - -ServerName "home.paperless" -ServerType standalone -DeferWelcome off - -DefaultServer on - -DisplayLogin welcome.msg -DisplayChdir .message true - -DenyFilter \*.*/ - -RequireValidShell off - -Port 21 - -PassivePorts 49152 50192 - -MaxInstances 30 - -User proftpd -Group nogroup - -Umask 022 022 - -TransferLog /var/log/proftpd/xferlog -SystemLog /var/log/proftpd/proftpd.log - - - QuotaEngine off - - - - Ratios off - - - - DelayEngine on - - - - ControlsEngine off - ControlsMaxClients 2 - ControlsLog /var/log/proftpd/controls.log - ControlsInterval 5 - ControlsSocket /var/run/proftpd/proftpd.sock - - - - AdminControlsEngine off - - - - User nobody - Group nogroup - UserAlias anonymous ftp - - - AllowAll - - diff --git a/data/ssl/_.franzi.business.crt.pem b/data/ssl/_.franzi.business.crt.pem new file mode 100644 index 0000000..b55b2de --- /dev/null +++ b/data/ssl/_.franzi.business.crt.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEijCCA3KgAwIBAgISA8l+oC4pMh1Q/UNiEPuiw39OMA0GCSqGSIb3DQEBCwUA +MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD +EwJSMzAeFw0yMzAxMjkwNDM5NTFaFw0yMzA0MjkwNDM5NTBaMBoxGDAWBgNVBAMT +D2ZyYW56aS5idXNpbmVzczB2MBAGByqGSM49AgEGBSuBBAAiA2IABMlQ1P5Y0aZ5 +vUzB4TAP8iIuiO3GJnYhnKrbe/Lz3gf6Ct9bGM4JLY3RI9xcSmol3sNKdVmbHMRe +z63GW4twSnS517axo6jcT0YQkFVyhWHvLnpBW42M1FpjzaDCbs74zKOCAl4wggJa +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQURw5+tfBU0aOBqfN40kz43fUcjx4wHwYD +VR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEG +CCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0 +dHA6Ly9yMy5pLmxlbmNyLm9yZy8wLQYDVR0RBCYwJIIRKi5mcmFuemkuYnVzaW5l +c3OCD2ZyYW56aS5idXNpbmVzczBMBgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEE +AYLfEwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9y +ZzCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB3AHoyjFTYty22IOo44FIe6YQWcDIT +hU070ivBOlejUutSAAABhfwJ/TEAAAQDAEgwRgIhAINjOWzyMeYZYFNk5cdghSwA +JDuxKo8/ubIlsAV9ymJWAiEAuVZjp2GQ0RmFyGVDiF865uC4lTtzMIwmpgwYiBqg +DQsAdgCt9776fP8QyIudPZwePhhqtGcpXc+xDCTKhYY069yCigAAAYX8Cf1OAAAE +AwBHMEUCIGoeOIHC8O+zj/3E89BHv+9siaKSOy/2I6i53V5faX3EAiEAsk/Lhr/0 +NpogdjroYqt1sKvTzmO0BrxWJ5a41JQdtX0wDQYJKoZIhvcNAQELBQADggEBAIM4 +moszjbZGKjaoCtsj5t7Dtxu/JmE9gOnwfxnUrDKn0T00dKQi8Mk6a4C5vdGnxorO +lj8VutznRvp1RKxb6WWyk0iW22rLm+kTudf/vf9lY0X7DmD/u3MO2tGumwjMdLRT +QgxP+yu8R03ZppnuzYZhERAbY6AuC/U+owiYjNfF4v1Eyn4zxe6L2v0UWGnBWObb +xv5RbhHFezr676GaLIrcVh0rN6YNK2J1Cei2pNtAVSLiSJvuuO5Qq1KE7wQqbGd+ +lqK2tcEZRtzaFrpW7C0ZW7LpgO8zdeN4BtD25ozhGJO/0H5hhKpQ/wtWqXYKkhC/ +G47QSheqKqJnHOCL0hA= +-----END CERTIFICATE----- diff --git a/data/ssl/_.franzi.business.crt_intermediate.pem b/data/ssl/_.franzi.business.crt_intermediate.pem new file mode 100644 index 0000000..efd07a1 --- /dev/null +++ b/data/ssl/_.franzi.business.crt_intermediate.pem @@ -0,0 +1,63 @@ + +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC +ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL +wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D +LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK +4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 +bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y +sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ +Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 +FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc +SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql +PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND +TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 +c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx ++tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB +ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu +b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E +U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu +MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC +5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW +9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG +WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O +he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC +Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 +-----END CERTIFICATE----- diff --git a/data/ssl/_.franzi.business.key.pem.vault b/data/ssl/_.franzi.business.key.pem.vault new file mode 100644 index 0000000..9a5202f --- /dev/null +++ b/data/ssl/_.franzi.business.key.pem.vault @@ -0,0 +1 @@ +encrypt$gAAAAABj1gankGocRRCdH6WqCUFJ6UtA1f07KpXYh4KcelenJv0ZbQ98f2nwIk29iXWEIsS9FTiRyEG95u_Lmm_p7GbKCMDSIZfZgAC2I3tp_BxZPerhEkwxTT_BjEYHRjMDFrzwoAypTO1Mj_XiT_CYvAZptHI3MZcI9QwPVw-CMJ4KqzG-IztkW8KVnuM7agiBdUt4IYkLyeZ0IoL4nOIWANtdM-y4rILv6N7WIMw6dgsSvLPEQR-PYdNLq866IR0-yFGOfYcQKOvpBqAt6A69E6JxSm3AakaJaS75QYF2lzGVjTfrFoGz60LUjC60KuTsu3dUckGUm7JEq1BSMxvc5b_a6pCazvoAnM0gbtbM_DjL0phLj7VWZEg-_1CHfc2S0-UxbxBjLKJ3NPPs93_En5RWxqxkhvvZgxzWJqQWP2eBprge8Q_EEXkMbxumVVx9Ymdynlw2AgkQhVVJIu_vnsZ4Uc8vIA== \ No newline at end of file diff --git a/data/ssl/_.home.kunbox.net.crt.pem b/data/ssl/_.home.kunbox.net.crt.pem index 27e795b..7449694 100644 --- a/data/ssl/_.home.kunbox.net.crt.pem +++ b/data/ssl/_.home.kunbox.net.crt.pem @@ -1,22 +1,27 @@ -----BEGIN CERTIFICATE----- -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 +cK9weiaIniziAnEjUr4= -----END CERTIFICATE----- diff --git a/data/ssl/_.home.kunbox.net.crt_intermediate.pem b/data/ssl/_.home.kunbox.net.crt_intermediate.pem index 4652201..efd07a1 100644 --- a/data/ssl/_.home.kunbox.net.crt_intermediate.pem +++ b/data/ssl/_.home.kunbox.net.crt_intermediate.pem @@ -1,27 +1,63 @@ -----BEGIN CERTIFICATE----- -MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw -WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G -h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV -6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw -gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD -ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj -v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB -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= +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC +ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL +wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D +LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK +4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 +bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y +sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ +Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 +FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc +SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql +PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND +TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 +c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx ++tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB +ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu +b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E +U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu +MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC +5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW +9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG +WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O +he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC +Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 -----END CERTIFICATE----- diff --git a/data/ssl/_.home.kunbox.net.key.pem.vault b/data/ssl/_.home.kunbox.net.key.pem.vault index dda0d06..f3cc906 100644 --- a/data/ssl/_.home.kunbox.net.key.pem.vault +++ b/data/ssl/_.home.kunbox.net.key.pem.vault @@ -1 +1 @@ -encrypt$gAAAAABoLkWaAM6hx5Tl_6sPRVNmmcx9OmWYGmrNLIF4J-p7Xhj4O0fQuPcnph0ZFtmlBNWcfGb8G2ysTeEN1-Be2O4JQamvxUyGFT-Jste8GzAH6btiM6ef1E0FO6ovmzUxAiFZCbeXqKXF0opPz2B6rbDKiU-yTEZpid6-D-yz3uGuunhOjL3RpWJ1ArZRiOoX3DKPf5BXn51-71TEhB-lg41sDqnMfl4lo9_9xb5_2MBLsVZ9EYjcxvwgzq7qtdExtmpkWQ7pU6uPSP5w5wc8MFvRbiXNlOrFMLjslcGp7_cbfBMmA56UCVAe2n8HqWRcKHeYo_gNVUi1nDi2GjBmUYygA9yzFcUBqcV5ZUPK-7uwYxh2ZFbBcbwmTtvXYqEEvTLuZbsYwhV5mJR6b7L3MR81g--9D8pSulsKjbrUXXTZ373SWXz_aQoBLg5vOiL4zUo8T0isXIGcGMS8LUn-LvpQyptE-A== \ No newline at end of file +encrypt$gAAAAABj1kcBpq8c_Ez3JkYJIB0evClkcblewwzBEbl4rfcd-3Z2xFlQ8OggIxGdlLGWjIN_ZBaENvXcqy4ZYlwpXgqrZJpBao8WyovZiKLK759r8qVRjbIBvHnH90t_JZ3-MydlpD1mUzHUy5oQq5Qn8jLoRTzHE2TM8VyhaBkMVQ9gacHdqNGW6dsvCRzXCQM1CNqs8pyc8nQxdARjv_FGwSeZlCxcYPSLEBeE-Hf-wJyVWnG7oyq9XKUyI8NWLPQNwWUjzMgKwumtDh21goRsSRAtLLFmqE_iU1IyZYwNh4J3SBMZKBl0fATtHXhnW1_k-RA1-l54PFMTR0KgS-uxYtqZ1Az0t1KEfEvyzfHAQLJ8RIwOOVtPNUvhSiMHr3jG0WpxymilOLfjFpnCZ8E_CA6L8hmytXEBfoM4ZHMCWzOIe_9tIKcMS146NOzaPnCXpKFganNuvV_S7zEn33zv-jYEHD4d8A== \ No newline at end of file diff --git a/data/ssl/_.home.sophies-kitchen.eu.crt.pem b/data/ssl/_.home.sophies-kitchen.eu.crt.pem deleted file mode 100644 index bc6c33e..0000000 --- a/data/ssl/_.home.sophies-kitchen.eu.crt.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID9jCCA3ygAwIBAgISBaRtAN5dI7hI3l+MeuwXGm48MAoGCCqGSM49BAMDMDIx -CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF -NTAeFw0yNTAzMTkxNzI1NTVaFw0yNTA2MTcxNzI1NTRaMCIxIDAeBgNVBAMTF2hv -bWUuc29waGllcy1raXRjaGVuLmV1MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEMpwz -KfaRqcoUak1UJzHRmcy1Zz/9KmlEoja94JwEO7qqARCOJedwJ/MS8Zkz3ZkJvjv5 -iIXe9u6qbn/C8RS+/UqunvnCxTJeWMcXaI2p9M+DE7PlPQiIP1t/SPQ2QsIso4IC -YzCCAl8wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF -BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSspYDX4yydAiYu+8XZw/Vu7IrW -xDAfBgNVHSMEGDAWgBSfK1/PPCFPnQS37SssxMZwi9LXDTBVBggrBgEFBQcBAQRJ -MEcwIQYIKwYBBQUHMAGGFWh0dHA6Ly9lNS5vLmxlbmNyLm9yZzAiBggrBgEFBQcw -AoYWaHR0cDovL2U1LmkubGVuY3Iub3JnLzA9BgNVHREENjA0ghkqLmhvbWUuc29w -aGllcy1raXRjaGVuLmV1ghdob21lLnNvcGhpZXMta2l0Y2hlbi5ldTATBgNVHSAE -DDAKMAgGBmeBDAECATAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8vZTUuYy5sZW5j -ci5vcmcvNjEuY3JsMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHcATnWjJ1yaEMM4 -W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGVr6ZJYgAABAMASDBGAiEA2TRwcna6 -vp3yZSUfXjd14SFvTZtXucSMJQQERKgwDekCIQCEppv+qukiFo4SjQBMQ50ptVXC -LMJZVy4A6VuMCmj3VQB1AOCSs/wMHcjnaDYf3mG5lk0KUngZinLWcsSwTaVtb1QE -AAABla+mSgEAAAQDAEYwRAIgXjJYEE32AFXfqx43ZOQrgP5cGdK5znOGCSxmjcMg -S/UCIBZNBTNVtJWGYKJQgS+bx7EbDDWobar7shNd1/jK0Kt3MAoGCCqGSM49BAMD -A2gAMGUCMQCoQeeM5wcNWCgtjoWPqduuEP/W0M4UrBydd2tVAAE7dbYb2Batj2Gg -qnaDMK2j/+ACMCNtwr4CWsgMAsK8HlDVM0UBvzEFOy2X+hkGzqOe0kfN+abHP0Sf -L0aZkl5gt8NcKg== ------END CERTIFICATE----- diff --git a/data/ssl/_.home.sophies-kitchen.eu.crt_intermediate.pem b/data/ssl/_.home.sophies-kitchen.eu.crt_intermediate.pem deleted file mode 100644 index 59039ae..0000000 --- a/data/ssl/_.home.sophies-kitchen.eu.crt_intermediate.pem +++ /dev/null @@ -1,27 +0,0 @@ - ------BEGIN CERTIFICATE----- -MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw -WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK -a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO -VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw -gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD -ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw -i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB -AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g -BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu -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----- diff --git a/data/ssl/_.home.sophies-kitchen.eu.key.pem.vault b/data/ssl/_.home.sophies-kitchen.eu.key.pem.vault deleted file mode 100644 index 8f76986..0000000 --- a/data/ssl/_.home.sophies-kitchen.eu.key.pem.vault +++ /dev/null @@ -1 +0,0 @@ -encrypt$gAAAAABn2wvcFmCiy7gpvvwJzRVNJSSxLvlld2ob9O2ivyekdR6y1_k90Q1xZhs7-ombGAIyez1D7lvuNhYQrnff5TqRa9wKbIVyqOOj4lc5qS2jJWyMl9BCr7Fu0mdW0_33Ke5nGpc3mAMjwTLCn8aw-I_I0kALuhKvZ_H31Oy0Mdjw9rau8TmeWGmJDiPMyHlg_C6s2Gvj2VKHVuGeSVg01frjlTveK-ZsJNGvKm7njCqvqGJytFeV6iHzWYyzMTk8-z_xtv-PKH82ME_IdGVv8YcgmCrXWzzA35A3YEaac7uKui1RFzqN6K5sYL1hsxU9rAyidNRd1fp0CRlpyJWgcf_ykoe2u3ManhFOdMmJdx_nrt2znNLaiQqcSHWuws7pGeSZtX72rGa5ZEBF5xeTruhRSQyjMUuBZrqi75QKyYnpmNSpgh0fDHqHUVmSQ5vInd8Tai2BWz3oqKhrkqJMIXlKQn35Jw== \ No newline at end of file diff --git a/data/travelynx/files/imprint/carlene b/data/travelynx/files/imprint/rx300 similarity index 100% rename from data/travelynx/files/imprint/carlene rename to data/travelynx/files/imprint/rx300 diff --git a/data/users/files/tmux/sophie.conf b/data/users/files/tmux/sophie.conf index 80598f6..d8c2819 100644 --- a/data/users/files/tmux/sophie.conf +++ b/data/users/files/tmux/sophie.conf @@ -1,4 +1,39 @@ -### keybindings +# https://github.com/seebi/tmux-colors-solarized/blob/master/tmuxcolors-256.conf +set-option -g status-style bg=colour235,fg=colour136 + +# set window split +bind-key v split-window -h +bind-key b split-window + +# default window title colors +set-window-option -g window-status-style fg=colour39,bg=default,dim + +# active window title colors +set-window-option -g window-status-current-style fg=colour235,bg=colour113,bright + +# pane border +set-option -g pane-border-style fg=colour235 #base02 +set-option -g pane-active-border-style fg=colour240 #base01 + +# message text +set-option -g message-style bg=colour235 #base02 +set-option -g message-style fg=colour166 #orange + +# pane number display +set-option -g display-panes-active-colour colour33 #blue +set-option -g display-panes-colour colour166 #orange +# clock +set-window-option -g clock-mode-colour green #green + + +set -g status-interval 1 +set -g status-justify left # center align window list +set -g status-left-length 14 +set -g status-right-length 140 +#set -g status-left '#[default]〘 ' +set -g status-left '#[fg=green,bright]#(uname -r | cut -c 1-8)#[default]〘' +set -g status-right "〙#[fg=red,bg=default]⇑#(uptime -p |sed 's/\ week/w/; s/\ days/d/; s/\ day/d/; s/\ hours/h/; s/\ minutes/m/; s/\ minute/m/; s/,//g; s/up//') #[fg=green,bg=default]⎋ #(cat /proc/loadavg | awk '{print $1,$2,$3}') #[fg=blue] %Y-%m-%d #[fg=white,bg=default] %H:%M #[fg=green] #H" + # C-b is not acceptable -- Vim uses it set-option -g prefix C-a bind-key C-a last-window @@ -24,7 +59,17 @@ set -g visual-activity on # Vi copypaste mode set-window-option -g mode-keys vi +#bind-key -t vi-copy 'v' begin-selection +#bind-key -t vi-copy 'y' copy-selection +#/home/sophie/.tmux.conf:68: usage: bind-key [-cnr] [-T key-table] key command [arguments] [0/0] + + +# hjkl pane traversal +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R # set to main-horizontal, 60% height for main pane bind m set-window-option main-pane-height 60\; select-layout main-horizontal @@ -34,51 +79,28 @@ bind-key C command-prompt -p "Name of new window: " "new-window -n '%%'" # reload config bind r source-file ~/.tmux.conf \; display-message "Config reloaded..." -# set window split -bind-key v split-window -h -bind-key b split-window - # auto window rename set-window-option -g automatic-rename -set -g status-interval 2 +# color +set -g default-terminal "tmux-256color" -#################################### -# new theme +# status bar +#set-option -g status-utf8 on -set-window-option -g status-style bg=colour236,fg=white -# left -set-window-option -g status-left "#[bg=colour240,fg=white] #S #[fg=colour236,reverse]" -set-window-option -g status-left-length 40 -# right -set-window-option -g status-right "#[fg=black,bg=colour208]#(uptime -p |sed 's/\ week/w/; s/\ day/d/; s/\ hour/h/; s/\ minute/m/; s/s//g; s/,//g; s/up//') #[bg=colour236,fg=white] #(cat /proc/loadavg | awk '{print $1,$2,$3}') #[fg=colour252]#[fg=black,bg=colour252,nobold] %Y-%m-%d #[bold]%H:%M #[fg=colour231,bg=colour240] #H " -set-window-option -g status-right-length 80 -# Status bar window currently active -set-window-option -g window-status-current-format "#[fg=colour236]#[default,bold] #I #[fg=colour123,reverse]#[default]#[bg=colour123] #W #[fg=colour236,reverse]" -# colour33 is green -set-window-option -g window-status-current-style none,bg=colour33,fg=black -# Status bar window in background (not active) -set-window-option -g window-status-format "#[fg=colour236,nounderscore]#[default,bold,nounderscore] #I #[fg=colour240,reverse]#[default]#[bg=colour240]#[nounderscore] #[default]#[fg=colour231,bg=colour240]#W#[nounderscore] #[fg=colour236,reverse]" +# https://github.com/edkolev/dots/blob/master/tmux.conf +# Updates for tmux 1.9's current pane splitting paths. -# Black on green -set-window-option -g window-status-style none,bg=colour76,fg=black +# from powerline +run-shell "tmux set-environment -g TMUX_VERSION_MAJOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f1 | sed 's/[^0-9]*//g')" +run-shell "tmux set-environment -g TMUX_VERSION_MINOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f2 | sed 's/[^0-9]*//g')" -# -# Status bar window last active (Tmux 1.8+) -# +# rm mouse mode fail +if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -ge 1\) -o #{$TMUX_VERSION_MAJOR} -gt 2' 'set -g mouse off' +if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 1\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'set -g mode-mouse off' -set-window-option -g window-status-last-style none,bg=cyan,fg=black - -# -# Status bar window with activity/silence (monitor-activity, monitor-silence) -# - -# colour127 is pink -set-window-option -g window-status-activity-style bold,bg=colour127,fg=black - -# -# Status bar window with bell triggered -# - -# red is urgent -set-window-option -g window-status-bell-style bold,bg=red,fg=black +# fix pane_current_path on new window and splits +if-shell "#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)" 'unbind c; bind c new-window -c "#{pane_current_path}"' +if-shell "#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)" "unbind '\"'; bind '\"' split-window -v -c '#{pane_current_path}'" +if-shell "#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)" 'unbind v; bind v split-window -h -c "#{pane_current_path}"' +if-shell "#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)" 'unbind %; bind % split-window -h -c "#{pane_current_path}"' diff --git a/groups.py b/groups.py index b5acfd9..d99ced7 100644 --- a/groups.py +++ b/groups.py @@ -3,6 +3,7 @@ from pathlib import Path from bundlewrap.utils import error_context +groups = {} for group in Path(join(repo_path, "groups")).rglob("*.py"): with error_context(filename=str(group)): with open(group, 'r') as f: diff --git a/groups/features.py b/groups/features.py index 04dc7d0..fca9379 100644 --- a/groups/features.py +++ b/groups/features.py @@ -11,11 +11,6 @@ groups['dns'] = { 'powerdns', }, 'metadata': { - 'apt': { - 'unattended-upgrades': { - 'spread_in_group': 'dns', - }, - }, 'powerdns': { # Overridden in node metadata for primary server 'is_secondary': True, @@ -27,11 +22,6 @@ groups['switches-mikrotik'] = { 'bundles': { 'routeros', }, - 'metadata': { - 'routeros': { - 'syslog-server': '172.19.138.20', - }, - }, 'locking_node': 'home.router', 'os': 'routeros', 'username': 'admin', diff --git a/groups/locations.py b/groups/locations.py index 43e7674..94d7d8d 100644 --- a/groups/locations.py +++ b/groups/locations.py @@ -1,3 +1,32 @@ +groups['gce'] = { + 'bundles': { + 'gce-workaround', + }, + 'member_patterns': { + r"gce\..*", + }, + 'metadata': { + 'hosts': { + 'entries': { + '169.254.169.254': { + 'metadata.google.internal', + }, + }, + }, + 'location': 'gce', + 'nameservers': { + '8.8.8.8', + '8.8.4.4', + }, + 'postfix': { + # It's fine to do this without authentificating to the relayhost. + # These Systems are not supposed to send mail anywhere else + # than our own domains. + 'relayhost': '[rx300.kunbox.net]:2525', + }, + }, +} + groups['htz'] = { 'subgroup_patterns': { r'htz\-.+', @@ -49,33 +78,29 @@ groups['home'] = { 'home.router', }, 'vars.notification.sms': False, - 'show_on_statuspage': False, }, 'postfix': { # It's fine to do this without authentificating to the relayhost. # These Systems are not supposed to send mail anywhere else # than our own domains. - 'relayhost': '[mail.franzi.business]:2525', + 'relayhost': '[rx300.kunbox.net]:2525', }, }, } -groups['sophie'] = { - 'supergroups': { - 'linux', - }, +groups['ovh'] = { 'member_patterns': { - r"sophie\..*", + r"ovh\..*", }, 'metadata': { - 'icinga_options': { - 'exclude_from_monitoring': True, - }, - 'backup-client': { - 'target': 'htz-hel.backup-sophie', + 'location': 'ovh', + 'postfix': { + 'relayhost': '[rx300.kunbox.net]:2525', }, 'users': { - 'sophie': {}, + 'debian': { + 'delete': True, + }, }, }, } @@ -92,9 +117,6 @@ groups['voc'] = { 'day': 1, }, }, - 'icinga_options': { - 'show_on_statuspage': False, - }, 'location': 'voc', }, } diff --git a/groups/os.py b/groups/os.py index 34f49b2..a1f3b72 100644 --- a/groups/os.py +++ b/groups/os.py @@ -13,13 +13,13 @@ groups['raspberry'] = { groups['linux'] = { 'subgroups': { + 'arch', 'debian', 'raspberry', }, 'bundles': { 'basic', 'cron', - 'kernel-modules', 'nftables', 'openssh', 'postfix', @@ -33,13 +33,21 @@ groups['linux'] = { 'users', }, 'metadata': { + 'apt': { + 'unattended-upgrades': { + 'reboot_mail_to': libs.defaults.hostmaster_email, + }, + }, 'backup-client': { - 'target': 'backup-kunsi', + 'target': 'htz-hel.backup-kunsi', }, 'firewall': { 'port_rules': { '*': { - 'icinga2', + 'ovh.icinga2', + }, + '*/udp': { + 'ovh.icinga2', }, }, }, @@ -47,9 +55,18 @@ groups['linux'] = { 'pip_command': 'pip3', } +groups['arch'] = { + 'bundles': { + 'pacman', + }, + 'os': 'arch', +} + groups['debian'] = { - 'subgroup_patterns': { - '^debian-[a-z]+$', + 'subgroups': { + 'debian-buster', + 'debian-bullseye', + 'debian-sid', }, 'bundles': { 'apt', @@ -67,14 +84,6 @@ groups['debian-bullseye'] = { 'os_version': (11,) } -groups['debian-bookworm'] = { - 'os_version': (12,) -} - -groups['debian-trixie'] = { - 'os_version': (13,) -} - groups['debian-sid'] = { 'os_version': (99,) } diff --git a/hooks/deploy_commit_hash_to_node.py b/hooks/deploy_commit_hash_to_node.py deleted file mode 100644 index caddaad..0000000 --- a/hooks/deploy_commit_hash_to_node.py +++ /dev/null @@ -1,5 +0,0 @@ -def node_apply_end(repo, node, duration, interactive, result, **kwargs): - if not node.os in node.OS_FAMILY_UNIX: - return - - node.run(f'echo "{repo.revision}" > /var/lib/bundlewrap/last_apply_commit_id') diff --git a/hooks/test_apply_dummy_mode.py b/hooks/test_apply_dummy_mode.py deleted file mode 100644 index 8ba58c1..0000000 --- a/hooks/test_apply_dummy_mode.py +++ /dev/null @@ -1,8 +0,0 @@ -from os import environ - -from bundlewrap.exceptions import SkipNode - - -def node_apply_start(repo, node, interactive=False, **kwargs): - if environ.get('BW_VAULT_DUMMY_MODE') or environ.get('BW_PASS_DUMMY_MODE'): - raise SkipNode('refusing apply because dummy mode is active') diff --git a/hooks/test_unattended_upgrades_spread.py b/hooks/test_unattended_upgrades_spread.py deleted file mode 100644 index dbf87ce..0000000 --- a/hooks/test_unattended_upgrades_spread.py +++ /dev/null @@ -1,24 +0,0 @@ -from bundlewrap.exceptions import BundleError -from bundlewrap.utils.text import bold, green, yellow -from bundlewrap.utils.ui import io - - -def test(repo, **kwargs): - for node in repo.nodes: - if not node.has_bundle('apt'): - continue - - spread = node.metadata.get('apt/unattended-upgrades/spread_in_group', None) - if spread is None: - continue - - for rnode in repo.nodes_in_group(spread): - rspread = rnode.metadata.get('apt/unattended-upgrades/spread_in_group', None) - - if spread != rspread: - raise BundleError(f'{node.name} sets apt/unattended-upgrades/spread_in_group to "{spread}", but node {rnode.name} in that group does set "{rspread}"!') - - io.stdout('{x} {node} apt/unattended-upgrades/spread_in_group matches'.format( - x=green("✓"), - node=bold(node.name), - )) diff --git a/hooks/test_zfs_consistency.py b/hooks/test_zfs_consistency.py index d7231e5..132afe3 100644 --- a/hooks/test_zfs_consistency.py +++ b/hooks/test_zfs_consistency.py @@ -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, diff --git a/libs/defaults.py b/libs/defaults.py index 3125b48..e746722 100644 --- a/libs/defaults.py +++ b/libs/defaults.py @@ -5,18 +5,17 @@ influxdb_org = 'encrypt$gAAAAABgg9hyjz4XtvG8NBw9uYxiumS3v7YKIrtc9tTTABg1f9R22gzn influxdb_token = 'encrypt$gAAAAABgg9Ag632Xyuc6SWXaR1uH2tLOChmVKAoBIikhjntSSD2qJFL_eouVQGXCLH2HEuSbSdEXcTPn2qmhOiA9jmFdoDSbVbQUsp0EID1wLsWYG_Um2KOxZSF-tn9eDZlgShQYySjzO3nQRmdlJpVLUnGHsiwv_sHD2FstXGpfzTPZq5_egUqEc0K2X-aN2J6BTYc2fZAN' influxdb_url = 'https://influxdb.kunsmann.eu/' -nameservers_ipv4 = ['1.1.1.1', '1.0.0.1'] -nameservers_ipv6 = ['2606:4700::1111', '2606:4700:4700::1001'] +nameservers_ipv4 = ['9.9.9.10'] +nameservers_ipv6 = ['2620:fe::10'] nameservers = [*nameservers_ipv4, *nameservers_ipv6] # FIXME database conflicts redis_databases = { 'matrix-media-repo': 7, 'netbox': (4, 5), - 'nextcloud': 7, + 'rspamd': 6, 'paperless-ng': None, # probably 0, but undocumented 'pretalx': (1, 2, 3), - 'rspamd': 6, } security_email = f'mailto:{hostmaster_email}' diff --git a/libs/demagify.py b/libs/demagify.py deleted file mode 100644 index 02180f0..0000000 --- a/libs/demagify.py +++ /dev/null @@ -1,22 +0,0 @@ -import bwpass - - -def demagify(something, vault): - if isinstance(something, str): - if something.startswith('!bwpass:'): - return bwpass.password(something[8:]) - elif something.startswith('!bwpass_attr:'): - identifier, attribute = something[13:].split(':', 1) - return bwpass.attr(identifier, attribute) - elif something.startswith('!decrypt:'): - return vault.decrypt(something[9:]) - return something - elif isinstance(something, dict): - return {k:demagify(v, vault) for k,v in something.items()} - elif isinstance(something, list): - return [demagify(i, vault) for i in something] - elif isinstance(something, set): - return {demagify(i, vault) for i in something} - elif isinstance(something, tuple): - return tuple([demagify(i, vault) for i in something]) - return something diff --git a/libs/faults.py b/libs/faults.py index 848ea84..91d8b2f 100644 --- a/libs/faults.py +++ b/libs/faults.py @@ -1,10 +1,7 @@ from json import dumps, loads -from tomlkit import dumps as toml_dumps - from bundlewrap.metadata import metadata_to_json from bundlewrap.utils import Fault -from bundlewrap.utils.text import toml_clean def resolve_faults(dictionary: dict) -> dict: @@ -40,19 +37,3 @@ def join_faults(faults, by=' '): lambda o: by.join([i.value for i in o]), o=result, ) - - -def dict_as_json(json): - return Fault( - 'dict_as_json', - lambda o: metadata_to_json(o) + '\n', - o=json - ) - - -def dict_as_toml(toml): - return Fault( - 'dict_as_toml', - lambda o: toml_clean(toml_dumps(resolve_faults(o), sort_keys=True)) + '\n', - o=toml - ) diff --git a/libs/firewall.py b/libs/firewall.py index 7a2fa32..b343824 100644 --- a/libs/firewall.py +++ b/libs/firewall.py @@ -44,8 +44,3 @@ named_networks = { }, }, } - -global_ip4_blocklist = { - "141.98.11.0/24", # 2024-01-21, smtp login bruteforce -} -global_ip6_blocklist = set() diff --git a/libs/s2s.py b/libs/s2s.py index 8372ec2..1d57128 100644 --- a/libs/s2s.py +++ b/libs/s2s.py @@ -4,38 +4,18 @@ AS_NUMBERS = { # 4290xxxxxx 'home': 4290000138, 'htz-cloud': 4290000137, - 'ionos': 4290000002, - 'revision': 4290000078, - 'rottenraptor': 4290000030, -} - -WG_AUTOGEN_NODES = [ - # only ever append to this list. If a node vanishes, set its name to - # `None`. You may remove nodes from the end of this, though it's not - # recommended to do so. - - None, # fkusei-locutus never used this - 'home.router', - 'htz-cloud.wireguard', - 'icinga2', - None, # daisy -] - -WG_AUTOGEN_SETTINGS = { - # special settings to apply when peering with a specific node - 'home.router': { - 'firewall': {'versatel'}, - 'no_autoconnect': True, - 'persistent_keepalive': False, - }, + 'ovh': 4290000001, } def get_subnet_for_connection(repo, peer_a, peer_b): - assert peer_a in WG_AUTOGEN_NODES - assert peer_b in WG_AUTOGEN_NODES + # XXX this assumes there are never more than 128 nodes which match that expression + nodes = sorted({node.name for node in repo.nodes if node.has_bundle('wireguard')}) - pos_peer_a = WG_AUTOGEN_NODES.index(peer_a) - pos_peer_b = WG_AUTOGEN_NODES.index(peer_b) + assert peer_a in nodes + assert peer_b in nodes + + pos_peer_a = nodes.index(peer_a) + pos_peer_b = nodes.index(peer_b) vpn_subnet = list(IPv4Network('169.254.0.0/16').subnets(new_prefix=24))[pos_peer_a] return list(IPv4Network(vpn_subnet).subnets(new_prefix=31))[pos_peer_b] diff --git a/libs/ssh.py b/libs/ssh.py index fe3b9b4..90fb674 100644 --- a/libs/ssh.py +++ b/libs/ssh.py @@ -3,10 +3,12 @@ from functools import lru_cache from hashlib import sha3_224 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey -from cryptography.hazmat.primitives.serialization import (Encoding, - NoEncryption, - PrivateFormat, - PublicFormat) +from cryptography.hazmat.primitives.serialization import ( + Encoding, + NoEncryption, + PrivateFormat, + PublicFormat, +) from bundlewrap.utils import Fault diff --git a/libs/tools.py b/libs/tools.py index 4f98677..40afde2 100644 --- a/libs/tools.py +++ b/libs/tools.py @@ -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): """ Try to resolve an identifier (group or node). Return a set of ip addresses valid for this identifier. @@ -34,15 +34,6 @@ def resolve_identifier(repo, identifier, linklocal=False, only_physical=False, a found_ips = set() for node in nodes: for interface, config in node.metadata.get('interfaces', {}).items(): - if only_physical and not ( - interface.startswith('bond') or - interface.startswith('br') or - interface.startswith('en') or - interface.startswith('et') or - interface == 'default' # dummy nodes use these - ): - continue - for ip in config.get('ips', set()): if '/' in ip: found_ips.add(ip_address(ip.split('/')[0])) @@ -62,15 +53,7 @@ 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: diff --git a/nodes.py b/nodes.py index 1798613..9be84b4 100644 --- a/nodes.py +++ b/nodes.py @@ -7,15 +7,6 @@ import bwpass from bundlewrap.metadata import atomic from bundlewrap.utils import error_context -for name, data in nodes.items(): - data.setdefault('metadata', {}) - - if 'password' in data: - data['password'] = vault.decrypt(data['password']) - if 'ipmi' in data: - data['ipmi'].update(libs.demagify.demagify(data['ipmi'], vault)) - data['metadata'].update(libs.demagify.demagify(data['metadata'], vault)) - for node in Path(join(repo_path, "nodes")).rglob("*.py"): with error_context(filename=str(node)): with open(node, 'r') as f: @@ -24,3 +15,6 @@ for node in Path(join(repo_path, "nodes")).rglob("*.py"): for name, data in nodes.items(): data.setdefault('hostname', '.'.join(reversed(name.split('.'))) + '.kunbox.net') data.setdefault('metadata', {}).setdefault('hostname', '.'.join(reversed(name.split('.'))) + '.kunbox.net') + + if 'password' in data: + data['password'] = vault.decrypt(data['password']) diff --git a/nodes/attributes.py b/nodes/attributes.py deleted file mode 100644 index eda23f4..0000000 --- a/nodes/attributes.py +++ /dev/null @@ -1,37 +0,0 @@ -from bundlewrap.utils.scm import get_rev -from bundlewrap.utils.text import bold, red -from bundlewrap.utils.ui import io - - -@node_attribute -def needs_apply(node): - if node.dummy: - return False - - if node.os not in node.OS_FAMILY_UNIX: - return True - - try: - applied = node.run( - 'cat /var/lib/bundlewrap/last_apply_commit_id', - may_fail=True, - ).stdout.decode().strip() - - if not applied or applied != get_rev(): - return True - except Exception as e: - io.stderr(f'{red("!!!")} {bold(node.name)} {e!r}') - - return False - - -@node_attribute -def uses_bw_managed_ssl(node): - if not node.has_bundle('nginx'): - return False - - for vhost in node.metadata.get('nginx/vhosts', {}).values(): - if vhost['ssl'] not in (None, False, 'letsencrypt'): - return True - - return False diff --git a/nodes/aurto.py b/nodes/aurto.py new file mode 100644 index 0000000..d7a98c3 --- /dev/null +++ b/nodes/aurto.py @@ -0,0 +1,99 @@ +nodes['aurto'] = { + 'hostname': '31.47.232.107', + 'bundles': { + 'backup-client', + 'check-mail-received', + }, + 'groups': { + 'arch', + 'webserver', + }, + 'metadata': { + 'icinga_options': { + 'also_affected_by': { + 'rx300', + }, + 'period': 'daytime', + }, + 'backups': { + 'paths': { + '/var/cache/pacman/aurto', + }, + }, + 'check-mail-received': { + 't-online': { + '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'), + }, + }, + 'description': [ + 'When adding packages to aurto, please also add those packages to ~/PACKAGES', + 'Wenn Pakete zu aurto hinzugefügt werden, trage sie bitte auch in ~/PACKAGES ein', + ], + 'interfaces': { + 'enp1s0': { + 'ips': { + '31.47.232.107/29', + '2a00:f820:528::3/64', + }, + 'gateway4': '31.47.232.105', + 'gateway6': '2a00:f820:528::1', + }, + }, + 'nginx': { + 'vhosts': { + 'aurto': { + 'domain': 'aurto.kunbox.net', + 'webroot': '/var/cache/pacman/aurto', + 'extras': True, + }, + }, + }, + 'pacman': { + 'enable_aurto': False, + 'additional_config': { + 'Include = /etc/pacman.d/aurto', + }, + 'unattended-upgrades': { + 'is_enabled': True, + 'hour': 22, # one hour after the host + }, + }, + 'sudo': { + 'extra_configs': { + '50_aurto_passwordless': { + '%wheel ALL=(ALL) NOPASSWD: /usr/bin/arch-nspawn', + '%wheel ALL=(ALL) NOPASSWD: /usr/bin/pacsync aurto', + '%wheel ALL=(ALL) NOPASSWD:SETENV: /usr/bin/makechrootpkg', + }, + }, + }, + 'users': { + 'aurto': { + 'groups': { + 'wheel', + }, + 'ssh_pubkey': { + # e1mo + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBfbb4m4o89EumFjE8ichX03CC/mWry0JYaz91HKVJPb e1mo', + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID9x/kL2fFqQSEyFvdEgiM2UKYAZyV1oct9alS6mweVa e1mo (ssh_0x6D617FD0A85BAADA)', + # f2k1de + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGrvhqC/tZzpLMs/qy+1xNSVi2mfn8LXPIEhh7dcGn9e', + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDH5+j2vDW1FHSSEEI/Sf5qiKJq1uoxGO5BPv84mqohvol7GxDFObv69tn7g6HYfZY/SaS75C4ZXy+cKa0xy8UCpF0SBa2xHASkenS9v55oweDL4rYSPARzn2XKt3RFJG/d8V5NOWtcyq5DFSzewUF35E4hx1pUc/CIxgJEem5ZvzvN0hlIKXUN2djkVUx+mz6RryBysLTJEFBamjJxIkvDG/PZU73W4SHaKAYV4Ojz2NY7T5/NYKePfIU5F9pkE3RU0LRj58usvA1eP0PvEArWlGNCd8EJU+HQ5xr2dZ6MKPpEyG0KJkC88DuapeF5RwUV53ZhNpF+QgzpI72fH5up', + # kunsi + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICYst1HK+gJYhNxzqJGnz4iB73pa89Xz2yH+8wufOcsA', + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+ja1z5VRQzaKCCePsUM14qMr9QR94qlWc7Je5Poki9UmC1t/TyxRVzcCBL1ZdIfBGx6QKtfkEbvhgb3nxVt3PvXjoJrc6wwGLmNrVsU6B88y35g7nzupQiPKYJwkNzJ9j6Dmkgj1F5Q+aY2SitDaX6vqICLJ4Al/ZFw2IQxVJfC7JXRJ9jRMG5o9gWoE3gWDYEAmw+HU2mNzyeuaD12qJw9DHUimAlgkOWzll3gh9WclsYnnXGrCCn5fyHFUCJl+XXAIy519z7YTpKih02rsIOw5dnaGClBZD/YQu2ZKVFZiwIVH7aBiqHOmtgRyWTQgjbh/fMpIN0ar2f/iZsWYUjd6et48TOmXZYIPCQ5FivXNvxt9oo1XZfq76UHBwlmypLJIWROMbz375n2M6hr3hECuxuPjKEUXAv05KiC1aJ4xc6pFoVhqwAR99hvHw5U4o7/ko2NVjNpTu6Jr5DT5VaQLIdDDjC/93kUjMpdD/8P72bEn7454+WexU6OE6uvNiHj1fetrptr2UAuzVfnCoaV8pBqY7X95gk+lnSENdpr8ltJYMg8s0Z7Pzz0OxsZtzzDY5VmWfC9TCdJkN5lT8IbnaixsYlWdjQl1lMmZGElmelfU3K7YQLAbZiHmHKe4hTl9ZoCcWdTQ3d4y2t1DBos+N2HZNdtFCyOS8esDdMw== cardno:000609506971', + # n0emis + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcOPtW5FWNIdlMQFoqeyA1vHw+cA8ft8oXSbXPzQNL9 n0emis@n0emis.eu', + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8xqVakxJ+AwcIrS/wyL03N++pE09epwMFlIMXWvlpwwEp1J/0H7nygwxk/9LIZdabs/ETWn0s8oHAkc7YR1c6ajSTCDiZEYATAWt7t8t4Gw/80c8u8T50lIqmiDEEVbOVv3Vta/pAN4hAUp9U5DpYCkQbvF+NKKcK3Yp8d9usNC6ohqgTK+IGAEdMhvpbbNppDMXoWHuynBzUX7TS6ST6yEr0tD+CBbCpbfcMuwTI3lNtfywEVpuFaeHqDZx2QDrEX4bg0dRKgQstbXYdqmBfnOiBpUr8Wyl8U1J24rN+E07pBw/8KDGWbVg19/Ex8o4ht/p5voUfKVjD/DwWXTLntBirjfAgQAm4GH/qP4x3zNiTtlYlQFbXSk6VEVrTrxCB5rTWvGnhg31tk5P3YwvagDmGABazY5s/8tlttSc1yWBctWQJCjxSqcCLekxG4D1rVuGKCKOZgflQ9QFdQlKycInPBek3zi0i3GYkE1YnNFye5ggOnxT8qGuKjfdtZI9qvMJQO8lbEDzbYQvNns1V/k4ZobiihYwrG5TJUzZFEpMYetDK6tI8BRU11d+ja0jWzguj5/7wc0nrr/BiZ8FkAr2fZ60j2aI5kG0s3qjbrQbB/RXaGP9hRU0+480+IokNJJIcjv5iwH5ophdrjC8GH4So2kPPt0NXob1yNysdjw== simeon@noemis.me (OLD)', + }, + }, + 'kunsi': { + 'groups': { + 'wheel', + }, + }, + }, + }, +} diff --git a/nodes/backup-kunsi.toml b/nodes/backup-kunsi.toml deleted file mode 100644 index 4a47ae4..0000000 --- a/nodes/backup-kunsi.toml +++ /dev/null @@ -1,38 +0,0 @@ -hostname = "2001:67c:b54:1::f" -bundles = ["backup-server", "dm-crypt", "zfs"] -groups = ["debian-bookworm"] - -[metadata] -nameservers = ["2001:4860:4860::8888"] - -[metadata.apt.packages.qemu-guest-agent] - -[metadata.apt.unattended-upgrades] -# requires manual apply to unlock disks -reboot_enabled = false - -[metadata.interfaces.ens18] -ips = ["2001:67c:b54:1::f/64"] -gateway6 = "2001:67c:b54:1::1" - -[metadata.backups] -# this is the backup server -exclude_from_backups = true - -[metadata.backup-server.zpool_create_options] -ashift = 12 - -[metadata.backup-server.encrypted-devices.WVT0RNKF] -device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi4" -passphrase = "!bwpass:bw/backup-kunsi/ata-ST20000NM007D-3DJ103_WVT0RNKF" - -[metadata.backup-server.encrypted-devices.WVT0V0NQ] -device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi5" -passphrase = "!bwpass:bw/backup-kunsi/ata-ST20000NM007D-3DJ103_WVT0V0NQ" - -[metadata.backup-server.encrypted-devices.WVT0W64H] -device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi6" -passphrase = "!bwpass:bw/backup-kunsi/ata-ST20000NM007D-3DJ103_WVT0W64H" - -[metadata.zfs] -scrub_when = "Wed 08:00 Europe/Berlin" diff --git a/nodes/carlene.toml b/nodes/carlene.toml deleted file mode 100644 index 2d36766..0000000 --- a/nodes/carlene.toml +++ /dev/null @@ -1,281 +0,0 @@ -hostname = "193.135.9.29" -groups = [ - "debian-bookworm", - "webserver", -] -bundles = [ - "check-mail-received", - "dovecot", - "forgejo", - "matrix-media-repo", - "matrix-stickerpicker", - "matrix-synapse", - "mautrix-telegram", - "mautrix-whatsapp", - "miniflux", - "netbox", - "nextcloud", - "ntfy", - "oidentd", - "php", - "postfixadmin", - "postgresql", - "redis", - "rspamd", - "smartd", - "travelynx", - "weechat", - "zfs", -] - -# for auto-deployment of salonkatrin.de -[metadata.apt.packages.jekyll] - -[metadata.check-mail-received.t-online] -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.forgejo] -version = "11.0.1" -sha1 = "d9d0051275830ca2ed328a633e25d936d0a2386a" -domain = "git.franzi.business" -enable_git_hooks = true -install_ssh_key = true -internal_token = "!decrypt:encrypt$gAAAAABfPncYwCX-NdBr9LdxLyGqmjRJqhmwMnWsdZy6kVOWdKrScW78xaqbJ1tpL1J4qa2hcZ7TQj3l-2mkyJNJOenGzU3TsI-gYMj9vC4m8Bhur5zboxjD4dQXaJbD1WSyHJ9sPJYsWP3Gjg6I19xeq9xMlAI6xaS9vOfuoI8nZnnQPx1NjfQEj03Jxf8a0-3F20sfICst1xRa5K48bpq1PFkK_oRojg==" -lfs_secret_key = "!decrypt:encrypt$gAAAAABfPnd1vgNDt86-91YhviQw8Z0djSp4f_tBt76klDv-ZcwxP1ryJzqJ7qnfaTe_6DYCfc82gEzvVDsyBlCoAkGpt1AI2_LCKetuSCnDPjtGvwdQl3A53lFEdG2UJl1uUiR7f8Vr" -oauth_secret_key = "!decrypt:encrypt$gAAAAABfPnbfTISbldhS0WyxVKBHVVoOMcar7Kxmh1kkmiUGd-RzbbnNzzhEER_owjttPQcACPfGKZ6WklaSsXjLq8km4P6A9QmPbC06GmHbc91m0odCb1KiY7SZeUD35PiRiGSq50dz" -security_secret_key = "!decrypt:encrypt$gAAAAABfPnc-R7pkDj4pQgHDb6pzlNYNJgiWdeBFsX7IsHSnCtNPbZxCdtSL8cHtQzVO1KbSxS7zCwssmgiR8Kj54Z-koD-FQbjpbKWoIPw8SsyeqBVlZhIeEzhw_1t7_7ZTvv1O8AePdNYel9JJb_TaAZ8Vx46ZfsEPy8zaaHrqOekHC6RAnB4=" - -[metadata.interfaces.'eno*'] -ips = [ - "193.135.9.29/24", - "2a0a:51c0:0:225::2/64", -] -gateway4 = "193.135.9.1" -gateway6 = "2a0a:51c0:0:225::1" - -[metadata.matrix-media-repo] -admins = ["@kunsi:franzi.business"] -datastore_id = "3fff5da324ed784c771d638bb6be5917" -sha1 = "453c12cfb9f2c44c509620b63f94f8a9e2d048ef" -upload_max_mb = 500 -version = "v1.3.8" -[metadata.matrix-media-repo.homeservers.'franzi.business'] -api = "synapse" -domain = "http://[::1]:20080/" -signing_key_path = "/etc/matrix-synapse/mmr.signing.key" - -[metadata.matrix-stickerpicker] -# use this bot token: encrypt$gAAAAABfVK51ErJ6gfsOOkbRxSHDnVYmf7EihAQf7Uwj9og3TlAw64WRsA6ZVEgTSvOdLB3SMKZ-cTEhwkCOpbymq-_WLhes-hZALhN-H_oXHaxTQErJ0lARynKmjM-4ZhoGlUWlfh4Q -domain = "matrix-stickers.franzi.business" -[metadata.matrix-stickerpicker.config] -access_token = "!decrypt:encrypt$gAAAAABg-wBmGbAy-Ou1mkG2w5UyoqWmWYzDr4ZavyUQdmG_VtrUSmwHjx-qcBGIz_7NniD3zKm9GGvzRZItDu5zYiojcudYr74TkWJKhdDrgFbcWlfJJ_m3bWzrSORaTYzBGRckp2Vz_8xHgDk1W03vpT6mdIPMDzjuINssIcPs0YDth25W942tMfPA2csvLADY50qVRMJpdBOVIWba55o0g6-mAAQLOz6Ld4cCvYqZsqXsxjT8JUytJv_uSG4zgCS_aX20JlAyJWpJgT8FQF5HzIbsko_-Z9-TwtY7yllJp5Ri3n0WaDaWoMmUfhLvkMJeymmOc32A4WJBAePQ_2F-_oUDE7t97A-m3ZiMVAEefDnH5MkoiQEJTfHrJsXRkdBT_BnJlY1CoAuXpRYDdvbVDwN_qZHHHtqsno437l9S6GgDK_-sKBiojYkYsfHcJCdSEqeFGuxT" -homeserver = "https://matrix.franzi.business" -user_id = "@dimension:franzi.business" - -[metadata.matrix-synapse] -admin_contact = "mailto:hostmaster@kunbox.net" -baseurl = "matrix.franzi.business" -server_name = "franzi.business" -trusted_key_servers = ["matrix.org", "161.rocks"] -additional_client_config.'im.vector.riot.jitsi'.preferredDomain = "meet.ffmuc.net" -wellknown_also_on_vhosts = ["franzi.business"] - -[metadata.mautrix-telegram] -version = "v0.15.2" -homeserver.domain = "franzi.business" -homeserver.url = "https://matrix.franzi.business" -telegram.api_id = "!decrypt:encrypt$gAAAAABfVK5SmDDru-UQxitkE5VhPArnUBhaRbAqQPvAW2Fh3fd1XDrWxa3Qn4BSnJAPNWglH5wil_SXUMcIm95FMhPe8dVeMQ==" -telegram.api_token = "!decrypt:encrypt$gAAAAABfVK5jHuUly1xr9Iku362k7oF4ZYRhLGzNJh3aJpiNrLfAy_DJpTwucx4FV_g45dyQF5boqG2rgdDfwsJN_Ab95es6T4SPGiXIxJOBlvIln1Torwh16pXKchhUTn_PQ077Ll1W" -# same as for matrix-dimension -telegram.bot_token = "!decrypt:encrypt$gAAAAABfVK51ErJ6gfsOOkbRxSHDnVYmf7EihAQf7Uwj9og3TlAw64WRsA6ZVEgTSvOdLB3SMKZ-cTEhwkCOpbymq-_WLhes-hZALhN-H_oXHaxTQErJ0lARynKmjM-4ZhoGlUWlfh4Q" -provisioning.enabled = true -provisioning.shared_secret = "!decrypt:encrypt$gAAAAABfVKflEMAi07C_QGP8cy97hF-4gGPym0oF6p4WSMdAveTpx-hFsZd2s7v9ubw99yIsyKx0dHOJI0UND7hV1rKZdvjy4Qa642abZ2wwW7SWTqvuP_qVtrf6-klc2QKTzeD9c_LVsyZ2dqz_JxRPq3MRXgkubZuWOZ6FmFlAlteTffoGfWE=" -[metadata.mautrix-telegram.permissions] -"'*'" = "relaybot" -'franzi.business' = "full" -"'@kunsi:franzi.business'" = "admin" - -[metadata.mautrix-whatsapp] -version = "v0.12.1" -sha1 = "e453f41ab57d703fcac90483f7f0ff36b6127f54" -permissions."'@kunsi:franzi.business'" = "admin" -[metadata.mautrix-whatsapp.homeserver] -domain = "franzi.business" -url = "https://matrix.franzi.business" - -[metadata.miniflux] -domain = "rss.franzi.business" - -[metadata.netbox] -domain = "netbox.franzi.business" -version = "v4.3.1" -admins.kunsi = "hostmaster@kunbox.net" - -[metadata.nextcloud] -domain = "warnochwas.de" - -[metadata.nginx.'security.txt'] -contact = "mailto:security@kunsmann.eu" -Encryption = "https://franzi.business/gpg_hi-kunsmann.eu.asc" - -[metadata.nginx.vhosts.'afra.berlin'.locations.'/'] -redirect = "https://afra-berlin.de" -mode = 302 - -[metadata.nginx.vhosts.forgejo] -domain_aliases = ["git.kunsmann.eu"] - -[metadata.nginx.vhosts.'franzi.business'] -domain = "franzi.business" -webroot_config.owner = "kunsi" - -[metadata.nginx.vhosts.'gaenseblum.eu'.webroot_config] -owner = "skye" - -[metadata.nginx.vhosts.kunsitracker] -domain = "kunsitracker.de" -locations.'/'.target = "https://travelynx.franzi.business/" -locations.'/'.proxy_pass_host = "travelynx.franzi.business" -locations.'= /'.target = "https://travelynx.franzi.business/p/Kunsi" -locations.'= /'.proxy_pass_host = "travelynx.franzi.business" - -[metadata.nginx.vhosts.mta-sts] -domain = "mta-sts.kunbox.net" -domain_aliases = [ - "mta-sts.franzi.business", - "mta-sts.kunsmann.eu", -] -force_domain = false - -[metadata.nginx.vhosts.redirector] -domain = "kunbox.net" -domain_aliases = [ - "carlene.kunbox.net", - "kunsmann.eu", -] -[metadata.nginx.vhosts.redirector.locations.'/'] -redirect = "https://franzi.business/" -[metadata.nginx.vhosts.redirector.locations.'/.well-known/openpgpkey/'] -alias = "/var/www/franzi.business/.well-known/openpgpkey" -additional_config = [ - "add_header Access-Control-Allow-Origin *", - "default_type application/octet-stream", -] - -[metadata.ntfy] -domain = "ntfy.franzi.business" -ratelimit-exempt-hosts = [ - "carlene", - "icinga2", -] - -[metadata.php] -packages = [ - 'gd', - 'imagick', - 'imap', - 'intl', - 'mbstring', - 'opcache', - 'pgsql', - 'readline', - 'xml', - 'yaml', -] - -[metadata.postfix] -message_size_limit_mb = 100 -myhostname = "mail.franzi.business" -blocked_recipients = [ - "!decrypt:encrypt$gAAAAABlrPHMqx7o9pscfSx4Elayrzwun9jcTYOM4XrcAoUWaHJ9vP_7P5G7V3nwdB8pWfObNew-2IOihn5EPS-0ej2gn9rI4iDnMG_6S2IBCDYMqZMn1W0=", # deadname - "tectu@kunsmann.eu", -] - -[metadata.postfixadmin] -domain = "postfixadmin.franzi.business" -setup_password = "!decrypt:encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ==" -version = "3.3.15" - -[metadata.postgresql] -version = 15 - -[metadata.rspamd] -ignore_spam_check_for_ips = [ - # entropia - '45.140.180.32/27', # Entropia e. V. - '45.140.180.112/28', # MicroPOC - '2a0e:c5c0:0:201::/64', # Entropia e. V. - '2a0e:c5c0:0:307::/64', # MicroPOC - - # c3kl - '116.202.19.236', - '2a01:4f8:1c17:cc52::/64', - - # ccc - '212.12.55.65', - '212.12.55.67', - '2a00:14b0:4200:3000:23:55:0:65', - - # IN-Berlin mailman - '130.133.8.35', - '192.109.42.28', - '192.109.42.122', - '193.29.188.9', - '217.197.80.23', - '217.197.80.134', - '2001:bf0:c000:a::2:134', - - # c3voc - '185.106.84.32/26', - '2001:67c:20a0:e::/64', - - # DENOG - '195.20.121.100', - '2001:1440:201:101::5', -] -password = "!bwpass:bw/rx300/rspamd" -dkim = "uO4aNejDvVdw8BKne3KJIqAvCQMJ0416" - -[metadata.smartd] -disks = [ - "/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NF0W503350", - "/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NX0W114380", -] - -[metadata.systemd-timers.timers.42c3-topic] -command = "/home/kunsi/42c3-topic.sh" -user = "kunsi" -when = "Mon 04:00:00 Europe/Berlin" - -[metadata.travelynx] -version = "2.11.35" -mail_from = "travelynx@franzi.business" -domain = "travelynx.franzi.business" - -[metadata.users.skye] -ssh_pubkey = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCO0KG3/hnMO6UsReyEHvV4y7fYmJGQeCVnmw2xUoM4so2ZacWDi27aQbMq6wWb/JsUh4j3OOvEfNvf27LU6wpqcxM/QO22YjLsOtVzVnGjupsKAnN/nKy+X7KhspaF9qKFpmseBpuEAAnaxnreEFNC2tHarzJzgj+Y+Bmkg4tnMWsVc6EoBp1R2xmsdeRtgcQwms3xX9COeAjkFNgniGfqigO2AxPgC68h3GqSlcPzgpJ7ukvtCRCs/g3R+9GCnxsamd3AYhaRCIKauIyA44WqtH8lAH5+g16tU8WYcK1KySuwLt418kXDDJrZXaOLbxRl+jrShIdPoGhqs1y6KlOVTbj9TBVGt8CtV8JsLwzH2GCdLjImcXWUob2j2sxgBGTWiTfWf98XBLmBQwbAlBJ01gsHhJxDx0E2ttxueSjyg4hTzWCH0TlRmbpUDdIlqLgwHxmh97YFF5oqkgWGjSt7jxrW8Q9+FeMi5L2qHzKez5Z3quOhDIXWjEcpxqQQ2Lc=", -] - -[metadata.weechat] -user = "kunsi" -relay_domain = "irc.franzi.business" - -[[metadata.zfs.pools.tank.when_creating.config]] -devices = [ - "/dev/nvme0n1p3", - "/dev/nvme1n1p3", -] -type = "mirror" - -[metadata.zfs.datasets.tank] -primarycache = "metadata" - -[metadata.zfs.datasets.'tank/sewfile'] -mountpoint = "/mnt/sewfile/" - -[metadata.vm] -cpu = 24 -ram = 64 diff --git a/nodes/entropia-jira.toml b/nodes/entropia-jira.toml new file mode 100644 index 0000000..84af119 --- /dev/null +++ b/nodes/entropia-jira.toml @@ -0,0 +1,22 @@ +hostname = "45.140.180.45" +dummy = true + +[metadata.icinga_options] +period = "daytime" +pretty_name = "ticket.gulas.ch" + +[metadata.icinga2_api.nginx.services."NGINX VHOST ticket-redirect CERTIFICATE"] +check_command = "check_https_cert_at_url" +"vars.domain" = "ticket.gulas.ch" +"vars.notification.mail" = true + +[metadata.icinga2_api.nginx.services."NGINX VHOST jira CERTIFICATE"] +check_command = "check_https_cert_at_url" +"vars.domain" = "jira.gulas.ch" +"vars.notification.mail" = true + +[metadata.icinga2_api.nginx.services."NGINX VHOST jira CONTENT"] +check_command = "check_http_wget" +"vars.http_wget_contains" = "login.jsp" +"vars.http_wget_url" = "https://jira.gulas.ch/secure/Dashboard.jspa" +"vars.notification.sms" = true diff --git a/nodes/fkusei-locutus.py b/nodes/fkusei-locutus.py new file mode 100644 index 0000000..397e851 --- /dev/null +++ b/nodes/fkusei-locutus.py @@ -0,0 +1,183 @@ +nodes['fkusei-locutus'] = { + 'hostname': '172.19.138.96', + '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': {'*'}, + }, + }, + 'interfaces': { + 'enp0s31f6': { + 'dhcp': True, + 'ips': { + '172.19.138.96', # for static dhcp lease + }, + 'mac': 'e8:6a:64:ef:cc:5c', + }, + # there is also wlp2s0, 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', + 'ipv6', + }, + }, + 'pacman': { + 'linux-lts': True, + 'packages': { + # video drivers + 'xf86-video-intel': {}, + + # all that other random stuff one needs + 'apachedirectorystudio': {}, + 'direnv': {}, + 'freerdp': {}, + 'sdl_ttf': {}, # for compiling testcard + 'thermald': {}, + }, + }, + 'systemd-boot': { + 'default': 'arch-lts', + 'entries': { + 'arch-lts': { + 'title': 'Arch Linux (LTS kernel)', + 'linux': '/vmlinuz-linux-lts', + 'initrd': [ + '/intel-ucode.img', + '/initramfs-linux-lts.img', + ], + 'options': { + 'zfs=zroot/system/root', + 'rw', + }, + }, + 'arch-lts-fallback': { + 'title': 'Arch Linux (LTS kernel, no ucode, fallback initramfs)', + 'linux': '/vmlinuz-linux-lts', + 'initrd': [ + '/initramfs-linux-lts-fallback.img', + ], + 'options': { + 'zfs=zroot/system/root', + 'rw', + }, + }, + }, + }, + 'timezone': 'Europe/Berlin', + 'users': { + 'fkunsmann': { + 'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='), + 'shell': '/usr/bin/fish', + 'sudo_commands': { + 'ALL', + }, + }, + 'sophie': { + 'delete': True, + }, + }, + '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': { + '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': { + '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', +} diff --git a/nodes/gce/bind01.py b/nodes/gce/bind01.py new file mode 100644 index 0000000..7239082 --- /dev/null +++ b/nodes/gce/bind01.py @@ -0,0 +1,37 @@ +# ns-1.kunbox.net +# Frankfurt, Germany + +nodes['gce.bind01'] = { + 'hostname': '34.89.208.78', + 'groups': { + 'debian-bullseye', + 'dns', + }, + 'metadata': { + 'backups': { + 'exclude_from_backups': True, + }, + 'interfaces': { + 'ens4': { + 'ips': { + '10.156.0.4', + }, + 'gateway4': '10.156.0.1', + }, + }, + 'external_ipv4': '34.89.208.78', + 'icinga_options': { + 'pretty_name': 'ns-1.kunbox.net', + }, + 'postgresql': { + 'version': '15', + }, + 'powerdns': { + 'my_hostname': 'ns-1.kunbox.net', + }, + 'vm': { + 'cpu': 1, + 'ram': 1, + }, + }, +} diff --git a/nodes/gce/dns02.py b/nodes/gce/dns02.py new file mode 100644 index 0000000..7eb1253 --- /dev/null +++ b/nodes/gce/dns02.py @@ -0,0 +1,38 @@ +# ns-2.kunbox.net +# Belgium + +nodes['gce.dns02'] = { + 'hostname': '35.187.109.249', + 'bundles': set(), + 'groups': { + 'debian-bullseye', + 'dns', + }, + 'metadata': { + 'interfaces': { + 'ens4': { + 'ips': { + '10.132.0.2', + }, + 'gateway4': '10.132.0.1', + }, + }, + 'external_ipv4': '35.187.109.249', + 'icinga_options': { + 'pretty_name': 'ns-2.kunbox.net', + }, + 'backups': { + 'exclude_from_backups': True, + }, + 'postgresql': { + 'version': '15', + }, + 'powerdns': { + 'my_hostname': 'ns-2.kunbox.net', + }, + 'vm': { + 'cpu': 1, + 'ram': 1, + }, + }, +} diff --git a/nodes/gce/dns03.py b/nodes/gce/dns03.py new file mode 100644 index 0000000..14a87d7 --- /dev/null +++ b/nodes/gce/dns03.py @@ -0,0 +1,38 @@ +# ns-3.kunbox.net +# Finland + +nodes['gce.dns03'] = { + 'hostname': '35.228.143.71', + 'bundles': set(), + 'groups': { + 'debian-bullseye', + 'dns', + }, + 'metadata': { + 'interfaces': { + 'ens4': { + 'ips': { + '10.166.0.2', + }, + 'gateway4': '10.166.0.1', + }, + }, + 'external_ipv4': '35.228.143.71', + 'icinga_options': { + 'pretty_name': 'ns-3.kunbox.net', + }, + 'backups': { + 'exclude_from_backups': True, + }, + 'postgresql': { + 'version': '15', + }, + 'powerdns': { + 'my_hostname': 'ns-3.kunbox.net', + }, + 'vm': { + 'cpu': 1, + 'ram': 1, + }, + }, +} diff --git a/nodes/home.appletv-wohnzimmer.toml b/nodes/home.appletv-wohnzimmer.toml deleted file mode 100644 index 5febb38..0000000 --- a/nodes/home.appletv-wohnzimmer.toml +++ /dev/null @@ -1,9 +0,0 @@ -dummy = true - -[metadata.interfaces.default] -ips = ["172.19.138.73"] -dhcp = true -mac = "c0:95:6d:5e:82:47" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.aruba325-office.toml b/nodes/home.aruba325-office.toml deleted file mode 100644 index 1515e76..0000000 --- a/nodes/home.aruba325-office.toml +++ /dev/null @@ -1,6 +0,0 @@ -dummy = true - -[metadata.interfaces.eth0] -ips = ["172.19.138.53"] -dhcp = true -mac = "f0:5c:19:cf:9e:72" diff --git a/nodes/home.aruba325-schlafzimmer.toml b/nodes/home.aruba325-schlafzimmer.toml deleted file mode 100644 index 27be1ce..0000000 --- a/nodes/home.aruba325-schlafzimmer.toml +++ /dev/null @@ -1,6 +0,0 @@ -dummy = true - -[metadata.interfaces.eth0] -ips = ["172.19.138.52"] -dhcp = true -mac = "b4:5d:50:c7:11:78" diff --git a/nodes/home.aruba325-wohnzimmer.toml b/nodes/home.aruba325-wohnzimmer.toml deleted file mode 100644 index e3263fd..0000000 --- a/nodes/home.aruba325-wohnzimmer.toml +++ /dev/null @@ -1,6 +0,0 @@ -dummy = true - -[metadata.interfaces.eth0] -ips = ["172.19.138.51"] -dhcp = true -mac = "f0:5c:19:cf:9f:7e" diff --git a/nodes/home.drucker-sophie.toml b/nodes/home.drucker-sophie.toml new file mode 100644 index 0000000..02c7141 --- /dev/null +++ b/nodes/home.drucker-sophie.toml @@ -0,0 +1,6 @@ +dummy = true + +[metadata.interfaces.default] +ips = ["172.19.138.61"] +dhcp = true +mac = "00:14:38:9E:29:E3" diff --git a/nodes/home.encoder96.toml b/nodes/home.ejgwdesk.toml similarity index 84% rename from nodes/home.encoder96.toml rename to nodes/home.ejgwdesk.toml index ca9bdce..7572ba7 100644 --- a/nodes/home.encoder96.toml +++ b/nodes/home.ejgwdesk.toml @@ -3,7 +3,7 @@ dummy = true [metadata.interfaces.default] ips = ["172.19.138.99"] dhcp = true -mac = "6c:4b:90:5c:e3:6d" +mac = "54:04:A6:EF:A8:01" [metadata.icinga_options] exclude_from_monitoring = true diff --git a/nodes/home.hass.toml b/nodes/home.hass.toml index c9e60d7..643a7a5 100644 --- a/nodes/home.hass.toml +++ b/nodes/home.hass.toml @@ -1,17 +1,12 @@ hostname = "172.19.138.25" bundles = [ 'homeassistant', - 'nginx', + 'nginx' ] -groups = ["debian-trixie"] - -[metadata.icinga_options] -also_affected_by = ['home.nas'] +groups = ["debian-bullseye"] [metadata.interfaces.enp1s0] -ips = [ - "172.19.138.25/24", -] +ips = ["172.19.138.25/24"] gateway4 = "172.19.138.1" ipv6_accept_ra = true @@ -21,7 +16,13 @@ ram = 2 [metadata.homeassistant] domain = 'hass.home.kunbox.net' -api_secret = '!decrypt:encrypt$gAAAAABm9lNg_mNhyzb4S6WRtVRDmQFBnPpoCwyqMnilRrAFUXc-EDvv-nYXPbSIbjTf7ZReTPtqr8k3WrGPqiuqhJ60LVv4A5DMqT5c6hTVr4WbhP4DPEIPgfd5aq6U9_-H9WDyQYHKjnunLJEYtEREzmhTq3XsYeQ05DyE7hfnQ-zVoBb0CsAK7GdhihRTdvhXv2N9M04_rigyBP-roRcUgCqwyHuWJc0IPAyn3R4Mr43ZqgR2fn6dNV_YUVKn9c0nWxIwRnYy6Ff_Te9NoGVmXxkiNUX-90bBLKFiCzrRAtizxrTiQb2SRipaWbgOlV6wbMy2KNux' +api_secret = 'encrypt$gAAAAABjpyuqXLoilokQW5c0zV8shHcOzN1zkEbS-I6WAAX-xDO_OF33YbjbkpELU2HGBzqiWX40J0hsaEbYJOnCHFk8gJ-Xt0vdqqbQ5vca_TGPNQHZPAS4qZoPTcUhmX_I-0EdT6ukhxejXFYBiYRZikTLjH3lcNM5qnckCm-H9NbRdjLb9hbCDIjbEglHmBl_g08S1_ukvX3dDSCIHIxgXXGsdK_Go1KxPJd8G22FL_MMhCfsTW-6ioIqoHSeSA1NGk3MZHEIM2errckiopKBxoBaROsacO9Uqk1zrrgXOs2NsgiTRtrbV1TNlFVaIX9mZdsUnMGZ' + +[metadata.nginx] +restrict-to = [ + '172.19.136.0/25', + '172.19.138.0/24', +] [metadata.nginx.vhosts.homeassistant] ssl = '_.home.kunbox.net' diff --git a/nodes/home.kodi-wohnzimmer.toml b/nodes/home.kodi-wohnzimmer.toml new file mode 100644 index 0000000..f3a2cf5 --- /dev/null +++ b/nodes/home.kodi-wohnzimmer.toml @@ -0,0 +1,26 @@ +hostname = "172.19.138.24" +bundles = ["kodi", "lm-sensors", "nfs-client", "smartd"] +groups = ["debian-bullseye"] + +[metadata.apt.packages.intel-media-va-driver-non-free] + +[metadata.apt.unattended-upgrades] +day = 6 +hour = 2 + +[metadata.interfaces.eno1] +ips = ["172.19.138.24/24"] +gateway4 = "172.19.138.1" +ipv6_accept_ra = true + +[metadata.nfs-client.mounts.nas-storage] +mountpoint = "/mnt/nas" +serverpath = "172.19.138.20:/storage/nas" +mount_options = ["retry=0", "ro"] + +[metadata.smartd] +disks = ["/dev/nvme0"] + +[metadata.vm] +cpu = 2 +ram = 4 diff --git a/nodes/home.lgtv-wohnzimmer.toml b/nodes/home.lgtv-wohnzimmer.toml deleted file mode 100644 index 611e16a..0000000 --- a/nodes/home.lgtv-wohnzimmer.toml +++ /dev/null @@ -1,9 +0,0 @@ -dummy = true - -[metadata.interfaces.default] -ips = ["172.19.138.72"] -dhcp = true -mac = "ac:5a:f0:32:05:7b" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.mitel-rfp35.toml b/nodes/home.mitel-rfp35.toml new file mode 100644 index 0000000..414658a --- /dev/null +++ b/nodes/home.mitel-rfp35.toml @@ -0,0 +1,4 @@ +dummy = true + +[metadata.interfaces.default] +ips = ["172.19.138.41"] diff --git a/nodes/home.mixer96.toml b/nodes/home.mixer96.toml deleted file mode 100644 index 815205f..0000000 --- a/nodes/home.mixer96.toml +++ /dev/null @@ -1,9 +0,0 @@ -dummy = true - -[metadata.interfaces.default] -ips = ["172.19.138.98"] -dhcp = true -mac = "54:e1:ad:a6:0d:1f" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.o2-joggler.toml b/nodes/home.o2-joggler.toml deleted file mode 100644 index 8dffb68..0000000 --- a/nodes/home.o2-joggler.toml +++ /dev/null @@ -1,16 +0,0 @@ -hostname = "172.19.138.95" -dummy = true -# - -[metadata.interfaces.eth0] -# only used for debugging, device uses wifi otherwise -ips = ["169.254.172.100"] -mac = "9a:d0:d7:e7:b0:bb" - -[metadata.interfaces.wlan0] -ips = ["172.19.138.94"] -dhcp = true -mac = "00:0e:8e:22:9c:9b" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.r630.toml b/nodes/home.r630.toml deleted file mode 100644 index f41bb19..0000000 --- a/nodes/home.r630.toml +++ /dev/null @@ -1,33 +0,0 @@ -hostname = "172.19.138.22" -groups = ["debian-bookworm"] -bundles = ["docker-engine", "nginx", "redis"] - -ipmi_hostname = "172.19.138.23" -ipmi_username = "root" -ipmi_password = "calvin" -ipmi_interface = "lanplus" - -[metadata] -icinga_options.exclude_from_monitoring = true -backups.exclude_from_backups = true - -[metadata.interfaces.eno3] -ips = [ - "172.19.138.22/24", -] -gateway4 = "172.19.138.1" -ipv6_accept_ra = true - -[metadata.nftables.forward] -50-local-forward = [ - 'ct state { related, established } accept', - 'iifname eno3 accept', - 'ip6 nexthdr ipv6-icmp accept', -] - -[metadata.users.molly] -password = "!decrypt:dummy$no" - -[metadata.vm] -cpu = 56 -ram = 128 diff --git a/nodes/home.winkeeinhorn-1.toml b/nodes/home.winkeeinhorn-1.toml new file mode 100644 index 0000000..f2505b5 --- /dev/null +++ b/nodes/home.winkeeinhorn-1.toml @@ -0,0 +1,11 @@ +dummy = true + +[metadata.interfaces.default] +ips = ["172.19.138.11"] +dhcp = true +mac = "f4:06:8d:df:05:60" + +[metadata.icinga2_api.freifunk.services."NODE HEALTH"] +check_command = "check_freifunk_node" +"vars.url" = "https://map.freifunk-mwu.de/data/meshviewer.json" +"vars.id" = "f4068ddf055f" diff --git a/nodes/home.winkeeinhorn-2.toml b/nodes/home.winkeeinhorn-2.toml new file mode 100644 index 0000000..61e954b --- /dev/null +++ b/nodes/home.winkeeinhorn-2.toml @@ -0,0 +1,11 @@ +dummy = true + +[metadata.interfaces.default] +ips = ["172.19.138.12"] +dhcp = true +mac = "f4:06:8d:df:03:38" + +[metadata.icinga2_api.freifunk.services."NODE HEALTH"] +check_command = "check_freifunk_node" +"vars.url" = "https://map.freifunk-mwu.de/data/meshviewer.json" +"vars.id" = "f4068ddf0337" diff --git a/nodes/home.winkeeinhorn-vm.toml b/nodes/home.winkeeinhorn-vm.toml index c28c39b..e94f390 100644 --- a/nodes/home.winkeeinhorn-vm.toml +++ b/nodes/home.winkeeinhorn-vm.toml @@ -1,8 +1,5 @@ dummy = true -[metadata.icinga_options] -also_affected_by = ['home.nas'] - [metadata.interfaces.default] ips = ["172.19.138.10"] dhcp = true @@ -12,4 +9,3 @@ mac = "52:54:00:b0:4e:4d" check_command = "check_freifunk_node" "vars.url" = "https://map.freifunk-mwu.de/data/meshviewer.json" "vars.id" = "525400b04e4d" -"vars.notification.mail" = true diff --git a/nodes/home.wled-aftonsparv.toml b/nodes/home.wled-aftonsparv.toml deleted file mode 100644 index 661a403..0000000 --- a/nodes/home.wled-aftonsparv.toml +++ /dev/null @@ -1,9 +0,0 @@ -dummy = true - -[metadata.interfaces.default] -ips = ["172.19.138.71"] -dhcp = true -mac = "84:fc:e6:11:34:80" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.wled-raketenlaemp.toml b/nodes/home.wled-raketenlaemp.toml deleted file mode 100644 index a151839..0000000 --- a/nodes/home.wled-raketenlaemp.toml +++ /dev/null @@ -1,9 +0,0 @@ -dummy = true - -[metadata.interfaces.default] -ips = ["172.19.138.74"] -dhcp = true -mac = "84:fc:e6:11:34:74" - -[metadata.icinga_options] -exclude_from_monitoring = true diff --git a/nodes/home.fujitsu-n7100.toml b/nodes/home.wled-wohnzimmer.toml similarity index 69% rename from nodes/home.fujitsu-n7100.toml rename to nodes/home.wled-wohnzimmer.toml index 07d51c0..c032230 100644 --- a/nodes/home.fujitsu-n7100.toml +++ b/nodes/home.wled-wohnzimmer.toml @@ -1,9 +1,9 @@ dummy = true [metadata.interfaces.default] -ips = ["172.19.138.75"] +ips = ["172.19.138.70"] dhcp = true -mac = "00:01:29:59:a9:8c" +mac = "3c:61:05:d0:f2:b9" [metadata.icinga_options] exclude_from_monitoring = true diff --git a/nodes/home/downloadhelper.py b/nodes/home/downloadhelper.py index 4bd2f10..d09d558 100644 --- a/nodes/home/downloadhelper.py +++ b/nodes/home/downloadhelper.py @@ -5,14 +5,9 @@ nodes['home.downloadhelper'] = { 'transmission', }, 'groups': { - 'debian-bullseye', + 'debian-buster', }, 'metadata': { - 'icinga_options': { - 'also_affected_by': { - 'home.nas', - }, - }, 'interfaces': { 'enp1s0.3001': { 'dhcp': True, @@ -24,7 +19,7 @@ nodes['home.downloadhelper'] = { }, 'routes': { # VPN - '172.19.128.0/20': { + '172.19.136.0/22': { 'via': '172.19.138.1', }, }, @@ -42,7 +37,7 @@ nodes['home.downloadhelper'] = { 'mounts': { 'storage': { 'mountpoint': '/mnt/nas', - 'serverpath': '172.19.138.20:/mnt/download', + 'serverpath': '172.19.138.20:/storage/download', 'mount_options': { 'retry=0', 'rw', @@ -56,7 +51,7 @@ nodes['home.downloadhelper'] = { 'download-queue-size': 10, }, 'restrict-to': { - '172.19.128.0/20', + '172.19.136.0/22', }, }, }, diff --git a/nodes/home/nas.py b/nodes/home/nas.py index d4a4211..37136d5 100644 --- a/nodes/home/nas.py +++ b/nodes/home/nas.py @@ -3,22 +3,18 @@ nodes['home.nas'] = { 'hostname': '172.19.138.20', 'bundles': { - 'avahi-daemon', 'backup-client', - 'jellyfin', 'lm-sensors', 'mixcloud-downloader', 'mosquitto', 'nfs-server', - 'rsyslogd', - 'samba', + 'scansnap', 'smartd', 'vmhost', 'zfs', }, 'groups': { 'debian-bullseye', - 'webserver', }, 'metadata': { 'interfaces': { @@ -39,10 +35,6 @@ nodes['home.nas'] = { 'packages': { 'mpv': {}, - # for hardware transcoding of video - 'firmware-amd-graphics': {}, - 'mesa-va-drivers': {}, - # for compiling yate 'autoconf': {}, 'subversion': {}, @@ -55,18 +47,15 @@ nodes['home.nas'] = { # systemctl start yate }, }, - 'avahi-daemon': { - 'use-ipv6': False, # because having a dynamic address confuses the network somehow - }, 'backups': { 'paths': { - '/home/kunsi/', - '/storage/nas/', - }, - }, - 'cron': { - 'jobs': { - 'avahi-aruba-fixup': '17,47 * * * * root /usr/bin/systemctl restart avahi-daemon.service', + '/storage/nas/Audiobooks', + '/storage/nas/Bilder', + '/storage/nas/Bilder_Archiv', + '/storage/nas/Books', + '/storage/nas/Musik', + '/storage/nas/Musikvideos', + '/storage/nas/normen', }, }, 'groups': { @@ -74,15 +63,17 @@ nodes['home.nas'] = { }, 'firewall': { 'port_rules': { - '4679/tcp': { # Dell ULNM + '4679': { # Dell ULNM '172.19.136.0/25', '172.19.138.0/24', }, - '5060/tcp': { # yate SIP + '5060': { # yate SIP 'home.snom-wohnzimmer', + 'home.mitel-rfp35', }, - '5061/tcp': { # yate SIPS + '5061': { # yate SIPS 'home.snom-wohnzimmer', + 'home.mitel-rfp35', }, # yate RTP uses some random UDP port. We cannot firewall # it, because for incoming calls the other side decides @@ -92,14 +83,7 @@ nodes['home.nas'] = { # to deal with randomly changing IPs here. '*/udp': { 'home.snom-wohnzimmer', - }, - }, - }, - 'mixcloud-downloader': { - 'netrc': { - 'soundcloud': { - 'username': 'oauth', - 'password': bwpass.attr('soundcloud.com/hi@kunsmann.eu', 'oauth_token'), + 'home.mitel-rfp35', }, }, }, @@ -130,60 +114,37 @@ nodes['home.nas'] = { 'restrict-to': { '172.19.136.0/25', '172.19.138.0/24', - 'htz-cloud.molly-connector', }, }, 'nfs-server': { 'shares': { - '/mnt/download': { + '/storage/download': { 'home.downloadhelper': 'rw,all_squash,anonuid=65534,anongid=1012,no_subtree_check', }, '/storage/nas': { - '172.19.138.0/24': 'ro,all_squash,anonuid=65534,anongid=65534,no_subtree_check,insecure', + '172.19.138.0/24': 'ro,all_squash,anonuid=65534,anongid=65534,no_subtree_check', }, '/srv/paperless': { 'home.paperless': 'rw,all_squash,anonuid=65534,anongid=65534,no_subtree_check', }, - }, - }, - 'nginx': { - 'vhosts': { - 'jellyfin': { - 'create_logs': True, - 'domain': 'jellyfin.home.kunbox.net', - 'ssl': '_.home.kunbox.net', + '/srv/scansnap': { + '172.19.138.0/24': 'rw,all_squash,anonuid=65534,anongid=65534,no_subtree_check', }, }, }, - 'rsyslogd': { - 'restrict-to': { - 'home', - }, - }, - 'samba': { - 'restrict-to': { - '172.19.138.0/24', - }, - 'timemachine-shares': { - 'apfelcomputer', - 'verrat', - }, - }, 'smartd': { 'disks': { '/dev/nvme0', - # nas/timemachine disks - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8GE15GR', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJ406R', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJBTLR', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJGN6R', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8J8ZKRR', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V9JS5UYL', - - # ssdpool disks - '/dev/disk/by-id/ata-INTEL_SSDSC2KB960G8_PHYF244001QU960CGN', - '/dev/disk/by-id/ata-INTEL_SSDSC2KB960G8_PHYF244002AS960CGN', + # ZFS cache disks + '/dev/disk/by-id/ata-TS64GSSD370_B807810503', + '/dev/disk/by-id/ata-TS64GSSD370_B807810527', + }, + }, + 'sysctl': { + 'options': { + # XXX find out if this is really needed + 'net.ipv4.ip_forward': '1', }, }, 'systemd-networkd': { @@ -198,11 +159,6 @@ nodes['home.nas'] = { 'br0.1138', }, }, - 'br1139': { - 'match': { - 'br0.1139', - }, - }, }, }, 'systemd-timers': { @@ -211,8 +167,8 @@ nodes['home.nas'] = { 'nas_permissions': { 'command': [ 'chown -R :nas /storage/nas/', - r'find /storage/nas/ -type d -exec chmod 0775 {} \;', - r'find /storage/nas/ -type f -exec chmod 0664 {} \;', + 'find /storage/nas/ -type d -exec chmod 0775 {} \;', + 'find /storage/nas/ -type f -exec chmod 0664 {} \;', ], 'when': '*-*-* 02:00:00', }, @@ -222,37 +178,44 @@ nodes['home.nas'] = { 'enable_x_forwarding_for_admins': True, }, 'users': { - #'inbox': { - # 'ssh_pubkey': { - # #'command="/usr/share/rsync/scripts/rrsync -wo /storage/inbox/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ', - # }, - #}, + 'f2k1de': { + 'ssh_pubkey': { + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGrvhqC/tZzpLMs/qy+1xNSVi2mfn8LXPIEhh7dcGn9e', + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDH5+j2vDW1FHSSEEI/Sf5qiKJq1uoxGO5BPv84mqohvol7GxDFObv69tn7g6HYfZY/SaS75C4ZXy+cKa0xy8UCpF0SBa2xHASkenS9v55oweDL4rYSPARzn2XKt3RFJG/d8V5NOWtcyq5DFSzewUF35E4hx1pUc/CIxgJEem5ZvzvN0hlIKXUN2djkVUx+mz6RryBysLTJEFBamjJxIkvDG/PZU73W4SHaKAYV4Ojz2NY7T5/NYKePfIU5F9pkE3RU0LRj58usvA1eP0PvEArWlGNCd8EJU+HQ5xr2dZ6MKPpEyG0KJkC88DuapeF5RwUV53ZhNpF+QgzpI72fH5up', + }, + }, + 'inbox': { + 'ssh_pubkey': { + #'command="/usr/share/rsync/scripts/rrsync -wo /storage/inbox/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ', + 'command="/usr/share/rsync/scripts/rrsync -wo /storage/inbox/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDl9zOB7FBeqecfGBRQXZB9nM8e2HNIOKj7IhjgD47GUPh/niD4kUWfVsd6JiNs6RZZE7mQBAKD1wh3/sTd5Twn3ptMIZpoTrLAYEknICzdtwoLRlkHVfb3eK/Q9ufpOGV7Pd24viONSSWSgtd/GcXFCclpEtM06/47USwytFcN5NPmE3/yi68IKDSbIo3hWNo5ZUdeS7g0v+/uF/DkYMJRv0oQatcZx+P/yPLrKqekg/5nMw3RHRwcYVCDqoTc2KjAwWJQw1hOtt105tOpfmbo4eX9cmjcw3Eihwdyl+EeZelaTay1oIzHlKnuxp2oTI0O0KHNQngRt7YDgnEICY16SvyIOJD9ZOam1VeOr0+Z8QgPgGu82Wv+UG+/21yjIoB48VlkNNNpUBeGTBad23Cb+wHVFC5PIQN4iEH2i0PS0xVCIU2bOlXUPJx6/XK51vFoZdknH/8/Mr0jvMsw9i3QSrSy76AjxkexNYje0phNiseMRCakZ8uKdL2yA0g3P5s=', + }, + }, 'kunsi': { 'groups': { 'nas', }, }, + 'sophie': { + 'groups': { + 'nas', + }, + }, + 'qcn': { + 'ssh_pubkey': { + #'command="/usr/share/rsync/scripts/rrsync -ro /storage/nas/movies/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ', + 'command="/usr/share/rsync/scripts/rrsync -ro /storage/nas/movies/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILAwUA5t2cSy9YD+ilu5nklvokSRAoNOq/gUV73/KTsv lexi@aranea', + 'command="/usr/share/rsync/scripts/rrsync -ro /storage/nas/movies/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC7cCmJ1+btuwpbGrGAuiK8R/hTMCK7CFK0aK2vPcSy+ lexi@kanaya', + 'command="/usr/share/rsync/scripts/rrsync -ro /storage/nas/movies/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILLx+8d429D1KjaqOaGRFK09j6j3/FuU4xQMsrNLdflg lexi@toriel', + 'command="/usr/share/rsync/scripts/rrsync -ro /storage/nas/Serien_Englisch/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPGPse+vv3+kHBYt6bdab/4AbP1hU34/3qH9SBuC8LCJ jenny@normandy', + }, + }, }, 'zfs': { 'module_options': { 'zfs_arc_max_gb': 8, }, 'pools': { - 'ssdpool': { - 'when_creating': { - 'config': [ - { - 'type': 'mirror', - 'devices': { - '/dev/disk/by-id/ata-INTEL_SSDSC2KB960G8_PHYF244001QU960CGN', - '/dev/disk/by-id/ata-INTEL_SSDSC2KB960G8_PHYF244002AS960CGN', - }, - }, - ], - 'ashift': 12, - }, - }, - 'tank': { + 'storage': { 'when_creating': { 'config': [ { @@ -262,58 +225,81 @@ nodes['home.nas'] = { '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJ406R', '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJBTLR', '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJGN6R', - '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V9JS5UYL', + '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8HJU4NR', '/dev/disk/by-id/ata-WDC_WD6003FFBX-68MU3N0_V8J8ZKRR', }, }, + { + 'type': 'log', + 'devices': { + '/dev/disk/by-id/ata-TS64GSSD370_B807810503-part1', + '/dev/disk/by-id/ata-TS64GSSD370_B807810527-part1', + }, + }, + { + 'type': 'cache', + 'devices': { + '/dev/disk/by-id/ata-TS64GSSD370_B807810503-part2', + '/dev/disk/by-id/ata-TS64GSSD370_B807810527-part2', + }, + }, ], 'ashift': 12, }, }, }, 'datasets': { - 'ssdpool': { + 'storage': { 'primarycache': 'metadata', }, - 'ssdpool/yate': { + 'storage/opt-yate': { 'mountpoint': '/opt/yate', }, - 'ssdpool/download': { - 'mountpoint': '/mnt/download', - 'quota': '858993459200', # 800 GB + 'storage/f2k1de': { + 'mountpoint': '/storage/f2k1de', }, - 'ssdpool/paperless': { + 'storage/download': { + 'mountpoint': '/storage/download', + }, + 'storage/inbox': { + 'quota': str(1024*1024*1024*1024), # 1TB + 'mountpoint': '/storage/inbox', + }, + 'storage/nas': { + 'mountpoint': '/storage/nas', + }, + 'storage/paperless': { 'mountpoint': '/srv/paperless', }, - 'tank': { - 'primarycache': 'metadata', - }, - 'tank/nas': { - 'acltype': 'off', - 'atime': 'off', - 'compression': 'off', - 'mountpoint': '/storage/nas', + 'storage/scan': { + 'mountpoint': '/srv/scansnap', }, }, 'snapshots': { 'retain_per_dataset': { - 'tank/nas': { - # juuuuuuuust to be sure. - 'daily': 14, - 'weekly': 6, - 'monthly': 12, - }, - 'ssdpool/download': { + 'storage/download': { 'hourly': 48, 'daily': 0, 'weekly': 0, 'monthly': 0, }, - 'ssdpool/paperless': { + 'storage/nas': { + # juuuuuuuust to be sure. + 'daily': 14, + 'weekly': 6, + 'monthly': 12, + }, + 'storage/paperless': { 'daily': 14, 'weekly': 6, 'monthly': 24, }, + 'storage/scan': { + 'hourly': 6, + 'daily': 0, + 'weekly': 0, + 'monthly': 0, + }, }, }, }, diff --git a/nodes/sophie/paperless.py b/nodes/home/paperless-sophie.py similarity index 76% rename from nodes/sophie/paperless.py rename to nodes/home/paperless-sophie.py index 9319c7a..929bd24 100644 --- a/nodes/sophie/paperless.py +++ b/nodes/home/paperless-sophie.py @@ -1,4 +1,4 @@ -nodes['sophie.paperless'] = { +nodes['home.paperless-sophie'] = { 'hostname': '172.19.138.30', 'bundles': { 'nfs-client', @@ -49,12 +49,22 @@ nodes['sophie.paperless'] = { 'nginx': { 'vhosts': { 'paperless': { + 'domain': 'paperless-sophie.home.kunbox.net', 'ssl': '_.home.kunbox.net', + 'locations': { + '/': { + 'target': 'http://127.0.0.1:22070', + 'websockets': True, + 'proxy_set_header': { + 'X-Forwarded-Host': '$server_name', + }, + }, + }, + 'extras': True, }, }, }, 'paperless': { - 'domain': 'paperless-sophie.home.kunbox.net', 'version': 'ng-1.4.4', 'timezone': 'Europe/Berlin', }, diff --git a/nodes/home/paperless.py b/nodes/home/paperless.py index 8c1a969..3dd957e 100644 --- a/nodes/home/paperless.py +++ b/nodes/home/paperless.py @@ -6,18 +6,12 @@ nodes['home.paperless'] = { 'redis', 'postgresql', 'paperless-ng', - 'proftpd', }, 'groups': { - 'debian-trixie', + 'debian-buster', 'webserver', }, 'metadata': { - 'icinga_options': { - 'also_affected_by': { - 'home.nas', - }, - }, 'interfaces': { 'enp1s0': { 'ips': { @@ -42,23 +36,30 @@ nodes['home.paperless'] = { 'nginx': { 'vhosts': { 'paperless': { - 'create_logs': True, + 'domain': 'paperless.home.kunbox.net', 'ssl': '_.home.kunbox.net', + 'locations': { + '/': { + 'target': 'http://127.0.0.1:22070', + 'websockets': True, + 'proxy_set_header': { + 'X-Forwarded-Host': '$server_name', + }, + }, + '/static/': { + 'alias': '/opt/paperless/static/', + }, + }, + 'max_body_size': '100M', }, }, }, 'paperless': { - 'domain': 'paperless.home.kunbox.net', - 'version': 'v2.16.2', + 'version': 'ng-1.4.4', 'timezone': 'Europe/Berlin', }, 'postgresql': { - 'version': 15, - }, - 'proftpd': { - 'restrict-to': { - 'home.fujitsu-n7100', - }, + 'version': '11', }, 'vm': { 'cpu': 2, diff --git a/nodes/sophie/rechenmonster.py b/nodes/home/rechenmonster.py similarity index 92% rename from nodes/sophie/rechenmonster.py rename to nodes/home/rechenmonster.py index ee862f7..f4e76ad 100644 --- a/nodes/sophie/rechenmonster.py +++ b/nodes/home/rechenmonster.py @@ -1,4 +1,4 @@ -nodes['sophie.rechenmonster'] = { +nodes['home.rechenmonster'] = { 'hostname': '172.19.138.98', 'bundles': { 'basic', @@ -54,6 +54,9 @@ nodes['sophie.rechenmonster'] = { }, }, 'users': { + 'kunsi': { + 'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='), + }, 'sophie': { 'password': vault.decrypt('encrypt$gAAAAABiEAyiedXL6ZnvelOMumhcB73X72SXZhjS_G0EDYVK5-NQ3_J_0h1W1HkFBNe5tShGNmg88jUiULRBn5u2IoiRGiDrYg=='), }, @@ -88,9 +91,6 @@ nodes['sophie.rechenmonster'] = { 'storage/video': { 'mountpoint': '/video', }, - 'storage/nas': { - 'mountpoint': '/nas', - }, }, }, }, diff --git a/nodes/home/router.py b/nodes/home/router.py index c84b4ef..cbdbc5d 100644 --- a/nodes/home/router.py +++ b/nodes/home/router.py @@ -2,8 +2,7 @@ nodes['home.router'] = { 'hostname': '172.19.138.1', 'bundles': { 'bird', - 'jool', - 'kea-dhcp-server', + 'dhcpd', 'nginx', 'pppd', 'radvd', @@ -13,20 +12,18 @@ nodes['home.router'] = { 'wireguard', }, 'groups': { - 'debian-bookworm', + 'debian-bullseye', }, 'metadata': { 'interfaces': { 'enp1s0.1138': { 'ips': { '172.19.138.1/24', - 'fe80::1/64', }, }, 'enp1s0.1139': { 'ips': { '172.19.139.1/24', - 'fe80::1/64', }, }, }, @@ -45,50 +42,65 @@ nodes['home.router'] = { # connected longer than 24 hours. We install this cronjob # to make sure we don't get disconnected randomly during the # day. - 'restart_pppd': r'23 2 * * * root systemctl restart pppoe && date -u +\%s > /var/tmp/pppd-last-restart.status', + 'restart_pppd': '23 2 * * * root systemctl restart pppoe && date -u +\%s > /var/tmp/pppd-last-restart.status', }, }, - 'kea-dhcp-server': { + 'dhcpd': { 'subnets': { 'enp1s0.1138': { - 'lower': '172.19.138.100', - 'higher': '172.19.138.250', + 'range_lower': '172.19.138.100', + 'range_higher': '172.19.138.250', 'subnet': '172.19.138.0/24', 'options': { + 'broadcast-address': '172.19.138.255', + 'domain-name': 'franzi-home.kunbox.net', 'domain-name-servers': '172.19.138.1', + 'domain-search': 'home.kunbox.net', 'routers': '172.19.138.1', + 'subnet-mask': '255.255.255.0', }, }, 'enp1s0.1139': { - 'lower': '172.19.139.200', - 'higher': '172.19.139.250', + 'range_lower': '172.19.139.200', + 'range_higher': '172.19.139.250', 'subnet': '172.19.139.0/24', 'options': { + 'broadcast-address': '172.19.139.255', 'domain-name-servers': '172.19.139.1', 'routers': '172.19.139.1', + 'subnet-mask': '255.255.255.0', }, }, }, }, + 'hosts': { + 'entries': { + # Hackaround to force wireguard to only use IPv4 for + # the connection to this system. + '51.195.47.180': { + 'wireguard.ovh.kunbox.net', + }, + }, + }, 'icinga_options': { # override group default - 'also_affected_by': atomic(set()), + 'also_affected_by': atomic({ + 'ovh.wireguard', + }), # disabled on group level # XXX reenable this once we can leave the house safely again #'vars.notification.sms': True }, 'nftables': { - 'forward': { + 'rules': { '50-router': [ - 'ct state { related, established } accept', - 'iifname enp1s0.1138 accept', - 'ip6 nexthdr ipv6-icmp accept', - 'tcp dport 22 accept', - ], - }, - 'prerouting': { - '50-router': [ - 'tcp dport 2022 dnat 172.19.138.20:22', + # This is a router. Allow forwarding traffic for internal networks. + 'inet filter forward ct state { related, established } accept', + + # yaaaaay, IPv6! No NAT! + 'inet filter forward ip6 nexthdr ipv6-icmp accept', + 'inet filter forward tcp dport 22 accept', + 'nat prerouting tcp dport 2022 dnat 172.19.138.20:22', ], }, }, @@ -96,7 +108,6 @@ nodes['home.router'] = { 'restrict-to': { '172.19.136.0/25', '172.19.138.0/24', - 'htz-cloud.molly-connector', }, 'vhosts': { 'vnstat': { @@ -107,16 +118,8 @@ nodes['home.router'] = { }, 'radvd': { 'interfaces': { - 'enp1s0.1138': { - 'rdnss': { - 'fe80::1', - }, - }, - 'enp1s0.1139': { - 'rdnss': { - 'fe80::1', - }, - }, + 'enp1s0.1138': {}, + 'enp1s0.1139': {}, }, }, 'postfix': { @@ -130,23 +133,32 @@ nodes['home.router'] = { 'interface': 'enp1s0.7', 'dyndns': { 'domain': 'franzi-home.kunbox.net', - 'url': 'https://ns-mephisto.kunbox.net/nic/update?hostname=franzi-home.kunbox.net&myip={ips}', + 'url': 'https://ns-primary.kunbox.net/nic/update?hostname=franzi-home.kunbox.net&myip={ip}', 'username': vault.decrypt('encrypt$gAAAAABfr8DLAJhmUIhdxLq83I8MnRRvkRgDZcO8Brvw1KpvplC3K8ZGj0jIIWD3Us33vIP6t0ybd_mgD8slpRUk78Kqd3BMoQ=='), 'password': vault.decrypt('encrypt$gAAAAABfr8Cq5M1hweeJTQAl0dLhFntdlw-QnkIYUQpY-_ycODVWOpyeAwjwOgWLSdsdXIUvqcoiXPZPV-BE12p5C42NGnj9r7sKYpoGz8xfuGIk6haMa2g='), }, 'nftables-rules.d': { + 'inet filter forward iifname enp1s0.1138 accept', 'inet filter forward iifname enp1s0.1139 oifname $INTERFACE accept', }, }, 'unbound': { - 'dns64': False, 'restrict-to': { '172.19.138.0/23', - 'fe80::/64', }, }, 'users': { - 'fkunsmann': {}, + 'f2k1de': { + 'ssh_pubkey': { + 'command="/bin/false",no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGrvhqC/tZzpLMs/qy+1xNSVi2mfn8LXPIEhh7dcGn9e', + 'command="/bin/false",no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDH5+j2vDW1FHSSEEI/Sf5qiKJq1uoxGO5BPv84mqohvol7GxDFObv69tn7g6HYfZY/SaS75C4ZXy+cKa0xy8UCpF0SBa2xHASkenS9v55oweDL4rYSPARzn2XKt3RFJG/d8V5NOWtcyq5DFSzewUF35E4hx1pUc/CIxgJEem5ZvzvN0hlIKXUN2djkVUx+mz6RryBysLTJEFBamjJxIkvDG/PZU73W4SHaKAYV4Ojz2NY7T5/NYKePfIU5F9pkE3RU0LRj58usvA1eP0PvEArWlGNCd8EJU+HQ5xr2dZ6MKPpEyG0KJkC88DuapeF5RwUV53ZhNpF+QgzpI72fH5up', + }, + }, + 'fkunsmann': { + 'sudo_commands': { + 'ALL', + }, + }, }, 'vnstat': { 'interface': 'enp1s0.7', @@ -163,7 +175,13 @@ nodes['home.router'] = { }, }, 'wireguard': { - 'snat_ip': '172.19.138.1', + 'external_hostname': 'franzi-home.kunbox.net', # Set via DynDNS + 'peers': { + 'ovh.wireguard': { + 'health_check': True, + 'snat_to': '172.19.138.1', + }, + }, }, }, } diff --git a/nodes/htz-cloud.molly-connector.toml b/nodes/htz-cloud.molly-connector.toml deleted file mode 100644 index eeea694..0000000 --- a/nodes/htz-cloud.molly-connector.toml +++ /dev/null @@ -1,8 +0,0 @@ -dummy = true - -# Machine is managed by molly and does SNAT for her vpn infrastructure. -# Putting this into my hetzner cloud project was the easiest way to do -# interconnect. - -[metadata.interfaces.default] -ips = ["172.19.137.5"] diff --git a/nodes/htz-cloud.prometheus.toml b/nodes/htz-cloud.prometheus.toml deleted file mode 100644 index 6532493..0000000 --- a/nodes/htz-cloud.prometheus.toml +++ /dev/null @@ -1,7 +0,0 @@ -hostname = "138.199.210.112" -groups = ["debian-bookworm"] - -[metadata.interfaces.eth0] -ips = ["138.199.210.112/32", "2a01:4f8:1c1e:65e4::1/64"] -gateway4 = "172.31.1.1" -gateway6 = "fe80::1" diff --git a/nodes/htz-cloud/influxdb.py b/nodes/htz-cloud/influxdb.py index e3dc166..8a8d884 100644 --- a/nodes/htz-cloud/influxdb.py +++ b/nodes/htz-cloud/influxdb.py @@ -3,12 +3,11 @@ nodes['htz-cloud.influxdb'] = { 'bundles': { 'grafana', 'influxdb2', - 'telegraf_airgradient', 'telegraf-monitors-mikrotik', 'zfs', }, 'groups': { - 'debian-bullseye', + 'debian-buster', 'webserver', }, 'metadata': { @@ -34,7 +33,7 @@ nodes['htz-cloud.influxdb'] = { }, 'routes': { # VPN - '172.19.128.0/20': { + '172.19.136.0/22': { 'via': '172.19.137.1', }, }, @@ -45,8 +44,7 @@ nodes['htz-cloud.influxdb'] = { 'login_max_duration': '30d', }, 'icinga_options': { - # no public access - 'show_on_statuspage': False, + 'pretty_name': 'InfluxDB', }, 'nginx': { 'vhosts': { @@ -67,9 +65,6 @@ nodes['htz-cloud.influxdb'] = { }, }, }, - 'telegraf_airgradient': { - 'Home': vault.decrypt('encrypt$gAAAAABlr3KvHLSHLFwVr5hvJ1j676Flm5fVLumqpBcffjYWXjPjSovDXCyEcVqhxfsX-GNut2dXsenFQoFShaAugLV_zVQYaLnNQipbZqI0cXfsMht1iZPyOxlSzy3YoZ3voSaeiLll'), - }, 'telegraf': { 'input_plugins': { 'builtin': { diff --git a/nodes/htz-cloud/luther.py b/nodes/htz-cloud/luther.py new file mode 100644 index 0000000..6e30f57 --- /dev/null +++ b/nodes/htz-cloud/luther.py @@ -0,0 +1,109 @@ +nodes['htz-cloud.luther'] = { + 'bundles': { + 'php', + 'postgresql', + 'zfs', + }, + 'groups': { + 'debian-buster', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '195.201.136.20', + '2a01:4f8:c2c:fc3b::1/64', + }, + 'gateway4': '172.31.1.1', + 'gateway6': 'fe80::1', + }, + 'ens10': { + 'ips': { + '172.19.137.4/32', + }, + 'routes': { + # VPN + '172.19.136.0/22': { + 'via': '172.19.137.1', + }, + }, + }, + }, + 'apt': { + 'packages': { + 'php-apcu': {}, + 'php-uploadprogress': {}, + }, + }, + 'cron': { + 'jobs': { + 'luther-ps': vault.decrypt('encrypt$gAAAAABfnUqTXXpUYCA2DxllTKgbKg6YguCBbguJ0rerFGi9UNxEuTO6eqReqraS9FzNmLl81S_20bYwXM5W8pNwV5I5i6BVz1M37TxdsMCAxMG-9G0ZHFXeE4K5a4MWxuyYkrVPtK_hNFOciwxDDwPYT8tH_Jahdqmr8fZcCcsICzsSOxycn89VEm2ODnfH24Azrj6mVq5cPMc_xkdWnn-dSMCvPXpjjg==').format_into('*/10 * * * * www-data /usr/bin/curl -s {}'), + }, + }, + 'icinga_options': { + 'period': 'daytime', + 'pretty_name': 'Lutherkirchengemeinde Pirmasens', + 'vars.notification.sms': False, + }, + 'nginx': { + 'vhosts': { + 'luther-ps': { + 'domain': 'luther-ps.kunsmann.eu', + 'php': True, + 'extras': True, + 'website_check_path': '/user/login', + 'website_check_string': 'Username', + }, + }, + }, + 'php': { + 'version': '7.4', + 'packages': { + 'curl', + 'gd', + 'json', + 'mbstring', + 'pgsql', + 'xml', + }, + }, + 'postgresql': { + 'version': '11', + 'users': { + 'luther-ps': { + # can't use password_for() here, application is unmanaged + 'password': vault.decrypt('encrypt$gAAAAABfnSxJtRTeWRTO_ubSqpBbH8L-khPamKtSiUYbuMIoyJnoF_oSfUlMpTpQsmdDh61F3JQEH0xfYOkzkiCGZONRHyYdqkTjWV4Ku1Avdb0SL74VG6NihUJOpZlhOKnuniopCwuW'), + }, + }, + 'databases': { + 'luther-ps': { + 'owner': 'luther-ps', + }, + }, + }, + 'zfs': { + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'devices': {'/dev/sdb'}, + }], + }, + }, + }, + 'datasets': { + 'tank/luther-website': { + 'mountpoint': '/var/www/luther-ps', + 'needed_by': { + 'directory:/var/www/luther-ps', + }, + }, + }, + }, + 'vm': { + 'cpu': 1, + 'ram': 2, + }, + }, +} diff --git a/nodes/htz-cloud/miniserver.py b/nodes/htz-cloud/miniserver.py new file mode 100644 index 0000000..90299a4 --- /dev/null +++ b/nodes/htz-cloud/miniserver.py @@ -0,0 +1,241 @@ +# sophie's miniserver + +nodes['htz-cloud.miniserver'] = { + 'bundles': { + 'element-web', + 'hedgedoc', + 'matrix-media-repo', + 'matrix-synapse', + 'nodejs', + 'ntfy', + 'mautrix-telegram', + 'postgresql', + 'zfs', + }, + 'groups': { + 'debian-bullseye', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '157.90.20.62', + '2a01:4f8:c2c:840f::1/64', + }, + 'gateway4': '172.31.1.1', + 'gateway6': 'fe80::1', + }, + }, + 'apt': { + 'packages': { + 'mosh': {}, + 'weechat': {}, + 'weechat-core': {}, + 'weechat-curses': {}, + 'weechat-perl': {}, + 'weechat-plugins': {}, + 'weechat-python': {}, + 'weechat-ruby': {}, + }, + 'repos': { + 'weechat': { + 'items': { + 'deb https://weechat.org/debian {os_release} main', + }, + }, + }, + }, + 'backup-client': { + 'pre-hooks': { + 'sophie-weechat': \ + 'echo \'core.weechat */layout store\' >> /home/sophie/.weechat/weechat_fifo\n' \ + 'echo \'core.weechat */save\' >> /home/sophie/.weechat/weechat_fifo\n', + }, + 'target': "htz-hel.backup-sophie", + }, + 'backups': { + 'paths': { + '/home/sophie/.weechat', + }, + }, + 'element-web': { + 'url': 'chat.sophies-kitchen.eu', + 'version': 'v1.11.28', + 'config': { + 'default_server_config': { + 'm.homeserver': { + 'base_url': 'https://matrix.sophies-kitchen.eu', + 'server_name': 'sophies-kitchen.eu', + }, + }, + 'brand': 'sophies-kitchen.eu', + 'showLabsSettings': True, + 'default_theme': 'dark', + 'defaultCountryCode': 'DE', + 'jitsi': { + 'preferredDomain': 'meet.ffmuc.net', + }, + 'map_style_url': "https://api.maptiler.com/maps/openstreetmap/style.json?key=fU3vlMsMn4Jb6dnEIFsx" + }, + }, + 'hedgedoc': { + 'version': '1.9.7', + 'config': { + 'production': { + 'allowAnonymousEdits': True, + 'domain': 'pad.sophies-kitchen.eu', + }, + }, + }, + 'icinga_options': { + 'pretty_name': 'sophies-kitchen.eu', + 'vars.notification.sms': False, + }, + 'letsencrypt': { + 'concat_and_deploy': { + 'sophie-weechat': { + 'match_domain': 'i.sophies-kitchen.eu', + 'target': '/home/sophie/.weechat/ssl/relay.pem', + 'chown': 'sophie:sophie', + 'chmod': '0440', + 'commands': [ + 'echo \'core.weechat */relay sslcertkey\' >> /home/sophie/.weechat/weechat_fifo' + ], + }, + }, + 'domains': { + 'i.sophies-kitchen.eu': set(), + 'webdump.sophies-kitchen.eu': set(), + 'matrix.sophies-kitchen.eu': { + 'sophies-kitchen.eu', + }, + }, + }, + 'matrix-media-repo': { + 'version': 'v1.2.13', + 'sha1': '0915bdf7c461368859180419d1f66717969cbe32', + 'homeservers': { + 'sophies-kitchen.eu': { + 'domain': 'http://[::1]:20080/', + 'api': 'synapse', + }, + }, + 'admins': { + '@sophie:sophies-kitchen.eu', + }, + 'upload_max_mb': 500, + }, + 'matrix-synapse': { + 'server_name': 'sophies-kitchen.eu', + 'baseurl': 'matrix.sophies-kitchen.eu', + 'admin_contact': 'mailto:foobar@sophies-kitchen.eu', + 'trusted_key_servers': { + 'matrix.org', + }, + }, + 'mautrix-telegram': { + 'version': 'v0.13.0', + 'homeserver': { + 'domain': 'sophies-kitchen.eu', + 'url': 'https://matrix.sophies-kitchen.eu', + }, + 'provisioning': { + 'enabled': False, + 'shared_secret': '""', + }, + 'permissions': { + 'sophies-kitchen.eu': 'full', + "'@sophie:sophies-kitchen.eu'": 'admin', + }, + 'telegram': { + 'api_id': vault.decrypt('encrypt$gAAAAABgnqdXhCTwtCXJhSaCZsiNfHPtjwlYtV1sUAux7JZdejN3xItU9RJLeNu4gUniv36XbBoxKwVtqqyV3RcAs-PgumcfYQ=='), + 'api_token': vault.decrypt('encrypt$gAAAAABgnqd5IdpYRmW-C4ONBSXQfiJrpTVQX0rP0eKoDnLnVTLg-5olSjcw2gVvEKWLnsGEZIgVcG7yEs-sqYRxeiQLFFpSn-Z4We0mhj0CUeFoD-eXJsp-bAgLv9PJoMv5Gjb8r9i6'), + 'bot_token': '""', + }, + }, + 'nameservers': { + '213.133.98.98', + '213.133.99.99', + '213.133.100.100', + '2a01:4f8:0:1::add:1010', + '2a01:4f8:0:1::add:9999', + '2a01:4f8:0:1::add:9898', + }, + 'nftables': { + 'rules': { + '50-sophie-weechat': [ + 'inet filter input udp dport { 60000-61000 } accept', + 'inet filter input tcp dport 9001 accept', + ], + }, + }, + 'nginx': { + 'vhosts': { + 'sophies-kitchen.eu': { + 'webroot': '/var/www/sophies-kitchen.eu/_site/', + 'extras': True, + }, + 'matrix-synapse': { + 'domain': 'matrix.sophies-kitchen.eu', + }, + 'webdump.sophies-kitchen.eu': { + 'webroot_config': { + 'owner': 'sophie', + 'group': 'sophie', + 'mode': '0755', + }, + 'extras': True, + }, + 'recipes.sophies-kitchen.eu': { + 'webroot_config': { + 'owner': 'sophie', + 'group': 'sophie', + 'mode': '0755', + }, + }, + }, + }, + 'nodejs': { + 'version': 16, + }, + 'ntfy': { + 'domain': 'ntfy.sophies-kitchen.eu', + }, + 'postgresql': { + 'version': '11', + }, + 'sysctl': { + 'options': { + # XXX find out if this is really needed + 'net.ipv4.ip_forward': '1', + 'net.ipv6.conf.all.forwarding': '1', + }, + }, + 'vm': { + 'cpu': 2, + 'ram': 4, + }, + 'users': { + 'sophie': { + 'enable_linger': True, + 'ssh_pubkey': [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDILcYrMQNRVXAm5L+7No1ZumqfCyRc1QZmTY3O7Q8hsE4+fCAvwsWm2aSMfLL3NnIl8Nm1Rixzic5jdYKYNIY3SlX1wvTB+MhGb2eyVSd7c/Y98aCLSlDkQ2sebjpdA1FoJOeGD3qxqDwj0+KckXU2ZaSSQY7CxVsjH65UxCHqVAg+6uLdNbj7j850s1B9NXVXef+sBQ5jUngXxnqQWwNh2Mn8auwumkeEG4SYf96wyFkLvmBitOng/GyLWl9YPnXXHHDnatcVipy7y34qw4CQ4P84anecbA+Bqr9IcxBW6qYmYgRKEnAcmEfjQd+BI1gCLB1BBEmb/qp+mVLd4tOh sophie@carbon" + ], + }, + }, + 'zfs': { + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'devices': { + '/dev/disk/by-id/scsi-0HC_Volume_23952298', + }, + }] + }, + }, + }, + }, + }, +} diff --git a/nodes/htz-cloud/pirmasens.py b/nodes/htz-cloud/pirmasens.py index 908e85e..67d7e12 100644 --- a/nodes/htz-cloud/pirmasens.py +++ b/nodes/htz-cloud/pirmasens.py @@ -10,7 +10,7 @@ nodes['htz-cloud.pirmasens'] = { 'unbound', }, 'groups': { - 'debian-bookworm', + 'debian-buster', 'webserver', }, 'metadata': { @@ -37,25 +37,39 @@ nodes['htz-cloud.pirmasens'] = { }, 'nginx': { 'vhosts': { - 'salonkatrin-v2': { - 'domain': 'salonkatrin.de', - 'domain_aliases': { - 'www.salonkatrin.de', - 'old.salonkatrin.de', - }, + 'mail.kunsmann.info': { + 'webroot': '/opt/postfixadmin/public/', + 'php': True, + 'website_check_path': '/login.php', + 'website_check_string': 'login', + }, + 'salonkatrin.de': { 'website_check_path': '/', 'website_check_string': 'Salon Katrin', + }, + 'salonkatrin-v2': { + 'domain': 'dev.salonkatrin.de', 'webroot_config': { - 'owner': 'forgejo-carlene', + 'owner': 'autojenkins', + }, + }, + 'salonkatrin-www': { + 'domain': 'www.salonkatrin.de', + 'locations': { + '/': { + 'redirect': 'https://salonkatrin.de$request_uri', + }, }, }, }, }, 'php': { + 'version': '7.4', 'packages': { 'gd', 'imap', 'intl', + 'json', 'mbstring', 'opcache', 'pgsql', @@ -68,8 +82,7 @@ nodes['htz-cloud.pirmasens'] = { 'message_size_limit_mb': 50, }, 'postfixadmin': { - 'domain': 'mail.kunsmann.info', - 'version': '3.3.15', + 'version': '3.3.13', 'setup_password': vault.decrypt('encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ=='), }, 'postgresql': { @@ -79,8 +92,11 @@ nodes['htz-cloud.pirmasens'] = { 'password': vault.decrypt('encrypt$gAAAAABfp7qzym32R6Go1A6oax0NGQM7EBMckbEbnZC6-RSKx-klSJsL57XbSUTD-AJM-gBIPzlmor-3bfVxPWLRYXtO8uTVw6jNQ1yt15ReHkOTijVqV2ACk-LTDBG3p4YKBn0pQgNvvjXhWV_J1-Pgjywbl4sHXc0zqjCGZ6xtEn6ywj0Pd599JJjREF4QCIFVZVWuKvo1'), }, 'users': { - 'forgejo-carlene': {}, + 'autojenkins': {}, 'frank': {}, + 'sophie': { + 'delete': True, + }, }, 'vm': { 'cpu': 2, diff --git a/nodes/htz-cloud/pleroma.py b/nodes/htz-cloud/pleroma.py new file mode 100644 index 0000000..b57d13c --- /dev/null +++ b/nodes/htz-cloud/pleroma.py @@ -0,0 +1,85 @@ +nodes['htz-cloud.pleroma'] = { + 'bundles': { + 'pleroma', + 'postgresql', + 'zfs', + }, + 'groups': { + 'debian-buster', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '159.69.11.231', + '2a01:4f8:c2c:c410::1/64', + }, + 'gateway4': '172.31.1.1', + 'gateway6': 'fe80::1', + }, + 'ens10': { + 'ips': { + '172.19.137.5/32', + }, + 'routes': { + # VPN + '172.19.136.0/22': { + 'via': '172.19.137.1', + }, + }, + }, + }, + 'icinga_options': { + 'period': 'daytime', + 'pretty_name': 'cybert-media.net', + }, + 'cron': { + 'jobs': { + 'auto-authorize-sm-users': '* * * * * root echo "UPDATE users SET approval_pending=false WHERE email LIKE \'\\%@seibert-media.net\' AND approval_pending=true;" | psql pleroma >/dev/null', + }, + }, + 'nginx': { + 'vhosts': { + 'pleroma': { + 'max_body_size': '16M', + 'extras': True, + }, + 'pleroma-www-redir': { + 'domain': 'www.cybert-media.net', + 'locations': { + '/': { + 'redirect': 'https://cybert-media.net$request_uri', + }, + }, + }, + }, + }, + 'pleroma': { + 'version': '2.2.2', + 'url': 'cybert-media.net', + 'secret_key': vault.decrypt('encrypt$gAAAAABgMVXXclfxVY022fM0Fdf94Oh3sxVlK0lYyBO_CsQFEbZcMua3w1oJY8_9d1JcrCJSSeBRTDnt-ZkRCQ6xKoALo8Rl7s9DPxa7J0vHdkggeZ3IHaOyXBcBPdx8vILyKDLHRXacaynOUBOjy6RIl6Qf2wH1ASbphCcjD-Njricg4PG6Rcixm87fF60rLBjAAkRoz5ZQnXlut1rhjLj-z-7UpA68fkeyPVJXbroWBJdmvCUt92dwjuGARsku2XI22mVvjtJJ'), + }, + 'postfix': { + 'myhostname': 'cybert-media.net', + }, + 'postgresql': { + 'version': '11', + }, + 'vm': { + 'cpu': 1, + 'ram': 2, + }, + 'zfs': { + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'devices': {'/dev/sdb'}, + }], + }, + }, + }, + }, + }, +} diff --git a/nodes/htz-cloud/sewfile.py b/nodes/htz-cloud/sewfile.py new file mode 100644 index 0000000..95cdcf3 --- /dev/null +++ b/nodes/htz-cloud/sewfile.py @@ -0,0 +1,93 @@ +# this node runs only seafile. Seafile and the mysql server are not +# managed by bundlewrap. + +nodes['htz-cloud.sewfile'] = { + 'bundles': { + 'seafile', + 'zfs', + }, + 'groups': { + 'debian-buster', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '116.203.205.248', + '2a01:4f8:c0c:c71b::1/64', + }, + 'gateway4': '172.31.1.1', + 'gateway6': 'fe80::1', + }, + 'ens10': { + 'ips': { + '172.19.137.3/32', + }, + 'routes': { + # VPN + '172.19.136.0/22': { + 'via': '172.19.137.1', + }, + }, + }, + }, + 'backups': { + 'paths': { + '/mnt/seafile-data', + '/var/tmp/mysqldumps', + }, + }, + 'backup-client': { + 'pre-hooks': { + 'mysqldump': \ + 'test -d /var/tmp/mysqldumps || mkdir -p /var/tmp/mysqldumps\n'\ + 'rm /var/tmp/mysqldumps/*.sql\n'\ + 'mysqldump --databases ccnet_db > /var/tmp/mysqldumps/ccnet_db.sql\n'\ + 'mysqldump --databases seafile_db > /var/tmp/mysqldumps/seafile_db.sql\n'\ + 'mysqldump --databases seahub_db > /var/tmp/mysqldumps/seahub_db.sql\n', + }, + }, + 'icinga_options': { + 'pretty_name': 'sewfile.franzi.business', + 'vars.notification.sms': False, + }, + 'nginx': { + 'vhosts': { + 'sewfile.franzi.business': { + 'ssl': '_.franzi.business', + 'max_body_size': '0', + 'extras': True, + 'website_check_path': '/accounts/login/', + 'website_check_string': 'Username', + }, + }, + }, + 'vm': { + 'cpu': 1, + 'ram': 2, + }, + 'zfs': { + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'devices': {'/dev/sdb'}, + }], + }, + }, + }, + 'datasets': { + 'tank/mysql': { + 'mountpoint': '/var/lib/mysql', + }, + 'tank/seafile-data': { + 'mountpoint': '/mnt/seafile-data', + 'needed_by': { + 'bundle:seafile', + }, + }, + }, + }, + }, +} diff --git a/nodes/htz-cloud/wireguard.py b/nodes/htz-cloud/wireguard.py index 1139390..2837438 100644 --- a/nodes/htz-cloud/wireguard.py +++ b/nodes/htz-cloud/wireguard.py @@ -5,7 +5,7 @@ nodes['htz-cloud.wireguard'] = { 'wireguard', }, 'groups': { - 'debian-bookworm', + 'debian-buster', }, 'metadata': { 'interfaces': { @@ -33,37 +33,7 @@ nodes['htz-cloud.wireguard'] = { }, 'bird': { 'static_routes': { - '10.73.0.0/16', '172.19.137.0/24', - '172.19.136.62/31', - '172.19.136.64/31', - '172.19.136.66/31', - '192.168.100.0/24', - }, - }, - 'nftables': { - 'forward': { - '50-router': [ - 'ct state { related, established } accept', - 'oifname eth0 accept', - ], - }, - 'input': { - '50-wireguard': [ - 'udp dport 1194 accept', - 'udp dport 51800 accept', - 'udp dport 51804 accept', - 'udp dport 51805 accept', - - # wg.c3voc.de - 'udp dport 51801 ip saddr 185.106.84.42 accept', - 'udp dport 51801 ip6 saddr 2001:67c:20a0:e::189 accept', - ], - }, - 'postrouting': { - '50-router': [ - 'oifname eth0 masquerade', - ], }, }, 'vm': { @@ -71,70 +41,14 @@ nodes['htz-cloud.wireguard'] = { 'ram': 2, }, 'wireguard': { - 'snat_ip': '172.19.137.2', 'peers': { - 'c3voc': { - 'endpoint': 'wg.c3voc.de:13337', - 'my_ip': '10.44.0.35/24', - 'my_port': 51801, - 'their_ip': '10.44.0.1', - 'pubkey': vault.decrypt('encrypt$gAAAAABl_fnDW_9u0RLQpKmiE9V-4DjEcEVSaGp5NohG8tBD3tayGkrDd-LahgeEhDeWlCnoomErZi6HHCag3ODeoKivPr9F_UfdKPEOlCoDkMahqud8p5_3edi-TvIt30Bq_45yeIOo'), - 'masquerade': True, - 'routes': { - '10.73.0.0/16', - }, - }, - 'fra-jana': { - 'endpoint': 'gw.as212226.net:40000', - 'my_ip': '192.168.48.11/24', - 'my_port': 51802, - 'their_ip': '192.168.48.1', - 'pubkey': vault.decrypt('encrypt$gAAAAABnCA7M0Jg0cQwIaYCYEYN74MOSQK30rbhxD6tDIi2VEBqPh-UHrt7MdRzI4AUZ-p0MzjIdsps_DdGBkUTwA_UKD15Q_tg_LJNwDb04zvgSqc3hnJ4jeS2ZZEED0T1dVJ7E0YNS'), - 'masquerade': True, - 'routes': { - '192.168.100.0/24', - }, - }, - 'kunsi-oneplus7': { - 'endpoint': None, - 'exclude_from_monitoring': True, - 'my_ip': '172.19.136.62', - 'my_port': 51800, - 'their_ip': '172.19.136.63', - 'psk': vault.decrypt('encrypt$gAAAAABlbr26kyQ_DNIObVNtG31e1uSZkfDKH9Y1tzq8ZNSAMeuEh30cMJBZQskLLYqt5HUGd-YFwYQB_E7oa-WWbHmDh4vAxJ22Efr85tA0TWsgkc2KvKHqZrNo-GCXhxCqs7SqhW1C'), - 'pubkey': vault.decrypt('encrypt$gAAAAABlbr27doNVsPXF7hMpAp93fP-h_jlW10zycZAHy05r4R7rOZrLqf5b-lhdamx_kQxypYtcW-jOCYgcqWNsId7RluEmFo3drFuUYKIa32YU_U0Pe5EjVRFz_tuf9NRPPugmHb22'), - }, - #'kunsi-p14s': { - # 'endpoint': None, - # 'exclude_from_monitoring': True, - # 'my_ip': '172.19.136.64', - # 'my_port': 1194, - # 'their_ip': '172.19.136.65', - #}, - 'apfelcomputer': { - 'endpoint': None, - 'exclude_from_monitoring': True, - 'my_ip': '172.19.136.64', - 'my_port': 1194, - 'their_ip': '172.19.136.65', - 'psk': vault.decrypt('encrypt$gAAAAABnc7LZSHWmOOQJpbtnpMn9QuWnbiB-6rShwgqbilVd45GzkUwOfEHBw28P_TVm9XJgFiQPOIo12DdxPCzSxKRtcqzji72QCzTlze4ZYWjL-iHm7TydLcKzXOTCO42LKpkMPUgR'), - 'pubkey': vault.decrypt('encrypt$gAAAAABnc7LZpfAeig8yCdcZ-NegshXl-DmkJr0F2OlQR2fqhVnrfKPjgOu-5Cq09KnhdvhomGx_9ZtoFS_3OsVqcFHEasBh27aQN41xZPzEN5-qIPQRnmVoTHpufcU6tC-37Fq-PeAE'), - }, - 'revision-dect-vpn': { - 'endpoint': None, - 'exclude_from_monitoring': True, - 'my_port': 51804, - 'my_ip': '172.19.136.66', - 'their_ip': '172.19.136.67', - }, - 'rottenraptor-vpn': { - 'endpoint': None, - 'exclude_from_monitoring': True, - 'my_port': 51805, - 'my_ip': '172.19.136.68', - 'their_ip': '172.19.136.69', + 'ovh.wireguard': { + 'snat_to': '172.19.137.2', }, }, + 'subnets': { + '172.19.137.0/24', + }, }, }, } diff --git a/nodes/htz-hel/backup-kunsi.py b/nodes/htz-hel/backup-kunsi.py new file mode 100644 index 0000000..be66592 --- /dev/null +++ b/nodes/htz-hel/backup-kunsi.py @@ -0,0 +1,53 @@ +nodes['htz-hel.backup-kunsi'] = { + 'hostname': '2a01:4f9:6b:2d99::1337', + 'bundles': { + 'backup-server', + 'dm-crypt', + 'zfs', + }, + 'groups': { + 'debian-bullseye', + }, + 'metadata': { + 'apt': { + 'unattended-upgrades': { + # requires manual apply after reboot to unlock dm-crypt + # devices + 'reboot_enabled': False, + }, + }, + 'interfaces': { + 'ens18': { + 'ips': { + '2a01:4f9:6b:2d99::1337/64', + }, + 'gateway6': '2a01:4f9:6b:2d99::2', + }, + }, + 'backups': { + # This is the backup target. + 'exclude_from_backups': True, + }, + 'backup-server': { + 'encrypted-devices': { + '/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi1-part1': bwpass.password('bw/backup-kunsi/encryption-passphrase'), + }, + 'clients': { + 'kunsi-t470': { + 'user': 'kunsi-t470', + 'exclude_from_monitoring': True, + 'retain': { + 'daily': 30, + 'weekly': 6, + 'monthly': 12, + }, + }, + }, + }, + 'openssh': { + 'allowed_users': { + 'kunsi-t470', # backup user + }, + }, + }, +} diff --git a/nodes/sophie/backupserver.py b/nodes/htz-hel/backup-sophie.py similarity index 84% rename from nodes/sophie/backupserver.py rename to nodes/htz-hel/backup-sophie.py index 42c6292..dfd492d 100644 --- a/nodes/sophie/backupserver.py +++ b/nodes/htz-hel/backup-sophie.py @@ -6,7 +6,6 @@ nodes['htz-hel.backup-sophie'] = { }, 'groups': { 'debian-bullseye', - 'sophie', }, 'metadata': { 'apt': { @@ -31,19 +30,21 @@ nodes['htz-hel.backup-sophie'] = { 'gateway6': '2a01:4f9:6b:2d99::2', }, }, + 'icinga_options': { + 'pretty_name': 'backup.sophies-kitchen.eu', + }, 'vm': { 'cpu': 4, 'ram': 8, }, 'backup-server': { 'zfs-base': 'tank/backups', - 'my_hostname': 'backup.sophies-kitchen.eu', }, 'nftables': { - 'input': { + 'rules': { '50-sophie-misc': [ - 'udp dport { 60000-61000 } accept', - 'tcp dport 5201 accept', + 'inet filter input udp dport { 60000-61000 } accept', + 'inet filter input tcp dport 5201 accept', ], }, }, @@ -52,9 +53,6 @@ nodes['htz-hel.backup-sophie'] = { 'tank/ejgwthink': { 'mountpoint': '/mnt/backups/ejgwthink', }, - 'tank/ejgwdesk': { - 'mountpoint': '/mnt/backups/ejgwdesk', - }, 'tank/moto-sophie': { 'mountpoint': '/mnt/backups/moto-sophie', }, diff --git a/nodes/htz-hel/proxmox-backupstorage.toml b/nodes/htz-hel/proxmox-backupstorage.toml new file mode 100644 index 0000000..19d83d3 --- /dev/null +++ b/nodes/htz-hel/proxmox-backupstorage.toml @@ -0,0 +1,19 @@ +hostname = "2a01:4f9:6b:2d99::c0ff:ee" +dummy = true + +# How to install: +# - Get server at Hetzner (no IPv4) +# - Install latest proxmox compatible debian +# - RAID5 +# - 50G for system +# - leave rest unpartitioned +# - install zfs +# - create additional partitions for remaining disk space +# - create raidz on those partitions +# - enable ipv6 forwarding +# - install proxmox via apt + +# VM config: +# - IPv6 only +# - IP from the /64 hetzner gives us +# - Gateway is the host itself, to work around the MAC filter hetzner uses diff --git a/nodes/icinga2.toml b/nodes/icinga2.toml deleted file mode 100644 index 3194c8b..0000000 --- a/nodes/icinga2.toml +++ /dev/null @@ -1,64 +0,0 @@ -hostname = "217.160.71.39" -bundles = [ - "bird", - "icinga2", - "icinga2-statuspage", - "php", - "postgresql", -# 'simple-icinga-dashboard', - "unbound", - "wireguard", -] -groups = [ - 'debian-bookworm', - 'webserver', -] - -[metadata] -location = "ionos" -icinga_options.pretty_name = "icinga.franzi.business" - -[metadata.interfaces.ens192] -ips = [ - "217.160.71.39/32", - "2001:8d8:1800:d5::1/128" -] -gateway4 = "10.255.255.1" -gateway6 = "fe80::1" - -[metadata.bird] -static_routes = ["172.19.136.4/32"] - -[metadata.icinga2] -web_domain = "icinga.franzi.business" -ntfy.pass = "!decrypt:encrypt$gAAAAABkMtfD8lenogwJc8uKeGZUQ8QVWHMpAqY_GLW3VhF3Jt0TOC4JiJn49qfaC9Ij5rw6GGsowNIsNBe1Ac83HXOLveANEU2o-O4fp5TxNF0xFWebCCtcaTkj_L2DjUbSUe8QVDn3" -ntfy.url = "https://ntfy.franzi.business/icinga2" -ntfy.user = "!decrypt:encrypt$gAAAAABkMtfW_tyGDUh7TkVX6AN8wSkKixWcQiOrPUWHtDZqnzjqrAkfD40fD8M_PiPDvW5pAa6xHNcUSU34jHolxnC44rDiLw==" -sipgate.pass = "!bwpass_attr:sipgate.de/hi@kunsmann.eu:icinga_token" -sipgate.user = "!bwpass_attr:sipgate.de/hi@kunsmann.eu:icinga_tokenid" - -[metadata.icinga2.api_users.icinga2beamer] -# Used with -password = "!decrypt:encrypt$gAAAAABf3wM9YS5ZpRdhp3xyIFX21_MK0omzqHqykWbWdkZWp2xyJ6awaUSXODnZQ5j-rws6n0yrpaeMdXoj1irb2FrgxMDTdfCh88hIsqcKGOObzwGaRg6Ze0tuiMrzIfOO3tRnc9Kd" -permissions = [ - "objects/query/Host", - "objects/query/Service", -] - -[metadata.icinga2-statuspage] -DOMAIN = "status.franzi.business" -SERVICEGROUP_ID = 80 - -[metadata.icinga2-statuspage.NAME_REPLACEMENTS] -" PROCESS$" = " SERVICE" -".+ VHOST (.+) CONTENT" = "WEB ACCESS \\1" - -[metadata.postgresql] -version = 15 - -[metadata.wireguard] -snat_ip = "172.19.136.4" - -[metadata.vm] -cpu = 2 -ram = 2 diff --git a/nodes/kunsi-p14s.py b/nodes/kunsi-p14s.py new file mode 100644 index 0000000..a341c5b --- /dev/null +++ b/nodes/kunsi-p14s.py @@ -0,0 +1,239 @@ +nodes['kunsi-p14s'] = { + 'hostname': 'localhost', + 'bundles': { + 'arch-with-gui', + 'backup-client', + 'lldp', + 'lm-sensors', + 'nfs-client', + 'openvpn-client', + 'systemd-boot', + 'telegraf-battery-usage', + 'vmhost', + 'voc-tracker-worker', + 'zfs', + }, + 'groups': { + 'arch', + }, + 'metadata': { + 'arch-with-gui': { + 'autologin_as': 'kunsi', + }, + 'backup-client': { + # only alert people if we're missing more than a week of backups + 'one_backup_every_hours': 7 * 24, + }, + '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': {'*'}, + }, + }, + 'interfaces': { + 'br0': { + #'ips': {'10.73.100.103/16'}, + #'gateway4': '10.73.0.254', + 'dhcp': True, + }, + # there is also wlp3s0, but that's managed by netctl + }, + 'nfs-client': { + 'mounts': { + 'nas-scansnap': { + 'mountpoint': '/mnt/scansnap', + 'serverpath': '172.19.138.20:/srv/scansnap', + 'mount_options': { + 'retry=0', + 'rw', + }, + }, + 'nas-storage': { + 'mountpoint': '/mnt/nas', + 'serverpath': '172.19.138.20:/storage/nas', + 'mount_options': { + 'retry=0', + 'ro', + }, + }, + }, + }, + 'openssh': { + 'restrict-to': { + 'rfc1918', + 'ipv6', + }, + }, + 'openvpn-client': { + 'configs': { + 'c3voc': { + 'running': None, + 'enabled': False, + }, + 'smedia-priv': { + 'running': None, + 'enabled': False, + }, + }, + }, + 'pacman': { + 'no_extract': { + 'etc/sudoers.d/ctdb', # samba junk + }, + 'packages': { + # for hardware support + 'amd-ucode': {}, + 'mesa': {}, + + # various video drivers + 'libva-mesa-driver': {}, + 'mesa-vdpau': {}, + 'xf86-video-amdgpu': {}, + + # all that other random stuff one needs + 'abcde': {}, + 'apachedirectorystudio': {}, + 'claws-mail': {}, + 'claws-mail-themes': {}, + 'ferdi-bin': {}, + 'gumbo-parser': {}, # for claws litehtml + 'perl-musicbrainz-discid': {}, # for abcde + 'perl-webservice-musicbrainz': {}, # for abcde + 'sdl_ttf': {}, # for compiling testcard + }, + }, + 'sysctl': { + 'options': { + # XXX temp, try to find out why the system randomly + # hangs when using wifi, but only after suspending or + # switching from ethernet. + 'net.ipv6.conf.wlp3s0.disable_ipv6': '1', + }, + }, + 'systemd-boot': { + 'default': 'arch', + 'entries': { + 'arch': { + 'title': 'Arch Linux', + 'linux': '/vmlinuz-linux', + 'initrd': [ + '/amd-ucode.img', + '/initramfs-linux.img', + ], + 'options': { + 'zfs=zroot/system/root', + 'rw', + }, + }, + 'arch-fallback': { + 'title': 'Arch Linux (no ucode, fallback initramfs)', + 'linux': '/vmlinuz-linux', + 'initrd': [ + '/initramfs-linux-fallback.img', + ], + 'options': { + 'zfs=zroot/system/root', + 'rw', + }, + }, + }, + }, + 'systemd-networkd': { + 'bridges': { + 'br0': { + 'match': { + 'en*', + 'eth*', + }, + }, + }, + }, + 'timezone': 'Europe/Berlin', + 'users': { + 'kunsi': { + 'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='), + 'shell': '/usr/bin/fish', + }, + 'sophie': { + 'delete': True, + }, + }, + 'voc-tracker-worker': { + 'url': 'https://tracker.c3voc.de/rpc', + 'token': vault.decrypt('encrypt$gAAAAABiYqaFl4CqOc8DTQIn49Qq0KgAJSzA19GKPNMbyHIjYg0JkvY0sK43ps8CbJWMRR6hJHVK-nP4vrWLwyoWWqt8N8aASMur4odC2s8pEHQKM0TXg4cRwobQz_lyJgrYa2VYdhcD'), + 'secret': vault.decrypt('encrypt$gAAAAABiYqaYbY-3IbnRk-S25pqxrOGN7ovgPo3kBYz8ZqKDedPRzskKZefpLHxBbCOZKjg1XNT4cKbIs5cPCLdj7HdY4beAhnXl4EHZZdxU1zVC7sJCmz9XOS_Ac0UOgOlUFMiet14U'), + }, + 'zfs': { + 'pools': { + 'zroot': { + 'when_creating': { + 'config': [{ + 'devices': [ + '/dev/disk/by-id/nvme-UMIS_RPETJ1T24MGE2QDQ_SS0L25218X3RC1BG1182-part2', + ], + }], + 'ashift': 12, + }, + }, + }, + '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/movies': { + 'mountpoint': '/media/movies', + }, + 'zroot/system/journal': { + 'mountpoint': '/var/log/journal', + 'acltype': 'posix', + }, + 'zroot/system/libvirt': { + 'mountpoint': '/var/lib/libvirt', + 'needed_by': { + 'bundle:vmhost', + }, + }, + 'zroot/system/video': { + 'mountpoint': '/video', + 'needed_by': { + 'bundle:voc-tracker-worker', + }, + }, + 'zroot/system/root': { + 'canmount': 'noauto', + 'mountpoint': 'legacy', + }, + 'zroot/user/kunsi': { + 'mountpoint': '/home/kunsi', + }, + }, + 'snapshots': { + 'retain_per_dataset': { + 'zroot/user/kunsi': { + # juuuuuuuust to be sure + 'hourly': 100, + }, + }, + 'snapshot_never': { + 'zroot/movies', + 'zroot/system/journal', + 'zroot/system/video', + }, + }, + }, + }, + 'os': 'arch', +} diff --git a/nodes/kunsi-seibert-x1.py b/nodes/kunsi-seibert-x1.py new file mode 100644 index 0000000..19ec8bf --- /dev/null +++ b/nodes/kunsi-seibert-x1.py @@ -0,0 +1,67 @@ +# work laptop. Only apply interactively. + +nodes['kunsi-seibert-x1'] = { + 'dummy': True, + 'hostname': '172.19.138.240', + 'bundles': { + 'basic', + 'lldp', + 'lm-sensors', + 'nfs-client', + 'pacman', + 'openssh', + 'sudo', + 'systemd', + 'telegraf', + 'telegraf-battery-usage', + 'users', + }, + 'groups': set(), + 'metadata': { + 'timezone': 'Europe/Berlin', + 'icinga_options': { + 'exclude_from_monitoring': True, + }, + 'locale': { + 'default': 'en_DK.UTF-8', + }, + 'lldp': { + 'hostname': 'fkunsmann-seibertmedia', + }, + 'nfs-client': { + 'mounts': { + 'nas-storage': { + 'mountpoint': '/mnt/nas', + 'serverpath': '172.19.138.20:/storage/nas', + 'mount_options': { + 'retry=0', + 'ro', + }, + }, + }, + }, + 'pacman': { + 'install_gui': True, + }, + 'telegraf': { + 'influxdb_url': 'https://influxdb.kunsmann.eu/', + 'influxdb_token': vault.decrypt('encrypt$gAAAAABgg9Ag632Xyuc6SWXaR1uH2tLOChmVKAoBIikhjntSSD2qJFL_eouVQGXCLH2HEuSbSdEXcTPn2qmhOiA9jmFdoDSbVbQUsp0EID1wLsWYG_Um2KOxZSF-tn9eDZlgShQYySjzO3nQRmdlJpVLUnGHsiwv_sHD2FstXGpfzTPZq5_egUqEc0K2X-aN2J6BTYc2fZAN'), + 'influxdb_org': vault.decrypt('encrypt$gAAAAABgg9hyjz4XtvG8NBw9uYxiumS3v7YKIrtc9tTTABg1f9R22gzn55q8ULP9X3wlsPMUQs_DH7CgGv9neYmvVAriRoyd8g=='), + 'influxdb_bucket': vault.decrypt('encrypt$gAAAAABgg9iMnq0nKpODMiMN4NtUw231iqpbyDXV-O8epOAGDSL4jcf3CaSa2bLZzH2fJFaKWjW-dpVd384x6KqSQU19XpfsWA=='), + }, + 'users': { + 'kunsi': { + 'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='), + 'shell': '/usr/bin/fish', + 'ssh_pubkey': { + # work key + 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICYst1HK+gJYhNxzqJGnz4iB73pa89Xz2yH+8wufOcsA', + }, + }, + 'sophie': { + 'delete': True, + }, + }, + }, + 'os': 'arch', +} diff --git a/nodes/kunsi-t470.py b/nodes/kunsi-t470.py new file mode 100644 index 0000000..61f21d4 --- /dev/null +++ b/nodes/kunsi-t470.py @@ -0,0 +1,104 @@ +# My own laptop. + +nodes['kunsi-t470'] = { + 'dummy': True, + 'hostname': 'no', + 'bundles': { + 'lldp', + 'lm-sensors', + 'nfs-client', + 'telegraf-battery-usage', + }, + 'groups': { + 'arch', + }, + 'metadata': { + 'timezone': 'Europe/Berlin', + 'icinga_options': { + 'exclude_from_monitoring': True, + }, + 'hosts': { + 'entries': { + '10.101.64.10': { + 'www.wifionice.de', + 'wifionice.de', + }, + }, + }, + 'interfaces': { + 'br0': { + 'dhcp': True, + 'use_dhcp_domains': True, + 'send_hostname': False, + }, + # there is also wlp4s0, but that's managed by netctl + }, + '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': {'*'}, + }, + }, + 'locale': { + 'default': 'en_DK.UTF-8', + }, + 'nfs-client': { + 'mounts': { + 'nas-scansnap': { + 'mountpoint': '/mnt/scansnap', + 'serverpath': '172.19.138.20:/srv/scansnap', + 'mount_options': { + 'retry=0', + 'rw', + }, + }, + 'nas-storage': { + 'mountpoint': '/mnt/nas', + 'serverpath': '172.19.138.20:/storage/nas', + 'mount_options': { + 'retry=0', + 'ro', + }, + }, + }, + }, + 'openssh': { + 'restrict-to': { + '10.0.0.0/8', + '172.16.0.0/12', + '192.168.0.0/16', + 'ipv6', + }, + }, + 'pacman': { + 'install_gui': True, + }, + 'systemd-networkd': { + 'bridges': { + 'br0': { + 'match': { + 'enp0s31f6', + }, + }, + }, + }, + 'users': { + 'kunsi': { + 'password': vault.decrypt('encrypt$gAAAAABgLmmuQGRUStrQawoPee-758emIYn2u8-8ebrgzNAFSp7ifeFDdXXvs-zL3QogwNYlCtBHboH2xfy1rSj6OF5bbNO-tg=='), + 'shell': '/usr/bin/fish', + # FIXME move qemu VMs out of /home/kunsi + 'home-mode': '0755', + }, + 'sophie': { + 'delete': True, + }, + }, + }, + 'os': 'arch', +} diff --git a/nodes/ns-ghirahim.toml b/nodes/ns-ghirahim.toml deleted file mode 100644 index a8581c6..0000000 --- a/nodes/ns-ghirahim.toml +++ /dev/null @@ -1,26 +0,0 @@ -hostname = "46.101.91.6" -groups = [ - "debian-bullseye", - "dns", -] - -[metadata.interfaces.eth0] -ips = [ - "46.101.91.6/20", - "2a03:b0c0:1:d0::bc2:6001/124", -] -gateway4 = "46.101.80.1" -gateway6 = "2a03:b0c0:1:d0::1" - -[metadata.postfix] -# It's fine to do this without authentificating to the relayhost. -# These Systems are not supposed to send mail anywhere else -# than our own domains. -relayhost = "[mail.franzi.business]:2525" - -[metadata.postgresql] -version = "15" - -[metadata.vm] -cpu = 1 -ram = 1 diff --git a/nodes/ns-mephisto.toml b/nodes/ns-mephisto.toml deleted file mode 100644 index a4494fa..0000000 --- a/nodes/ns-mephisto.toml +++ /dev/null @@ -1,36 +0,0 @@ -hostname = "82.165.52.168" -bundles = [ - "nodejs", - "powerdnsadmin", -] -groups = [ - "debian-bullseye", - "dns", - "webserver", -] - -[metadata.interfaces.ens192] -ips = [ - "82.165.52.168/32", - "2a01:239:31c:9b00::1/80" -] -gateway4 = "82.165.52.1" -gateway6 = "fe80::1" - -[metadata.nginx.vhosts.powerdnsadmin] -domain = "ns-mephisto.kunbox.net" - -[metadata.postgresql] -version = "15" - -[metadata.powerdns] -is_secondary = false -secondary_nameservers = "dns" -features.bind = true - -[metadata.powerdnsadmin] -version = "v0.4.2" - -[metadata.vm] -cpu = 2 -ram = 2 diff --git a/nodes/ns-primary.toml b/nodes/ns-primary.toml new file mode 100644 index 0000000..c2ef311 --- /dev/null +++ b/nodes/ns-primary.toml @@ -0,0 +1,43 @@ +hostname = "82.165.52.168" +bundles = [ + "nodejs", + "powerdnsadmin", +] +groups = [ + "debian-bullseye", + "dns", + "webserver", +] + +[metadata.interfaces.ens192] +ips = [ + "82.165.52.168", + "2001:8d8:1801:7d4::1/64", +] +gateway4 = "10.255.255.1" +gateway6 = "fe80::250:56ff:fea8:628f" + +[metadata.icinga_options] +pretty_name = "ns-primary.kunbox.net" + +[metadata.nginx.vhosts."ns-primary.kunbox.net"] +website_check_path = "/login" +website_check_string = "PowerDNS" + +[metadata.nginx.vhosts."ns-primary.kunbox.net".locations."/"] +target = "http://127.0.0.1:8000/" + +[metadata.postgresql] +version = "15" + +[metadata.powerdns] +is_secondary = false +secondary_nameservers = "dns" +features.bind = true + +[metadata.powerdnsadmin] +version = "v0.4.0" + +[metadata.vm] +cpu = 2 +ram = 2 diff --git a/nodes/ns-sargeras.toml b/nodes/ns-sargeras.toml deleted file mode 100644 index 53f64b0..0000000 --- a/nodes/ns-sargeras.toml +++ /dev/null @@ -1,26 +0,0 @@ -hostname = "46.102.156.104" -groups = [ - "debian-bookworm", - "dns", -] - -[metadata.interfaces.ens18] -ips = [ - "46.102.156.104/26", - "2a0d:f302:113:73e6::1/48", -] -gateway4 = "46.102.156.65" -gateway6 = "2a0d:f302:113::1" - -[metadata.postfix] -# It's fine to do this without authentificating to the relayhost. -# These Systems are not supposed to send mail anywhere else -# than our own domains. -relayhost = "[mail.franzi.business]:2525" - -[metadata.postgresql] -version = "15" - -[metadata.vm] -cpu = 2 -ram = 2 diff --git a/nodes/ovh/icinga2.py b/nodes/ovh/icinga2.py new file mode 100644 index 0000000..1c930be --- /dev/null +++ b/nodes/ovh/icinga2.py @@ -0,0 +1,158 @@ +nodes['ovh.icinga2'] = { + 'bundles': { + 'bird', + 'icinga2', + 'php', + 'postgresql', + 'simple-icinga-dashboard', + 'unbound', + 'wireguard', + 'zfs', + }, + 'groups': { + 'debian-bullseye', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '51.195.44.8', + '2001:41d0:701:1100::2618/128' + }, + 'gateway4': '51.195.44.1', + 'gateway6': '2001:41d0:701:1100::1' + }, + 'dummy-snat': { + 'ips': { + '172.19.136.3', + }, + }, + }, + 'bird': { + 'static_routes': { + '172.19.136.3/32', + }, + }, + 'icinga2': { + 'api_users': { + 'dashboard': { + 'password': vault.password_for('ovh.icinga2 icinga2 api_user dashboard'), + 'permissions': { + 'objects/query/Service' + }, + }, + # Used with + 'icinga2beamer': { + 'password': vault.decrypt('encrypt$gAAAAABf3wM9YS5ZpRdhp3xyIFX21_MK0omzqHqykWbWdkZWp2xyJ6awaUSXODnZQ5j-rws6n0yrpaeMdXoj1irb2FrgxMDTdfCh88hIsqcKGOObzwGaRg6Ze0tuiMrzIfOO3tRnc9Kd'), + 'permissions': { + 'objects/query/Host', + 'objects/query/Service' + }, + }, + }, + 'restrict-to': { + '172.19.138.0/24', + }, + 'sipgate_user': bwpass.attr('sipgate.de/hi@kunsmann.eu', 'icinga_tokenid'), + 'sipgate_pass': bwpass.attr('sipgate.de/hi@kunsmann.eu', 'icinga_token'), + }, + 'icinga2_api': { + 'custom': { + # redundant monitoring of services/hosts + 'services': { + 'flauschekatze.space CERTIFICATE': { + 'check_command': 'check_https_cert_at_url', + 'vars.domain': 'flauschekatze.space', + }, + 'matrix.flauschekatze.space CERTIFICATE': { + 'check_command': 'check_https_cert_at_url', + 'vars.domain': 'matrix.flauschekatze.space', + }, + }, + }, + }, + 'nginx': { + 'vhosts': { + 'icingaweb': { + 'domain': 'icinga.kunsmann.eu', + 'webroot': '/usr/share/icingaweb2/public', + 'extras': True, + }, + 'icinga_statusmonitor': { + 'domain': 'statusmonitor.icinga.kunsmann.eu', + 'locations': { + '/': { + 'target': 'http://127.0.0.1:5000/', + } + }, + }, + 'statuspage': { + 'domain': 'status.franzi.business', + 'ssl': '_.franzi.business', + 'webroot': '/opt/simple-icinga-dashboard/out', + }, + }, + }, + 'php': { + 'version': '8.0', + 'packages': { + 'curl', + 'gd', + 'intl', + 'imagick', + 'ldap', + 'mysql', + 'opcache', + 'pgsql', + 'readline', + 'xml', + }, + }, + 'postgresql': { + 'version': '11', + }, + 'simple-icinga-dashboard': { + 'icinga2_api': { + 'baseurl': 'https://127.0.0.1:5665', + 'username': 'dashboard', + 'password': vault.password_for('ovh.icinga2 icinga2 api_user dashboard'), + }, + 'filters': { + 'services': '"checks_with_sms" in service.groups', + }, + 'output': { + 'page_title': 'franzi.business Service Status', + }, + 'prettify': { + 'CONTENT': '', + 'NGINX': 'WEBSERVER', + 'PROCESS': 'SERVICE', + }, + }, + 'wireguard': { + 'peers': { + 'ovh.wireguard': { + 'snat_to': '172.19.136.3', + }, + }, + }, + 'zfs': { + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'devices': { + '/dev/sdb' + }, + }], + }, + }, + }, + }, + 'vm': { + 'cpu': 1, + 'ram': 2, + }, + }, +} diff --git a/nodes/ovh/wireguard.py b/nodes/ovh/wireguard.py new file mode 100644 index 0000000..6e92c59 --- /dev/null +++ b/nodes/ovh/wireguard.py @@ -0,0 +1,61 @@ +nodes['ovh.wireguard'] = { + 'bundles': { + 'bird', + 'wireguard', + }, + 'groups': { + 'debian-buster', + }, + 'metadata': { + 'interfaces': { + 'eth0': { + 'ips': { + '51.195.47.180', + '2001:41d0:701:1100::20da/128' + }, + 'gateway4': '51.195.44.1', + 'gateway6': '2001:41d0:701:1100::1' + }, + }, + 'bird': { + 'static_routes': { + '172.19.136.64/26', + }, + }, + 'backups': { + 'exclude_from_backups': True, + }, + 'vm': { + 'cpu': 1, + 'ram': 2, + }, + 'wireguard': { + 'peers': { + 'ovh.icinga2': {}, + 'home.router': { + 'health_check': True, + }, + 'htz-cloud.wireguard': {}, + 'kunsi-oneplus3': { + 'their_ip': '172.19.136.65', + 'my_ip': '172.19.136.64', + 'my_port': 51819, + 'psk': vault.decrypt('encrypt$gAAAAABgKYeeuPfokbk7lSbbJX-52kap5Cs3tdCHpezkKcExV-yLTHPjszIcAh1T9wW1BtGElRdZea7VTikV3qEu3bupiSqEW4l2lmD5cn2ERYRfuVCoYSkOlmEGokHUX7Nja4G_A2_x'), + 'pubkey': vault.decrypt('encrypt$gAAAAABgKYdTqLG3DcB13QqQadUxyzIjvSxwgZQNjorQi-ADSLsNdDbhikSAGQnSmGelLB74V175awIIir768WEnpLJUKX6nt_i2BxOP3JazvKZSQECkiK8G-IRn8wWWgKarfmtqRwh6'), + 'exclude_from_monitoring': True, + }, + 'sophie-ejgwthink': { + 'their_ip': '172.19.136.67', + 'my_ip': '172.19.136.66', + 'my_port': 51818, + 'psk': vault.decrypt('encrypt$gAAAAABhWWg7WWnVAl3R46oXfPHnmsuXIFELWoMb4wGeDDInKUAwjtI6Y9nYkMpvdxiPRbHnwG4sPxgUAu3l83E4BLTNwb-9_ZYPjz6bQQGYA7oYvCdsezWYYx22hmu8wJhq_j4sMyLK'), + 'pubkey': vault.decrypt('encrypt$gAAAAABhWWg7fSm9snyXS_VLCpEv28_o2fvu6MRzrqngbKQ41DSAQE5fg4ADSbQpi0uwP_6VE_aGo56z1qmLV9wHpOUYCqgYk57w2KcuHR92r_Cw6iNs_h85k38nFGkmuvHzUecqpCNa'), + 'exclude_from_monitoring': True, + }, + }, + 'restrict-to': { + '*', + }, + }, + }, +} diff --git a/nodes/proxmox-backupstorage.toml b/nodes/proxmox-backupstorage.toml deleted file mode 100644 index 3943102..0000000 --- a/nodes/proxmox-backupstorage.toml +++ /dev/null @@ -1,39 +0,0 @@ -hostname = "192.168.100.31" -dummy = true - -ipmi_hostname = "192.168.100.30" -ipmi_username = "root" -ipmi_password = "!bwpass:192.168.100.30/root" -ipmi_interface = "lanplus" - -[metadata.icinga2_api.smartd.services."SMART STATUS CT480BX500SSD1_2314E6C5C695"] -check_command = "sshmon" -"vars.sshmon_command" = "CT480BX500SSD1_2314E6C5C695" - -[metadata.icinga2_api.smartd.services."SMART STATUS CT480BX500SSD1_2314E6C5C6C8"] -check_command = "sshmon" -"vars.sshmon_command" = "CT480BX500SSD1_2314E6C5C6C8" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST20000NM007D-3DJ103_WVT0RNKF"] -check_command = "sshmon" -"vars.sshmon_command" = "ST20000NM007D-3DJ103_WVT0RNKF" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST20000NM007D-3DJ103_WVT0V0NQ"] -check_command = "sshmon" -"vars.sshmon_command" = "ST20000NM007D-3DJ103_WVT0V0NQ" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST20000NM007D-3DJ103_WVT0W64H"] -check_command = "sshmon" -"vars.sshmon_command" = "ST20000NM007D-3DJ103_WVT0W64H" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST8000NM0045-1RL112_ZA1EYQWR"] -check_command = "sshmon" -"vars.sshmon_command" = "ST8000NM0045-1RL112_ZA1EYQWR" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST8000NM0045-1RL112_ZA1EYZQF"] -check_command = "sshmon" -"vars.sshmon_command" = "ST8000NM0045-1RL112_ZA1EYZQF" - -[metadata.icinga2_api.smartd.services."SMART STATUS ST8000NM0045-1RL112_ZA1EZ0X5"] -check_command = "sshmon" -"vars.sshmon_command" = "ST8000NM0045-1RL112_ZA1EZ0X5" diff --git a/nodes/revision-dect-vpn.toml b/nodes/revision-dect-vpn.toml deleted file mode 100644 index 1340297..0000000 --- a/nodes/revision-dect-vpn.toml +++ /dev/null @@ -1,27 +0,0 @@ -hostname = "10.1.3.252" -bundles = ["bird", "wireguard"] -groups = ["debian-bookworm"] - -[metadata] -location = "revision" -backups.exclude_from_backups = true -icinga_options.exclude_from_monitoring = true - -[metadata.bird] -static_routes = [ - "10.1.3.0/24", -] - -[metadata.interfaces.ens18] -ips = ["10.1.3.252/24"] -gateway4 = "10.1.3.1" - -[metadata.nftables.postrouting] -"50-router" = [ - "oifname ens18 masquerade", -] - -[metadata.wireguard.peers."htz-cloud.wireguard"] -my_port = 51804 -my_ip = "172.19.136.67" -their_ip = "172.19.136.66" diff --git a/nodes/rottenraptor-server.toml b/nodes/rottenraptor-server.toml deleted file mode 100644 index c3f3d33..0000000 --- a/nodes/rottenraptor-server.toml +++ /dev/null @@ -1,101 +0,0 @@ -hostname = "91.198.192.207" -groups = [ - "debian-bookworm", - "webserver", -] -bundles = [ - "docker-engine", - "docker-goauthentik", - "docker-immich", - "ipmitool", - "php", - "smartd", - "zfs", -] - -ipmi_hostname = "192.168.100.27" -ipmi_username = "Administrator" -ipmi_password = "!bwpass:bw/rottenraptor-server/ipmi" -ipmi_interface = "lanplus" - -[metadata.apt.repos.tailscale] -items = [ - "deb https://pkgs.tailscale.com/stable/debian {os_release} main", -] - -[metadata.docker-immich] -enable_auto_album_share = true - -[metadata.icinga_options] -period = "daytime" - -[metadata.interfaces.eno4] -ips = [ - "91.198.192.207/27", - "2001:67c:b54:1::e/64", -] -gateway4 = "91.198.192.193" -gateway6 = "2001:67c:b54:1::1" - -[metadata.nginx.vhosts.'rotten.city'.locations.'/'] -redirect = "https://www.rottenraptor.com/" -mode = 302 - -[metadata.nginx.vhosts.dokuwiki] -domain = "wiki.rotten.city" -php = true -extras = true -webroot_config.owner = "www-data" - -[metadata.nginx.vhosts.goauthentik] -domain = "sso.rotten.city" - -[metadata.nginx.vhosts.immich] -domain = "immich.rotten.city" - -[metadata.nginx.vhosts.radio] -domain = "eventradio.rotten.city" -extras = true - -[metadata.php] -packages = [ - "xml", -] - -[metadata.smartd] -disks = [ - "/dev/disk/by-id/ata-HUH721008ALN600_7SGH125C", - "/dev/disk/by-id/ata-HUH721008ALN600_7SGH726C", - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21133V800321", - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21283J446103", - "/dev/disk/by-id/nvme-TOSHIBA-RC100_58UPC29HPW5S", -] - -[metadata.vm] -cpu = 4 -ram = 8 - -[metadata.zfs.pools.tank.when_creating] -ashift = 12 - -[[metadata.zfs.pools.tank.when_creating.config]] -type = "mirror" -devices = [ - "/dev/disk/by-id/ata-HUH721008ALN600_7SGH125C", - "/dev/disk/by-id/ata-HUH721008ALN600_7SGH726C", -] - -[[metadata.zfs.pools.tank.when_creating.config]] -type = "log" -devices = [ - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21133V800321-part1", - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21283J446103-part1", -] - -[[metadata.zfs.pools.tank.when_creating.config]] -type = "cache" -devices = [ - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21133V800321-part2", - "/dev/disk/by-id/ata-WDC_WDS100T1R0A-68A4W0_21283J446103-part2", -] - diff --git a/nodes/rottenraptor-stromdisplay.toml b/nodes/rottenraptor-stromdisplay.toml deleted file mode 100644 index a111bef..0000000 --- a/nodes/rottenraptor-stromdisplay.toml +++ /dev/null @@ -1,40 +0,0 @@ -hostname = "192.168.1.252" -os = "debian" -os_version = [12,] -bundles = [ - "apt", - "basic", - "kernel-modules", - "openssh", - "raspberrypi", - "sdm630_mqtt", - "sudo", - "sysctl", - "systemd", - "systemd-networkd", - "users", -] - -[metadata.apt.unattended-upgrades] -enabled = false - -[metadata.icinga_options] -exclude_from_monitoring = true - -[metadata.interfaces.eth0] -ips = [ - "192.168.1.252/24", -] -dhcp = true - -[metadata.raspberrypi] -enable_display = true - -[metadata.sdm630_mqtt] -enable_stats_collection = false -enable_local_printout = true -config.mqtt.host = "192.168.1.253" - -[metadata.users.kutscher] -password = "!decrypt:encrypt$gAAAAABmqQgvrVuPqFJWJSu8Yxd9NV4ppo5STfCPFqUWn0KepLRdFCktEMla0EJPPxZR5HbNnD6K2Vp-c63raeWwahFUT24SUrAoBFeWfToYWaRDi5WeXJU=" -sudo_commands = ["ALL"] diff --git a/nodes/rottenraptor-stromzaehler.toml b/nodes/rottenraptor-stromzaehler.toml deleted file mode 100644 index c04d6a4..0000000 --- a/nodes/rottenraptor-stromzaehler.toml +++ /dev/null @@ -1,46 +0,0 @@ -hostname = "192.168.1.253" -os = "debian" -os_version = [12,] -bundles = [ - "apt", - "basic", - "kernel-modules", - "mosquitto", - "openssh", - "raspberrypi", - "sdm630_mqtt", - "sudo", - "sysctl", - "systemd", - "systemd-networkd", - "telegraf", - "users", -] - -[metadata.apt.unattended-upgrades] -enabled = false - -[metadata.icinga_options] -exclude_from_monitoring = true - -[metadata.interfaces.eth0] -ips = [ - "192.168.1.253/24", -] -dhcp = true - -[metadata.sdm630_mqtt] -enable_local_printout = true -config.modbus.host = "192.168.1.254" -config.modbus.port = 4196 -config.telegraf.identifier = 'rottenraptor_truck' - -[metadata.sysctl.options] -'net.ipv6.conf.all.disable_ipv6' = '1' - -[metadata.telegraf] -collect_default_metrics = false - -[metadata.users.kutscher] -password = "!decrypt:encrypt$gAAAAABmqQgvrVuPqFJWJSu8Yxd9NV4ppo5STfCPFqUWn0KepLRdFCktEMla0EJPPxZR5HbNnD6K2Vp-c63raeWwahFUT24SUrAoBFeWfToYWaRDi5WeXJU=" -sudo_commands = ["ALL"] diff --git a/nodes/rottenraptor-vpn.toml b/nodes/rottenraptor-vpn.toml deleted file mode 100644 index 342ce1c..0000000 --- a/nodes/rottenraptor-vpn.toml +++ /dev/null @@ -1,27 +0,0 @@ -hostname = "172.30.17.53" -bundles = ["bird", "wireguard"] -groups = ["debian-bookworm"] - -[metadata] -location = "rottenraptor" -backups.exclude_from_backups = true -icinga_options.exclude_from_monitoring = true - -[metadata.bird] -static_routes = [ - "172.30.17.0/24", -] - -[metadata.interfaces.ens18] -ips = ["172.30.17.53/24"] -gateway4 = "172.30.17.1" - -[metadata.nftables.postrouting] -"50-router" = [ - "oifname ens18 masquerade", -] - -[metadata.wireguard.peers."htz-cloud.wireguard"] -my_port = 51804 -my_ip = "172.19.136.69" -their_ip = "172.19.136.68" diff --git a/nodes/rx300.py b/nodes/rx300.py new file mode 100644 index 0000000..b1ad5ee --- /dev/null +++ b/nodes/rx300.py @@ -0,0 +1,579 @@ +# To use the serial console in iRMC, set up grub as follows: +# GRUB_TIMEOUT=30 +# GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0,115200 console=tty0" +# GRUB_TERMINAL=serial +# GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1" + +nodes['rx300'] = { + 'hostname': '31.47.232.106', + 'bundles': { + 'check-mail-received', + 'dovecot', + 'element-web', + 'gitea', + 'ipmitool', + 'jenkins-ci', + 'lm-sensors', + 'matrix-dimension', + 'matrix-media-repo', + 'matrix-synapse', + 'mautrix-telegram', + 'mautrix-whatsapp', + 'miniflux', + 'minecraft', + 'mx-puppet-discord', + 'netbox', + 'nodejs', + 'oidentd', + 'php', + 'postfixadmin', + 'postgresql', + 'radicale', + 'redis', + 'rspamd', + 'smartd', + 'travelynx', + 'unbound', + 'vmhost', + 'zfs', + }, + 'groups': { + 'debian-bullseye', + 'webserver', + }, + 'metadata': { + 'interfaces': { + 'br0': { + 'ips': { + '31.47.232.106/29', + '2a00:f820:528::2/64', + }, + 'gateway4': '31.47.232.105', + 'gateway6': '2a00:f820:528::1', + }, + }, + 'apt': { + 'packages': { + # for franzi.business deployment + 'ruby': {}, + 'ruby-dev': {}, + 'ruby-bundler': {}, + + # for `bw test` on jenkins + 'bind9utils': {}, + + # used by user:kunsi + 'mosh': {}, + 'weechat': {}, + 'weechat-core': {}, + 'weechat-curses': {}, + 'weechat-perl': {}, + 'weechat-plugins': {}, + 'weechat-python': {}, + 'weechat-ruby': {}, + + # for weechat scripts + 'libpod-parser-perl': {}, + }, + 'repos': { + 'weechat': { + 'items': { + 'deb https://weechat.org/debian {os_release} main', + }, + }, + }, + }, + 'backup-client': { + 'pre-hooks': { + 'kunsi-weechat': \ + 'echo \'core.weechat */layout store\' >> /home/kunsi/.weechat/weechat_fifo\n' \ + 'echo \'core.weechat */save\' >> /home/kunsi/.weechat/weechat_fifo\n', + }, + }, + 'backups': { + 'paths': { + '/home/kunsi/.weechat', + }, + }, + 'check-mail-received': { + 't-online': { + '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'), + }, + }, + 'element-web': { + 'url': 'chat.franzi.business', + 'version': 'v1.11.28', + 'config': { + 'default_server_config': { + 'm.homeserver': { + 'base_url': 'https://matrix.franzi.business', + 'server_name': 'franzi.business', + }, + }, + 'brand': 'franzi.business', + 'showLabsSettings': True, + 'integrations_ui_url': 'https://dimension.franzi.business/riot', + 'integrations_rest_url': 'https://dimension.franzi.business/api/v1/scalar', + 'integrations_widgets_urls': { + 'https://dimension.franzi.business/widgets' + }, + 'default_theme': 'dark', + 'defaultCountryCode': 'DE', + 'jitsi': { + 'preferredDomain': 'meet.ffmuc.net', + }, + }, + }, + 'gitea': { + 'url': 'https://codeberg.org/attachments/7bd411b7-0e75-4e0f-89e3-9274cb9c0120', + 'sha1': 'c4b80feb8dcaa9d38612895cd9828dfa11b98333', + 'domain': 'git.franzi.business', + 'email_domain_blocklist': { + 'aol.com', + 'bamibi.com', + 'beezom.buzz', + 'block521.com', + 'cloud-mail.top', + 'comcast.net', + 'cox.net', + 'cupbest.com', + 'dakcans.com', + 'fitshot.xyz', + 'gmail.co', + 'gmail.com', + 'grabmail.club', + 'hbehs.com', + 'hotmail.com', + 'msn.com', + 'nycexercise.com', + 'oceore.com', + 'popcornfly.com', + 'qqhow.com', + 'runqx.com', + 'spicethainj.com', + 'spruzme.com', + 'syswift.com', + 'tagbert.com', + 'teleg.eu', + 'tempinbox.xyz', + 'verizon.net', + 'vusra.com', + 'yahoo.com', + }, + 'enable_git_hooks': True, + 'install_ssh_key': True, + 'internal_token': vault.decrypt('encrypt$gAAAAABfPncYwCX-NdBr9LdxLyGqmjRJqhmwMnWsdZy6kVOWdKrScW78xaqbJ1tpL1J4qa2hcZ7TQj3l-2mkyJNJOenGzU3TsI-gYMj9vC4m8Bhur5zboxjD4dQXaJbD1WSyHJ9sPJYsWP3Gjg6I19xeq9xMlAI6xaS9vOfuoI8nZnnQPx1NjfQEj03Jxf8a0-3F20sfICst1xRa5K48bpq1PFkK_oRojg=='), + 'lfs_secret_key': vault.decrypt('encrypt$gAAAAABfPnd1vgNDt86-91YhviQw8Z0djSp4f_tBt76klDv-ZcwxP1ryJzqJ7qnfaTe_6DYCfc82gEzvVDsyBlCoAkGpt1AI2_LCKetuSCnDPjtGvwdQl3A53lFEdG2UJl1uUiR7f8Vr'), + 'oauth_secret_key': vault.decrypt('encrypt$gAAAAABfPnbfTISbldhS0WyxVKBHVVoOMcar7Kxmh1kkmiUGd-RzbbnNzzhEER_owjttPQcACPfGKZ6WklaSsXjLq8km4P6A9QmPbC06GmHbc91m0odCb1KiY7SZeUD35PiRiGSq50dz'), + 'security_secret_key': vault.decrypt('encrypt$gAAAAABfPnc-R7pkDj4pQgHDb6pzlNYNJgiWdeBFsX7IsHSnCtNPbZxCdtSL8cHtQzVO1KbSxS7zCwssmgiR8Kj54Z-koD-FQbjpbKWoIPw8SsyeqBVlZhIeEzhw_1t7_7ZTvv1O8AePdNYel9JJb_TaAZ8Vx46ZfsEPy8zaaHrqOekHC6RAnB4='), + }, + 'icinga_options': { + 'pretty_name': 'franzi.business', + }, + 'jenkins-ci': { + 'install_ssh_key': True, + 'domain': 'jenkins.franzi.business', + 'writeable_paths': { + '/var/www/franzi.business', # for deployment task + }, + }, + 'letsencrypt': { + 'concat_and_deploy': { + 'kunsi-weechat': { + 'match_domain': 'rx300.kunbox.net', + 'target': '/home/kunsi/.weechat/ssl/relay.pem', + 'chown': 'kunsi:kunsi', + 'chmod': '0440', + 'commands': [ + 'echo \'core.weechat */relay sslcertkey\' >> /home/kunsi/.weechat/weechat_fifo' + ], + }, + }, + 'domains': { + 'rx300.kunbox.net': set(), + }, + }, + 'matrix-media-repo': { + 'version': 'v1.2.13', + 'sha1': '0915bdf7c461368859180419d1f66717969cbe32', + 'homeservers': { + 'franzi.business': { + 'domain': 'http://[::1]:20080/', + 'api': 'synapse', + }, + }, + 'admins': { + '@kunsi:franzi.business', + }, + 'upload_max_mb': 500, + }, + 'matrix-dimension': { + 'url': 'dimension.franzi.business', + 'version': 'c6d047c', # XXX master is broken as of 2021-11-27 + 'homeserver': { + 'name': 'franzi.business', + 'clientServerUrl': 'https://matrix.franzi.business', + 'accessToken': vault.decrypt('encrypt$gAAAAABg-wBmGbAy-Ou1mkG2w5UyoqWmWYzDr4ZavyUQdmG_VtrUSmwHjx-qcBGIz_7NniD3zKm9GGvzRZItDu5zYiojcudYr74TkWJKhdDrgFbcWlfJJ_m3bWzrSORaTYzBGRckp2Vz_8xHgDk1W03vpT6mdIPMDzjuINssIcPs0YDth25W942tMfPA2csvLADY50qVRMJpdBOVIWba55o0g6-mAAQLOz6Ld4cCvYqZsqXsxjT8JUytJv_uSG4zgCS_aX20JlAyJWpJgT8FQF5HzIbsko_-Z9-TwtY7yllJp5Ri3n0WaDaWoMmUfhLvkMJeymmOc32A4WJBAePQ_2F-_oUDE7t97A-m3ZiMVAEefDnH5MkoiQEJTfHrJsXRkdBT_BnJlY1CoAuXpRYDdvbVDwN_qZHHHtqsno437l9S6GgDK_-sKBiojYkYsfHcJCdSEqeFGuxT'), + }, + 'admins': [ + '@kunsi:franzi.business', + ], + 'telegram': { + # same as for mautrix-telegram + 'botToken': vault.decrypt('encrypt$gAAAAABfVK51ErJ6gfsOOkbRxSHDnVYmf7EihAQf7Uwj9og3TlAw64WRsA6ZVEgTSvOdLB3SMKZ-cTEhwkCOpbymq-_WLhes-hZALhN-H_oXHaxTQErJ0lARynKmjM-4ZhoGlUWlfh4Q'), + }, + }, + 'matrix-synapse': { + 'server_name': 'franzi.business', + 'baseurl': 'matrix.franzi.business', + 'admin_contact': 'mailto:hostmaster@kunbox.net', + 'trusted_key_servers': { + 'matrix.org', + 'finallycoffee.eu', + 'nyantec.com', + }, + 'additional_client_config': { + 'im.vector.riot.jitsi': { + 'preferredDomain': 'meet.ffmuc.net', + }, + }, + 'wellknown_also_on_vhosts': { + 'franzi.business', + }, + }, + 'mautrix-telegram': { + 'version': 'v0.13.0', + 'homeserver': { + 'domain': 'franzi.business', + 'url': 'https://matrix.franzi.business', + }, + 'provisioning': { + 'enabled': True, + 'shared_secret': vault.decrypt('encrypt$gAAAAABfVKflEMAi07C_QGP8cy97hF-4gGPym0oF6p4WSMdAveTpx-hFsZd2s7v9ubw99yIsyKx0dHOJI0UND7hV1rKZdvjy4Qa642abZ2wwW7SWTqvuP_qVtrf6-klc2QKTzeD9c_LVsyZ2dqz_JxRPq3MRXgkubZuWOZ6FmFlAlteTffoGfWE='), + }, + 'permissions': { + "'*'": 'relaybot', + 'nyantec.com': 'full', + 'franzi.business': 'full', + "'@kunsi:franzi.business'": 'admin', + }, + 'telegram': { + 'api_id': vault.decrypt('encrypt$gAAAAABfVK5SmDDru-UQxitkE5VhPArnUBhaRbAqQPvAW2Fh3fd1XDrWxa3Qn4BSnJAPNWglH5wil_SXUMcIm95FMhPe8dVeMQ=='), + 'api_token': vault.decrypt('encrypt$gAAAAABfVK5jHuUly1xr9Iku362k7oF4ZYRhLGzNJh3aJpiNrLfAy_DJpTwucx4FV_g45dyQF5boqG2rgdDfwsJN_Ab95es6T4SPGiXIxJOBlvIln1Torwh16pXKchhUTn_PQ077Ll1W'), + # same as for matrix-dimension + 'bot_token': vault.decrypt('encrypt$gAAAAABfVK51ErJ6gfsOOkbRxSHDnVYmf7EihAQf7Uwj9og3TlAw64WRsA6ZVEgTSvOdLB3SMKZ-cTEhwkCOpbymq-_WLhes-hZALhN-H_oXHaxTQErJ0lARynKmjM-4ZhoGlUWlfh4Q'), + }, + }, + 'mautrix-whatsapp': { + 'version': 'v0.8.3', + 'sha1': '89ac3134ed6ca81b498122113754dd4548982685', + 'homeserver': { + 'domain': 'franzi.business', + 'url': 'https://matrix.franzi.business', + }, + 'permissions': { + "'@kunsi:franzi.business'": 'admin', + }, + }, + 'miniflux': { + 'domain': 'rss.franzi.business', + }, + 'minecraft': { + 'heap_mb': 16*1024, + 'sha1': '82be5e1bbdfd1bcb001644780562282fd42ee5a9', + 'version': ('1.19.2', '261'), + 'allowlist': { + # use https://mcuuid.net/ + 'kunsi': 'a2b93640-9dff-4c3c-a6c7-bd75329d8997', + 'sophie': '7e593cbb-9d61-4d46-a416-6edbcf8a2109', + }, + 'ops': { + 'kunsi': 'a2b93640-9dff-4c3c-a6c7-bd75329d8997', + }, + 'restrict-to': {'*'}, + }, + 'mx-puppet-discord': { + 'homeserver': { + 'domain': 'franzi.business', + 'url': 'https://matrix.franzi.business', + }, + 'allowed-users': { + '@.*:franzi\\\\.business', + }, + }, + 'netbox': { + 'domain': 'netbox.franzi.business', + 'version': 'v3.4.7', + 'changelog_retention_days': 360, + 'admins': { + 'kunsi': 'hostmaster@kunbox.net', + }, + }, + 'nftables': { + 'rules': { + '50-kunsi-weechat': [ + 'inet filter input udp dport { 60000-61000 } accept', + 'inet filter input tcp dport 9001 accept', + ], + }, + }, + 'nginx': { + 'security.txt': { + 'contact': 'mailto:security@kunsmann.eu', + 'Encryption': 'https://franzi.business/gpg_hi-kunsmann.eu.asc', + }, + 'vhosts': { + 'element-web': {'ssl': '_.franzi.business'}, + 'forgejo': {'ssl': '_.franzi.business'}, + 'jenkins-ci': {'ssl': '_.franzi.business'}, + 'matrix-dimension': {'ssl': '_.franzi.business'}, + 'matrix-synapse': {'ssl': '_.franzi.business'}, + 'miniflux': {'ssl': '_.franzi.business'}, + 'netbox': {'ssl': '_.franzi.business'}, + 'radicale': {'ssl': '_.franzi.business'}, + 'travelynx': {'ssl': '_.franzi.business'}, + 'daskritzelt-redirect': { + 'domain': 'die-brontosaurier-waren-es.org', + 'ssl': None, + 'locations': { + '/': { + 'redirect': 'https://twitter.com/daskritzelt/status/1259167444373028864', + 'mode': 302, + }, + }, + }, + 'franzi.business': { + 'webroot': '/var/www/franzi.business/_site/', + 'ssl': '_.franzi.business', + 'extras': True, + }, + 'git.kunsmann.eu': { + 'locations': { + '/': { + 'redirect': 'https://git.franzi.business$request_uri', + }, + }, + }, + 'kunbox.net': {}, + 'kunsmann.eu': { + 'locations': { + '/': { + 'redirect': 'https://franzi.business$request_uri', + }, + '/.well-known/openpgpkey': { + 'alias': '/var/www/kunsmann.eu/.well-known/openpgpkey/', + 'additional_config': { + 'default_type application/octet-stream', + 'add_header Access-Control-Allow-Origin *', + }, + }, + }, + }, + 'mta-sts': { + 'domain': 'mta-sts.kunbox.net', + 'domain_aliases': { + 'mta-sts.franzi.business', + 'mta-sts.kunsmann.eu', + 'mta-sts.trans-agenda.eu', + }, + }, + 'paste.franzi.business': { + 'ssl': '_.franzi.business', + 'extras': True, + 'webroot_config': { + 'owner': 'kunsi', + }, + }, + 'postfixadmin': { + 'domain': 'postfixadmin.franzi.business', + 'ssl': '_.franzi.business', + 'webroot': '/opt/postfixadmin/public/', + 'php': True, + 'locations': { + '/rspamd/': { + 'target': 'http://localhost:11334/', + 'websockets': True, + }, + } + }, + 'wiki.franzi.business': { + 'ssl': '_.franzi.business', + 'extras': True, + 'php': True, + 'webroot_config': { + 'owner': 'www-data', + 'group': 'www-data', + }, + 'website_check_path': '/start?do=login', + 'website_check_string': 'Username', + }, + }, + 'worker_processes': 8, + }, + 'oidentd': { + 'allows': { + 'kunsi': { + 'spoof', + 'spoof_all', + }, + }, + }, + 'php': { + 'version': '8.0', + 'packages': { + 'gd', + 'imagick', + 'imap', + 'intl', + 'mbstring', + 'opcache', + 'pgsql', + 'readline', + 'xml', + 'yaml', + }, + }, + 'postfix': { + 'message_size_limit_mb': 75, + 'mynetworks': { + 'gce', + 'ovh', + }, + }, + 'postfixadmin': { + 'version': '3.3.13', + 'setup_password': vault.decrypt('encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ=='), + }, + 'postgresql': { + 'version': '13', + 'max_connections': 500, + }, + 'radicale': { + 'domain': 'radicale.franzi.business', + 'users': { + 'kunsi': bwpass.password('radicale.franzi.business/kunsi'), + }, + }, + 'rspamd': { + 'ignore_spam_check_for_ips': { + # entropia + '45.140.180.32/27', # Entropia e. V. + '45.140.180.112/28', # MicroPOC + '2a0e:c5c0:0:201::/64', # Entropia e. V. + '2a0e:c5c0:0:307::/64', # MicroPOC + + # c3kl + '116.202.19.236', + '2a01:4f8:1c17:cc52::/64', + + # ccc + '212.12.55.65', + '212.12.55.67', + '2a00:14b0:4200:3000:23:55:0:65', + + # IN-Berlin mailman + '130.133.8.35', + '192.109.42.28', + '192.109.42.122', + '193.29.188.9', + '217.197.80.23', + '217.197.80.134', + '2001:bf0:c000:a::2:134', + + # c3voc + '185.106.84.32/26', + '2001:67c:20a0:e::/64', + + # DENOG + '195.20.121.100', + '2001:1440:201:101::5', + }, + 'password': bwpass.password('bw/rx300/rspamd'), + 'dkim': 'uO4aNejDvVdw8BKne3KJIqAvCQMJ0416', + }, + 'smartd': { + 'disks': { + '/dev/nvme0', + }, + }, + 'systemd': { + 'journal': { + 'maxuse': '4G', + }, + }, + 'systemd-networkd': { + 'bridges': { + 'br0': { + 'match': { + 'eno1', + }, + }, + }, + }, + 'systemd-timers': { + 'timers': { + 'cleanup-paste.franzi.business': { + 'command': '/usr/bin/find /var/www/paste.franzi.business/ -maxdepth 1 -type d -mtime +60 -exec rm -r {} \;', + 'user': 'kunsi', + 'when': 'daily', + }, + }, + }, + 'travelynx': { + 'version': '1.30.9', + 'mail_from': 'travelynx@franzi.business', + 'domain': 'travelynx.franzi.business', + }, + 'unbound': { + 'threads': 8, + 'cache_slabs': 8, + }, + 'users': { + 'kunsi': { + 'enable_linger': True, + }, + }, + 'zfs': { + 'module_options': { + 'zfs_arc_max_gb': 16, + }, + 'pools': { + 'tank': { + 'when_creating': { + 'config': [{ + 'type': 'raidz', + 'devices': { + '/dev/sda', + '/dev/sdb', + '/dev/sdc', + '/dev/sdd', + }, + }], + 'ashift': 12, + }, + }, + }, + 'datasets': { + 'tank/libvirt': { + 'mountpoint': '/var/lib/libvirt', + 'compression': 'on', + 'needed_by': { + 'bundle:vmhost', + }, + }, + 'tank/home-kunsi': { + 'mountpoint': '/home/kunsi', + 'needed_by': { + 'directory:/home/kunsi', + }, + }, + }, + }, + 'vm': { + 'cpu': 32, + 'ram': 256, + }, + }, +} diff --git a/nodes/sophie/miniserver.py b/nodes/sophie/miniserver.py deleted file mode 100644 index b852a35..0000000 --- a/nodes/sophie/miniserver.py +++ /dev/null @@ -1,263 +0,0 @@ -# sophie's miniserver - -nodes["htz-cloud.miniserver"] = { - "bundles": { - "element-web", - "hedgedoc", - "matrix-media-repo", - "matrix-synapse", - "matrix-stickerpicker", - "nodejs", - "ntfy", - "mautrix-telegram", - "postgresql", - "zfs", - }, - "groups": { - "debian-bookworm", - "sophie", - "webserver", - }, - "metadata": { - "interfaces": { - "eth0": { - "ips": { - "157.90.20.62", - "2a01:4f8:c2c:840f::1/64", - }, - "gateway4": "172.31.1.1", - "gateway6": "fe80::1", - }, - }, - "apt": { - "packages": { - "mosh": {}, - "weechat": {}, - "weechat-core": {}, - "weechat-curses": {}, - "weechat-perl": {}, - "weechat-plugins": {}, - "weechat-python": {}, - "weechat-ruby": {}, - }, - "repos": { - "weechat": { - "items": { - "deb https://weechat.org/debian {os_release} main", - }, - }, - }, - }, - "backup-client": { - "pre-hooks": { - "sophie-weechat": "echo 'core.weechat */layout store' >> /home/sophie/.weechat/weechat_fifo\n" - "echo 'core.weechat */save' >> /home/sophie/.weechat/weechat_fifo\n", - }, - }, - "backups": { - "paths": { - "/home/sophie/.weechat", - }, - }, - "element-web": { - "url": "chat.sophies-kitchen.eu", - "version": "v1.11.96", - "config": { - "default_server_config": { - "m.homeserver": { - "base_url": "https://matrix.sophies-kitchen.eu", - "server_name": "sophies-kitchen.eu", - }, - }, - "brand": "sophies-kitchen.eu", - "showLabsSettings": True, - "default_theme": "dark", - "defaultCountryCode": "DE", - "jitsi": { - "preferredDomain": "meet.ffmuc.net", - }, - "map_style_url": "https://api.maptiler.com/maps/openstreetmap/style.json?key=fU3vlMsMn4Jb6dnEIFsx", - }, - }, - "hedgedoc": { - "version": "1.10.0", - "config": { - "production": { - "allowAnonymousEdits": True, - "domain": "pad.sophies-kitchen.eu", - }, - }, - }, - "letsencrypt": { - "concat_and_deploy": { - "sophie-weechat": { - "match_domain": "i.sophies-kitchen.eu", - "target": "/home/sophie/.weechat/ssl/relay.pem", - "chown": "sophie:sophie", - "chmod": "0440", - "commands": [ - "echo 'core.weechat */relay sslcertkey' >> /home/sophie/.weechat/weechat_fifo" - ], - }, - }, - "domains": { - "i.sophies-kitchen.eu": set(), - "webdump.sophies-kitchen.eu": set(), - "matrix.sophies-kitchen.eu": { - "sophies-kitchen.eu", - }, - }, - }, - "matrix-media-repo": { - "version": "v1.3.7", - "datastore_id": "99c09e24edc4e9be6c4c9486bc147e385bc87044", - "sha1": "3e2bb7089b0898b86000243a82cc58ae998dc9d9", - "homeservers": { - "sophies-kitchen.eu": { - "domain": "http://[::1]:20080/", - "api": "synapse", - "signing_key_path": "/etc/matrix-synapse/mmr.signing.key", - }, - }, - "admins": { - "@sophie:sophies-kitchen.eu", - }, - "upload_max_mb": 500, - }, - "matrix-stickerpicker": { - # use this bot token for telegram import: encrypt$gAAAAABg4bcQVzBF_iXdDtjRQD-O37GHdbHwWXyhCLPOuJLbv3ezUeXKR203hkCXkjfItSHi4NiTEgQPadDZTRkavaRpvAoaQV1a4srCS_Y-NU4RiOmkrVFJ_Xhw6UZvwjQUQ0QPOx9t - "domain": "matrix-stickers.sophies-kitchen.eu", - "config": { - "access_token": vault.decrypt( - "encrypt$gAAAAABg4btB0KGk068ahGZzR0w_Lm1bj1wUbB2WfNNs2bp3PwM4Ftp6MjQnrF-CejZfrF0NjPJw9Z4MrgileHP0sVw04mvgKSHfTf8gv4kTB6WuCIxHeMWHUDx00LTWL73fSlhCK0o1" - ), - "homeserver": "https://matrix.sophies-kitchen.eu", - "user_id": "@dimension:sophies-kitchen.eu", - }, - }, - "matrix-synapse": { - "server_name": "sophies-kitchen.eu", - "baseurl": "matrix.sophies-kitchen.eu", - "admin_contact": "mailto:foobar@sophies-kitchen.eu", - "trusted_key_servers": { - "matrix.org", - }, - }, - "mautrix-telegram": { - "version": "v0.15.2", - "homeserver": { - "domain": "sophies-kitchen.eu", - "url": "https://matrix.sophies-kitchen.eu", - }, - "provisioning": { - "enabled": False, - "shared_secret": '""', - }, - "permissions": { - "sophies-kitchen.eu": "full", - "'@sophie:sophies-kitchen.eu'": "admin", - }, - "telegram": { - "api_id": vault.decrypt( - "encrypt$gAAAAABgnqdXhCTwtCXJhSaCZsiNfHPtjwlYtV1sUAux7JZdejN3xItU9RJLeNu4gUniv36XbBoxKwVtqqyV3RcAs-PgumcfYQ==" - ), - "api_token": vault.decrypt( - "encrypt$gAAAAABgnqd5IdpYRmW-C4ONBSXQfiJrpTVQX0rP0eKoDnLnVTLg-5olSjcw2gVvEKWLnsGEZIgVcG7yEs-sqYRxeiQLFFpSn-Z4We0mhj0CUeFoD-eXJsp-bAgLv9PJoMv5Gjb8r9i6" - ), - "bot_token": '""', - }, - }, - "nameservers": { - "213.133.98.98", - "213.133.99.99", - "213.133.100.100", - "2a01:4f8:0:1::add:1010", - "2a01:4f8:0:1::add:9999", - "2a01:4f8:0:1::add:9898", - }, - "nftables": { - "input": { - "50-sophie-weechat": [ - "udp dport { 60000-61000 } accept", - "tcp dport 9001 accept", - ], - }, - }, - "nginx": { - "vhosts": { - "sophies-kitchen.eu": { - "webroot": "/var/www/sophies-kitchen.eu/_site/", - "extras": True, - }, - "matrix-synapse": { - "domain": "matrix.sophies-kitchen.eu", - }, - "webdump.sophies-kitchen.eu": { - "webroot_config": { - "owner": "sophie", - "group": "sophie", - "mode": "0755", - }, - "extras": True, - }, - "recipes.sophies-kitchen.eu": { - "webroot_config": { - "owner": "sophie", - "group": "sophie", - "mode": "0755", - }, - }, - }, - }, - "nodejs": { - "version": 20, - }, - "ntfy": { - "domain": "ntfy.sophies-kitchen.eu", - "allow_unauthorized_write": True, - }, - "postgresql": { - "version": "13", - }, - "sysctl": { - "options": { - # XXX find out if this is really needed - "net.ipv4.conf.all.forwarding": "1", - "net.ipv6.conf.all.forwarding": "1", - }, - }, - "vm": { - "cpu": 2, - "ram": 4, - }, - "users": { - "sophie": { - "enable_linger": True, - "ssh_pubkey": [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDILcYrMQNRVXAm5L+7No1ZumqfCyRc1QZmTY3O7Q8hsE4+fCAvwsWm2aSMfLL3NnIl8Nm1Rixzic5jdYKYNIY3SlX1wvTB+MhGb2eyVSd7c/Y98aCLSlDkQ2sebjpdA1FoJOeGD3qxqDwj0+KckXU2ZaSSQY7CxVsjH65UxCHqVAg+6uLdNbj7j850s1B9NXVXef+sBQ5jUngXxnqQWwNh2Mn8auwumkeEG4SYf96wyFkLvmBitOng/GyLWl9YPnXXHHDnatcVipy7y34qw4CQ4P84anecbA+Bqr9IcxBW6qYmYgRKEnAcmEfjQd+BI1gCLB1BBEmb/qp+mVLd4tOh sophie@carbon" - ], - }, - }, - "zfs": { - "datasets": { - "tank/webdump": { - "mountpoint": "/var/www/webdump.sophies-kitchen.eu", - "needed_by": ["directory:/var/www/webdump.sophies-kitchen.eu"], - } - }, - "pools": { - "tank": { - "when_creating": { - "config": [ - { - "devices": { - "/dev/disk/by-id/scsi-0HC_Volume_23952298", - }, - } - ] - }, - }, - }, - }, - }, -} diff --git a/nodes/sophie/sophie.homeassistant.toml b/nodes/sophie/sophie.homeassistant.toml deleted file mode 100644 index 42e25d0..0000000 --- a/nodes/sophie/sophie.homeassistant.toml +++ /dev/null @@ -1,36 +0,0 @@ -hostname = "172.19.164.3" -bundles = [ - 'homeassistant', - 'nginx', - 'pyenv', -] -groups = [ - "debian-bookworm", -] - -[metadata.interfaces.enp7s0] -ips = [ - "172.19.164.3/24", -] -gateway4 = "172.19.164.1" -ipv6_accept_ra = true - -[metadata.vm] -cpu = 2 -ram = 4 - -[metadata.homeassistant] -domain = 'homeassistant.home.sophies-kitchen.eu' -api_secret = 'encrypt$gAAAAABjpyuqXLoilokQW5c0zV8shHcOzN1zkEbS-I6WAAX-xDO_OF33YbjbkpELU2HGBzqiWX40J0hsaEbYJOnCHFk8gJ-Xt0vdqqbQ5vca_TGPNQHZPAS4qZoPTcUhmX_I-0EdT6ukhxejXFYBiYRZikTLjH3lcNM5qnckCm-H9NbRdjLb9hbCDIjbEglHmBl_g08S1_ukvX3dDSCIHIxgXXGsdK_Go1KxPJd8G22FL_MMhCfsTW-6ioIqoHSeSA1NGk3MZHEIM2errckiopKBxoBaROsacO9Uqk1zrrgXOs2NsgiTRtrbV1TNlFVaIX9mZdsUnMGZ' - -[metadata.nginx] -restrict-to = [ - '172.19.164.0/22', -] - -[metadata.pyenv] -version = 'v2.3.36' -python_versions = ["3.12.2"] - -[metadata.nginx.vhosts.homeassistant] -ssl = '_.home.sophies-kitchen.eu' diff --git a/nodes/sophie/unbound.py b/nodes/sophie/unbound.py deleted file mode 100644 index e0cb10d..0000000 --- a/nodes/sophie/unbound.py +++ /dev/null @@ -1,32 +0,0 @@ -nodes["sophie.unbound"] = { - "hostname": "172.19.164.4", - "bundles": { - "unbound", - }, - "groups": { - "debian-bookworm", - }, - "metadata": { - "interfaces": { - "enp1s0": { - "ips": { - "172.19.164.4/24", - "fe80::4/64", - }, - "gateway4": "172.19.164.1", - "ipv6_accept_ra": True, - }, - }, - "vm": { - "cpu": 2, - "ram": 2, - }, - "unbound": { - "dns64": False, - "restrict-to": { - "172.19.164.0/24", - "fe80::/64", - }, - }, - }, -} diff --git a/nodes/sophie/vmhost.py b/nodes/sophie/vmhost.py deleted file mode 100644 index aca520c..0000000 --- a/nodes/sophie/vmhost.py +++ /dev/null @@ -1,145 +0,0 @@ -nodes['sophie.vmhost'] = { - 'hostname': '172.19.164.2', - 'bundles': { - 'backup-client', - 'lm-sensors', - 'nfs-server', - 'mosquitto', - 'smartd', - 'vmhost', - 'zfs', - }, - 'groups': { - 'debian-bookworm', - }, - 'metadata': { - 'apt': { - 'packages': { - 'irqbalance': {}, - }, - }, - 'groups': { - 'nas': {}, - }, - 'interfaces': { - 'br1': { - 'ips': { - '172.19.164.2/24', - }, - 'gateway4': '172.19.164.1', - 'ipv6_accept_ra': True, - }, - }, - 'mosquitto': { - 'bridges': { - 'c3voc': { - 'peer': 'mqtt.c3voc.de', - 'client_id': 'sophie-vm-host', - 'auth': { - 'username': vault.decrypt('encrypt$gAAAAABgaBa5UZyZlsMM9TV5pa-VyOieFWYzAslxWVnXjOeXHvF4kMHHSHSMOrv-U9k7Ec3mMCDuJFO3ybpOsZSeFQDL7GgEfw=='), - 'password': vault.decrypt('encrypt$gAAAAABgaBbfm65cYBuod0UehWNmY0NfeUH9xsrP2kENYNF_LWP2iV5a8db_cqMoITwyjjBsHpvjaeDq07Z5K5nQ_BLZG6zPqapL-Qvp20wyck49Dy2R4V4='), - }, - 'topics': [ - { - 'pattern': '#', - 'remote_prefix': '/voc/', - 'local_prefix': 'voc' - }, - ], - }, - }, - 'listeners': { - '8083': { - 'protocol': 'websockets', - }, - }, - 'tasmota-telegraf-topic': '/switch/#', - 'restrict-to': { - '172.19.164.0/24', - }, - }, - 'nfs-server': { - 'version': 4, - 'shares': { - '/srv/nas': { - '172.19.164.0/24': 'ro,all_squash,anonuid=65534,anongid=65534,no_subtree_check', - }, - }, - }, - 'smartd': { - 'disks': { - '/dev/nvme0', - - # nas disks - '/dev/disk/by-id/ata-ST20000NM007D-3DJ103_ZVT7BHBQ', - '/dev/disk/by-id/ata-ST20000NM007D-3DJ103_ZVT7D6JP', - }, - }, - 'systemd-networkd': { - 'bridges': { - 'br0': { - 'match': { - 'enp1s0', - }, - }, - 'br1': { - 'match': { - 'br0.1', - }, - }, - }, - }, - 'systemd-timers': { - 'timers': { - # Ensure every user is able to read and write to the NAS dataset. - 'nas_permissions': { - 'command': [ - 'chown -R :nas /srv/nas/', - r'find /srv/nas/ -type d -exec chmod 0775 {} \;', - r'find /srv/nas/ -type f -exec chmod 0664 {} \;', - ], - 'when': '*-*-* 02:00:00', - }, - }, - }, - 'users': { - 'sophie': { - 'groups': { - 'nas', - }, - }, - }, - 'zfs': { - 'pools': { - 'storage': { - 'when_creating': { - 'config': [{ - 'devices': { - '/dev/disk/by-id/nvme-SAMSUNG_MZVLB256HAHQ-000L7_S41GNX0M481966-part3', - }, - }] - } - }, - 'nas': { - 'when_creating': { - 'config': [{ - 'type': 'mirror', - 'devices': { - '/dev/disk/by-id/ata-ST20000NM007D-3DJ103_ZVT7BHBQ', - '/dev/disk/by-id/ata-ST20000NM007D-3DJ103_ZVT7D6JP', - }, - }] - } - } - }, - "datasets": { - "storage/libvirt": { - "mountpoint": "/var/lib/libvirt", - }, - "nas": { - "mountpoint": "/srv/nas", - }, - }, - }, - }, -} diff --git a/nodes/voc/infobeamer-cms.py b/nodes/voc/infobeamer-cms.py index 55949e2..ef285c8 100644 --- a/nodes/voc/infobeamer-cms.py +++ b/nodes/voc/infobeamer-cms.py @@ -1,12 +1,11 @@ nodes['voc.infobeamer-cms'] = { - 'hostname': 'infobeamer.c3voc.de', + 'hostname': 'infobeamer-cms.c3voc.de', 'bundles': { 'infobeamer-cms', - 'infobeamer-monitor', 'redis', }, 'groups': { - 'debian-bookworm', + 'debian-bullseye', 'webserver', }, 'metadata': { @@ -23,106 +22,32 @@ nodes['voc.infobeamer-cms'] = { 'gateway6': '2001:67c:20a0:e::1', }, }, + 'icinga_options': { + 'pretty_name': 'infobeamer-cms.c3voc.de', + }, 'infobeamer-cms': { - 'domain': 'infobeamer.c3voc.de', - 'event_start_date': '2025-02-28', - 'event_duration_days': 3, + 'domain': 'infobeamer-cms.c3voc.de', + 'event_start_date': '2022-07-22', + 'event_duration_days': 5, 'config': { - 'ADMIN_USERS': [], - 'NO_LIMIT_USERS': [], - 'HOSTED_API_KEY': vault.decrypt('encrypt$gAAAAABhxJPH2sIGMAibU2Us1HoCVlNfF0SQQnVl0eiod48Zu8webL_-xk3wDw3yXw1Hkglj-2usl-D3Yd095yTSq0vZMCv2fh-JWwSPdJewQ45x9Ai4vXVD4CNz5vuJBESKS9xQWXTc'), - 'INTERRUPT_KEY': vault.human_password_for('infobeamer-cms interrupt key 38c3', words=1), - 'SETUP_IDS': [ - 258552, + 'ADMIN_USERS': [ + 'kunsi', + 'sophieschi', + 'hexchen', ], -# 'EXTRA_ASSETS': [{ -# 'type': "image", -# 'asset': 1316000, -# # bottom left, 10px from border -# 'x1': 10, -# 'y1': 970, -# 'x2': 110, -# 'y2': 1070, -# }], - 'NOTIFIER': { - 'MQTT_PASSWORD': vault.decrypt('encrypt$gAAAAABhxakfhhwWn0vxhoO1FiMEpdCkomWvo0dHIuBrqDKav8WDpI6dXpb0hoXiWRsPV6p5m-8RlbfFbjPhz47AY-nFOOAAW6Yis3-IVD-U-InKJo9dvms='), - 'MQTT_HOST': 'mqtt.c3voc.de', - 'MQTT_TOPIC': '/voc/alert', - 'MQTT_USERNAME': vault.decrypt('encrypt$gAAAAABhxakKHC_kHmHP2mFHorb4niuNTH4F24w1D6m5JUxl117N7znlZA6fpMmY3_NcmBr2Ihw4hL3FjZr9Fm_1oUZ1ZQdADA=='), - 'NTFY': [ - vault.decrypt('encrypt$gAAAAABm_RXKqIgRfe24frA_uvUMwJECr0TmL6TWPOmrPlS0CJuuBlpN6vGHrMkm5pjD5c5h1brC-aqQavsTk_AHXwq8bHG1QiZtQwqPxGuD_fEVP4-xOZ3t-RjqG3kPLz6ebqPoqyPl'), - ], - }, - 'FAQ': { - 'SOURCE': 'https://github.com/voc/infobeamer-cms', - 'CONTACT': ''' - Please use the IRC - Channel #infobeamer on irc.hackint.org (also - bridged to matrix) - or #info-beamer on the cccv rocketchat instance. - '''.strip(), - }, - 'DEFAULT_SSO_PROVIDER': 'github', - 'DEFAULT_ADMIN_SSO_PROVIDER': 'c3voc', - 'oauth2_providers': { - 'github': { - 'client_id': vault.decrypt('encrypt$gAAAAABiNwHfIu9PYFfJrF7qirn_9vdvvUlEhJnadoNSS5XlCDbI_aMyj21_ZYQxaCkc6_eVX6Cj1jEHZ7Vs6wM-XyQdW0nUOahtqG4uvnYCiM3GFKHW_wQ='), - 'client_secret': vault.decrypt('encrypt$gAAAAABiNwHtdZC2XQ8IjosL7vsmrxZMwDIM6AD5dUlLo996tJs4qV7KJETHgYYZil2aMzClwhcE6JmxdhARRp7IJQ4rQQibelTNmyYSzj_V4puVpvma7SU0UZkTIG95SdPpoHY--Zba'), - }, - 'c3voc': { - 'client_id': 'uqzN2mYeMq4vxnHL6HNmBC80hsvYcfhzniiczdqV', - 'client_secret': vault.decrypt('encrypt$gAAAAABnaZ0z-hQ3yYf8P1g4gyLLvNHcNkiXVtIq7M11qswbzcVM4upfgtxCWBlCgwLN3v7CxwDFQbJnosEq0hbX4c0TEoOausV4upJD0-5zP_1U18gbMGicpZ0TCzYyEhOqvCye7UmFOWzOmplSX1fz43Pf7peDeaPxHjqmxjw0khyExzWw4JPOd1V7LhnesJmPCfGKXn5YHMDicrdYeqFf0FySN1yA5gfLNo7y-S1QMJ6-n6Jct7uuifF9t2OV-zyOj3cKK13B'), - }, - #'c3hub': { - # 'client_id': '16oHBcVstcOKwt3EuX9E2urpYeVC0Dfo3Gzn2XhS', - # 'client_secret': vault.decrypt('encrypt$gAAAAABnaoRKbORUcceyKu3tda3lgMIFC-e0cG0AeMdDYJ--EnTRxp8QcULOTf2oBtKQUk17hgwfsafTFi4eZq1FrjNgq1h5gm83oJYWLQ6pp8Rsp9kjwgtAXf72jIU-AOQxx02SoFMU8r5pdEFEX4FkU_ksbU6s7xgBW8oxq_WO2CXAppTUX61TeB9me2nSLFdJc5-v6RDpQfDvVAm7yNS_PhMvMgVzfEZrFM-EWF_bl0S_q0ejf88o9zaXHIMJpzMruVZOXD0T'), - #}, - }, + 'GITHUB_CLIENT_ID': vault.decrypt('encrypt$gAAAAABiNwHfIu9PYFfJrF7qirn_9vdvvUlEhJnadoNSS5XlCDbI_aMyj21_ZYQxaCkc6_eVX6Cj1jEHZ7Vs6wM-XyQdW0nUOahtqG4uvnYCiM3GFKHW_wQ='), + 'GITHUB_CLIENT_SECRET': vault.decrypt('encrypt$gAAAAABiNwHtdZC2XQ8IjosL7vsmrxZMwDIM6AD5dUlLo996tJs4qV7KJETHgYYZil2aMzClwhcE6JmxdhARRp7IJQ4rQQibelTNmyYSzj_V4puVpvma7SU0UZkTIG95SdPpoHY--Zba'), + 'HOSTED_API_KEY': vault.decrypt('encrypt$gAAAAABhxJPH2sIGMAibU2Us1HoCVlNfF0SQQnVl0eiod48Zu8webL_-xk3wDw3yXw1Hkglj-2usl-D3Yd095yTSq0vZMCv2fh-JWwSPdJewQ45x9Ai4vXVD4CNz5vuJBESKS9xQWXTc'), + 'MQTT_MESSAGE': '{{"level":"info","component":"infobeamer-cms","msg":"{asset} uploaded by {user}. Check it at {url}"}}', + 'MQTT_PASSWORD': vault.decrypt('encrypt$gAAAAABhxakfhhwWn0vxhoO1FiMEpdCkomWvo0dHIuBrqDKav8WDpI6dXpb0hoXiWRsPV6p5m-8RlbfFbjPhz47AY-nFOOAAW6Yis3-IVD-U-InKJo9dvms='), + 'MQTT_SERVER': 'mqtt.c3voc.de', + 'MQTT_TOPIC': '/voc/alert', + 'MQTT_USERNAME': vault.decrypt('encrypt$gAAAAABhxakKHC_kHmHP2mFHorb4niuNTH4F24w1D6m5JUxl117N7znlZA6fpMmY3_NcmBr2Ihw4hL3FjZr9Fm_1oUZ1ZQdADA=='), + 'SETUP_IDS': [220674], }, 'rooms': { - 'Saal 1': 34430, # s1 - 'Saal GLITCH': 37731, # s2 - 'Saal ZIGZAG': 26610, # s3 - 'Sendezentrum': 38641, # s4 - 'Stage YELL': 38642, # s5 - 'Stage HUFF': 35042, # s6 + 'infobeamer stream': 23541, }, - 'interrupts': { - 'Questions': 'questions', - 'Translations': 'translations', - }, - }, - 'infobeamer-monitor': { - 'api_key': vault.decrypt('encrypt$gAAAAABlitmDR1duKo_4KuMJBF_HbPO2GFo_gdoT1rvUKQ2kkugPbe2RljM4bxW5bmwhs5avjxiaSAvjnOBte9ioyPEr7cIh79WFEfMnsHeexlCHwMt6NV_t-8EAhuuEQEf3Py93g8zQ'), - 'mqtt': { - 'password': vault.decrypt('encrypt$gAAAAABhxakfhhwWn0vxhoO1FiMEpdCkomWvo0dHIuBrqDKav8WDpI6dXpb0hoXiWRsPV6p5m-8RlbfFbjPhz47AY-nFOOAAW6Yis3-IVD-U-InKJo9dvms='), - 'host': 'mqtt.c3voc.de', - 'topic': '/voc/alert', - 'user': vault.decrypt('encrypt$gAAAAABhxakKHC_kHmHP2mFHorb4niuNTH4F24w1D6m5JUxl117N7znlZA6fpMmY3_NcmBr2Ihw4hL3FjZr9Fm_1oUZ1ZQdADA=='), - }, - }, - 'nginx': { - 'vhosts': { - 'redirect': { - 'domain': 'infobeamer-cms.c3voc.de', - 'locations': { - '/': { - 'redirect': 'https://infobeamer.c3voc.de', - }, - }, - }, - }, - }, - 'users': { - 'hexchen': { - 'ssh_pubkey': { - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJ0tCxsEilAzV6LaNpUpcjzyEn4ptw8kFz3R+Z3YjEF", - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDI3T1eFS77URHZ/HVWkMOqx7W1U54zJtn9C7QWsHOtyH72i/4EVj8SxYqLllElh1kuKUXSUipPeEzVsipFVvfH0wEuTDgFffiSQ3a8lfUgdEBuoySwceEoPgc5deapkOmiDIDeeWlrRe3nqspLRrSWU1DirMxoFPbwqJXRvpl6qJPxRg+2IolDcXlZ6yxB4Vv48vzRfVzZNUz7Pjmy2ebU8PbDoFWL/S3m7yOzQpv3L7KYBz7+rkjuF3AU2vy6CAfIySkVpspZZLtkTGCIJF228ev0e8NvhuN6ZnjzXxVTQOy32HCdPdbBbicu0uHfZ5O7JX9DjGd8kk1r2dnZwwy/", - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4CLJ+mFfq5XiBXROKewmN9WYmj+79bj/AoaR6Iud2pirulot3tkrrLe2cMjiNWFX8CGVqrsAELKUA8EyUTJfStlcTE0/QNESTRmdDaC+lZL41pWUO9KOiD6/0axAhHXrSJ0ScvbqtD0CtpnCKKxtuOflVPoUGZsH9cLKJNRKfEka0H0GgeKb5Tp618R/WNAQOwaCcXzg/nG4Bgv3gJW4Nm9IKy/MwRZqtILi8Mtd+2diTqpMwyNRmbenmRHCQ1vRw46joYkledVqrmSlfSMFgIHI1zRSBXb/JkG2IvIyB5TGbTkC4N2fqJNpH8wnCKuOvs46xmgdiRA26P48C2em3", - }, - 'sudo_commands': {'ALL'}, - }, - 'sophie': {}, }, }, } diff --git a/nodes/voc/pretalx.py b/nodes/voc/pretalx.py index f37a29c..e14a740 100644 --- a/nodes/voc/pretalx.py +++ b/nodes/voc/pretalx.py @@ -8,7 +8,6 @@ nodes['voc.pretalx'] = { 'backup-client', 'check-mail-received', 'c3voc-addons', - 'nodejs', 'pretalx', 'postfix', 'postgresql', @@ -17,7 +16,7 @@ nodes['voc.pretalx'] = { }, 'metadata': { 'backup-client': { - 'target': 'backup-kunsi', + 'target': 'htz-hel.backup-kunsi', }, 'check-mail-received': { 't-online': { @@ -36,6 +35,9 @@ nodes['voc.pretalx'] = { 'gateway6': '2a01:a700:48d1::1', }, }, + 'icinga_options': { + 'pretty_name': 'pretalx.c3voc.de', + }, 'nginx': { 'vhosts': { 'pretalx': { @@ -49,23 +51,18 @@ nodes['voc.pretalx'] = { }, }, 'pretalx': { - # 2023.3.1 with some bugfixes - 'version': '05e377398cecdd45d3ca6013040c5857bbe225d6', + 'version': 'v2.3.2', 'domain': 'pretalx.c3voc.de', 'mail_from': 'pretalx@c3voc.de', 'administrators-from-group-id': 1, 'plugins': { - 'broadcast_tools': { - 'repo': 'https://github.com/Kunsi/pretalx-plugin-broadcast-tools.git', - 'rev': '2.4.0', - }, 'downstream': { 'repo': 'https://github.com/pretalx/pretalx-downstream.git', - 'rev': 'main', + 'rev': 'v1.1.5', }, - 'halfnarp': { - 'repo': 'https://github.com/seibert-media/pretalx-halfnarp.git', - 'rev': '1.1.2', + 'broadcast_tools': { + 'repo': 'https://github.com/Kunsi/pretalx-plugin-broadcast-tools.git', + 'rev': '1.1.0', }, 'media.ccc.de': { 'repo': 'https://github.com/pretalx/pretalx-media-ccc-de.git', @@ -78,10 +75,10 @@ nodes['voc.pretalx'] = { 'relayhost': 'mng.c3voc.de', }, 'postgresql': { - 'version': '13', + 'version': '11', }, }, 'os': 'debian', - 'os_version': (12,), + 'os_version': (10,), 'pip_command': 'pip3', } diff --git a/requirements.txt b/requirements.txt index 6b2227f..eaec252 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -bundlewrap>=4.22.0 +bundlewrap~=4.16.0 PyNaCl bundlewrap-pass -semver diff --git a/scripts/netbox-dump b/scripts/netbox-dump index 117bae9..f3c79a6 100755 --- a/scripts/netbox-dump +++ b/scripts/netbox-dump @@ -1,240 +1,158 @@ #!/usr/bin/env python3 -from argparse import ArgumentParser from json import dump -from os import environ, makedirs, remove, scandir -from os.path import abspath, dirname, join +from os import environ +from os.path import dirname, join from sys import exit import bwpass from requests import post -from bundlewrap.utils.text import bold, red, validate_name -from bundlewrap.utils.ui import io +from bundlewrap.utils.text import validate_name TOKEN = environ.get("NETBOX_AUTH_TOKEN") + +# editorconfig-checker-disable +QUERY = """{ + device_list(tag: "bundlewrap") { + name + site { + id + } + interfaces { + id + name + enabled + description + mode + type + ip_addresses { + address + } + untagged_vlan { + name + } + tagged_vlans { + name + } + link_peers { + ... on InterfaceType { + name + device { + name + } + } + ... on FrontPortType { + name + device { + name + } + } + } + connected_endpoints { + ... on InterfaceType { + name + device { + name + } + } + } + } + } + site_list { + id + vlans { + name + vid + } + } +}""" +# editorconfig-checker-enable + if not TOKEN: try: TOKEN = bwpass.attr("netbox.franzi.business/kunsi", "token") except Exception: - print("NETBOX_AUTH_TOKEN missing") + print("NETBOX_AUTH_TOKEN is missing") exit(1) -TARGET_PATH = join(dirname(dirname(abspath(__file__))), "configs", "netbox") +r = post( + "https://netbox.franzi.business/graphql/", + headers={ + "Accept": "application/json", + "Authorization": f"Token {TOKEN}", + }, + json={ + "query": QUERY, + }, +) +r.raise_for_status() -QUERY_SITES = """{ - site_list { - name - id - vlans { - name - vid - } +data = r.json()["data"] + +site_vlans = {site["id"]: site["vlans"] for site in data["site_list"]} + +for device in data["device_list"]: + if not device["name"] or not validate_name(device["name"]): + # invalid node name, ignore + continue + + result = { + "interfaces": {}, + "vlans": site_vlans[device["site"]["id"]], } -}""" -QUERY_DEVICES = """{ - device_list(filters: {site_id: "SITE_ID", tags: {name: {exact: "bundlewrap"}}}) { - name - id - } -}""" + for interface in device["interfaces"]: + description = "" + peers = None -QUERY_DEVICE_DETAILS = """{ - device(id: DEVICE_ID) { - name - interfaces { - id - name - enabled - description - mode - type - ip_addresses { - address - } - untagged_vlan { - name - } - tagged_vlans { - name - } - link_peers { - ... on InterfaceType { - name - device { - name - } - } - ... on FrontPortType { - name - device { - name - } - } - } - connected_endpoints { - ... on InterfaceType { - name - device { - name - } - } - } - } - } -}""" + if interface["connected_endpoints"]: + peers = interface["connected_endpoints"] + elif interface["link_peers"]: + peers = interface["link_peers"] + if interface["description"]: + description = interface["description"] + elif peers: + peer_list = set() -def graphql(query): - r = post( - "https://netbox.franzi.business/graphql/", - headers={ - "Accept": "application/json", - "Authorization": f"Token {TOKEN}", - }, - json={ - "query": query, - }, - ) - r.raise_for_status() - return r.json()["data"] - - -def filter_results(results, filter_by): - if filter_by is None: - return results - - out = [] - for result in results: - if str(result["id"]) in filter_by or result["name"] in filter_by: - out.append(result) - return out - - -parser = ArgumentParser() -parser.add_argument("--only-site", nargs="+", type=str) -parser.add_argument("--only-device", nargs="+", type=str) -args = parser.parse_args() - -try: - io.activate() - filenames_used = set() - - with io.job("getting sites"): - sites = filter_results( - graphql(QUERY_SITES).get("site_list", []), args.only_site - ) - - io.stdout(f"Processing {len(sites)} sites in total") - - for site in sites: - with io.job(f"{bold(site['name'])} getting devices"): - devices = filter_results( - graphql(QUERY_DEVICES.replace("SITE_ID", site["id"])).get( - "device_list", [] - ), - args.only_device, - ) - io.stdout(f"Site {bold(site['name'])} has {len(devices)} devices to process") - - for device in devices: - if not device["name"] or not validate_name(device["name"]): - # invalid node name, ignore - continue - - with io.job( - f"{bold(site['name'])} {bold(device['name'])} getting interfaces" - ): - details = graphql( - QUERY_DEVICE_DETAILS.replace("DEVICE_ID", device["id"]) - )["device"] - - result = { - "interfaces": {}, - "vlans": site["vlans"], - } - - for interface in details["interfaces"]: - peers = None - - if interface["connected_endpoints"]: - peers = interface["connected_endpoints"] - elif interface["link_peers"]: - peers = interface["link_peers"] - - if interface["description"]: - description = interface["description"] - elif peers: - peer_list = set() - - for i in peers: - peer_list.add( - "{} ({})".format( - i["device"]["name"], - i["name"], - ) - ) - - description = "; ".join(sorted(peer_list)) - else: - description = "" - - assert description.isascii() - - result["interfaces"][interface["name"]] = { - "description": description, - "enabled": interface["enabled"], - "mode": interface["mode"], - "type": interface["type"], - "ips": sorted( - {i["address"] for i in interface["ip_addresses"]} - ), - "untagged_vlan": ( - interface["untagged_vlan"]["name"] - if interface["untagged_vlan"] - else None - ), - "tagged_vlans": sorted( - {v["name"] for v in interface["tagged_vlans"]} - ), - } - - if result["interfaces"]: - filename = f"{device['name']}.json" - filenames_used.add(filename) - file_with_path = join(TARGET_PATH, filename) - - with io.job( - f"{bold(site['name'])} {bold(device['name'])} writing to {file_with_path}" - ): - with open( - file_with_path, - "w+", - ) as f: - dump( - result, - f, - indent=4, - sort_keys=True, - ) - else: - io.stdout( - f"device {bold(device['name'])} has no interfaces, {red('not')} dumping!" + for i in peers: + peer_list.add( + "{} ({})".format( + i["device"]["name"], + i["name"], + ) ) - if not args.only_site and not args.only_device and filenames_used: - with io.job(f"cleaning leftover files from {TARGET_PATH}"): - for direntry in scandir(TARGET_PATH): - filename = direntry.name - if filename.startswith("."): - continue - if not direntry.is_file(): - io.stderr( - f"found non-file {filename} in {TARGET_PATH}, please check what's going on!" - ) - continue - if filename not in filenames_used: - remove(join(TARGET_PATH, filename)) -finally: - io.deactivate() + description = "; ".join(sorted(peer_list)) + else: + description = "" + + assert description.isascii() + + result["interfaces"][interface["name"]] = { + "description": description, + "enabled": interface["enabled"], + "mode": interface["mode"], + "type": interface["type"], + "ips": sorted({i['address'] for i in interface['ip_addresses']}), + "untagged_vlan": interface["untagged_vlan"]["name"] + if interface["untagged_vlan"] + else None, + "tagged_vlans": sorted({v["name"] for v in interface["tagged_vlans"]}), + } + + with open( + join( + dirname(dirname(__file__)), + "configs", + "netbox_device_{}.json".format(device["name"]), + ), + "w+", + ) as f: + dump( + result, + f, + indent=4, + sort_keys=True, + ) diff --git a/scripts/passwords-for b/scripts/passwords-for index d019e74..10beb14 100755 --- a/scripts/passwords-for +++ b/scripts/passwords-for @@ -1,21 +1,17 @@ #!/usr/bin/env python3 - from os import environ -from os.path import abspath, dirname from sys import argv -from bundlewrap.exceptions import FaultUnavailable from bundlewrap.metagen import NodeMetadataProxy +from bundlewrap.exceptions import FaultUnavailable from bundlewrap.repo import Repository from bundlewrap.utils import Fault -repo = Repository( - dirname(dirname(abspath(__file__))) -) +path = environ.get('BW_REPO_PATH', '.') +repo = Repository(path) def print_faults(dictionary, keypath=[]): for key, value in sorted(dictionary.items()): - key = str(key) if isinstance(value, Fault): try: resolved_fault = value.value @@ -29,22 +25,12 @@ def print_faults(dictionary, keypath=[]): elif isinstance(value, (dict, NodeMetadataProxy)): print_faults(value, keypath=keypath+[key]) - if len(argv) == 1: print('node name missing') exit(1) node = repo.get_node(argv[1]) -if node.username or node.password: - print_faults({ - 'username': node.username, - 'password': node.password, - }) -#if node.ipmi_username or node.ipmi_password: -# print_faults({ -# 'ipmi_username': node.ipmi_username, -# 'ipmi_password': node.ipmi_password, -# }) print_faults({ + 'password': node.password, 'metadata': node.metadata, }) diff --git a/scripts/update-ssh-client-config b/scripts/update-ssh-client-config index ba5acde..0c2f7fd 100755 --- a/scripts/update-ssh-client-config +++ b/scripts/update-ssh-client-config @@ -12,20 +12,10 @@ BW_TABLE_STYLE=grep bw nodes -a hostname -- "lambda:not node.dummy" | \ while read node addr do - if [[ -n "$BW_SSH_HOOK_EXTRA_LINE" ]] - then - echo "Host $addr" >>"$tmpfile" - echo "$BW_SSH_HOOK_EXTRA_LINE" >>"$tmpfile" - echo "" >>"$tmpfile" - fi echo "Host $node" >>"$tmpfile" echo "HostName $addr" >>"$tmpfile" - if [[ -n "$BW_SSH_HOOK_EXTRA_LINE" ]] - then - echo "$BW_SSH_HOOK_EXTRA_LINE" >>"$tmpfile" - fi echo "" >>"$tmpfile" done - mv "$tmpfile" ~/.ssh/config.d/bwnodes + mv "$tmpfile" ~/.ssh/bwnodes ) & diff --git a/users.json b/users.json index 0dab537..7769c17 100644 --- a/users.json +++ b/users.json @@ -1,18 +1,17 @@ { + "autojenkins": { + "ssh_pubkey": [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHZnYhsdtGUYJiFcvfqTLljGkInnFTOoDF/WZniLtPjH" + ] + }, "fkunsmann": { "ssh_pubkey": [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICYst1HK+gJYhNxzqJGnz4iB73pa89Xz2yH+8wufOcsA" ] }, - "forgejo-carlene": { - "ssh_pubkey": [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA3aj7Ij9aIgSBgIAyIPAQa/w++7eVKIxbK0iFuVvjeH" - ] - }, "kunsi": { "ssh_pubkey": [ - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLpRRSFhzPC8xNorYiNDG37JivSSER+oUNjSFwJ+4Gn8QdcM5sjQZsokAEFs5AsAWl1i7d/qceA2JGG4jCwDBx0=", - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+ja1z5VRQzaKCCePsUM14qMr9QR94qlWc7Je5Poki9UmC1t/TyxRVzcCBL1ZdIfBGx6QKtfkEbvhgb3nxVt3PvXjoJrc6wwGLmNrVsU6B88y35g7nzupQiPKYJwkNzJ9j6Dmkgj1F5Q+aY2SitDaX6vqICLJ4Al/ZFw2IQxVJfC7JXRJ9jRMG5o9gWoE3gWDYEAmw+HU2mNzyeuaD12qJw9DHUimAlgkOWzll3gh9WclsYnnXGrCCn5fyHFUCJl+XXAIy519z7YTpKih02rsIOw5dnaGClBZD/YQu2ZKVFZiwIVH7aBiqHOmtgRyWTQgjbh/fMpIN0ar2f/iZsWYUjd6et48TOmXZYIPCQ5FivXNvxt9oo1XZfq76UHBwlmypLJIWROMbz375n2M6hr3hECuxuPjKEUXAv05KiC1aJ4xc6pFoVhqwAR99hvHw5U4o7/ko2NVjNpTu6Jr5DT5VaQLIdDDjC/93kUjMpdD/8P72bEn7454+WexU6OE6uvNiHj1fetrptr2UAuzVfnCoaV8pBqY7X95gk+lnSENdpr8ltJYMg8s0Z7Pzz0OxsZtzzDY5VmWfC9TCdJkN5lT8IbnaixsYlWdjQl1lMmZGElmelfU3K7YQLAbZiHmHKe4hTl9ZoCcWdTQ3d4y2t1DBos+N2HZNdtFCyOS8esDdMw==" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC+ja1z5VRQzaKCCePsUM14qMr9QR94qlWc7Je5Poki9UmC1t/TyxRVzcCBL1ZdIfBGx6QKtfkEbvhgb3nxVt3PvXjoJrc6wwGLmNrVsU6B88y35g7nzupQiPKYJwkNzJ9j6Dmkgj1F5Q+aY2SitDaX6vqICLJ4Al/ZFw2IQxVJfC7JXRJ9jRMG5o9gWoE3gWDYEAmw+HU2mNzyeuaD12qJw9DHUimAlgkOWzll3gh9WclsYnnXGrCCn5fyHFUCJl+XXAIy519z7YTpKih02rsIOw5dnaGClBZD/YQu2ZKVFZiwIVH7aBiqHOmtgRyWTQgjbh/fMpIN0ar2f/iZsWYUjd6et48TOmXZYIPCQ5FivXNvxt9oo1XZfq76UHBwlmypLJIWROMbz375n2M6hr3hECuxuPjKEUXAv05KiC1aJ4xc6pFoVhqwAR99hvHw5U4o7/ko2NVjNpTu6Jr5DT5VaQLIdDDjC/93kUjMpdD/8P72bEn7454+WexU6OE6uvNiHj1fetrptr2UAuzVfnCoaV8pBqY7X95gk+lnSENdpr8ltJYMg8s0Z7Pzz0OxsZtzzDY5VmWfC9TCdJkN5lT8IbnaixsYlWdjQl1lMmZGElmelfU3K7YQLAbZiHmHKe4hTl9ZoCcWdTQ3d4y2t1DBos+N2HZNdtFCyOS8esDdMw== cardno:000609506971" ], "email": "encrypt$gAAAAABfuXj1DQ3yUn0rEdN2koT1hzgHwCwNp00a0KkWoT_FTsild1zIBpfIiI07AmgIZ5FpyhKH5bSdCVLKc0p4rQuxLrLWpw==", "phone": "encrypt$gAAAAABfuXkP2GetSvTd9JJFz4V2v5r5NubihFRg2AB91mtvXpUVUiflzy1VHQJ_qbp6Rke5LEXbtlluNkAa3OOAr_c9L6Pstw==", @@ -20,7 +19,8 @@ }, "sophie": { "ssh_pubkey": [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU7XmpX4w+rGQDi+dF6M0q65K2iHVgD1wHBoHREjyqCzmPGZgrnLIv6EN9WWJXjCgRdLEUXgPn7PNJnAgBs3U8G8MsF55yrPNUIsEeg6v+Y6zibEujMrwmeDSk0XAn8iSZcy+4cnqykIMk9Hd5WXW7ZhSHGs4MftWn3Z/q15qPHl/w9OyaKDJAjk8yEsD1sZoAQMhomKliKjJ5a6jNyf7otS3HdbZx4KXABJNuWn/IvmwkcaIU8ljyuPkPkiMn5JWhcUK2kE81Y4a5zJxxusSXSF6Ip7W2Rhv+4gnScTjhTPsG70HlSF/LAB2ytKo0F0N/ZB2hJk+Jq6cAwNBzuST7" - ] + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU7XmpX4w+rGQDi+dF6M0q65K2iHVgD1wHBoHREjyqCzmPGZgrnLIv6EN9WWJXjCgRdLEUXgPn7PNJnAgBs3U8G8MsF55yrPNUIsEeg6v+Y6zibEujMrwmeDSk0XAn8iSZcy+4cnqykIMk9Hd5WXW7ZhSHGs4MftWn3Z/q15qPHl/w9OyaKDJAjk8yEsD1sZoAQMhomKliKjJ5a6jNyf7otS3HdbZx4KXABJNuWn/IvmwkcaIU8ljyuPkPkiMn5JWhcUK2kE81Y4a5zJxxusSXSF6Ip7W2Rhv+4gnScTjhTPsG70HlSF/LAB2ytKo0F0N/ZB2hJk+Jq6cAwNBzuST7 sophie@ejgwmobile" + ], + "is_admin": true } }