Compare commits

..

No commits in common. "main" and "new-wildcard-sophies-kitchen" have entirely different histories.

80 changed files with 636 additions and 1111 deletions

View file

@ -1,39 +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}'
])
containers = loads(f"[{','.join([l for l in docker_ps.decode().splitlines() if l])}]")
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)

View file

@ -1,50 +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 "docker-${name}")"
PGID="$(id -g "docker-${name}")"
if [ "$ACTION" == "start" ]
then
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 host \
% for host_port, container_port in sorted(ports.items()):
--expose "127.0.0.1:${host_port}:${container_port}" \
% endfor
% for host_path, container_path in sorted(volumes.items()):
--volume "/var/opt/docker-engine/${name}/${host_path}:${container_path}" \
% endfor
--restart unless-stopped \
"${image}"
elif [ "$ACTION" == "stop" ]
then
docker stop "${name}"
docker rm "${name}"
else
echo "Unknown action $ACTION"
exit 1
fi
% if node.has_bundle('nftables'):
systemctl reload nftables
% endif

View file

@ -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

View file

@ -1,99 +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',
}
for app, config in node.metadata.get('docker-engine/containers', {}).items():
volumes = config.get('volumes', {})
files[f'/opt/docker-engine/{app}'] = {
'source': 'docker-wrapper',
'content_type': 'mako',
'context': {
'environment': config.get('environment', {}),
'image': config['image'],
'name': app,
'ports': config.get('ports', {}),
'timezone': node.metadata.get('timezone'),
'volumes': volumes,
},
'mode': '0755',
'triggers': {
f'svc_systemd:docker-{app}:restart',
},
}
users[f'docker-{app}'] = {
'home': f'/var/opt/docker-engine/{app}',
'groups': {
'docker',
},
'after': {
# provides docker group
'pkg_apt:docker-ce',
},
}
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'file:/opt/docker-engine/{app}',
f'file:/usr/local/lib/systemd/system/docker-{app}.service',
f'user:docker-{app}',
'svc_systemd:docker',
*set(config.get('needs', set())),
},
}
for volume in volumes:
directories[f'/var/opt/docker-engine/{app}/{volume}'] = {
'owner': f'docker-{app}',
'group': f'docker-{app}',
'needed_by': {
f'svc_systemd:docker-{app}',
},
# don't do anything if the directory exists, docker images
# mangle owners
'unless': f'test -d /var/opt/docker-engine/{app}/{volume}',
}

View file

@ -1,83 +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',
},
},
},
},
'backups': {
'paths': {
'/var/opt/docker-engine',
},
},
'hosts': {
'entries': {
'172.17.0.1': {
'host.docker.internal',
},
},
},
'docker-engine': {
'config': {
'iptables': False,
'no-new-privileges': True,
},
},
'zfs': {
'datasets': {
'tank/docker-data': {
'mountpoint': '/var/opt/docker-engine',
},
},
},
}
@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(
'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}'
}
return {
'zfs': {
'datasets': datasets,
},
}

View file

@ -1,64 +0,0 @@
assert node.has_bundle('docker-engine')
assert node.has_bundle('redis')
assert not node.has_bundle('postgresql') # docker container uses that port
defaults = {
'docker-engine': {
'containers': {
'immich': {
'image': 'ghcr.io/imagegenius/immich:latest',
'environment': {
'DB_DATABASE_NAME': 'immich',
'DB_HOSTNAME': 'host.docker.internal',
'DB_PASSWORD': repo.vault.password_for(f'{node.name} postgresql immich'),
'DB_USERNAME': 'immich',
'REDIS_HOSTNAME': 'host.docker.internal',
},
'volumes': {
'config': '/config',
'libraries': '/libraries',
'photos': '/photos',
},
'needs': {
'svc_systemd:docker-postgresql14',
},
'requires': {
'docker-postgresql14.service',
},
},
'postgresql14': {
'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',
},
},
},
},
'nginx': {
'vhosts': {
'immich': {
'locations': {
'/': {
'target': 'http://127.0.0.1:8080/',
'websockets': True,
'max_body_size': '500m',
},
#'/api/socket.io/': {
# 'target': 'http://127.0.0.1:8081/',
# 'websockets': True,
#},
},
},
},
},
'redis': {
'bind': '0.0.0.0',
},
}

View file

@ -29,8 +29,8 @@ mail_location = maildir:/var/mail/vmail/%d/%n
protocols = imap lmtp sieve
ssl = required
ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/fullchain.pem
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/privkey.pem
ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/fullchain.pem
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/privkey.pem
ssl_dh = </etc/ssl/certs/dhparam.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = 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

View file

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

View file

@ -100,7 +100,7 @@ def nginx(metadata):
},
},
'website_check_path': '/user/login',
'website_check_string': 'Sign in',
'website_check_string': 'Sign In',
},
},
},

View file

@ -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)

View file

@ -5,8 +5,6 @@ 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

View file

@ -30,7 +30,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',

View file

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

View file

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

View file

@ -23,7 +23,7 @@ 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',
},
@ -96,6 +96,14 @@ files = {
},
}
pkg_pip = {
'github-flask': {
'needed_by': {
'svc_systemd:infobeamer-cms',
},
},
}
svc_systemd = {
'infobeamer-cms': {
'needs': {

View file

@ -1,13 +1,10 @@
from datetime import datetime, timedelta
assert node.has_bundle('redis')
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'),

View file

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

View file

@ -31,7 +31,7 @@ homeservers:
% endfor
accessTokens:
maxCacheTimeSeconds: 10
maxCacheTimeSeconds: 0
useLocalAppserviceConfig: false
admins:
@ -137,8 +137,8 @@ thumbnails:
rateLimit:
enabled: true
requestsPerSecond: 100
burst: 5000
requestsPerSecond: 10
burst: 50
identicons:
enabled: true

View file

@ -23,8 +23,9 @@ table inet filter {
icmp type timestamp-request drop
icmp type timestamp-reply drop
meta l4proto {icmp, ipv6-icmp} accept
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
% for ruleset, rules in sorted(input.items()):
# ${ruleset}

View file

@ -29,7 +29,7 @@ defaults = {
},
}
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,

View file

@ -11,7 +11,7 @@ events {
http {
include /etc/nginx/mime.types;
types {
application/javascript mjs;
application/javascript js mjs;
}
default_type application/octet-stream;
charset UTF-8;

View file

@ -149,18 +149,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;

View file

@ -32,9 +32,21 @@ Include = /etc/pacman.d/mirrorlist
Server = ${node.metadata.get('pacman/repository')}
Include = /etc/pacman.d/mirrorlist
% endif
% if node.metadata.get('pacman/enable_aurto'):
% if node.metadata.get('pacman/enable_aurto', True):
[aurto]
Server = https://aurto.kunbox.net/
SigLevel = Optional TrustAll
% endif
% if node.has_bundle('zfs'):
[archzfs]
Server = http://archzfs.com/archzfs/x86_64
% if node.metadata.get('pacman/linux-lts', False):
[zfs-linux-lts]
% else:
[zfs-linux]
% endif
Server = http://kernels.archzfs.com/$repo/
% endif

View file

@ -33,7 +33,6 @@ svc_systemd['paccache.timer'] = {
}
pkg_pacman = {
'acpi_call-lts': {},
'at': {},
'autoconf': {},
'automake': {},
@ -62,7 +61,6 @@ pkg_pacman = {
'ldns': {},
'less': {},
'libtool': {},
'linux-lts': {},
'logrotate': {},
'lsof': {},
'm4': {},
@ -104,6 +102,12 @@ pkg_pacman = {
'zip': {},
}
if node.metadata.get('pacman/linux-lts', False):
pkg_pacman['linux-lts'] = {}
pkg_pacman['acpi_call-lts'] = {}
else:
pkg_pacman['linux'] = {}
pkg_pacman['acpi_call'] = {}
for pkg, config in node.metadata.get('pacman/packages', {}).items():
pkg_pacman[pkg] = config

View file

@ -4,7 +4,6 @@ defaults = {
'glibc',
'pacman',
},
'enable_aurto': True,
'no_extract': {
'etc/cron.d/0hourly',
# don't install systemd-homed pam module. It produces a lot of spam in

View file

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

View file

@ -1,5 +1,3 @@
devnull@${node.metadata.get('postfix/myhostname')} DISCARD DEV-NULL
% for address in sorted(blocked):
${address} REJECT
% endfor

View file

@ -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
</%text>
% 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,7 +48,7 @@ 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_recipient_restrictions = permit_mynetworks, check_recipient_access hash:/etc/postfix/blocked_recipients
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

View file

@ -25,7 +25,7 @@ my_package = 'pkg_pacman:postfix' if node.os == 'arch' else 'pkg_apt:postfix'
files = {
'/etc/mailname': {
'content': node.metadata.get('postfix/myhostname'),
'content': node.metadata.get('postfix/myhostname', node.metadata['hostname']),
'before': {
my_package,
},

View file

@ -87,7 +87,7 @@ def letsencrypt(metadata):
}
result['domains'] = {
metadata.get('postfix/myhostname'): set(),
metadata.get('postfix/myhostname', metadata.get('hostname')): set(),
}
return {
@ -148,14 +148,3 @@ def icinga2(metadata):
},
},
}
@metadata_reactor.provides(
'postfix/myhostname',
)
def myhostname(metadata):
return {
'postfix': {
'myhostname': metadata.get('hostname'),
},
}

View file

@ -57,7 +57,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 +67,10 @@ if node.has_bundle('backup-client'):
'mode': '0700',
}
directories['/var/tmp/postgresdumps'] = {}
else:
files['/var/tmp/postgresdumps'] = {
'delete': True,
}
postgres_roles = {
'root': {

View file

@ -11,7 +11,6 @@ defaults = {
'backups': {
'paths': {
'/var/lib/postgresql',
'/var/tmp/postgresdumps',
},
},
'bash_functions': {
@ -75,6 +74,8 @@ if node.has_bundle('zfs'):
},
},
}
else:
defaults['backups']['paths'].add('/var/tmp/postgresdumps')
@metadata_reactor.provides(

View file

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

View file

@ -71,8 +71,8 @@ actions = {
'chown -R powerdnsadmin:powerdnsadmin /opt/powerdnsadmin/src/powerdnsadmin/static/',
]),
'needs': {
'action:nodejs_install_yarn',
'action:powerdnsadmin_install_deps',
'bundle:nodejs',
'pkg_apt:',
},
},

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -48,4 +48,3 @@ tcp-keepalive 0
timeout 0
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
protected-mode no

View file

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

View file

@ -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;

View file

@ -43,6 +43,30 @@ 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']:
if search(r'p([0-9]+)$', disk) or disk.startswith('/dev/mapper/'):
continue
disks.add(disk)
return {
'smartd': {
'disks': disks,
},
}
@metadata_reactor.provides(
'icinga2_api/smartd/services',
)

View file

@ -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']))

View file

@ -22,8 +22,7 @@ case "$issuer_hash" in
# 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|462422cf|9aad238c|31dfb39d)
warn_days=10
crit_days=3
;;

View file

@ -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',

View file

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

View file

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

View file

@ -2,9 +2,6 @@ from json import dumps
from bundlewrap.metadata import MetadataJSONEncoder
if node.has_bundle('pacman'):
assert node.metadata.get('pacman/enable_aurto'), f'{node.name}: bundle:zfs needs aurto for zfs-linux-lts package'
files = {
'/etc/modprobe.d/zfs.conf': {
'source': 'zfs-modprobe.conf',

View file

@ -48,12 +48,6 @@ defaults = {
'etc/sudoers.d/zfs',
},
'packages': {
'zfs-linux-lts': {
'needed_by': {
'zfs_dataset:',
'zfs_pool:',
},
},
'zfs-utils': {
'needed_by': {
'svc_systemd:zfs-zed',
@ -127,6 +121,27 @@ if node.has_bundle('telegraf'):
}
@metadata_reactor.provides(
'pacman/packages',
)
def packages(metadata):
if node.metadata.get('pacman/linux-lts', False):
pkgname = 'zfs-linux-lts'
else:
pkgname = 'zfs-linux'
return {
'pacman': {
'packages': {
pkgname: {
'needed_by': {
'zfs_dataset:',
'zfs_pool:',
},
},
},
},
}
@metadata_reactor.provides(
'apt/packages',
)

View file

@ -1,62 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
=0YYh
-----END PGP PUBLIC KEY BLOCK-----

View file

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

View file

@ -1,22 +1,22 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

View file

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

View file

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

View file

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

View file

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

View file

@ -61,9 +61,6 @@ groups['home'] = {
}
groups['sophie'] = {
'supergroups': {
'linux',
},
'member_patterns': {
r"sophie\..*",
},

View file

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

View file

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

View file

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

View file

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

View file

@ -40,7 +40,7 @@ imap_pass = "!bwpass_attr:t-online.de/franzi.kunsmann@t-online.de:imap"
[metadata.element-web]
url = "chat.franzi.business"
version = "v1.11.89"
version = "v1.11.77"
[metadata.element-web.config]
default_server_config.'m.homeserver'.base_url = "https://matrix.franzi.business"
default_server_config.'m.homeserver'.server_name = "franzi.business"
@ -49,8 +49,8 @@ defaultCountryCode = "DE"
jitsi.preferredDomain = "meet.ffmuc.net"
[metadata.forgejo]
version = "9.0.3"
sha1 = "a04a8d5bee7321610d91da780a24e18f7407403c"
version = "8.0.3"
sha1 = "a19aa24f26c1ff5a38cf12619b6a6064242d0cf2"
domain = "git.franzi.business"
enable_git_hooks = true
install_ssh_key = true
@ -90,7 +90,7 @@ user_id = "@dimension:franzi.business"
admin_contact = "mailto:hostmaster@kunbox.net"
baseurl = "matrix.franzi.business"
server_name = "franzi.business"
trusted_key_servers = ["matrix.org", "161.rocks"]
trusted_key_servers = ["matrix.org", "finallycoffee.eu"]
additional_client_config.'im.vector.riot.jitsi'.preferredDomain = "meet.ffmuc.net"
wellknown_also_on_vhosts = ["franzi.business"]
[metadata.matrix-synapse.sliding_sync]
@ -114,8 +114,8 @@ provisioning.shared_secret = "!decrypt:encrypt$gAAAAABfVKflEMAi07C_QGP8cy97hF-4g
"'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp]
version = "v0.11.2"
sha1 = "0bd8ebef237473989c4e9658c72595e9f7c09d44"
version = "v0.10.9"
sha1 = "1619579ec6b9fca84fec085a94842d309d3f730c"
permissions."'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp.homeserver]
domain = "franzi.business"
@ -126,7 +126,7 @@ domain = "rss.franzi.business"
[metadata.netbox]
domain = "netbox.franzi.business"
version = "v4.1.9"
version = "v4.1.1"
admins.kunsi = "hostmaster@kunbox.net"
[metadata.nextcloud]
@ -136,10 +136,6 @@ domain = "warnochwas.de"
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"]
@ -152,10 +148,8 @@ 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"
locations.'/'.redirect = "https://travelynx.franzi.business/p/Kunsi"
locations.'/'.mode = 302
[metadata.nginx.vhosts.mta-sts]
domain = "mta-sts.kunbox.net"
@ -213,7 +207,7 @@ blocked_recipients = [
[metadata.postfixadmin]
domain = "postfixadmin.franzi.business"
setup_password = "!decrypt:encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ=="
version = "3.3.15"
version = "3.3.13"
[metadata.postgresql]
version = 15
@ -257,12 +251,12 @@ dkim = "uO4aNejDvVdw8BKne3KJIqAvCQMJ0416"
[metadata.smartd]
disks = [
"/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NF0W508470",
"/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NX0W114380",
"/dev/nvme0",
"/dev/nvme1",
]
[metadata.travelynx]
version = "2.9.6"
version = "2.8.38"
mail_from = "travelynx@franzi.business"
domain = "travelynx.franzi.business"

View file

@ -22,11 +22,17 @@ 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.pyenv]
version = 'v2.4.23'
python_versions = ["3.13.1"]
version = 'v2.3.36'
python_versions = ["3.12.2"]
[metadata.nginx.vhosts.homeassistant]
ssl = '_.home.kunbox.net'

View file

@ -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

View file

@ -1,15 +1,9 @@
hostname = "172.19.138.22"
groups = ["debian-bookworm"]
bundles = ["docker-engine", "nginx", "redis"]
[metadata]
icinga_options.exclude_from_monitoring = true
[metadata.docker-engine.config]
# this is a dev machine, it's fine if docker does shenanigans with
# iptables
iptables = true
[metadata.interfaces.eno3]
ips = [
"172.19.138.22/24",
@ -17,7 +11,7 @@ ips = [
gateway4 = "172.19.138.1"
ipv6_accept_ra = true
[metadata.nftables.forward]
[metadata.nftable.forward]
50-local-forward = [
'ct state { related, established } accept',
'iifname eno3 accept',

View file

@ -177,18 +177,10 @@ nodes['home.nas'] = {
},
'samba': {
'shares': {
'TV': {
'path': '/storage/nas/TV',
'force_group': 'nas',
},
'music': {
'path': '/storage/nas/Musik',
'force_group': 'nas',
},
'music_videos': {
'path': '/storage/nas/Musikvideos',
'force_group': 'nas',
},
},
'restrict-to': {
'172.19.138.0/24',
@ -198,14 +190,6 @@ nodes['home.nas'] = {
'disks': {
'/dev/nvme0',
# old nas 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',
# encrypted disks
'/dev/disk/by-id/ata-Samsung_SSD_870_QVO_8TB_S5SSNJ0X409404K',
'/dev/disk/by-id/ata-Samsung_SSD_870_QVO_8TB_S5SSNJ0X409845F',
@ -316,7 +300,7 @@ nodes['home.nas'] = {
'acltype': 'off',
'atime': 'off',
'compression': 'off',
'mountpoint': '/storage/nas',
'mountpoint': '/media/nas',
},
'encrypted/paperless': {
'mountpoint': '/media/paperless',
@ -334,7 +318,7 @@ nodes['home.nas'] = {
'acltype': 'off',
'atime': 'off',
'compression': 'off',
'mountpoint': '/media/nas_old',
'mountpoint': '/storage/nas',
},
'storage/paperless': {
'mountpoint': '/srv/paperless',

View file

@ -48,7 +48,7 @@ nodes['home.paperless'] = {
},
'paperless': {
'domain': 'paperless.home.kunbox.net',
'version': 'v2.13.5',
'version': 'v2.12.0',
'timezone': 'Europe/Berlin',
},
'postgresql': {

100
nodes/htz-cloud.afra.toml Normal file
View file

@ -0,0 +1,100 @@
hostname = "91.107.203.234"
bundles = [
"element-web",
"matrix-media-repo",
"matrix-registration",
"matrix-synapse",
"nodejs",
"postgresql",
"zfs",
]
groups = [
"debian-bookworm",
"webserver",
]
[metadata.icinga_options]
pretty_name = "afra.berlin"
[metadata.interfaces.eth0]
ips = [
"91.107.203.234/32",
"2a01:4f8:c010:b0e1::1/64",
]
gateway4 = '172.31.1.1'
gateway6 = 'fe80::1'
[metadata.interfaces.ens10]
ips = [
"172.19.137.7/32",
]
routes.'172.19.128.0/20'.via = "172.19.137.1"
[metadata.element-web]
url = "element.afra.berlin"
version = "v1.11.77"
[metadata.element-web.config]
default_server_config.'m.homeserver'.base_url = "https://matrix.afra.berlin"
default_server_config.'m.homeserver'.server_name = "afra.berlin"
brand = "afra.berlin"
defaultCountryCode = "DE"
jitsi.preferredDomain = "meet.ffmuc.net"
[metadata.matrix-media-repo]
admins = ['@administress:afra.berlin']
datastore_id = "e33b50474021fba9977f912414cdd7fe8890ed57"
sha1 = "3e2bb7089b0898b86000243a82cc58ae998dc9d9"
upload_max_mb = 50
version = "v1.3.7"
[metadata.matrix-media-repo.homeservers.'afra.berlin']
domain = "http://[::1]:20080/"
api = "synapse"
signing_key_path = "/etc/matrix-synapse/mmr.signing.key"
[metadata.matrix-registration]
base_path = "/matrix"
client_redirect = "https://element.afra.berlin"
[metadata.matrix-synapse]
server_name = "afra.berlin"
baseurl = "matrix.afra.berlin"
admin_contact = 'mailto:hostmaster@kunbox.net'
trusted_key_servers = [
"matrix.org",
"franzi.business",
]
wellknown_also_on_vhosts = ["redirect"]
[metadata.nginx.vhosts.redirect]
domain = "afra.berlin"
[metadata.nginx.vhosts.redirect.locations.'/']
redirect = "https://afra-berlin.de"
mode = 302
#[metadata.nginx.vhosts.redirect.locations.'/.well-known/host-meta']
#redirect = "https://fedi.afra.berlin/.well-known/host-meta"
#mode = 301
#[metadata.nginx.vhosts.redirect.locations.'/.well-known/nodeinfo']
#redirect = "https://fedi.afra.berlin/.well-known/nodeinfo"
#mode = 301
#[metadata.nginx.vhosts.redirect.locations.'/.well-known/webfinger']
#redirect = "https://fedi.afra.berlin/.well-known/webfinger"
#mode = 301
[metadata.nginx.vhosts.redirect.locations.'/matrix/']
target = "http://127.0.0.1:20100/"
[metadata.postgresql]
version = "15"
work_mem = 1024
cache_size = 2048
[[metadata.zfs.pools.tank.when_creating.config]]
devices = ["/dev/disk/by-id/scsi-0HC_Volume_32207877"]
[metadata.vm]
cpu = 2
ram = 8

View file

@ -71,7 +71,7 @@ nodes['htz-cloud.pirmasens'] = {
},
'postfixadmin': {
'domain': 'mail.kunsmann.info',
'version': '3.3.15',
'version': '3.3.13',
'setup_password': vault.decrypt('encrypt$gAAAAABgnNGpAqUs--qBXII9ZPcHtxaELy9e2Dx9O44n4l0O4nMHPoIyaPW5HkvpQ2zWTlh5OfjjOgunRtE_voJuY0Kdtji37ixAnuL9ErOJ0LDY5QfMkNPUgPs5alwz1baqYq6rqJ7NDmB0gHraY46v5eG79R2EyQ=='),
},
'postgresql': {

View file

@ -37,7 +37,6 @@ nodes['htz-cloud.wireguard'] = {
'172.19.137.0/24',
'172.19.136.62/31',
'172.19.136.64/31',
'192.168.100.0/24',
},
},
'nftables': {
@ -81,17 +80,6 @@ nodes['htz-cloud.wireguard'] = {
'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,

View file

@ -1,6 +1,5 @@
hostname = "2a01:4f9:6b:2d99::c0ff:ee"
#dummy = true
bundles = ["sshmon", "smartd"]
dummy = true
# How to install:
# - Get server at Hetzner (no IPv4)
@ -18,11 +17,3 @@ bundles = ["sshmon", "smartd"]
# - IPv6 only
# - IP from the /64 hetzner gives us
# - Gateway is the host itself, to work around the MAC filter hetzner uses
[metadata.smartd]
disks = [
"/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd",
]

View file

@ -97,15 +97,16 @@ nodes['kunsi-p14s'] = {
'xf86-video-amdgpu': {},
# all that other random stuff one needs
#'abcde': {},
'abcde': {},
'apachedirectorystudio': {},
'claws-mail': {},
'claws-mail-themes': {},
'ferdium-bin': {},
'gumbo-parser': {}, # for claws litehtml
'inkstitch': {}, # for RZL embroidery machine
'obs-studio': {},
#'perl-musicbrainz-discid': {}, # for abcde
#'perl-webservice-musicbrainz': {}, # for abcde
'perl-musicbrainz-discid': {}, # for abcde
'perl-webservice-musicbrainz': {}, # for abcde
'sdl_ttf': {}, # for compiling testcard
'x32edit': {},
},
@ -115,10 +116,10 @@ nodes['kunsi-p14s'] = {
'entries': {
'arch': {
'title': 'Arch Linux',
'linux': '/vmlinuz-linux-lts',
'linux': '/vmlinuz-linux',
'initrd': [
'/amd-ucode.img',
'/initramfs-linux-lts.img',
'/initramfs-linux.img',
],
'options': {
'net.ifnames=0',
@ -128,9 +129,9 @@ nodes['kunsi-p14s'] = {
},
'arch-fallback': {
'title': 'Arch Linux (no ucode, fallback initramfs)',
'linux': '/vmlinuz-linux-lts',
'linux': '/vmlinuz-linux',
'initrd': [
'/initramfs-linux-lts-fallback.img',
'/initramfs-linux-fallback.img',
],
'options': {
'net.ifnames=0',

View file

@ -1,7 +0,0 @@
dummy = true
[metadata.icinga_options]
period = "daytime"
[metadata.interfaces.default]
ips = ["192.168.100.27/24"]

View file

@ -1,61 +0,0 @@
hostname = "91.198.192.207"
groups = [
"debian-bookworm",
"webserver",
]
bundles = [
"docker-engine",
"docker-immich",
"ipmitool",
"redis",
"smartd",
"zfs",
]
[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.immich]
domain = "rr-immich.franzi.business"
[metadata.smartd]
disks = [
"/dev/disk/by-id/ata-WDC_WD30EZRX-00DC0B0_WD-WMC1T0287704",
"/dev/disk/by-id/ata-WDC_WD30EZRX-00DC0B0_WD-WMC1T0387139",
"/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.zfs.pools.tank.when_creating]
ashift = 12
[[metadata.zfs.pools.tank.when_creating.config]]
type = "mirror"
devices = [
"/dev/disk/by-id/ata-WDC_WD30EZRX-00DC0B0_WD-WMC1T0287704",
"/dev/disk/by-id/ata-WDC_WD30EZRX-00DC0B0_WD-WMC1T0387139",
]
[[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",
]

View file

@ -37,7 +37,6 @@ nodes['htz-hel.backup-sophie'] = {
},
'backup-server': {
'zfs-base': 'tank/backups',
'my_hostname': 'backup.sophies-kitchen.eu',
},
'nftables': {
'input': {

View file

@ -1,260 +1,254 @@
# sophie's miniserver
nodes["htz-cloud.miniserver"] = {
"bundles": {
"element-web",
"hedgedoc",
"matrix-media-repo",
"matrix-synapse",
nodes['htz-cloud.miniserver'] = {
'bundles': {
'element-web',
'hedgedoc',
'matrix-media-repo',
'matrix-synapse',
"matrix-stickerpicker",
"nodejs",
"ntfy",
"mautrix-telegram",
"postgresql",
"zfs",
'nodejs',
'ntfy',
'mautrix-telegram',
'postgresql',
'zfs',
},
"groups": {
"debian-bookworm",
"sophie",
"webserver",
'groups': {
'debian-bookworm',
'sophie',
'webserver',
},
"metadata": {
"interfaces": {
"eth0": {
"ips": {
"157.90.20.62",
"2a01:4f8:c2c:840f::1/64",
'metadata': {
'interfaces': {
'eth0': {
'ips': {
'157.90.20.62',
'2a01:4f8:c2c:840f::1/64',
},
"gateway4": "172.31.1.1",
"gateway6": "fe80::1",
'gateway4': '172.31.1.1',
'gateway6': 'fe80::1',
},
},
"apt": {
"packages": {
"mosh": {},
"weechat": {},
"weechat-core": {},
"weechat-curses": {},
"weechat-perl": {},
"weechat-plugins": {},
"weechat-python": {},
"weechat-ruby": {},
'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",
'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",
'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",
'backups': {
'paths': {
'/home/sophie/.weechat',
},
},
"element-web": {
"url": "chat.sophies-kitchen.eu",
"version": "v1.11.86",
"config": {
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.sophies-kitchen.eu",
"server_name": "sophies-kitchen.eu",
'element-web': {
'url': 'chat.sophies-kitchen.eu',
'version': 'v1.11.72',
'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",
'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",
'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",
'hedgedoc': {
'version': '1.9.9',
'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"
'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",
'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",
'matrix-media-repo': {
'version': 'v1.3.7',
'datastore_id': '99c09e24edc4e9be6c4c9486bc147e385bc87044',
'sha1': '3e2bb7089b0898b86000243a82cc58ae998dc9d9',
'homeservers': {
'sophies-kitchen.eu': {
'domain': 'http://[::1]:20080/',
'api': 'synapse',
},
},
"admins": {
"@sophie:sophies-kitchen.eu",
'admins': {
'@sophie:sophies-kitchen.eu',
},
"upload_max_mb": 500,
'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-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",
'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",
'mautrix-telegram': {
'version': 'v0.15.2',
'homeserver': {
'domain': 'sophies-kitchen.eu',
'url': 'https://matrix.sophies-kitchen.eu',
},
"provisioning": {
"enabled": False,
"shared_secret": '""',
'provisioning': {
'enabled': False,
'shared_secret': '""',
},
"permissions": {
"sophies-kitchen.eu": "full",
"'@sophie:sophies-kitchen.eu'": "admin",
'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": '""',
'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",
'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",
'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,
'nginx': {
'vhosts': {
'sophies-kitchen.eu': {
'webroot': '/var/www/sophies-kitchen.eu/_site/',
'extras': True,
},
"matrix-synapse": {
"domain": "matrix.sophies-kitchen.eu",
'matrix-synapse': {
'domain': 'matrix.sophies-kitchen.eu',
},
"webdump.sophies-kitchen.eu": {
"webroot_config": {
"owner": "sophie",
"group": "sophie",
"mode": "0755",
'webdump.sophies-kitchen.eu': {
'webroot_config': {
'owner': 'sophie',
'group': 'sophie',
'mode': '0755',
},
"extras": True,
'extras': True,
},
"recipes.sophies-kitchen.eu": {
"webroot_config": {
"owner": "sophie",
"group": "sophie",
"mode": "0755",
'recipes.sophies-kitchen.eu': {
'webroot_config': {
'owner': 'sophie',
'group': 'sophie',
'mode': '0755',
},
},
},
},
"nodejs": {
"version": 20,
'nodejs': {
'version': 20,
},
"ntfy": {
"domain": "ntfy.sophies-kitchen.eu",
"allow_unauthorized_write": True,
'ntfy': {
'domain': 'ntfy.sophies-kitchen.eu',
'allow_unauthorized_write': True,
},
"postgresql": {
"version": "11",
'postgresql': {
'version': '11',
},
"sysctl": {
"options": {
'sysctl': {
'options': {
# XXX find out if this is really needed
"net.ipv4.conf.all.forwarding": "1",
"net.ipv6.conf.all.forwarding": "1",
'net.ipv4.conf.all.forwarding': '1',
'net.ipv6.conf.all.forwarding': '1',
},
},
"vm": {
"cpu": 2,
"ram": 4,
'vm': {
'cpu': 2,
'ram': 4,
},
"users": {
"sophie": {
"enable_linger": True,
"ssh_pubkey": [
'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": {
'zfs': {
"datasets": {
"tank/webdump": {
"mountpoint": "/var/www/webdump.sophies-kitchen.eu",
"needed_by": ["directory:/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",
},
}
]
'pools': {
'tank': {
'when_creating': {
'config': [{
'devices': {
'/dev/disk/by-id/scsi-0HC_Volume_23952298',
},
}]
},
},
},

View file

@ -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",
},
},
},
}

View file

@ -1,12 +1,12 @@
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': {
@ -25,27 +25,27 @@ nodes['voc.infobeamer-cms'] = {
},
'infobeamer-cms': {
'domain': 'infobeamer.c3voc.de',
'event_start_date': '2024-12-26',
'event_start_date': '2024-05-29',
'event_duration_days': 5,
'config': {
'ADMIN_USERS': [
'evilscientress',
'hexchen',
'jbeyerstedt',
'jwacalex',
'kunsi',
'sophieschi',
'v0tti',
],
'NO_LIMIT_USERS': [
'stblassitude',
],
'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'),
'INTERRUPT_KEY': vault.human_password_for('infobeamer-cms interrupt key 38c3', words=1),
'INTERRUPT_KEY': vault.human_password_for('infobeamer-cms interrupt key'),
'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': [
255228,
250294,
],
# 'EXTRA_ASSETS': [{
# 'type': "image",
@ -56,32 +56,13 @@ nodes['voc.infobeamer-cms'] = {
# '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 <a href="https://chat.hackint.org/?join=infobeamer">IRC
Channel #infobeamer on irc.hackint.org</a> (also
<a href="https://www.hackint.org/transport/matrix">bridged to matrix</a>)
or #info-beamer on the cccv rocketchat instance.
'''.strip(),
},
},
'rooms': {
'Saal 1': 34430, # s1
'Saal GLITCH': 37731, # s2
'Saal ZIGZAG': 26610, # s3
'Sendezentrum': 38641, # s4
'Stage YELL': 38642, # s5
'Stage HUFF': 35042, # s6
'Saal 1': 34430,
'Saal G': 26598,
'Saal Z': 26610,
'Saal E (SoS/Lightning-Talks)': 32814,
'Saal F (Sendezentrum/DLF)': 9717,
},
'interrupts': {
'Questions': 'questions',

View file

@ -49,15 +49,14 @@ nodes['voc.pretalx'] = {
},
},
'pretalx': {
# 2023.3.1 with some bugfixes
'version': '05e377398cecdd45d3ca6013040c5857bbe225d6',
'version': 'v2024.2.1',
'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',
'rev': 'main',
},
'downstream': {
'repo': 'https://github.com/pretalx/pretalx-downstream.git',
@ -65,7 +64,7 @@ nodes['voc.pretalx'] = {
},
'halfnarp': {
'repo': 'https://github.com/seibert-media/pretalx-halfnarp.git',
'rev': '1.1.2',
'rev': '1.1.0',
},
'media.ccc.de': {
'repo': 'https://github.com/pretalx/pretalx-media-ccc-de.git',
@ -82,6 +81,6 @@ nodes['voc.pretalx'] = {
},
},
'os': 'debian',
'os_version': (12,),
'os_version': (11,),
'pip_command': 'pip3',
}