Compare commits

..

76 commits

Author SHA1 Message Date
128a61706e
bundles/infobeamer-monitor: some more improvements in status display 2024-11-28 08:27:36 +01:00
8e23747400
home.hass: remove nginx ip restriction 2024-11-28 08:27:17 +01:00
3b608d95ec
add static ip reservation for mixer96 as well 2024-11-23 13:31:00 +01:00
3a5db80843
bundles/icinga2: notify per sms if ntfy does not respond in time 2024-11-23 13:30:22 +01:00
a9b16c18ad
bundles/postfix: remove smtp_use_tls option
Log says:

postconf: warning: /etc/postfix/main.cf: support for parameter "smtp_use_tls" will be removed; instead, specify "smtp_tls_security_level"
2024-11-22 20:50:52 +01:00
8f705fc8e3
update mautrix-whatsapp to 0.11.1 2024-11-17 11:48:08 +01:00
b3070a8b8b
bundles/infobeamer-monitor: announce online devices at 09:00 CE(S)T 2024-11-16 14:14:05 +01:00
6a203085b9
bundles/pretalx: we do not need to regenerate_css anymore 2024-11-16 13:35:24 +01:00
669b28f6ed
voc.pretalx: update to 2023.3.1 2024-11-16 13:02:39 +01:00
9884b703cd
update forgejo to 9.0.2 2024-11-16 12:11:01 +01:00
fa63ad72d5
update paperless-ngx to 2.13.5 2024-11-15 10:24:42 +01:00
3a56995ab1
update netbox to 4.1.6 2024-11-15 10:24:28 +01:00
50b71bc8b8
update element-web to 1.11.85 2024-11-15 10:24:13 +01:00
fcd097599d
home.nas: samba share for music videos 2024-11-15 10:17:37 +01:00
563ba266ff
fix icinga2 bundle (gpg key / packages) 2024-11-10 18:56:35 +01:00
209dedccf9
isort the whole repo 2024-11-08 06:39:59 +01:00
e51c24f837
bundles/powerdns: use *repo* commit time instead of *file* commit time for serial 2024-11-08 06:39:05 +01:00
72638e0856
bundles/infobeamer-monitor: add account data monitoring 2024-11-03 17:51:12 +01:00
2c83a5c4fc
voc.infobeamer-cms: prepare for 38c3 2024-10-31 16:58:26 +01:00
ec49c8d3ff
voc.infobeamer-cms: hackint changed their webirc service 2024-10-31 16:36:07 +01:00
46ec4cc2e7
bundles/postgresql: please also always do dumps 2024-10-28 16:55:10 +01:00
e29a838fad
bundles/forgejo: fix website_check_string 2024-10-28 16:54:53 +01:00
f6cb540007
update paperless-ngx to 2.13.0 2024-10-28 16:17:16 +01:00
6eb2c6651b
update netbox to 4.1.4 2024-10-28 16:16:48 +01:00
c006748165
update mautrix-whatsapp to 0.11.0 2024-10-28 16:16:36 +01:00
1be5ab268b
update forgejo to 9.0.1 2024-10-28 16:16:24 +01:00
12c735f4aa
update element-web to 1.11.82 2024-10-28 16:16:10 +01:00
9b0e627274
bundles/homeassistant: ensure virtualenv is in PATH 2024-10-27 17:45:22 +01:00
4f0ced4d9a
bundles/homeassistant: fix version check 2024-10-27 17:37:14 +01:00
af78e959ae Merge pull request 'new-wildcard-sophies-kitchen' (#72) from new-wildcard-sophies-kitchen into main
Reviewed-on: #72
2024-10-27 10:40:32 +00:00
58964cc10f
bundles/rspamd: send dmarc report emails from devnull address 2024-10-27 11:21:12 +01:00
ec8af84fb1
bundles/postfix: add devnull@myhostname mail address 2024-10-27 11:19:42 +01:00
9bfb531214
kunsi-p14s: clean up packages 2024-10-27 11:19:26 +01:00
84867ff1e6
bundles/postfix: provide myhostname from reactor 2024-10-27 11:19:05 +01:00
6647e71484
rottenraptor-server: add docker-immich 2024-10-26 16:28:09 +02:00
2e8cbd6061
add bundle:docker-immich 2024-10-26 16:27:54 +02:00
453d2a7889
home.r630: add docker, fix firewall 2024-10-26 16:27:16 +02:00
4238eeb6d8
add bundle:docker-engine 2024-10-26 16:25:54 +02:00
729b975b77
bundles/redis: ensure protected mode is off 2024-10-26 16:25:06 +02:00
c4e3d0abc2
bundles/nginx: we need a type definition for .mjs 2024-10-26 16:24:47 +02:00
078d52c075
carlene: rework kunsitracker 2024-10-26 08:20:01 +02:00
a83b380490
bundles/nginx: more config options 2024-10-26 08:19:43 +02:00
ed9607433d
rottenraptor-server: add smartd and zfs 2024-10-24 19:25:23 +02:00
d1b369fb26
bundles/smartd: do not try to guess disk names 2024-10-24 19:25:00 +02:00
07a44598d2
rottenraptor-server is in its colo now 2024-10-24 18:18:35 +02:00
e35fbdd183
add rottenraptor-server 2024-10-10 19:40:01 +02:00
c5fb1b8a28
htz-cloud.wireguard: add wg connection to fra-jana 2024-10-10 19:39:38 +02:00
814b67a9d0
voc.infobeamer-cms add v0tti to admins 2024-10-05 16:58:50 +02:00
3ff7db7d6d
bundles/sshmon: more letsencrypt issuer hashes 2024-10-03 22:43:25 +02:00
b57f205696
voc.infobeamer-cms: prepare for mrmcd24 2024-10-02 17:45:58 +02:00
ef8d3368c1
voc.infobeamer-cms: add FAQ entries 2024-10-01 11:03:50 +02:00
a5ea87b4e9
voc.infobeamer-cms: fix mqtt config 2024-10-01 10:53:04 +02:00
df69b876a9
voc.infobeamer-cms: prepare for mrmcd 2024-09-30 22:40:07 +02:00
4fbbf83952
update infobeamer-cms to debian bookworm 2024-09-30 22:24:53 +02:00
a1d1351411
update infobeamer-cms to current version 2024-09-30 22:24:34 +02:00
e2b430fd0e
update travelynx to 2.8.40 2024-09-30 10:21:05 +02:00
663f7eec9f
remove finallycoffee.eu from trusted key servers 2024-09-30 10:20:57 +02:00
95860e978b
remove htz-cloud.afra 2024-09-29 16:17:48 +02:00
52e891d3a7
move afra.berlin redirect to carlene 2024-09-29 16:17:10 +02:00
8ba63e112c
bundles/sshmon: fix SyntaxWarning 2024-09-27 10:22:58 +02:00
67f901c1c9
bundles/powerdnsadmin: fix dependencies 2024-09-27 10:19:01 +02:00
8c28d612cb
groups/sophie: fix group conflict 2024-09-27 10:16:07 +02:00
54f669313a
home.nas: nas dataset goes ssd 2024-09-27 10:15:50 +02:00
7b6d811128
bundles/sshmon: better cpu check 2024-09-27 10:02:27 +02:00
2564f416c2
update paperless to 2.12.1 2024-09-27 08:51:20 +02:00
8a28886012
update netbox to 4.1.2 2024-09-27 08:51:08 +02:00
c699f0d510
update element-web to 1.11.78 2024-09-27 08:50:52 +02:00
4a28bc55c0
bundles/homeassistant: rework check_homeassistant_update 2024-09-27 08:42:58 +02:00
abdc7f751e
update pretalx-halfnarp to 1.1.2 2024-09-25 21:45:52 +02:00
423049667f
bundles/nftables: improve handling for icmp 2024-09-23 18:09:49 +02:00
c6421c7bd4
update travelynx to 2.8.39 2024-09-20 15:34:14 +02:00
95c5b28469
basic monitoring for proxmox-backupstorage 2024-09-20 15:34:12 +02:00
7dc0afe299 Merge pull request 'miniserver: element-web update' (#71) from updates into main
Reviewed-on: #71
2024-09-19 20:59:48 +00:00
Sophie Schiller
121a261ecd miniserver: actually use signing key 2024-09-04 23:06:23 +02:00
Sophie Schiller
b9216f230b matrix-media-repo: extend rate limits 2024-09-04 23:06:07 +02:00
Sophie Schiller
497d4fff30 miniserver: element-web update 2024-09-04 21:25:50 +02:00
59 changed files with 795 additions and 352 deletions

View file

@ -0,0 +1,39 @@
#!/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

@ -0,0 +1,50 @@
#!/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

@ -0,0 +1,14 @@
[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

@ -0,0 +1,99 @@
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

@ -0,0 +1,83 @@
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

@ -0,0 +1,64 @@
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 protocols = imap lmtp sieve
ssl = required ssl = required
ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/fullchain.pem ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/fullchain.pem
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/privkey.pem ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/privkey.pem
ssl_dh = </etc/ssl/certs/dhparam.pem ssl_dh = </etc/ssl/certs/dhparam.pem
ssl_min_protocol = TLSv1.2 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 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

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

View file

@ -2,48 +2,42 @@
from sys import exit from sys import exit
import requests from packaging.version import parse
from packaging import version from requests import get
bearer = "${bearer}" API_TOKEN = "${token}"
domain = "${domain}" 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: try:
stable_version = version.parse( r = get("https://version.home-assistant.io/stable.json")
s.get("https://version.home-assistant.io/stable.json").json()["homeassistant"][ r.raise_for_status()
"generic-x86-64" stable_version = parse(r.json()["homeassistant"]["generic-x86-64"])
]
)
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:
status = 2
message = f"CRITICAL - update necessary, running version {running_version} is lower than stable version {stable_version}"
except Exception as e: except Exception as e:
message = f"{message}: {repr(e)}" print(f"Could not get stable version information from home-assistant.io: {e!r}")
exit(3)
print(message) try:
exit(status) r = get(
f"https://{DOMAIN}/api/config",
headers={"Authorization": f"Bearer {API_TOKEN}", "Content-Type": "application/json"},
)
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)
else:
print(
f"Currently running version {running_version} matches newest release on home-assistant.io"
)
exit(0)
except Exception as e:
print(repr(e))
exit(3)

View file

@ -5,6 +5,8 @@ After=network-online.target
[Service] [Service]
Type=simple Type=simple
User=homeassistant 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 WorkingDirectory=/var/opt/homeassistant
ExecStart=/opt/homeassistant/venv/bin/hass -c "/var/opt/homeassistant" ExecStart=/opt/homeassistant/venv/bin/hass -c "/var/opt/homeassistant"
RestartForceExitStatus=100 RestartForceExitStatus=100

View file

@ -30,7 +30,7 @@ files = {
'/usr/local/share/icinga/plugins/check_homeassistant_update': { '/usr/local/share/icinga/plugins/check_homeassistant_update': {
'content_type': 'mako', 'content_type': 'mako',
'context': { 'context': {
'bearer': repo.vault.decrypt(node.metadata.get('homeassistant/api_secret')), 'token': node.metadata.get('homeassistant/api_secret'),
'domain': node.metadata.get('homeassistant/domain'), 'domain': node.metadata.get('homeassistant/domain'),
}, },
'mode': '0755', 'mode': '0755',

View file

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

View file

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

View file

@ -23,7 +23,7 @@ actions = {
git_deploy = { git_deploy = {
'/opt/infobeamer-cms/src': { '/opt/infobeamer-cms/src': {
'rev': 'master', 'rev': 'master',
'repo': 'https://github.com/sophieschi/36c3-cms.git', 'repo': 'https://github.com/voc/infobeamer-cms.git',
'needs': { 'needs': {
'directory:/opt/infobeamer-cms/src', 'directory:/opt/infobeamer-cms/src',
}, },
@ -96,14 +96,6 @@ files = {
}, },
} }
pkg_pip = {
'github-flask': {
'needed_by': {
'svc_systemd:infobeamer-cms',
},
},
}
svc_systemd = { svc_systemd = {
'infobeamer-cms': { 'infobeamer-cms': {
'needs': { 'needs': {

View file

@ -1,9 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging import logging
from datetime import datetime, timezone from datetime import datetime
from json import dumps from json import dumps
from time import sleep from time import sleep
from zoneinfo import ZoneInfo
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from requests import RequestException, get from requests import RequestException, get
@ -24,7 +25,8 @@ logging.basicConfig(
) )
LOG = logging.getLogger("main") LOG = logging.getLogger("main")
MLOG = logging.getLogger("mqtt") TZ = ZoneInfo("Europe/Berlin")
DUMP_TIME = "0900"
state = None state = None
@ -61,14 +63,14 @@ def mqtt_dump_state(device):
out.append("Location: {}".format(device["location"])) out.append("Location: {}".format(device["location"]))
out.append("Setup: {} ({})".format(device["setup"]["name"], device["setup"]["id"])) out.append("Setup: {} ({})".format(device["setup"]["name"], device["setup"]["id"]))
out.append("Resolution: {}".format(device["run"].get("resolution", "unknown"))) out.append("Resolution: {}".format(device["run"].get("resolution", "unknown")))
if not device["is_synced"]:
out.append("syncing ...")
mqtt_out( mqtt_out(
" - ".join(out), " - ".join(out),
device=device, device=device,
) )
def is_dump_time():
return datetime.now(TZ).strftime("%H%M") == DUMP_TIME
mqtt_out("Monitor starting up") mqtt_out("Monitor starting up")
while True: while True:
@ -81,14 +83,13 @@ while True:
r.raise_for_status() r.raise_for_status()
ib_state = r.json()["devices"] ib_state = r.json()["devices"]
except RequestException as e: except RequestException as e:
LOG.exception("Could not get data from info-beamer") LOG.exception("Could not get device data from info-beamer")
mqtt_out( mqtt_out(
f"Could not get data from info-beamer: {e!r}", f"Could not get device data from info-beamer: {e!r}",
level="WARN", level="WARN",
) )
else: else:
new_state = {} new_state = {}
online_devices = set()
for device in ib_state: for device in ib_state:
did = str(device["id"]) did = str(device["id"])
@ -97,7 +98,8 @@ while True:
continue continue
new_state[did] = device new_state[did] = device
must_dump_state = False # 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 state is not None:
if did not in state: if did not in state:
@ -140,16 +142,15 @@ while True:
if device["is_online"]: if device["is_online"]:
if device["maintenance"]: if device["maintenance"]:
mqtt_out( mqtt_out(
"maintenance required: {}".format(' '.join( "maintenance required: {}".format(
sorted(device["maintenance"]) " ".join(sorted(device["maintenance"]))
)), ),
level="WARN", level="WARN",
device=device, device=device,
) )
if ( if (
device["is_synced"] != state[did]["is_synced"] device["location"] != state[did]["location"]
or device["location"] != state[did]["location"]
or device["setup"]["id"] != state[did]["setup"]["id"] or device["setup"]["id"] != state[did]["setup"]["id"]
or device["run"].get("resolution") or device["run"].get("resolution")
!= state[did]["run"].get("resolution") != state[did]["run"].get("resolution")
@ -161,23 +162,52 @@ while True:
else: else:
LOG.info("adding device {} to empty state".format(device["id"])) 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 state = new_state
if ( try:
datetime.now(timezone.utc).strftime("%H%M") == "1312" r = get(
and online_devices "https://info-beamer.com/api/v1/account",
and int(datetime.now(timezone.utc).strftime("%S")) < 30 auth=("", CONFIG["api_key"]),
): )
mqtt_out("Online Devices: {}".format(", ".join(sorted(online_devices)))) r.raise_for_status()
sleep(30) 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: except KeyboardInterrupt:
break break

View file

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

View file

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

View file

@ -29,7 +29,7 @@ defaults = {
}, },
} }
if not node.has_bundle('vmhost'): if not node.has_bundle('vmhost') and not node.has_bundle('docker-engine'):
# see comment in bundles/vmhost/items.py # see comment in bundles/vmhost/items.py
defaults['apt']['packages']['iptables'] = { defaults['apt']['packages']['iptables'] = {
'installed': False, 'installed': False,

View file

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

View file

@ -149,18 +149,18 @@ server {
% if 'target' in options: % if 'target' in options:
proxy_pass ${options['target']}; proxy_pass ${options['target']};
proxy_http_version ${options.get('http_version', '1.1')}; proxy_http_version ${options.get('http_version', '1.1')};
proxy_set_header Host ${domain}; proxy_set_header Host ${options.get('proxy_pass_host', domain)};
% if options.get('websockets', False): % if options.get('websockets', False):
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
% endif % endif
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host ${options.get('x_forwarded_host', domain)}; proxy_set_header X-Forwarded-Host ${options.get('x_forwarded_host', options.get('proxy_pass_host', domain))};
% for option, value in options.get('proxy_set_header', {}).items(): % for option, value in options.get('proxy_set_header', {}).items():
proxy_set_header ${option} ${value}; proxy_set_header ${option} ${value};
% endfor % endfor
% if location != '/': % if location != '/' and location != '= /':
proxy_set_header X-Script-Name ${location}; proxy_set_header X-Script-Name ${location};
% endif % endif
proxy_buffering off; proxy_buffering off;

View file

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

View file

@ -3,7 +3,7 @@ biff = no
append_dot_mydomain = no append_dot_mydomain = no
readme_directory = no readme_directory = no
compatibility_level = 2 compatibility_level = 2
myhostname = ${node.metadata.get('postfix/myhostname', node.metadata['hostname'])} myhostname = ${node.metadata.get('postfix/myhostname')}
myorigin = /etc/mailname myorigin = /etc/mailname
mydestination = $myhostname, localhost mydestination = $myhostname, localhost
mynetworks = ${' '.join(sorted(mynetworks))} mynetworks = ${' '.join(sorted(mynetworks))}
@ -25,7 +25,6 @@ inet_interfaces = 127.0.0.1
% endif % endif
<%text> <%text>
smtp_use_tls = yes
smtp_tls_loglevel = 1 smtp_tls_loglevel = 1
smtp_tls_note_starttls_offer = yes smtp_tls_note_starttls_offer = yes
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
@ -38,8 +37,8 @@ smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
</%text> </%text>
% if node.has_bundle('postfixadmin'): % if node.has_bundle('postfixadmin'):
smtpd_tls_cert_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname', node.metadata['hostname'])}/fullchain.pem 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', node.metadata['hostname'])}/privkey.pem smtpd_tls_key_file = /var/lib/dehydrated/certs/${node.metadata.get('postfix/myhostname')}/privkey.pem
<%text> <%text>
smtpd_use_tls=yes smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
@ -48,7 +47,7 @@ smtpd_client_restrictions = permit_mynetworks permit_sasl_authenticated
smtpd_helo_required = yes smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks reject_invalid_helo_hostname smtpd_helo_restrictions = permit_mynetworks reject_invalid_helo_hostname
smtpd_data_restrictions = reject_unauth_pipelining smtpd_data_restrictions = reject_unauth_pipelining
smtpd_recipient_restrictions = permit_mynetworks, check_recipient_access hash:/etc/postfix/blocked_recipients smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/blocked_recipients, permit_mynetworks
smtpd_relay_before_recipient_restrictions = yes 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 # 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 = { files = {
'/etc/mailname': { '/etc/mailname': {
'content': node.metadata.get('postfix/myhostname', node.metadata['hostname']), 'content': node.metadata.get('postfix/myhostname'),
'before': { 'before': {
my_package, my_package,
}, },

View file

@ -87,7 +87,7 @@ def letsencrypt(metadata):
} }
result['domains'] = { result['domains'] = {
metadata.get('postfix/myhostname', metadata.get('hostname')): set(), metadata.get('postfix/myhostname'): set(),
} }
return { return {
@ -148,3 +148,14 @@ 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') and not node.has_bundle('zfs'): if node.has_bundle('backup-client'):
files['/etc/backup-pre-hooks.d/90-postgresql-dump-all'] = { files['/etc/backup-pre-hooks.d/90-postgresql-dump-all'] = {
'source': 'backup-pre-hook', 'source': 'backup-pre-hook',
'content_type': 'mako', 'content_type': 'mako',
@ -67,10 +67,6 @@ if node.has_bundle('backup-client') and not node.has_bundle('zfs'):
'mode': '0700', 'mode': '0700',
} }
directories['/var/tmp/postgresdumps'] = {} directories['/var/tmp/postgresdumps'] = {}
else:
files['/var/tmp/postgresdumps'] = {
'delete': True,
}
postgres_roles = { postgres_roles = {
'root': { 'root': {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
assert node.has_bundle('redis'), f'{node.name}: pretalx needs redis' assert node.has_bundle('redis'), f'{node.name}: pretalx needs redis'
assert node.has_bundle('nodejs'), f'{node.name}: pretalx needs nodejs for rebuild and regenerate_css step' assert node.has_bundle('nodejs'), f'{node.name}: pretalx needs nodejs for rebuild step'
actions = { actions = {
'pretalx_create_virtualenv': { 'pretalx_create_virtualenv': {
@ -53,17 +53,6 @@ actions = {
}, },
'triggered': True, '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 = { users = {
@ -90,7 +79,6 @@ git_deploy = {
'action:pretalx_install', 'action:pretalx_install',
'action:pretalx_migrate', 'action:pretalx_migrate',
'action:pretalx_rebuild', 'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'svc_systemd:pretalx-web:restart', 'svc_systemd:pretalx-web:restart',
'svc_systemd:pretalx-worker:restart', 'svc_systemd:pretalx-worker:restart',
}, },
@ -121,7 +109,6 @@ svc_systemd = {
'action:pretalx_install', 'action:pretalx_install',
'action:pretalx_migrate', 'action:pretalx_migrate',
'action:pretalx_rebuild', 'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'file:/etc/systemd/system/pretalx-web.service', 'file:/etc/systemd/system/pretalx-web.service',
'file:/opt/pretalx/pretalx.cfg', 'file:/opt/pretalx/pretalx.cfg',
}, },
@ -129,7 +116,8 @@ svc_systemd = {
'pretalx-worker': { 'pretalx-worker': {
'needs': { 'needs': {
'action:pretalx_install', 'action:pretalx_install',
'action:pretalx_migrate', 'action:pretalx_migrate',,
'action:pretalx_rebuild',
'file:/etc/systemd/system/pretalx-worker.service', 'file:/etc/systemd/system/pretalx-worker.service',
'file:/opt/pretalx/pretalx.cfg', 'file:/opt/pretalx/pretalx.cfg',
}, },
@ -204,7 +192,6 @@ for plugin_name, plugin_config in node.metadata.get('pretalx/plugins', {}).items
'triggers': { 'triggers': {
'action:pretalx_migrate', 'action:pretalx_migrate',
'action:pretalx_rebuild', 'action:pretalx_rebuild',
'action:pretalx_regenerate-css',
'svc_systemd:pretalx-web:restart', 'svc_systemd:pretalx-web:restart',
'svc_systemd:pretalx-worker:restart', 'svc_systemd:pretalx-worker:restart',
}, },

View file

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

View file

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

View file

@ -1,7 +1,7 @@
reporting { reporting {
enabled = true; enabled = true;
email = 'dmarc+${node.name.replace('.', '-')}@kunbox.net'; email = 'devnull@${node.metadata.get('postfix/myhostname')}';
domain = '${node.metadata.get('hostname')}'; domain = '${node.metadata.get('postfix/myhostname')}';
org_name = 'kunbox.net'; org_name = 'kunbox.net';
smtp = '127.0.0.1'; smtp = '127.0.0.1';
smtp_port = 25; smtp_port = 25;

View file

@ -43,30 +43,6 @@ 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( @metadata_reactor.provides(
'icinga2_api/smartd/services', 'icinga2_api/smartd/services',
) )

View file

@ -4,27 +4,30 @@ from re import findall
from subprocess import check_output from subprocess import check_output
from sys import exit from sys import exit
ITERATIONS = 10
try: try:
top_output = None top_output = None
for line in check_output(['top', '-b', '-n1', '-d1']).decode('UTF-8').splitlines(): top_output = check_output(rf"top -b -n{ITERATIONS} -d1 | grep -i '^%cpu'", shell=True).decode('UTF-8')
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 = {} cpu_usage = {}
for value, identifier in findall('([0-9\.\,]{3,5}) ([a-z]{2})', top_output): for value, identifier in findall(r'([0-9\.\,]{3,5}) ([a-z]{2})', top_output):
cpu_usage[identifier] = float(value.replace(',', '.')) 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))
warn = set() warn = set()
crit = set() crit = set()
print(top_output)
# steal # steal
if cpu_usage['st'] > 10: if cpu_usage['st'] > 10:
crit.add('CPU steal is {}% (>10%)'.format(cpu_usage['st'])) crit.add('CPU steal is {}% (>10%)'.format(cpu_usage['st']))

View file

@ -22,7 +22,8 @@ case "$issuer_hash" in
# 462422cf: issuer=C = US, O = Let's Encrypt, CN = E5 # 462422cf: issuer=C = US, O = Let's Encrypt, CN = E5
# 9aad238c: issuer=C = US, O = Let's Encrypt, CN = E6 # 9aad238c: issuer=C = US, O = Let's Encrypt, CN = E6
# 31dfb39d: issuer=C = US, O = Let's Encrypt, CN = R11 # 31dfb39d: issuer=C = US, O = Let's Encrypt, CN = R11
4f06f81d|8d33f237|462422cf|9aad238c|31dfb39d) # aa578057: issuer=C = US, O = Let's Encrypt, CN = R10
4f06f81d|8d33f237|462422cf|9aad238c|31dfb39d|aa578057)
warn_days=10 warn_days=10
crit_days=3 crit_days=3
;; ;;

View file

@ -19,6 +19,8 @@ defaults = {
'services': { 'services': {
'CPU': { 'CPU': {
'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_cpu_stats', 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_cpu_stats',
# takes samples over 10 seconds
'vars.sshmon_timeout': 20
}, },
'LOAD': { 'LOAD': {
'command_on_monitored_host': '/usr/lib/nagios/plugins/check_load -r -w 4,2,1 -c 8,4,2', 'command_on_monitored_host': '/usr/lib/nagios/plugins/check_load -r -w 4,2,1 -c 8,4,2',

View file

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

View file

@ -1,30 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.19 (GNU/Linux)
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 ifY/dQmUP37n5XgMADRc
=icbY =O0zm
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----

View file

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

View file

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

View file

@ -1,6 +1,7 @@
from bundlewrap.utils.ui import io
from bundlewrap.utils.scm import get_rev from bundlewrap.utils.scm import get_rev
from bundlewrap.utils.text import red, bold from bundlewrap.utils.text import bold, red
from bundlewrap.utils.ui import io
@node_attribute @node_attribute
def needs_apply(node): 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] [metadata.element-web]
url = "chat.franzi.business" url = "chat.franzi.business"
version = "v1.11.77" version = "v1.11.85"
[metadata.element-web.config] [metadata.element-web.config]
default_server_config.'m.homeserver'.base_url = "https://matrix.franzi.business" default_server_config.'m.homeserver'.base_url = "https://matrix.franzi.business"
default_server_config.'m.homeserver'.server_name = "franzi.business" default_server_config.'m.homeserver'.server_name = "franzi.business"
@ -49,8 +49,8 @@ defaultCountryCode = "DE"
jitsi.preferredDomain = "meet.ffmuc.net" jitsi.preferredDomain = "meet.ffmuc.net"
[metadata.forgejo] [metadata.forgejo]
version = "8.0.3" version = "9.0.2"
sha1 = "a19aa24f26c1ff5a38cf12619b6a6064242d0cf2" sha1 = "5aecc64f93e8ef05c6d6f83d4b647bdb2c831d9f"
domain = "git.franzi.business" domain = "git.franzi.business"
enable_git_hooks = true enable_git_hooks = true
install_ssh_key = true install_ssh_key = true
@ -90,7 +90,7 @@ user_id = "@dimension:franzi.business"
admin_contact = "mailto:hostmaster@kunbox.net" admin_contact = "mailto:hostmaster@kunbox.net"
baseurl = "matrix.franzi.business" baseurl = "matrix.franzi.business"
server_name = "franzi.business" server_name = "franzi.business"
trusted_key_servers = ["matrix.org", "finallycoffee.eu"] trusted_key_servers = ["matrix.org", "161.rocks"]
additional_client_config.'im.vector.riot.jitsi'.preferredDomain = "meet.ffmuc.net" additional_client_config.'im.vector.riot.jitsi'.preferredDomain = "meet.ffmuc.net"
wellknown_also_on_vhosts = ["franzi.business"] wellknown_also_on_vhosts = ["franzi.business"]
[metadata.matrix-synapse.sliding_sync] [metadata.matrix-synapse.sliding_sync]
@ -114,8 +114,8 @@ provisioning.shared_secret = "!decrypt:encrypt$gAAAAABfVKflEMAi07C_QGP8cy97hF-4g
"'@kunsi:franzi.business'" = "admin" "'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp] [metadata.mautrix-whatsapp]
version = "v0.10.9" version = "v0.11.1"
sha1 = "1619579ec6b9fca84fec085a94842d309d3f730c" sha1 = "ada2dc6acfd5cb15fae341266b383d3f6e8b42bd"
permissions."'@kunsi:franzi.business'" = "admin" permissions."'@kunsi:franzi.business'" = "admin"
[metadata.mautrix-whatsapp.homeserver] [metadata.mautrix-whatsapp.homeserver]
domain = "franzi.business" domain = "franzi.business"
@ -126,7 +126,7 @@ domain = "rss.franzi.business"
[metadata.netbox] [metadata.netbox]
domain = "netbox.franzi.business" domain = "netbox.franzi.business"
version = "v4.1.1" version = "v4.1.6"
admins.kunsi = "hostmaster@kunbox.net" admins.kunsi = "hostmaster@kunbox.net"
[metadata.nextcloud] [metadata.nextcloud]
@ -136,6 +136,10 @@ domain = "warnochwas.de"
contact = "mailto:security@kunsmann.eu" contact = "mailto:security@kunsmann.eu"
Encryption = "https://franzi.business/gpg_hi-kunsmann.eu.asc" 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] [metadata.nginx.vhosts.forgejo]
domain_aliases = ["git.kunsmann.eu"] domain_aliases = ["git.kunsmann.eu"]
@ -148,8 +152,10 @@ owner = "skye"
[metadata.nginx.vhosts.kunsitracker] [metadata.nginx.vhosts.kunsitracker]
domain = "kunsitracker.de" domain = "kunsitracker.de"
locations.'/'.redirect = "https://travelynx.franzi.business/p/Kunsi" locations.'/'.target = "https://travelynx.franzi.business/"
locations.'/'.mode = 302 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] [metadata.nginx.vhosts.mta-sts]
domain = "mta-sts.kunbox.net" domain = "mta-sts.kunbox.net"
@ -251,12 +257,12 @@ dkim = "uO4aNejDvVdw8BKne3KJIqAvCQMJ0416"
[metadata.smartd] [metadata.smartd]
disks = [ disks = [
"/dev/nvme0", "/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NF0W508470",
"/dev/nvme1", "/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NX0W114380",
] ]
[metadata.travelynx] [metadata.travelynx]
version = "2.8.38" version = "2.8.40"
mail_from = "travelynx@franzi.business" mail_from = "travelynx@franzi.business"
domain = "travelynx.franzi.business" domain = "travelynx.franzi.business"

View file

@ -22,13 +22,7 @@ ram = 2
[metadata.homeassistant] [metadata.homeassistant]
domain = 'hass.home.kunbox.net' domain = 'hass.home.kunbox.net'
api_secret = 'encrypt$gAAAAABjpyuqXLoilokQW5c0zV8shHcOzN1zkEbS-I6WAAX-xDO_OF33YbjbkpELU2HGBzqiWX40J0hsaEbYJOnCHFk8gJ-Xt0vdqqbQ5vca_TGPNQHZPAS4qZoPTcUhmX_I-0EdT6ukhxejXFYBiYRZikTLjH3lcNM5qnckCm-H9NbRdjLb9hbCDIjbEglHmBl_g08S1_ukvX3dDSCIHIxgXXGsdK_Go1KxPJd8G22FL_MMhCfsTW-6ioIqoHSeSA1NGk3MZHEIM2errckiopKBxoBaROsacO9Uqk1zrrgXOs2NsgiTRtrbV1TNlFVaIX9mZdsUnMGZ' api_secret = '!decrypt:encrypt$gAAAAABm9lNg_mNhyzb4S6WRtVRDmQFBnPpoCwyqMnilRrAFUXc-EDvv-nYXPbSIbjTf7ZReTPtqr8k3WrGPqiuqhJ60LVv4A5DMqT5c6hTVr4WbhP4DPEIPgfd5aq6U9_-H9WDyQYHKjnunLJEYtEREzmhTq3XsYeQ05DyE7hfnQ-zVoBb0CsAK7GdhihRTdvhXv2N9M04_rigyBP-roRcUgCqwyHuWJc0IPAyn3R4Mr43ZqgR2fn6dNV_YUVKn9c0nWxIwRnYy6Ff_Te9NoGVmXxkiNUX-90bBLKFiCzrRAtizxrTiQb2SRipaWbgOlV6wbMy2KNux'
[metadata.nginx]
restrict-to = [
'172.19.136.0/25',
'172.19.138.0/24',
]
[metadata.pyenv] [metadata.pyenv]
version = 'v2.3.36' version = 'v2.3.36'

9
nodes/home.mixer96.toml Normal file
View file

@ -0,0 +1,9 @@
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,9 +1,15 @@
hostname = "172.19.138.22" hostname = "172.19.138.22"
groups = ["debian-bookworm"] groups = ["debian-bookworm"]
bundles = ["docker-engine", "nginx", "redis"]
[metadata] [metadata]
icinga_options.exclude_from_monitoring = true 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] [metadata.interfaces.eno3]
ips = [ ips = [
"172.19.138.22/24", "172.19.138.22/24",
@ -11,7 +17,7 @@ ips = [
gateway4 = "172.19.138.1" gateway4 = "172.19.138.1"
ipv6_accept_ra = true ipv6_accept_ra = true
[metadata.nftable.forward] [metadata.nftables.forward]
50-local-forward = [ 50-local-forward = [
'ct state { related, established } accept', 'ct state { related, established } accept',
'iifname eno3 accept', 'iifname eno3 accept',

View file

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

View file

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

View file

@ -1,100 +0,0 @@
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

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

View file

@ -1,5 +1,6 @@
hostname = "2a01:4f9:6b:2d99::c0ff:ee" hostname = "2a01:4f9:6b:2d99::c0ff:ee"
dummy = true #dummy = true
bundles = ["sshmon", "smartd"]
# How to install: # How to install:
# - Get server at Hetzner (no IPv4) # - Get server at Hetzner (no IPv4)
@ -17,3 +18,11 @@ dummy = true
# - IPv6 only # - IPv6 only
# - IP from the /64 hetzner gives us # - IP from the /64 hetzner gives us
# - Gateway is the host itself, to work around the MAC filter hetzner uses # - 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,16 +97,15 @@ nodes['kunsi-p14s'] = {
'xf86-video-amdgpu': {}, 'xf86-video-amdgpu': {},
# all that other random stuff one needs # all that other random stuff one needs
'abcde': {}, #'abcde': {},
'apachedirectorystudio': {},
'claws-mail': {}, 'claws-mail': {},
'claws-mail-themes': {}, 'claws-mail-themes': {},
'ferdium-bin': {}, 'ferdium-bin': {},
'gumbo-parser': {}, # for claws litehtml 'gumbo-parser': {}, # for claws litehtml
'inkstitch': {}, # for RZL embroidery machine 'inkstitch': {}, # for RZL embroidery machine
'obs-studio': {}, 'obs-studio': {},
'perl-musicbrainz-discid': {}, # for abcde #'perl-musicbrainz-discid': {}, # for abcde
'perl-webservice-musicbrainz': {}, # for abcde #'perl-webservice-musicbrainz': {}, # for abcde
'sdl_ttf': {}, # for compiling testcard 'sdl_ttf': {}, # for compiling testcard
'x32edit': {}, 'x32edit': {},
}, },

View file

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

View file

@ -0,0 +1,61 @@
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

@ -62,7 +62,7 @@ nodes['htz-cloud.miniserver'] = {
}, },
'element-web': { 'element-web': {
'url': 'chat.sophies-kitchen.eu', 'url': 'chat.sophies-kitchen.eu',
'version': 'v1.11.72', 'version': 'v1.11.76',
'config': { 'config': {
'default_server_config': { 'default_server_config': {
'm.homeserver': { 'm.homeserver': {
@ -117,6 +117,7 @@ nodes['htz-cloud.miniserver'] = {
'sophies-kitchen.eu': { 'sophies-kitchen.eu': {
'domain': 'http://[::1]:20080/', 'domain': 'http://[::1]:20080/',
'api': 'synapse', 'api': 'synapse',
'signing_key_path': "/etc/matrix-synapse/mmr.signing.key"
}, },
}, },
'admins': { 'admins': {

View file

@ -1,12 +1,12 @@
nodes['voc.infobeamer-cms'] = { nodes['voc.infobeamer-cms'] = {
'hostname': 'infobeamer-cms.c3voc.de', 'hostname': 'infobeamer.c3voc.de',
'bundles': { 'bundles': {
'infobeamer-cms', 'infobeamer-cms',
'infobeamer-monitor', 'infobeamer-monitor',
'redis', 'redis',
}, },
'groups': { 'groups': {
'debian-bullseye', 'debian-bookworm',
'webserver', 'webserver',
}, },
'metadata': { 'metadata': {
@ -25,7 +25,7 @@ nodes['voc.infobeamer-cms'] = {
}, },
'infobeamer-cms': { 'infobeamer-cms': {
'domain': 'infobeamer.c3voc.de', 'domain': 'infobeamer.c3voc.de',
'event_start_date': '2024-05-29', 'event_start_date': '2024-12-26',
'event_duration_days': 5, 'event_duration_days': 5,
'config': { 'config': {
'ADMIN_USERS': [ 'ADMIN_USERS': [
@ -34,18 +34,14 @@ nodes['voc.infobeamer-cms'] = {
'jwacalex', 'jwacalex',
'kunsi', 'kunsi',
'sophieschi', 'sophieschi',
'v0tti',
], ],
'GITHUB_CLIENT_ID': vault.decrypt('encrypt$gAAAAABiNwHfIu9PYFfJrF7qirn_9vdvvUlEhJnadoNSS5XlCDbI_aMyj21_ZYQxaCkc6_eVX6Cj1jEHZ7Vs6wM-XyQdW0nUOahtqG4uvnYCiM3GFKHW_wQ='), 'GITHUB_CLIENT_ID': vault.decrypt('encrypt$gAAAAABiNwHfIu9PYFfJrF7qirn_9vdvvUlEhJnadoNSS5XlCDbI_aMyj21_ZYQxaCkc6_eVX6Cj1jEHZ7Vs6wM-XyQdW0nUOahtqG4uvnYCiM3GFKHW_wQ='),
'GITHUB_CLIENT_SECRET': vault.decrypt('encrypt$gAAAAABiNwHtdZC2XQ8IjosL7vsmrxZMwDIM6AD5dUlLo996tJs4qV7KJETHgYYZil2aMzClwhcE6JmxdhARRp7IJQ4rQQibelTNmyYSzj_V4puVpvma7SU0UZkTIG95SdPpoHY--Zba'), 'GITHUB_CLIENT_SECRET': vault.decrypt('encrypt$gAAAAABiNwHtdZC2XQ8IjosL7vsmrxZMwDIM6AD5dUlLo996tJs4qV7KJETHgYYZil2aMzClwhcE6JmxdhARRp7IJQ4rQQibelTNmyYSzj_V4puVpvma7SU0UZkTIG95SdPpoHY--Zba'),
'HOSTED_API_KEY': vault.decrypt('encrypt$gAAAAABhxJPH2sIGMAibU2Us1HoCVlNfF0SQQnVl0eiod48Zu8webL_-xk3wDw3yXw1Hkglj-2usl-D3Yd095yTSq0vZMCv2fh-JWwSPdJewQ45x9Ai4vXVD4CNz5vuJBESKS9xQWXTc'), 'HOSTED_API_KEY': vault.decrypt('encrypt$gAAAAABhxJPH2sIGMAibU2Us1HoCVlNfF0SQQnVl0eiod48Zu8webL_-xk3wDw3yXw1Hkglj-2usl-D3Yd095yTSq0vZMCv2fh-JWwSPdJewQ45x9Ai4vXVD4CNz5vuJBESKS9xQWXTc'),
'INTERRUPT_KEY': vault.human_password_for('infobeamer-cms interrupt key'), 'INTERRUPT_KEY': vault.human_password_for('infobeamer-cms interrupt key 38c3', words=1),
'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': [ 'SETUP_IDS': [
250294, 253559,
], ],
# 'EXTRA_ASSETS': [{ # 'EXTRA_ASSETS': [{
# 'type': "image", # 'type': "image",
@ -56,17 +52,35 @@ nodes['voc.infobeamer-cms'] = {
# 'x2': 110, # 'x2': 110,
# 'y2': 1070, # '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': { 'rooms': {
'Saal 1': 34430, # 'Saal 1': 34430,
'Saal G': 26598, # 'Saal G': 26598,
'Saal Z': 26610, # 'Saal Z': 26610,
'Saal E (SoS/Lightning-Talks)': 32814, # 'Saal E (SoS/Lightning-Talks)': 32814,
'Saal F (Sendezentrum/DLF)': 9717, # 'Saal F (Sendezentrum/DLF)': 9717,
}, },
'interrupts': { 'interrupts': {
'Questions': 'questions', # 'Questions': 'questions',
'Translations': 'translations', # 'Translations': 'translations',
}, },
}, },
'infobeamer-monitor': { 'infobeamer-monitor': {

View file

@ -49,14 +49,15 @@ nodes['voc.pretalx'] = {
}, },
}, },
'pretalx': { 'pretalx': {
'version': 'v2024.2.1', # 2023.3.1 with some bugfixes
'version': '05e377398cecdd45d3ca6013040c5857bbe225d6',
'domain': 'pretalx.c3voc.de', 'domain': 'pretalx.c3voc.de',
'mail_from': 'pretalx@c3voc.de', 'mail_from': 'pretalx@c3voc.de',
'administrators-from-group-id': 1, 'administrators-from-group-id': 1,
'plugins': { 'plugins': {
'broadcast_tools': { 'broadcast_tools': {
'repo': 'https://github.com/Kunsi/pretalx-plugin-broadcast-tools.git', 'repo': 'https://github.com/Kunsi/pretalx-plugin-broadcast-tools.git',
'rev': 'main', 'rev': '2.4.0',
}, },
'downstream': { 'downstream': {
'repo': 'https://github.com/pretalx/pretalx-downstream.git', 'repo': 'https://github.com/pretalx/pretalx-downstream.git',
@ -64,7 +65,7 @@ nodes['voc.pretalx'] = {
}, },
'halfnarp': { 'halfnarp': {
'repo': 'https://github.com/seibert-media/pretalx-halfnarp.git', 'repo': 'https://github.com/seibert-media/pretalx-halfnarp.git',
'rev': '1.1.0', 'rev': '1.1.2',
}, },
'media.ccc.de': { 'media.ccc.de': {
'repo': 'https://github.com/pretalx/pretalx-media-ccc-de.git', 'repo': 'https://github.com/pretalx/pretalx-media-ccc-de.git',
@ -81,6 +82,6 @@ nodes['voc.pretalx'] = {
}, },
}, },
'os': 'debian', 'os': 'debian',
'os_version': (11,), 'os_version': (12,),
'pip_command': 'pip3', 'pip_command': 'pip3',
} }