Compare commits

...

287 commits

Author SHA1 Message Date
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
0d28883da3 fix name of backup server 2024-09-19 22:55:15 +02:00
Sophie Schiller
8980c05c74 new wildcard for sophie's home infra 2024-09-19 22:52:01 +02:00
9415b281ce
update travelynx to 2.8.38 2024-09-15 13:33:23 +02:00
64fb1906d1
htz-hel.backup-kunsi: move scrub to wednesday 2024-09-15 10:27:08 +02:00
ce76b03fe7
bundles/zfs: configurable scrub time 2024-09-15 10:26:51 +02:00
a712c098c6
update netbox to 4.1.1 2024-09-14 18:32:39 +02:00
ec834f2a92
update element-web to 1.11.77 2024-09-14 18:32:27 +02:00
aa30b78fcf
remove daisy 2024-09-14 18:29:55 +02:00
be3a7a44d6
home.nas: new ssd-based pool 2024-09-12 19:58:15 +02:00
2e72f107e9
update paperles to 2.12.0 2024-09-10 06:15:48 +02:00
07f6fb99f2
bundles/backup-server: more time for monitoring please 2024-09-10 06:14:55 +02:00
3f9f84f230
home.paperless: add proftpd for paperless ingest 2024-09-08 19:42:27 +02:00
40fcaf56ee
add home.fujitsu-n7100 2024-09-08 19:42:15 +02:00
06a94d7cba
home.nas: clean up nodefile 2024-09-08 17:19:13 +02:00
6483f863ff
bundles/rsyslogd: add backups 2024-09-08 17:19:03 +02:00
3a52cf55c4
remove bundle:scansnap 2024-09-08 17:17:25 +02:00
455c5c5ce5
update as3320 and as8881 2024-09-07 13:01:37 +02:00
5e55dc6fb9
update forgejo to 8.0.3 2024-09-07 09:09:03 +02:00
d5881da154
fix sophie backup locations 2024-09-07 09:07:40 +02: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
9f1dc01d6b
bundles/arch-with-gui: s/rfkill/util-linux/ 2024-09-04 20:02:18 +02:00
a7baf225ff
kunsi-p14s: s/ferdi/ferdium/ 2024-09-04 20:00:54 +02:00
331d363a45
bump _.home.kunbox.net 2024-09-04 19:04:47 +02:00
3f02f7b8f5
bundles/icinga2: ignore lines starting with ;; in check_spam_blocklist 2024-09-04 18:56:48 +02:00
b73ac2b7ce
update paperless to 2.11.6 2024-09-04 18:54:18 +02:00
41b76aec9c
update forgejo to 8.0.2 2024-09-04 18:52:10 +02:00
2b5a76ffb0
update netbox to 4.1.0 2024-09-04 18:50:58 +02:00
319dc8ad21
icinga: fix logic error, do not send sms for service problems 2024-09-03 21:09:17 +02:00
bfbbffe22c
home.r630: allow forwarding traffic
So i can actually reach the docker containers running on there
2024-08-31 19:12:05 +02:00
23fb2aba1c
home.nas: add br1139 2024-08-31 13:14:24 +02:00
3d86923e9e
update travelynx to 2.8.35 2024-08-28 15:42:07 +02:00
2fbf122660
update netbox to 4.0.9 2024-08-28 15:41:54 +02:00
4234070514
update element-web to 1.11.76 2024-08-28 15:41:39 +02:00
13bae5c993
bundles/samba: fix typo 2024-08-23 19:47:19 +02:00
aff1329122
add rottenraptor devices 2024-08-23 19:43:27 +02:00
82aeeb585d
add samba share for music on nas 2024-08-23 19:43:04 +02:00
e8983829ed
bundles/infobeamer-monitor: fix maintenance warnings 2024-08-16 14:35:33 +02:00
10b1fb8a5b
remove legacy nodes 2024-08-12 19:39:57 +02:00
c66bc8b5eb
add home.{appletv-wohnzimmer,encoder96} 2024-08-12 19:36:32 +02:00
422303ee5b update pretalx to 2024.2.1 2024-08-10 19:14:57 +02:00
c48e11d787 update paperless to 2.11.4 2024-08-10 19:14:57 +02:00
a8678fc01b update netbox to 4.0.8 2024-08-10 19:14:57 +02:00
6fe0598032 update matrix-media-repo to 1.3.7 2024-08-10 19:14:57 +02:00
6fb8d81159 carlene: fix network config
Apparently, the DC technicians are unable to plug in a server into the
correct network ports after changing disks ...
2024-08-10 19:14:57 +02:00
e4eb00bdbe update forgejo to 8.0.1 2024-08-10 19:14:57 +02:00
94e56fd92d update element-web to 1.11.73 2024-08-10 19:14:57 +02:00
01a8d7a6db add bundle:sdm630_mqtt 2024-08-10 19:14:57 +02:00
f0ebed5dba bundles/sshmon: yet another letsencrypt hash 2024-08-10 19:14:57 +02:00
30cf20c28d bundles/c3voc-addons: add action:apt_execute_update_commands 2024-08-10 19:14:57 +02:00
5af7b92663 bw/data/apt: grafana changed their gpg key 2024-08-10 19:14:57 +02:00
5a1e37a41c bundles/systemd-networkd: remove networkmanager 2024-08-10 19:14:57 +02:00
a1eb9cb3fc bundles/telegraf: add option to opt-out of default metrics 2024-08-10 19:14:57 +02:00
6854bd55ff Merge pull request 'update-miniserver' (#70) from update-miniserver into main
Reviewed-on: #70
2024-08-09 01:00:17 +00:00
Sophie Schiller
fb70a068d8 nodejs: deb-src no longer available 2024-08-09 02:59:52 +02:00
Sophie Schiller
6fa3abc217 hedgedoc: fix install needs 2024-08-09 02:59:52 +02:00
Sophie Schiller
7fd248af8d version bumps on miniserver 2024-08-09 02:59:52 +02:00
98d2bb3942 Merge pull request 'vmhost: document interface change' (#69) from vmhostumzug into main
Reviewed-on: #69
2024-08-09 00:58:34 +00:00
Sophie Schiller
89000c12e6 vmhost: document interface change 2024-08-09 00:56:40 +00:00
fa47322bb0
bundles/raspberrypi: fix config.txt for lcd display 2024-07-31 15:30:48 +02:00
de6073bdcf
bundles/apt: add option to disable unattended upgrades 2024-07-31 14:53:22 +02:00
7649396b8a
bundles/mosquitto: only install telegraf plugin if we have telegraf 2024-07-30 17:55:03 +02:00
b1790ece35
bundles/apt: 32bit raspbian is no longer supported 2024-07-30 17:45:05 +02:00
242279636f
bundles/raspberrypi: things have changed since buster 2024-07-30 17:44:09 +02:00
95bb7c52fe
bundles/apt: add bissing default for update commands 2024-07-22 21:31:27 +02:00
2a8c1ef84b
update mautrix-whatsapp to 0.10.9 2024-07-19 19:22:05 +02:00
c1fc942b1d
update mautrix-telegram to 0.15.2 2024-07-19 19:21:50 +02:00
c4bf96482f
update element-web to 1.11.71 2024-07-19 19:21:37 +02:00
69691f75c5
data/apt: new gpg key for nodesource 2024-07-19 19:20:40 +02:00
263440296d
bundles: no default for nodejs version anymore 2024-07-19 19:20:23 +02:00
55a3e6675f
bundles/nodejs: everything changed, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 2024-07-19 19:19:45 +02:00
350c436e4d
bundles/apt: add action to execute additional_update_commands 2024-07-19 19:19:14 +02:00
205fea377a
update paperless to 2.11.0 2024-07-12 19:06:55 +02:00
fb46d81f97
update netbox to 4.0.7 2024-07-12 19:06:43 +02:00
466a620bca
update element-web to 1.11.70 2024-07-12 19:06:28 +02:00
04094df418
update matrix-media-repo to 1.3.6 2024-07-12 18:46:10 +02:00
c348953611
bundles/sshmon: even more letsencrypt shenanigans 2024-07-12 18:45:43 +02:00
e4dfd17bb6
bundles/matrix-media-repo: has live config reload 2024-07-12 18:42:31 +02:00
08f2c46c31
bundles/matrix-synapse: media-repo needs more paths now 2024-07-12 18:39:09 +02:00
b2028855d1
bundles/sshmon: new issuer hash for letsencrypt 2024-07-12 18:24:27 +02:00
a472ca4657
bw/bundles/matrix-media-repo: adjust config for 1.3.6 2024-07-12 18:20:53 +02:00
d08e9f12ab
add icinga_options.also_affected_by to systems running in vm on home.nas 2024-07-12 18:13:43 +02:00
2fddd57ed8
bundles/backup-client: only log to logfile when not running in debug mode 2024-07-07 10:23:20 +02:00
5a86e657ff
bundles/mixcloud-downloader: add login via netrc 2024-07-07 10:22:26 +02:00
52b68d6e42
home.nas: clean up smartd config 2024-07-06 10:59:46 +02:00
fbe2197055
add home.r630 2024-07-06 10:56:13 +02:00
ced6479b8e
home.nas: clean up zfs datasets 2024-07-06 09:49:22 +02:00
6e677a7a0b
update paperless-ngx to 2.10.2 2024-07-06 09:45:41 +02:00
c0b3db55ec
update travelynx to 2.7.7 2024-07-06 09:45:18 +02:00
fc4aaf4abb
update netbox to 4.0.6 2024-07-06 09:44:57 +02:00
ce44926920
update forgejo to 7.0.5 2024-07-06 09:44:41 +02:00
4736e3b281
update travelynx to 2.7.6 2024-07-04 11:43:43 +02:00
b3ab18a32c
bundles/nginx: don't cache stuff when running through php 2024-07-01 17:17:30 +02:00
79bb4169a7
ns-mephisto: new ip config 2024-07-01 11:34:36 +02:00
101928339f
bundles/powerdns: fix SyntaxWarning 2024-06-26 07:11:44 +02:00
67198c5fd9
bundles/grafana: needs websockets 2024-06-25 17:32:24 +02:00
791eb8d1a9
bump netbox-dump 2024-06-25 17:10:32 +02:00
0ce0e34382 Merge pull request 'sophiesheomenetwork' (#68) from sophiesheomenetwork into main
Reviewed-on: #68
2024-06-23 12:54:01 +00:00
668ae0432b
htz-hel.backup-kunsi: remove backup target for kunsi-t470 2024-06-23 14:52:09 +02:00
b72d82b894
bundles/routeros: this does not need to be a metadata reactor 2024-06-22 20:39:04 +02:00
d1f182607d
rework netbox-dump script and routeros bundle for better usability 2024-06-22 20:04:51 +02:00
Sophie Schiller
9be31b8850 homeassistant: use correct network interface 2024-06-22 00:51:33 +02:00
Sophie Schiller
182cdada22 homeassistant metadata reshuffle 2024-06-21 21:25:48 +02:00
Sophie Schiller
2c51caa524 update nginx signing key 2024-06-21 20:58:17 +02:00
Sophie Schiller
263301b265 add homeassistant in sophies home 2024-06-21 20:32:06 +02:00
Sophie Schiller
2f4b90c147 miniserver: element update 2024-06-21 19:32:43 +02:00
Sophie Schiller
e5c5672554 add vmhost for sophies home 2024-06-21 19:32:28 +02:00
c47b412cf3
update forgejo to 7.0.4 2024-06-18 20:43:55 +02:00
cda7e3b7fd
update paperless to 2.10.0 2024-06-18 20:43:41 +02:00
e876d39002
update netbox to 4.0.5 2024-06-18 20:43:25 +02:00
b9583d9a64
update element-web to 1.11.69 2024-06-18 20:43:10 +02:00
60a0737187
bundles/jellyfin: fix firewall defaults 2024-06-18 20:40:09 +02:00
52c093427f
ssl: bump _.home.kunbox.net 2024-06-11 17:42:43 +02:00
Sophie Schiller
658acbd12b rechenmonster: add dataset 2024-06-09 10:21:08 +02:00
56df06e981
clean up some nodefiles 2024-06-08 18:50:55 +02:00
d1e28c3f0c
sophie gets her own group 2024-06-08 18:46:51 +02:00
Sophie Schiller
1c2127437c voc.infobeamer-cms: gpn22 2024-05-30 21:44:07 +02:00
Sophie Schiller
768ae0a37a htz-cloud.miniserver: backlinks to social media 2024-05-29 00:02:29 +02:00
bebc603c43
update paperless-ngx to 2.8.6 2024-05-24 17:07:21 +02:00
43fe831395
update netbox to 4.0.3 2024-05-24 17:07:10 +02:00
5b8784e916
update forgejo to 7.0.3 2024-05-24 17:06:53 +02:00
ea21e4b119
update element-web to 1.11.67 2024-05-24 17:06:38 +02:00
a6c1d67b55
remove entropia-jira 2024-05-24 17:03:18 +02:00
a8ef19f4ff
bundles/icinga2: add check_omm 2024-05-24 15:26:35 +02:00
8c42c9411a
bundles/postfix: fix typo 2024-05-24 15:24:14 +02:00
1dce906b3d
bundles/netbox: reindex must be lazy 2024-05-12 19:46:07 +02:00
5c1ff593e1
carlene: add kunsitracker.de 2024-05-12 19:43:07 +02:00
fd1cbcfd50
update paperless to 2.8.3 2024-05-12 19:42:54 +02:00
799f275e4e
update netbox to 4.0.1 2024-05-12 19:42:42 +02:00
cf82ed5dd3
update element-web to 1.11.66 2024-05-12 19:42:24 +02:00
88fce3405e
bundles/netbox: fix f-string 2024-05-12 19:42:04 +02:00
a17833698d
bundles/apt: run autoremove first, then clean cached packages 2024-05-12 19:36:31 +02:00
c806d7b890
bundles/netbox: rework 2024-05-05 16:49:42 +02:00
a8da2aef44
update netbox to 3.7.7 2024-05-05 16:18:27 +02:00
cc9c127296
update forgejo to 7.0.2 2024-05-05 16:18:13 +02:00
35331f5f4c
update ssl configuration of some bundles 2024-05-05 15:49:45 +02:00
dd32ed075b
remove kunsi-p14s 2024-05-04 10:18:18 +02:00
c9b393c6dc
update travelynx to 2.6.9 2024-04-28 21:40:46 +02:00
9e78b9e07b
python3.12 compat 2024-04-28 21:40:35 +02:00
65af9ae0c5
update netbox to 3.7.6 2024-04-28 20:57:44 +02:00
516a543719
update forgejo to 7.0.1 2024-04-28 20:57:31 +02:00
dbf17424d2
update element-web to 1.11.65 2024-04-28 20:57:14 +02:00
09e59af95f
bundles/nginx: listen ... http2; is deprecated 2024-04-24 23:04:06 +02:00
610c1d0978
update forgejo to 1.21.11-1 2024-04-20 18:35:00 +02:00
0bfcd8df45
update travelynx to 2.6.7 2024-04-20 18:31:44 +02:00
27cb0cb0df
update mautrix-whatsapp to 0.10.7 2024-04-20 18:31:30 +02:00
d02d26cb5e
update forgejo to 1.21.11-1 2024-04-20 18:31:13 +02:00
bbc69dfd25
bundles/icinga2: re-add statusmonitor 2024-04-20 18:30:39 +02:00
e64ae3aef7
bundles/icinga2: run check_mounts check as well 2024-04-17 06:42:58 +02:00
1ec545e080
update element-web to 1.11.64 2024-04-17 06:33:37 +02:00
7491ec840c
bundles/dovecot: add full text indexing 2024-04-14 12:17:44 +02:00
a155fe22cb
Revert "home.router: disable pppd restart at night"
This reverts commit 493dc91e0d.
2024-04-14 10:09:08 +02:00
0f9222424e
dns/kunbox.net: add htz-cloud.pirmasens to SPF 2024-04-13 11:05:18 +02:00
6be9fb3614
bundles/pacman: 'dnsutils' is now part of 'bind' 2024-04-09 06:09:03 +02:00
ab61444a1f
bundles/letsencrypt: do not monitor renew timer 2024-04-09 06:06:29 +02:00
f8b833720a
bundles/systemd-timers: better exclude_from_monitoring support 2024-04-09 06:06:02 +02:00
33ae4796d4
update paperless to 2.7.2 2024-04-09 06:03:11 +02:00
8f09170b44
update travelynx to 2.6.5 2024-04-09 06:01:01 +02:00
a6e7359ec0
update netbox to 3.7.5 2024-04-09 06:00:42 +02:00
128ac48fd6
update forgejo to 1.21.10-0 2024-04-09 06:00:23 +02:00
4a44ae1048
kunbox.net: fix tlsrpt address 2024-04-09 06:00:05 +02:00
ed05a74f56
update travelynx to 2.6.4 2024-04-03 17:27:40 +02:00
896781e53d
update travelynx to 2.6.3 2024-04-02 21:54:31 +02:00
c0c83338ad
bundles/icinga2: do not send out URGENT for recovery messages 2024-04-02 15:06:52 +02:00
b028c20758
update element-web to 1.11.63 2024-03-31 13:47:53 +02:00
efeee3fa62
update travelynx to 2.5.23 2024-03-31 13:47:15 +02:00
139d5ff948
htz-cloud.wireguard: actually allow wg.c3voc.de to connect 2024-03-31 12:45:26 +02:00
df8955fa35
bundles/infobeamer-monitor: better state dump output 2024-03-25 14:54:59 +01:00
713f7e02d8
update forgejo to 1.21.8-0 2024-03-24 09:06:48 +01:00
272bccf42d
update paperless-ngx to 2.6.3 2024-03-23 12:19:24 +01:00
a3d582c2c5
update travelynx to 2.5.21 2024-03-23 12:19:10 +01:00
cad026c1ef
update mautrix-whatsapp to 0.10.6 2024-03-23 12:18:49 +01:00
a027faa8ca
fix tests 2024-03-23 10:35:02 +01:00
773e8d118f
add repo.libs.faults.dict_as_toml 2024-03-23 10:34:41 +01:00
1d5bcf74c0
remove bundle:openvpn-client 2024-03-23 10:27:30 +01:00
9b4a473236
htz-cloud.wireguard: add c3voc vpn connection 2024-03-23 10:19:56 +01:00
aa0d4e5a76
kunsi-p14s: set correct ip 2024-03-23 10:19:35 +01:00
e6f6229b87
bundles/wireguard: do not generate PSKs for unmanaged nodes 2024-03-23 10:19:15 +01:00
104d1f11bf
bundles/wireguard: support s2s connection to other services 2024-03-22 22:52:12 +01:00
ae14265abc
bundles/matrix-synapse: add sliding-sync proxy 2024-03-17 18:40:28 +01:00
a4e51c5d54
home.router: remove dns search domain 2024-03-16 14:49:28 +01:00
6296ab583d
add node attribute for all hosts that don't use letsencrypt ssl certs 2024-03-16 11:04:49 +01:00
f5b87d995b
bump _.home.kunbox.net 2024-03-16 11:01:56 +01:00
abb408c907
carlene: ensure kunsi can write to the franzi.business vhost 2024-03-16 10:51:56 +01:00
bd0cb5e1b4
update element-web to 1.11.61 2024-03-16 10:49:04 +01:00
4c5167fefa
update paperless-ngx to 2.6.2 2024-03-16 10:48:26 +01:00
a344bde87d
update netbox to 3.7.4 2024-03-16 10:48:05 +01:00
1573bdc384
update forgejo to 1.21.7-0 2024-03-16 10:47:37 +01:00
4d92211862
home.hass: use pyenv for homeassistant 2024-03-07 08:23:04 +01:00
ac10630fb9
add bundle:pyenv 2024-03-07 08:15:23 +01:00
6b387c9d11
add dummy htz-cloud.molly-connector 2024-03-06 23:02:18 +01:00
0d362bdb22
EOL htz-cloud.sewfile 2024-03-06 20:06:42 +01:00
e386b44442
bundles/paperless: PLEASE just import my files 2024-03-04 21:23:19 +01:00
dd80579fae
bundles/paperless: add missing dependency 2024-03-04 21:23:00 +01:00
faa30962aa
bundles/paperless: restart please 2024-03-04 21:20:39 +01:00
232e087905
bundles/paperless: please, just import documents 2024-03-04 21:02:19 +01:00
e3d7cae251
net.ipv4.ip_forward -> net.ipv4.conf.all.forwarding 2024-03-03 15:44:31 +01:00
0fa9ef91ae
kunsi-p14s: add dataset for nextcloud client 2024-03-03 13:16:53 +01:00
f5a1a50472
carlene: add sewfile zfs dataset 2024-03-03 12:47:24 +01:00
8d8f457468
bundles/nginx: add mjs to mime types 2024-03-03 12:44:41 +01:00
ffc9c1651c
fix some leftover ULA addressing 2024-02-29 07:40:36 +01:00
b34879d0ca
update element-web to 1.11.59 2024-02-29 07:40:19 +01:00
32e67ff5ec
update paperless to 2.5.4 2024-02-29 07:39:05 +01:00
409a1c900a
remove ULA from remaining home nodes 2024-02-26 19:56:23 +01:00
3749be6144
home.router: remove ipv6-only vlan 2024-02-26 19:54:59 +01:00
c5550bf552
bundles/unbound: add option to disable dns64 even when jool is installed 2024-02-26 19:26:01 +01:00
699c7acf93
bundles/radvd: increase intervals again 2024-02-26 19:25:43 +01:00
79c4dcdf97
Revert "change a bunch of nodes to use their ipv6 address as hostname"
This reverts commit e73dcf16e3.
2024-02-26 19:12:13 +01:00
661d8895dc
home.{downloadhelper,paperless}: add ipv6 unique local addresses 2024-02-26 07:49:02 +01:00
a045e701a6
home.router: add bundle:jool, fix dns 2024-02-26 07:30:50 +01:00
575fe91685
bundles/radvd: fix syntax 2024-02-26 07:27:25 +01:00
12c6b5fc54
add bundle:jool 2024-02-26 07:27:18 +01:00
4514541e8f
bundles/radvd: decrease RDNSS lifetime 2024-02-26 06:41:59 +01:00
0d0548311c
bundles/powerdns: add private ipv6 addresses as well 2024-02-26 06:34:30 +01:00
e73dcf16e3
change a bunch of nodes to use their ipv6 address as hostname 2024-02-26 06:34:23 +01:00
decbcf9bfd
Merge branch 'feature/kunsi-ipv6-only-vlan' 2024-02-26 06:04:58 +01:00
7c9bb42c03
home.switch-rack: new vlan 2024-02-25 20:51:02 +01:00
206 changed files with 3418 additions and 2292 deletions

View file

@ -30,6 +30,7 @@ Rule of thumb: keep ports below 10000 free for stuff that reserves ports.
| 20010 | mautrix-telegram | Bridge | | 20010 | mautrix-telegram | Bridge |
| 20020 | mautrix-whatsapp | Bridge | | 20020 | mautrix-whatsapp | Bridge |
| 20030 | matrix-dimension | Matrix Integrations Manager| | 20030 | matrix-dimension | Matrix Integrations Manager|
| 20070 | matrix-synapse | sliding-sync |
| 20080 | matrix-synapse | client, federation | | 20080 | matrix-synapse | client, federation |
| 20081 | matrix-synapse | prometheus metrics | | 20081 | matrix-synapse | prometheus metrics |
| 20090 | matrix-media-repo | media_repo | | 20090 | matrix-media-repo | media_repo |

View file

@ -6,10 +6,10 @@ apt-get update
DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold dist-upgrade DEBIAN_FRONTEND=noninteractive apt-get -y -q -o Dpkg::Options::=--force-confold dist-upgrade
DEBIAN_FRONTEND=noninteractive apt-get -y -q autoclean
DEBIAN_FRONTEND=noninteractive apt-get -y -q autoremove DEBIAN_FRONTEND=noninteractive apt-get -y -q autoremove
DEBIAN_FRONTEND=noninteractive apt-get -y -q clean
% if clean_old_kernels: % if clean_old_kernels:
existing=$(dpkg --get-selections | grep -E '^linux-(image|headers)-[0-9]' || true) existing=$(dpkg --get-selections | grep -E '^linux-(image|headers)-[0-9]' || true)

View file

@ -1 +0,0 @@
deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi

View file

@ -7,9 +7,6 @@ supported_os = {
12: 'bookworm', 12: 'bookworm',
99: 'unstable', 99: 'unstable',
}, },
'raspbian': {
10: 'buster',
},
} }
try: try:
@ -27,6 +24,10 @@ actions = {
'triggered': True, 'triggered': True,
'cascade_skip': False, 'cascade_skip': False,
}, },
'apt_execute_update_commands': {
'command': ' && '.join(sorted(node.metadata.get('apt/additional_update_commands', {'true'}))),
'triggered': True,
},
} }
files = { files = {

View file

@ -21,6 +21,9 @@ defaults = {
'cron/jobs/upgrade-and-reboot' 'cron/jobs/upgrade-and-reboot'
) )
def patchday(metadata): def patchday(metadata):
if not node.metadata.get('apt/unattended-upgrades/enabled', True):
return {}
day = metadata.get('apt/unattended-upgrades/day') day = metadata.get('apt/unattended-upgrades/day')
hour = metadata.get('apt/unattended-upgrades/hour') hour = metadata.get('apt/unattended-upgrades/hour')

View file

@ -33,7 +33,7 @@ defaults = {
# networking # networking
'avahi': {}, 'avahi': {},
'netctl': {}, 'netctl': {},
'rfkill': {}, 'util-linux': {}, # provides rfkill
'wpa_supplicant': {}, 'wpa_supplicant': {},
'wpa_actiond': {}, 'wpa_actiond': {},

View file

@ -62,10 +62,13 @@ trap "on_exit" EXIT
# redirect stdout and stderr to logfile # redirect stdout and stderr to logfile
prepare_and_cleanup_logdir prepare_and_cleanup_logdir
logfile="$logdir/backup--$(date '+%F--%H-%M-%S')--$$.log.gz" if [[ -z "$DEBUG" ]]
echo "All log output will go to $logfile" | logger -it backup-client then
exec > >(gzip >"$logfile") logfile="$logdir/backup--$(date '+%F--%H-%M-%S')--$$.log.gz"
exec 2>&1 echo "All log output will go to $logfile" | logger -it backup-client
exec > >(gzip >"$logfile")
exec 2>&1
fi
# this is where the real work starts # this is where the real work starts
ts_begin=$(date +%s) ts_begin=$(date +%s)

View file

@ -160,7 +160,7 @@ def monitoring(metadata):
client, client,
config['one_backup_every_hours'], config['one_backup_every_hours'],
), ),
'vars.sshmon_timeout': 20, 'vars.sshmon_timeout': 40,
} }
return { return {

View file

@ -29,6 +29,17 @@ files = {
}, },
} }
if node.has_any_bundle([
'dovecot',
'nginx',
'postfix',
]):
actions['generate-dhparam'] = {
'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048',
'unless': 'test -f /etc/ssl/certs/dhparam.pem',
}
locale_needs = set() locale_needs = set()
for locale in sorted(node.metadata.get('locale/installed')): for locale in sorted(node.metadata.get('locale/installed')):
actions[f'ensure_locale_{locale}_is_enabled'] = { actions[f'ensure_locale_{locale}_is_enabled'] = {
@ -41,11 +52,9 @@ for locale in sorted(node.metadata.get('locale/installed')):
} }
locale_needs = {f'action:ensure_locale_{locale}_is_enabled'} locale_needs = {f'action:ensure_locale_{locale}_is_enabled'}
actions = { actions['locale-gen'] = {
'locale-gen': { 'triggered': True,
'triggered': True, 'command': 'locale-gen',
'command': 'locale-gen',
},
} }
description = [] description = []

View file

@ -24,7 +24,7 @@ defaults = {
}, },
'sysctl': { 'sysctl': {
'options': { 'options': {
'net.ipv4.ip_forward': '1', 'net.ipv4.conf.all.forwarding': '1',
'net.ipv6.conf.all.forwarding': '1', 'net.ipv6.conf.all.forwarding': '1',
}, },
}, },

View file

@ -7,9 +7,6 @@ supported_os = {
12: 'bookworm', 12: 'bookworm',
99: 'unstable', 99: 'unstable',
}, },
'raspbian': {
10: 'buster',
},
} }
try: try:
@ -82,6 +79,10 @@ actions = {
'triggered': True, 'triggered': True,
'cascade_skip': False, 'cascade_skip': False,
}, },
'apt_execute_update_commands': {
'command': ' && '.join(sorted(node.metadata.get('apt/additional_update_commands', {'true'}))),
'triggered': True,
},
} }
directories = { directories = {

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

@ -3,3 +3,4 @@ driver = pgsql
default_pass_scheme = MD5-CRYPT default_pass_scheme = MD5-CRYPT
password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active = true password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active = true
user_query = SELECT '/var/mail/vmail/' || maildir as home, 65534 as uid, 65534 as gid FROM mailbox WHERE username = '%u' AND active = true user_query = SELECT '/var/mail/vmail/' || maildir as home, 65534 as uid, 65534 as gid FROM mailbox WHERE username = '%u' AND active = true
iterate_query = SELECT username as user FROM mailbox WHERE active = true

View file

@ -28,19 +28,19 @@ namespace inbox {
mail_location = maildir:/var/mail/vmail/%d/%n mail_location = maildir:/var/mail/vmail/%d/%n
protocols = imap lmtp sieve protocols = imap lmtp sieve
ssl = yes 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/dovecot/ssl/dhparam.pem ssl_dh = </etc/ssl/certs/dhparam.pem
ssl_min_protocol = TLSv1.2 ssl_min_protocol = TLSv1.2
ssl_cipher_list = EECDH+AESGCM:EDH+AESGCM 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_prefer_server_ciphers = yes ssl_prefer_server_ciphers = no
login_greeting = IMAPd ready login_greeting = IMAPd ready
auth_mechanisms = plain login auth_mechanisms = plain login
first_valid_uid = 65534 first_valid_uid = 65534
disable_plaintext_auth = yes disable_plaintext_auth = yes
mail_plugins = $mail_plugins zlib old_stats mail_plugins = $mail_plugins zlib old_stats fts fts_xapian
plugin { plugin {
zlib_save_level = 6 zlib_save_level = 6
@ -56,6 +56,15 @@ plugin {
old_stats_refresh = 30 secs old_stats_refresh = 30 secs
old_stats_track_cmds = yes old_stats_track_cmds = yes
fts = xapian
fts_xapian = partial=3 full=20
fts_autoindex = yes
fts_enforced = yes
# Index attachements
fts_decoder = decode2text
% if node.has_bundle('rspamd'): % if node.has_bundle('rspamd'):
sieve_before = /var/mail/vmail/sieve/global/spam-global.sieve sieve_before = /var/mail/vmail/sieve/global/spam-global.sieve
@ -86,14 +95,19 @@ service auth {
} }
} }
service lmtp { service decode2text {
unix_listener /var/spool/postfix/private/dovecot-lmtp { executable = script /usr/lib/dovecot/decode2text.sh
group = postfix user = dovecot
mode = 0600 unix_listener decode2text {
user = postfix mode = 0666
} }
} }
service indexer-worker {
vsz_limit = 0
process_limit = 0
}
service imap { service imap {
executable = imap executable = imap
} }
@ -104,6 +118,14 @@ service imap-login {
vsz_limit = 64M vsz_limit = 64M
} }
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
group = postfix
mode = 0600
user = postfix
}
}
service managesieve-login { service managesieve-login {
inet_listener sieve { inet_listener sieve {
port = 4190 port = 4190

View file

@ -2,10 +2,6 @@
# by this bundle # by this bundle
repo.libs.tools.require_bundle(node, 'postfix') repo.libs.tools.require_bundle(node, 'postfix')
directories = {
'/etc/dovecot/ssl': {},
}
files = { files = {
'/etc/dovecot/dovecot.conf': { '/etc/dovecot/dovecot.conf': {
'content_type': 'mako', 'content_type': 'mako',
@ -49,25 +45,17 @@ files = {
}, },
} }
actions = { symlinks['/usr/lib/dovecot/decode2text.sh'] = {
'dovecot_generate_dhparam': { 'target': '/usr/share/doc/dovecot-core/examples/decode2text.sh',
'command': 'openssl dhparam -out /etc/dovecot/ssl/dhparam.pem 2048', 'before': {
'unless': 'test -f /etc/dovecot/ssl/dhparam.pem', 'svc_systemd:dovecot',
'cascade_skip': False,
'needs': {
'directory:/etc/dovecot/ssl',
'pkg_apt:'
},
'triggers': {
'svc_systemd:dovecot:restart',
},
}, },
} }
svc_systemd = { svc_systemd = {
'dovecot': { 'dovecot': {
'needs': { 'needs': {
'action:dovecot_generate_dhparam', 'action:generate-dhparam',
'file:/etc/dovecot/dovecot.conf', 'file:/etc/dovecot/dovecot.conf',
'file:/etc/dovecot/dovecot-sql.conf', 'file:/etc/dovecot/dovecot-sql.conf',
}, },

View file

@ -3,6 +3,7 @@ from bundlewrap.metadata import atomic
defaults = { defaults = {
'apt': { 'apt': {
'packages': { 'packages': {
'dovecot-fts-xapian': {},
'dovecot-imapd': {}, 'dovecot-imapd': {},
'dovecot-lmtpd': {}, 'dovecot-lmtpd': {},
'dovecot-managesieved': {}, 'dovecot-managesieved': {},
@ -35,6 +36,16 @@ defaults = {
'dovecot', 'dovecot',
}, },
}, },
'systemd-timers': {
'timers': {
'dovecot_fts_optimize': {
'command': [
'/usr/bin/doveadm fts optimize -A',
],
'when': '02:{}:00'.format(node.magic_number % 60),
},
},
},
} }
if node.has_bundle('postfixadmin'): if node.has_bundle('postfixadmin'):

View file

@ -33,7 +33,7 @@ actions = {
'yarn build', 'yarn build',
]), ]),
'needs': { 'needs': {
'action:nodejs_install_yarn', 'action:apt_execute_update_commands',
'pkg_apt:nodejs', 'pkg_apt:nodejs',
}, },
'triggered': True, 'triggered': True,

View file

@ -11,6 +11,26 @@ defaults = {
}, },
} }
@metadata_reactor.provides(
'nodejs/version',
)
def nodejs(metadata):
version = tuple([int(i) for i in metadata.get('element-web/version')[1:].split('.')])
if version >= (1, 11, 71):
return {
'nodejs': {
'version': 20,
},
}
else:
return {
'nodejs': {
'version': 18,
},
}
@metadata_reactor.provides( @metadata_reactor.provides(
'nginx/vhosts/element-web', 'nginx/vhosts/element-web',
) )

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

@ -43,6 +43,7 @@ def nginx(metadata):
'locations': { 'locations': {
'/': { '/': {
'target': 'http://127.0.0.1:21010', 'target': 'http://127.0.0.1:21010',
'websockets': True,
}, },
'/api/ds/query': { '/api/ds/query': {
'target': 'http://127.0.0.1:21010', 'target': 'http://127.0.0.1:21010',

View file

@ -72,7 +72,6 @@ actions = {
'yarn build', 'yarn build',
]), ]),
'needs': { 'needs': {
'action:nodejs_install_yarn',
'file:/opt/hedgedoc/config.json', 'file:/opt/hedgedoc/config.json',
'git_deploy:/opt/hedgedoc', 'git_deploy:/opt/hedgedoc',
'pkg_apt:nodejs', 'pkg_apt:nodejs',

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

@ -1,6 +1,13 @@
if node.has_bundle('pyenv'):
python_version = sorted(node.metadata.get('pyenv/python_versions'))[-1]
python_path = f'/opt/pyenv/versions/{python_version}/bin/python'
else:
python_path = '/usr/bin/python3'
users = { users = {
'homeassistant': { 'homeassistant': {
'home': '/var/opt/homeassistant', 'home': '/var/opt/homeassistant',
"groups": ["dialout"],
}, },
} }
@ -23,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',
@ -32,7 +39,7 @@ files = {
actions = { actions = {
'homeassistant_create_virtualenv': { 'homeassistant_create_virtualenv': {
'command': 'sudo -u homeassistant /usr/bin/python3 -m virtualenv -p python3 /opt/homeassistant/venv/', 'command': f'sudo -u homeassistant virtualenv -p {python_path} /opt/homeassistant/venv/',
'unless': 'test -d /opt/homeassistant/venv/', 'unless': 'test -d /opt/homeassistant/venv/',
'needs': { 'needs': {
'directory:/opt/homeassistant', 'directory:/opt/homeassistant',

View file

@ -0,0 +1,132 @@
#!/usr/bin/env python3
import re
from hashlib import md5
from sys import argv, exit
# Supress SSL certificate warnings for ssl_verify=False
import urllib3
from lxml import html
from requests import Session
USERNAME_FIELD = "g2"
PASSWORD_FIELD = "g3"
CRSF_FIELD = "password"
STATUS_OK = 0
STATUS_WARNING = 1
STATUS_CRITICAL = 2
STATUS_UNKNOWN = 3
class OMMCrawler:
def __init__(self, hostname, username, password):
self.session = Session()
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
self.session.verify = False
self.url = f"https://{hostname}"
self.login_data = {
USERNAME_FIELD: username,
PASSWORD_FIELD: password,
CRSF_FIELD: md5(password.encode()).hexdigest(),
}
self.logged_in = False
def login(self):
# if we have multiple dect masters, find out which one is the current master
current_master_url = self.session.get(self.url, verify=False).url
self.hostname = re.search(r"^(.*[\\\/])", current_master_url).group(0)[:-1]
response = self.session.post(f"{self.url}/login_set.html", data=self.login_data)
response.raise_for_status()
# set cookie
pass_value = re.search(r"(?<=pass=)\d+(?=;)", response.text).group(0)
self.session.cookies.set("pass", pass_value)
self.logged_in = True
def get_station_status(self):
if not self.logged_in:
self.login()
data = {}
response = self.session.get(f"{self.url}/fp_pnp_status.html")
response.raise_for_status()
tree = html.fromstring(response.text)
xpath_results = tree.xpath('//tr[@class="l0" or @class="l1"]')
for result in xpath_results:
bubble_is_in_inactive_cluster = False
bubble_is_connected = False
bubble_is_active = False
bubble_name = result.xpath("td[4]/text()")[0]
try:
bubble_is_connected = result.xpath("td[11]/img/@alt")[0] == "yes"
if bubble_is_connected:
try:
bubble_is_active = result.xpath("td[12]/img/@alt")[0] == "yes"
except IndexError:
# If an IndexError occurs, there is no image in the
# 12th td. This means this bubble is in the not inside
# an active DECT cluster, but is a backup bubble.
# This is probably fine.
bubble_is_active = False
bubble_is_in_inactive_cluster = True
else:
bubble_is_active = False
except:
# There is no Image in the 11th td. This usually means there
# is a warning message in the 10th td. We do not care about
# that, currently.
pass
data[bubble_name] = {
"is_connected": bubble_is_connected,
"is_active": bubble_is_active,
"is_in_inactive_cluster": bubble_is_in_inactive_cluster,
}
return data
def handle_station_data(self):
try:
data = self.get_station_status()
except Exception as e:
print(f"Something went wrong. You should take a look at {self.url}")
print(repr(e))
exit(STATUS_UNKNOWN)
critical = False
for name, status in data.items():
if not status["is_active"] and not status["is_connected"]:
print(
f"Base station {name} is not active or connected! Check manually!"
)
critical = True
elif not status["is_active"] and not status["is_in_inactive_cluster"]:
# Bubble is part of an active DECT cluster, but not active.
# This shouldn't happen.
print(
f"Base station {name} is not active but connected! Check manually!"
)
critical = True
elif not status["is_connected"]:
# This should never happen. Seeing this state means OMM
# itself is broken.
print(
f"Base station {name} is not connected but active! Check manually!"
)
critical = True
if critical:
exit(STATUS_CRITICAL)
else:
print(f"OK - {len(data)} base stations connected")
exit(STATUS_OK)
if __name__ == "__main__":
omm = OMMCrawler(argv[1], argv[2], argv[3])
omm.handle_station_data()

View file

@ -50,17 +50,13 @@ def check_list(ip_list, blocklist, warn_ips):
]).decode().splitlines() ]).decode().splitlines()
for item in result: for item in result:
if item.startswith(';;'): if item.startswith(';;'):
msgs.append('{} - {}'.format( continue
blocklist, msgs.append('{} listed in {} as {}'.format(
item, ip,
)) blocklist,
else: item,
msgs.append('{} listed in {} as {}'.format( ))
ip, if item in warn_ips and returncode < 2:
blocklist,
item,
))
if (item in warn_ips or item.startswith(';;')) and returncode < 2:
returncode = 1 returncode = 1
else: else:
returncode = 2 returncode = 2

View file

@ -9,6 +9,11 @@ app = Flask(__name__)
@app.route('/status') @app.route('/status')
def statuspage(): def statuspage():
everything_fine = True everything_fine = True
try:
check_output(['/usr/local/share/icinga/plugins/check_mounts'])
except:
everything_fine = False
try: try:
check_output(['/usr/lib/nagios/plugins/check_procs', '-C', 'icinga2', '-c', '1:']) check_output(['/usr/lib/nagios/plugins/check_procs', '-C', 'icinga2', '-c', '1:'])
except: except:

View file

@ -3,8 +3,6 @@ Description=Icinga2 Statusmonitor
After=network.target After=network.target
[Service] [Service]
User=nagios
Group=nagios
Environment="FLASK_APP=/etc/icinga2/icinga_statusmonitor.py" Environment="FLASK_APP=/etc/icinga2/icinga_statusmonitor.py"
ExecStart=/usr/bin/python3 -m flask run ExecStart=/usr/bin/python3 -m flask run
WorkingDirectory=/tmp WorkingDirectory=/tmp

View file

@ -113,9 +113,14 @@ def notify_per_ntfy():
else: else:
subject = '[ICINGA] {}'.format(args.host_name) subject = '[ICINGA] {}'.format(args.host_name)
if args.notification_type.lower() == 'recovery':
priority = 'default'
else:
priority = 'urgent'
headers = { headers = {
'Title': subject, 'Title': subject,
'Priority': 'urgent', 'Priority': priority,
} }
try: try:
@ -194,7 +199,7 @@ if __name__ == '__main__':
notify_per_mail() notify_per_mail()
if args.sms: if args.sms:
if args.service_name: if not args.service_name:
notify_per_sms() notify_per_sms()
if CONFIG['ntfy']['user']: if CONFIG['ntfy']['user']:
notify_per_ntfy() notify_per_ntfy()

View file

@ -275,6 +275,27 @@ files = {
'mode': '0660', 'mode': '0660',
'group': 'icingaweb2', 'group': 'icingaweb2',
}, },
# monitoring
'/etc/icinga2/icinga_statusmonitor.py': {
'triggers': {
'svc_systemd:icinga_statusmonitor:restart',
},
},
'/usr/local/lib/systemd/system/icinga_statusmonitor.service': {
'triggers': {
'action:systemd-reload',
'svc_systemd:icinga_statusmonitor:restart',
},
},
}
svc_systemd['icinga_statusmonitor'] = {
'needs': {
'file:/etc/icinga2/icinga_statusmonitor.py',
'file:/usr/local/lib/systemd/system/icinga_statusmonitor.service',
'pkg_apt:python3-flask',
},
} }
actions = { actions = {
@ -316,15 +337,12 @@ for name in files:
for name in symlinks: for name in symlinks:
icinga_run_deps.add(f'symlink:{name}') icinga_run_deps.add(f'symlink:{name}')
svc_systemd = { svc_systemd['icinga2'] = {
'icinga2': { 'needs': icinga_run_deps,
'needs': icinga_run_deps,
},
} }
# The actual hosts and services management starts here # The actual hosts and services management starts here
bundles = set() bundles = set()
downtimes = [] downtimes = []

View file

@ -17,8 +17,8 @@ defaults = {
'icinga2': {}, 'icinga2': {},
'icinga2-ido-pgsql': {}, 'icinga2-ido-pgsql': {},
'icingaweb2': {}, 'icingaweb2': {},
'icingaweb2-module-monitoring': {},
'python3-easysnmp': {}, 'python3-easysnmp': {},
'python3-flask': {},
'snmp': {}, 'snmp': {},
} }
}, },
@ -131,6 +131,9 @@ def nginx(metadata):
'/api/': { '/api/': {
'target': 'https://127.0.0.1:5665/', 'target': 'https://127.0.0.1:5665/',
}, },
'/statusmonitor/': {
'target': 'http://127.0.0.1:5000/',
},
}, },
'extras': True, 'extras': True,
}, },

View file

@ -1,4 +0,0 @@
<%
from tomlkit import dumps as toml_dumps
from bundlewrap.utils.text import toml_clean
%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(config), sort_keys=True))}

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',
}, },
@ -68,10 +68,7 @@ for room, device_id in sorted(node.metadata.get('infobeamer-cms/rooms', {}).item
files = { files = {
'/opt/infobeamer-cms/settings.toml': { '/opt/infobeamer-cms/settings.toml': {
'content_type': 'mako', 'content': repo.libs.faults.dict_as_toml(config),
'context': {
'config': config,
},
'triggers': { 'triggers': {
'svc_systemd:infobeamer-cms:restart', 'svc_systemd:infobeamer-cms:restart',
}, },
@ -99,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,4 +0,0 @@
<%
from tomlkit import dumps as toml_dumps
from bundlewrap.utils.text import toml_clean
%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(config), sort_keys=True))}

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
@ -55,14 +56,15 @@ def mqtt_out(message, level="INFO", device=None):
def mqtt_dump_state(device): def mqtt_dump_state(device):
if not device["is_online"]: if not device["is_online"]:
return return
out = []
if device["location"]:
out.append("Location: {}".format(device["location"]))
out.append("Setup: {} ({})".format(device["setup"]["name"], device["setup"]["id"]))
out.append("Resolution: {}".format(device["run"].get("resolution", "unknown")))
mqtt_out( mqtt_out(
"Sync status: {} - Location: {} - Running Setup: {} ({}) - Resolution: {}".format( " - ".join(out),
"yes" if device["is_synced"] else "syncing",
device["location"],
device["setup"]["name"],
device["setup"]["id"],
device["run"].get("resolution", "unknown"),
),
device=device, device=device,
) )
@ -70,6 +72,9 @@ def mqtt_dump_state(device):
mqtt_out("Monitor starting up") mqtt_out("Monitor starting up")
while True: while True:
try: try:
online_devices = set()
available_credits = None
try: try:
r = get( r = get(
"https://info-beamer.com/api/v1/device/list", "https://info-beamer.com/api/v1/device/list",
@ -85,7 +90,6 @@ while True:
) )
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"])
@ -137,17 +141,15 @@ while True:
if device["is_online"]: if device["is_online"]:
if device["maintenance"]: if device["maintenance"]:
mqtt_out( mqtt_out(
"maintenance required: {}".join( "maintenance required: {}".format(
sorted(device["maintenance"]) " ".join(sorted(device["maintenance"]))
), ),
level="WARN", level="WARN",
device=device, device=device,
) )
must_dump_state = True
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")
@ -169,13 +171,56 @@ while True:
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 data from info-beamer")
mqtt_out(
f"Could not get data from info-beamer: {e!r}",
level="WARN",
)
else:
available_credits = ib_account["balance"]
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",
)
if datetime.now(ZoneInfo("Europe/Berlin")).strftime("%H%M") == "0900":
if available_credits is not None:
mqtt_out(f"Available Credits: {available_credits}")
if online_devices:
mqtt_out(
"Online Devices: {}".format(", ".join(sorted(online_devices)))
)
sleep(60)
except KeyboardInterrupt: except KeyboardInterrupt:
break break

View file

@ -1,10 +1,7 @@
assert node.has_bundle('infobeamer-cms') # uses same venv assert node.has_bundle('infobeamer-cms') # uses same venv
files['/opt/infobeamer-monitor/config.toml'] = { files['/opt/infobeamer-monitor/config.toml'] = {
'content_type': 'mako', 'content': repo.libs.faults.dict_as_toml(node.metadata.get('infobeamer-monitor')),
'context': {
'config': node.metadata.get('infobeamer-monitor'),
},
'triggers': { 'triggers': {
'svc_systemd:infobeamer-monitor:restart', 'svc_systemd:infobeamer-monitor:restart',
}, },

View file

@ -63,7 +63,7 @@ def firewall(metadata):
return { return {
'firewall': { 'firewall': {
'port_rules': { 'port_rules': {
'8096/tcp': atomic(metadata.get('jellyfin/restrict-to', {'*'})), '8096/tcp': atomic(metadata.get('jellyfin/restrict-to', set())),
}, },
}, },
} }

15
bundles/jool/items.py Normal file
View file

@ -0,0 +1,15 @@
actions['modprobe_jool'] = {
'command': 'modprobe jool',
'unless': 'lsmod | grep -F jool',
}
actions['jool_add_nat64_instance'] = {
'command': 'jool instance add "nat64" --netfilter --pool6 64:ff9b::/96',
'unless': 'jool instance display --no-headers --csv | grep -E ",nat64,netfilter$"',
'needs': {
'action:modprobe_jool',
'pkg_apt:jool-dkms',
'pkg_apt:jool-tools',
'pkg_apt:linux-headers-amd64',
},
}

14
bundles/jool/metadata.py Normal file
View file

@ -0,0 +1,14 @@
defaults = {
'apt': {
'packages': {
'jool-dkms': {},
'jool-tools': {},
'linux-headers-amd64': {},
},
},
'modules': {
'jool': [
'jool',
],
},
}

View file

@ -1,4 +0,0 @@
<%
from tomlkit import dumps as toml_dumps
from bundlewrap.utils.text import toml_clean
%>${toml_clean(toml_dumps(repo.libs.faults.resolve_faults(node.metadata.get('jugendhackt_tools')), sort_keys=True))}

View file

@ -47,7 +47,7 @@ actions['jugendhackt_tools_migrate'] = {
} }
files['/opt/jugendhackt_tools/config.toml'] = { files['/opt/jugendhackt_tools/config.toml'] = {
'content_type': 'mako', 'content': repo.libs.faults.dict_as_toml(node.metadata.get('jugendhackt_tools')),
'triggers': { 'triggers': {
'svc_systemd:jugendhackt_tools:restart', 'svc_systemd:jugendhackt_tools:restart',
}, },

View file

@ -0,0 +1,8 @@
# This file is managed using bundlewrap
% for identifier, modules in sorted(node.metadata.get('modules', {}).items()):
# ${identifier}
% for module in modules:
${module}
% endfor
% endfor

View file

@ -0,0 +1,3 @@
files['/etc/modules'] = {
'content_type': 'mako',
}

View file

@ -39,6 +39,7 @@ def cron(metadata):
'/usr/bin/dehydrated --cleanup', '/usr/bin/dehydrated --cleanup',
], ],
'when': '04:{}:00'.format(node.magic_number % 60), 'when': '04:{}:00'.format(node.magic_number % 60),
'exclude_from_monitoring': True,
}, },
}, },
}, },

View file

@ -3,6 +3,9 @@ repo:
bindAddress: '${node.metadata.get('matrix-media-repo/listen-addr', '127.0.0.1')}' bindAddress: '${node.metadata.get('matrix-media-repo/listen-addr', '127.0.0.1')}'
port: ${node.metadata.get('matrix-media-repo/port', 20090)} port: ${node.metadata.get('matrix-media-repo/port', 20090)}
logDirectory: '-' logDirectory: '-'
logColors: false
jsonLogs: false
logLevel: 'info'
trustAnyForwardedAddress: false trustAnyForwardedAddress: false
useForwardedHost: true useForwardedHost: true
@ -22,10 +25,13 @@ homeservers:
csApi: "${config['domain']}" csApi: "${config['domain']}"
backoffAt: ${config.get('backoff_at', 10)} backoffAt: ${config.get('backoff_at', 10)}
adminApiKind: "${config.get('api', 'matrix')}" adminApiKind: "${config.get('api', 'matrix')}"
% if config.get('signing_key_path'):
signingKeyPath: "${config['signing_key_path']}"
% endif
% endfor % endfor
accessTokens: accessTokens:
maxCacheTimeSeconds: 0 maxCacheTimeSeconds: 10
useLocalAppserviceConfig: false useLocalAppserviceConfig: false
admins: admins:
@ -53,7 +59,9 @@ archiving:
uploads: uploads:
maxBytes: ${node.metadata.get('matrix-media-repo/upload_max_mb')*1024*1024} maxBytes: ${node.metadata.get('matrix-media-repo/upload_max_mb')*1024*1024}
minBytes: 100 minBytes: 100
reportedMaxBytes: 0 #reportedMaxBytes: 0
maxPending: 5
maxAgeSeconds: 1800
quotas: quotas:
enabled: false enabled: false
@ -61,14 +69,6 @@ downloads:
maxBytes: ${node.metadata.get('matrix-media-repo/download_max_mb')*1024*1024} maxBytes: ${node.metadata.get('matrix-media-repo/download_max_mb')*1024*1024}
numWorkers: ${node.metadata.get('matrix-media-repo/workers')} numWorkers: ${node.metadata.get('matrix-media-repo/workers')}
failureCacheMinutes: 5 failureCacheMinutes: 5
cache:
enabled: true
maxSizeBytes: ${node.metadata.get('matrix-media-repo/download_max_mb')*10*1024*1024}
maxFileSizeBytes: ${node.metadata.get('matrix-media-repo/download_max_mb')*1024*1024}
trackedMinutes: 30
minDownloads: 5
minCacheTimeSeconds: 300
minEvictedTimeSeconds: 60
expireAfterDays: 0 expireAfterDays: 0
urlPreviews: urlPreviews:
@ -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

@ -19,9 +19,6 @@ files = {
'/opt/matrix-media-repo/config.yaml': { '/opt/matrix-media-repo/config.yaml': {
'owner': 'matrix-media-repo', 'owner': 'matrix-media-repo',
'content_type': 'mako', 'content_type': 'mako',
'triggers': {
'svc_systemd:matrix-media-repo:restart',
},
}, },
'/etc/systemd/system/matrix-media-repo.service': { '/etc/systemd/system/matrix-media-repo.service': {
'triggers': { 'triggers': {

View file

@ -0,0 +1,27 @@
<%
database = node.metadata.get('matrix-synapse/database')
db_string = 'postgresql://{}:{}@{}/{}?sslmode=disable'.format(
database['user'],
database['password'],
database.get('host', 'localhost'),
database['database'],
)
%>\
[Unit]
Description=matrix-org sliding-sync proxy
After=network.target
Requires=postgresql.service
[Service]
User=matrix-synapse
Group=matrix-synapse
Environment=SYNCV3_SERVER=https://${node.metadata.get('matrix-synapse/baseurl')}
Environment=SYNCV3_DB=${db_string}
Environment=SYNCV3_SECRET=${node.metadata.get('matrix-synapse/sliding_sync/secret')}
Environment=SYNCV3_BINDADDR=127.0.0.1:20070
ExecStart=/usr/local/bin/matrix-sliding-sync
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target

View file

@ -57,3 +57,32 @@ svc_systemd = {
}, },
}, },
} }
if node.metadata.get('matrix-synapse/sliding_sync/version', None):
files['/usr/local/bin/matrix-sliding-sync'] = {
'content_type': 'download',
'source': 'https://github.com/matrix-org/sliding-sync/releases/download/{}/syncv3_linux_amd64'.format(
node.metadata.get('matrix-synapse/sliding_sync/version'),
),
'content_hash': node.metadata.get('matrix-synapse/sliding_sync/sha1', None),
'mode': '0755',
'triggers': {
'svc_systemd:matrix-sliding-sync:restart',
},
}
files['/usr/local/lib/systemd/system/matrix-sliding-sync.service'] = {
'content_type': 'mako',
'triggers': {
'action:systemd-reload',
'svc_systemd:matrix-sliding-sync:restart',
},
}
svc_systemd['matrix-sliding-sync'] = {
'needs': {
'file:/usr/local/bin/matrix-sliding-sync',
'file:/usr/local/lib/systemd/system/matrix-sliding-sync.service',
'postgres_db:synapse',
},
}

View file

@ -88,6 +88,14 @@ def nginx(metadata):
if not node.has_bundle('nginx'): if not node.has_bundle('nginx'):
raise DoNotRunAgain raise DoNotRunAgain
wellknown_client_sliding_sync = {}
if metadata.get('matrix-synapse/sliding_sync/version', None):
wellknown_client_sliding_sync = {
'org.matrix.msc3575.proxy': {
'url': 'https://{}'.format(metadata.get('matrix-synapse/baseurl')),
},
}
wellknown = { wellknown = {
'/.well-known/matrix/client': { '/.well-known/matrix/client': {
'content': dumps({ 'content': dumps({
@ -97,6 +105,7 @@ def nginx(metadata):
'm.identity_server': { 'm.identity_server': {
'base_url': metadata.get('matrix-synapse/identity_server', 'https://matrix.org'), 'base_url': metadata.get('matrix-synapse/identity_server', 'https://matrix.org'),
}, },
**wellknown_client_sliding_sync,
**metadata.get('matrix-synapse/additional_client_config', {}), **metadata.get('matrix-synapse/additional_client_config', {}),
}, sort_keys=True), }, sort_keys=True),
'return': 200, 'return': 200,
@ -118,10 +127,16 @@ def nginx(metadata):
} }
locations = { locations = {
'/_client/': {
'target': 'http://127.0.0.1:20070',
},
'/_matrix': { '/_matrix': {
'target': 'http://[::1]:20080', 'target': 'http://[::1]:20080',
'max_body_size': '50M', 'max_body_size': '50M',
}, },
'/_matrix/client/unstable/org.matrix.msc3575/sync': {
'target': 'http://127.0.0.1:20070',
},
'/_synapse': { '/_synapse': {
'target': 'http://[::1]:20080', 'target': 'http://[::1]:20080',
}, },
@ -129,13 +144,14 @@ def nginx(metadata):
} }
if node.has_bundle('matrix-media-repo'): if node.has_bundle('matrix-media-repo'):
locations['/_matrix/media'] = { for path in ('/_matrix/media', '/_matrix/client/v1/media', '/_matrix/federation/v1/media'):
'target': 'http://localhost:20090', locations[path] = {
'max_body_size': '{}M'.format(metadata.get('matrix-media-repo/upload_max_mb')), 'target': 'http://localhost:20090',
# matrix-media-repo needs this to be the 'max_body_size': '{}M'.format(metadata.get('matrix-media-repo/upload_max_mb')),
# homeserver address. # matrix-media-repo needs this to be the
'x_forwarded_host': metadata.get('matrix-synapse/server_name'), # homeserver address.
} 'x_forwarded_host': metadata.get('matrix-synapse/server_name'),
}
vhosts = { vhosts = {
'matrix-synapse': { 'matrix-synapse': {

View file

@ -1,11 +1,15 @@
#!/bin/bash #!/bin/bash
OPTS="" OPTS="--netrc"
OPTS="$OPTS --netrc-location /opt/mixcloud-downloader/netrc"
OPTS="$OPTS --retry-sleep linear=1::2"
OPTS="$OPTS --retry-sleep fragment:exp=1:60"
OPTS="$OPTS --extractor-retries 5"
if [[ -n "$DEBUG" ]] if [[ -n "$DEBUG" ]]
then then
set -x set -x
else else
OPTS="-q" OPTS="$OPTS -q"
fi fi
set -euo pipefail set -euo pipefail

View file

@ -0,0 +1,3 @@
% for domain, data in sorted(node.metadata.get('mixcloud-downloader/netrc', {}).items()):
machine ${domain} login ${data['username']} password ${data['password']}
% endfor

View file

@ -6,3 +6,9 @@ files['/opt/mixcloud-downloader/download.sh'] = {
directories['/opt/mixcloud-downloader'] = { directories['/opt/mixcloud-downloader'] = {
'owner': 'kunsi', 'owner': 'kunsi',
} }
files['/opt/mixcloud-downloader/netrc'] = {
'content_type': 'mako',
'mode': '0400',
'owner': 'kunsi',
}

View file

@ -5,12 +5,6 @@ files = {
'svc_systemd:mosquitto:restart', 'svc_systemd:mosquitto:restart',
}, },
}, },
'/usr/local/bin/tasmota-telegraf-plugin': {
'mode': '0755',
'needs': {
'pkg_apt:python3-paho-mqtt',
},
},
} }
svc_systemd = { svc_systemd = {
@ -23,6 +17,12 @@ svc_systemd = {
} }
if node.has_bundle('telegraf'): if node.has_bundle('telegraf'):
files['/usr/local/bin/tasmota-telegraf-plugin']['triggers'] = { files['/usr/local/bin/tasmota-telegraf-plugin'] = {
'svc_systemd:telegraf:restart', 'mode': '0755',
'needs': {
'pkg_apt:python3-paho-mqtt',
},
'triggers': {
'svc_systemd:telegraf:restart',
},
} }

View file

@ -5,7 +5,6 @@ defaults = {
'packages': { 'packages': {
'mosquitto': {}, 'mosquitto': {},
'mosquitto-clients': {}, 'mosquitto-clients': {},
'python3-paho-mqtt': {}, # for telegraf plugin
}, },
}, },
'icinga2_api': { 'icinga2_api': {
@ -24,6 +23,9 @@ defaults = {
}, },
} }
if node.has_bundle('telegraf'):
defaults['apt']['packages']['python3-paho-mqtt'] = {}
@metadata_reactor.provides( @metadata_reactor.provides(
'firewall/port_rules', 'firewall/port_rules',

View file

@ -1,124 +1,138 @@
users = { users['netbox'] = {
'netbox': { 'home': '/opt/netbox',
'home': '/opt/netbox',
},
} }
directories = { directories['/opt/netbox/src'] = {}
'/opt/netbox/src': {},
'/opt/netbox/media': { directories['/opt/netbox/media'] = {
'owner': 'netbox', 'owner': 'netbox',
},
'/opt/netbox/scripts': {
'owner': 'netbox',
},
} }
git_deploy = { directories['/opt/netbox/scripts'] = {
'/opt/netbox/src': { 'owner': 'netbox',
'repo': 'https://github.com/netbox-community/netbox.git', }
'rev': node.metadata.get('netbox/version'),
'triggers': { git_deploy['/opt/netbox/src'] = {
'action:netbox_install', 'repo': 'https://github.com/netbox-community/netbox.git',
'action:netbox_upgrade', 'rev': node.metadata.get('netbox/version'),
'svc_systemd:netbox-web:restart', 'triggers': {
'svc_systemd:netbox-worker:restart', 'action:netbox_install',
}, 'svc_systemd:netbox-web:restart',
'svc_systemd:netbox-worker:restart',
},
'tags': {
'netbox-install',
}, },
} }
# This is a recreation of https://github.com/netbox-community/netbox/blob/develop/upgrade.sh # This is a recreation of https://github.com/netbox-community/netbox/blob/develop/upgrade.sh
actions = { actions['netbox_create_virtualenv'] = {
'netbox_create_virtualenv': { 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/netbox/venv',
'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/netbox/venv', 'unless': 'test -d /opt/netbox/venv/',
'unless': 'test -d /opt/netbox/venv/', 'needed_by': {
'needed_by': { 'action:netbox_install',
'action:netbox_install',
},
},
'netbox_install': {
'triggered': True,
'command': ' && '.join([
'cd /opt/netbox/src',
'/opt/netbox/venv/bin/pip install --upgrade pip wheel setuptools django-auth-ldap gunicorn',
'/opt/netbox/venv/bin/pip install --upgrade -r requirements.txt',
]),
'needs': {
'pkg_apt:build-essential',
'pkg_apt:graphviz',
'pkg_apt:libffi-dev',
'pkg_apt:libldap2-dev',
'pkg_apt:libpq-dev',
'pkg_apt:libsasl2-dev',
'pkg_apt:libssl-dev',
'pkg_apt:libxml2-dev',
'pkg_apt:libxslt1-dev',
'pkg_apt:python3-dev',
'pkg_apt:zlib1g-dev',
}
},
'netbox_upgrade': {
'triggered': True,
'command': ' && '.join([
'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py migrate',
'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py collectstatic --no-input',
'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py remove_stale_contenttypes --no-input',
'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py clearsessions',
]),
'needs': {
'action:netbox_install',
'file:/opt/netbox/src/netbox/netbox/configuration.py',
},
}, },
} }
files = { actions['netbox_install'] = {
'/usr/local/lib/systemd/system/netbox-web.service': { 'triggered': True,
'triggers': { 'command': ' && '.join([
'action:systemd-reload', 'cd /opt/netbox/src',
'svc_systemd:netbox-web:restart', '/opt/netbox/venv/bin/pip install --upgrade pip wheel setuptools django-auth-ldap gunicorn',
}, '/opt/netbox/venv/bin/pip install --upgrade -r requirements.txt',
]),
'needs': {
'pkg_apt:build-essential',
'pkg_apt:graphviz',
'pkg_apt:libffi-dev',
'pkg_apt:libldap2-dev',
'pkg_apt:libpq-dev',
'pkg_apt:libsasl2-dev',
'pkg_apt:libssl-dev',
'pkg_apt:libxml2-dev',
'pkg_apt:libxslt1-dev',
'pkg_apt:python3-dev',
'pkg_apt:zlib1g-dev',
}, },
'/usr/local/lib/systemd/system/netbox-worker.service': { 'tags': {
'triggers': { 'netbox-install',
'action:systemd-reload',
'svc_systemd:netbox-worker:restart',
},
},
'/opt/netbox/src/netbox/netbox/configuration.py': {
'content_type': 'mako',
'triggers': {
'svc_systemd:netbox-web:restart',
'svc_systemd:netbox-worker:restart',
},
'needs': {
'git_deploy:/opt/netbox/src',
},
},
'/opt/netbox/gunicorn_config.py': {
'content_type': 'mako',
'triggers': {
'svc_systemd:netbox-web:restart',
},
}, },
} }
svc_systemd = { last_action = 'netbox_install'
'netbox-web': { for upgrade_command in (
'migrate',
'trace_paths --no-input',
'collectstatic --no-input',
'remove_stale_contenttypes --no-input',
'reindex --lazy',
'clearsessions',
):
actions[f'netbox_upgrade_{upgrade_command.split()[0]}'] = {
'triggered': True,
'command': f'/opt/netbox/venv/bin/python /opt/netbox/src/netbox/manage.py {upgrade_command}',
'needs': { 'needs': {
'action:netbox_install', f'action:{last_action}',
'action:netbox_upgrade',
'file:/usr/local/lib/systemd/system/netbox-web.service',
'file:/opt/netbox/gunicorn_config.py',
'file:/opt/netbox/src/netbox/netbox/configuration.py',
}, },
}, 'tags': {
'netbox-worker': { 'netbox-upgrade',
'needs': {
'action:netbox_install',
'action:netbox_upgrade',
'file:/usr/local/lib/systemd/system/netbox-worker.service',
'file:/opt/netbox/src/netbox/netbox/configuration.py',
}, },
'triggered_by': {
'tag:netbox-install',
},
}
last_action = f'netbox_upgrade_{upgrade_command.split()[0]}'
files['/usr/local/lib/systemd/system/netbox-web.service'] = {
'triggers': {
'action:systemd-reload',
'svc_systemd:netbox-web:restart',
},
}
files['/usr/local/lib/systemd/system/netbox-worker.service'] = {
'triggers': {
'action:systemd-reload',
'svc_systemd:netbox-worker:restart',
},
}
files['/opt/netbox/src/netbox/netbox/configuration.py'] = {
'content_type': 'mako',
'triggers': {
'svc_systemd:netbox-web:restart',
'svc_systemd:netbox-worker:restart',
},
'needs': {
'git_deploy:/opt/netbox/src',
},
'tags': {
'netbox-install',
},
}
files['/opt/netbox/gunicorn_config.py'] = {
'content_type': 'mako',
'triggers': {
'svc_systemd:netbox-web:restart',
},
}
svc_systemd['netbox-web'] = {
'needs': {
'file:/usr/local/lib/systemd/system/netbox-web.service',
'file:/opt/netbox/gunicorn_config.py',
'file:/opt/netbox/src/netbox/netbox/configuration.py',
'tag:netbox-install',
'tag:netbox-upgrade',
},
}
svc_systemd['netbox-worker'] = {
'needs': {
'file:/usr/local/lib/systemd/system/netbox-worker.service',
'file:/opt/netbox/src/netbox/netbox/configuration.py',
'tag:netbox-install',
'tag:netbox-upgrade',
}, },
} }

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

@ -10,6 +10,9 @@ events {
http { http {
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
types {
application/javascript mjs;
}
default_type application/octet-stream; default_type application/octet-stream;
charset UTF-8; charset UTF-8;
override_charset on; override_charset on;

View file

@ -29,8 +29,9 @@ server {
root ${webroot if webroot else '/var/www/{}/'.format(vhost)}; root ${webroot if webroot else '/var/www/{}/'.format(vhost)};
index ${' '.join(index)}; index ${' '.join(index)};
listen 443 ssl http2; listen 443 ssl;
listen [::]:443 ssl http2; listen [::]:443 ssl;
http2 on;
% if ssl == 'letsencrypt': % if ssl == 'letsencrypt':
ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem; ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem;
@ -70,8 +71,9 @@ server {
root ${webroot if webroot else '/var/www/{}/'.format(vhost)}; root ${webroot if webroot else '/var/www/{}/'.format(vhost)};
index ${' '.join(index)}; index ${' '.join(index)};
listen 443 ssl http2; listen 443 ssl;
listen [::]:443 ssl http2; listen [::]:443 ssl;
http2 on;
% if ssl == 'letsencrypt': % if ssl == 'letsencrypt':
ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem; ssl_certificate /var/lib/dehydrated/certs/${domain}/fullchain.pem;
@ -80,12 +82,13 @@ server {
ssl_certificate /etc/nginx/ssl/${vhost}.crt; ssl_certificate /etc/nginx/ssl/${vhost}.crt;
ssl_certificate_key /etc/nginx/ssl/${vhost}.key; ssl_certificate_key /etc/nginx/ssl/${vhost}.key;
% endif % endif
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_prefer_server_ciphers off;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m; ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; ssl_session_tickets off;
ssl_session_timeout 1d;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
% endif % endif
@ -146,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;
@ -198,6 +201,8 @@ server {
fastcgi_hide_header X-XSS-Protection; fastcgi_hide_header X-XSS-Protection;
% endif % endif
fastcgi_hide_header Permissions-Policy; fastcgi_hide_header Permissions-Policy;
fastcgi_request_buffering off;
proxy_buffering off;
} }
% if not max_body_size: % if not max_body_size:
client_max_body_size 5M; client_max_body_size 5M;

View file

@ -78,17 +78,10 @@ if node.has_bundle('pacman'):
}, },
} }
actions = {
'nginx-generate-dhparam': {
'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048',
'unless': 'test -f /etc/ssl/certs/dhparam.pem',
},
}
svc_systemd = { svc_systemd = {
'nginx': { 'nginx': {
'needs': { 'needs': {
'action:nginx-generate-dhparam', 'action:generate-dhparam',
'directory:/var/log/nginx-timing', 'directory:/var/log/nginx-timing',
package, package,
}, },

View file

@ -200,8 +200,8 @@ def telegraf_anon_timing(metadata):
result[f'nginx-{vname}'] = { result[f'nginx-{vname}'] = {
'files': [f'/var/log/nginx-timing/{vname}.log'], 'files': [f'/var/log/nginx-timing/{vname}.log'],
'from_beginning': False, 'from_beginning': False,
'grok_patterns': ['%{LOGPATTERN}'], 'grok_patterns': [r'%{LOGPATTERN}'],
'grok_custom_patterns': 'LOGPATTERN \[%{HTTPDATE:ts:ts-httpd}\] %{NUMBER:request_time:float} (?:%{NUMBER:upstream_response_time:float}|-) "%{WORD:verb:tag} %{NOTSPACE:request} HTTP/%{NUMBER:http_version:float}" %{NUMBER:resp_code:tag}', 'grok_custom_patterns': r'LOGPATTERN \[%{HTTPDATE:ts:ts-httpd}\] %{NUMBER:request_time:float} (?:%{NUMBER:upstream_response_time:float}|-) "%{WORD:verb:tag} %{NOTSPACE:request} HTTP/%{NUMBER:http_version:float}" %{NUMBER:resp_code:tag}',
'data_format': 'grok', 'data_format': 'grok',
'name_override': 'nginx_timing', 'name_override': 'nginx_timing',
} }

View file

@ -1,9 +0,0 @@
actions = {
'nodejs_install_yarn': {
'command': 'npm install -g yarn@latest',
'unless': 'test -e /usr/lib/node_modules/yarn',
'after': {
'pkg_apt:',
},
},
}

View file

@ -1,23 +1,24 @@
defaults = { defaults = {
'apt': { 'apt': {
'additional_update_commands': { 'additional_update_commands': {
# update npm to latest version # update npm and yarn to latest version
'npm install -g npm@latest',
'npm install -g yarn@latest', 'npm install -g yarn@latest',
}, },
'packages': { 'packages': {
'nodejs': {}, 'nodejs': {
'triggers': {
'action:apt_execute_update_commands',
},
},
'npm': {
'installed': False,
'triggers': {
'action:apt_execute_update_commands',
},
},
}, },
}, },
'nodejs': {
'version': 18,
},
}
VERSIONS_SHIPPED_BY_DEBIAN = {
10: 10,
11: 12,
12: 18,
13: 18,
} }
@metadata_reactor.provides( @metadata_reactor.provides(
@ -26,28 +27,14 @@ VERSIONS_SHIPPED_BY_DEBIAN = {
def nodejs_from_version(metadata): def nodejs_from_version(metadata):
version = metadata.get('nodejs/version') version = metadata.get('nodejs/version')
if version != VERSIONS_SHIPPED_BY_DEBIAN[node.os_version[0]]: return {
return { 'apt': {
'apt': { 'repos': {
'additional_update_commands': { 'nodejs': {
# update npm to latest version 'items': {
'npm install -g npm@latest', f'deb https://deb.nodesource.com/node_{version}.x nodistro main',
},
'repos': {
'nodejs': {
'items': {
f'deb https://deb.nodesource.com/node_{version}.x {{os_release}} main',
f'deb-src https://deb.nodesource.com/node_{version}.x {{os_release}} main',
},
}, },
}, },
}, },
} },
else: }
return {
'apt': {
'packages': {
'npm': {},
},
},
}

View file

@ -1,25 +0,0 @@
from os.path import join
directories = {
'/etc/openvpn/client': {
'mode': '0750',
'owner': 'openvpn',
'group': None,
'purge': True,
},
}
for fname, config in node.metadata.get('openvpn-client/configs', {}).items():
files[f'/etc/openvpn/client/{fname}.conf'] = {
'content': repo.vault.decrypt_file(join('openvpn-client', f'{fname}.conf.vault')),
'triggers': {
f'svc_systemd:openvpn-client@{config}:restart',
} if config.get('running', True) else set(),
}
svc_systemd[f'openvpn-client@{fname}'] = {
'needs': {
f'file:/etc/openvpn/client/{fname}.conf',
},
**config,
}

View file

@ -1,20 +0,0 @@
defaults = {
'apt': {
'packages': {
'openvpn': {
'needed_by': {
'directory:/etc/openvpn/client',
},
},
},
},
'pacman': {
'packages': {
'openvpn': {
'needed_by': {
'directory:/etc/openvpn/client',
},
},
},
},
}

View file

@ -36,13 +36,13 @@ pkg_pacman = {
'at': {}, 'at': {},
'autoconf': {}, 'autoconf': {},
'automake': {}, 'automake': {},
'bind': {},
'binutils': {}, 'binutils': {},
'bison': {}, 'bison': {},
'bzip2': {}, 'bzip2': {},
'curl': {}, 'curl': {},
'dialog': {}, 'dialog': {},
'diffutils': {}, 'diffutils': {},
'dnsutils': {},
'fakeroot': {}, 'fakeroot': {},
'file': {}, 'file': {},
'findutils': {}, 'findutils': {},

View file

@ -8,6 +8,9 @@ Group=paperless
Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf
WorkingDirectory=/opt/paperless/src/paperless-ngx/src WorkingDirectory=/opt/paperless/src/paperless-ngx/src
ExecStart=/opt/paperless/venv/bin/python manage.py document_consumer ExecStart=/opt/paperless/venv/bin/python manage.py document_consumer
Restart=always
RestartSec=10
SyslogIdentifier=paperless-consumer
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View file

@ -8,6 +8,9 @@ Group=paperless
Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf
WorkingDirectory=/opt/paperless/src/paperless-ngx/src WorkingDirectory=/opt/paperless/src/paperless-ngx/src
ExecStart=/opt/paperless/venv/bin/celery --app paperless beat --loglevel INFO ExecStart=/opt/paperless/venv/bin/celery --app paperless beat --loglevel INFO
Restart=always
RestartSec=10
SyslogIdentifier=paperless-scheduler
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View file

@ -8,6 +8,9 @@ Group=paperless
Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf
WorkingDirectory=/opt/paperless/src/paperless-ngx/src WorkingDirectory=/opt/paperless/src/paperless-ngx/src
ExecStart=/opt/paperless/venv/bin/celery --app paperless worker --loglevel INFO ExecStart=/opt/paperless/venv/bin/celery --app paperless worker --loglevel INFO
Restart=always
RestartSec=10
SyslogIdentifier=paperless-taskqueue
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View file

@ -10,6 +10,9 @@ Group=paperless
Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf Environment=PAPERLESS_CONFIGURATION_PATH=/opt/paperless/paperless.conf
WorkingDirectory=/opt/paperless/src/paperless-ngx/src WorkingDirectory=/opt/paperless/src/paperless-ngx/src
ExecStart=/opt/paperless/venv/bin/gunicorn -c /opt/paperless/src/paperless-ngx/gunicorn.conf.py -b 127.0.0.1:22070 paperless.asgi:application ExecStart=/opt/paperless/venv/bin/gunicorn -c /opt/paperless/src/paperless-ngx/gunicorn.conf.py -b 127.0.0.1:22070 paperless.asgi:application
Restart=always
RestartSec=10
SyslogIdentifier=paperless-webserver
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View file

@ -30,6 +30,8 @@ PAPERLESS_CORS_ALLOWED_HOSTS=http://${node.metadata.get('paperless/domain')},htt
PAPERLESS_OCR_LANGUAGE=${'+'.join(sorted(node.metadata.get('paperless/ocr_languages', {'deu', 'eng'})))} PAPERLESS_OCR_LANGUAGE=${'+'.join(sorted(node.metadata.get('paperless/ocr_languages', {'deu', 'eng'})))}
PAPERLESS_OCR_MODE=skip PAPERLESS_OCR_MODE=skip
PAPERLESS_OCR_SKIP_ARCHIVE_FILE=never PAPERLESS_OCR_SKIP_ARCHIVE_FILE=never
PAPERLESS_OCR_USER_ARGS='{"invalidate_digital_signatures": true}'
PAPERLESS_PRE_CONSUME_SCRIPT=/opt/paperless/pre-consume.sh
#PAPERLESS_OCR_OUTPUT_TYPE=pdfa #PAPERLESS_OCR_OUTPUT_TYPE=pdfa
#PAPERLESS_OCR_PAGES=1 #PAPERLESS_OCR_PAGES=1
#PAPERLESS_OCR_IMAGE_DPI=300 #PAPERLESS_OCR_IMAGE_DPI=300

View file

@ -0,0 +1,11 @@
#!/bin/bash
[[ -n "$DEBUG" ]] && set -x
set -euo pipefail
pdfinfo "${DOCUMENT_WORKING_PATH}" | grep -q "Encrypted:"
if pdfinfo "${DOCUMENT_WORKING_PATH}" | grep -q "Encrypted: yes"
then
qpdf --replace-input --decrypt "${DOCUMENT_WORKING_PATH}"
fi

View file

@ -15,6 +15,10 @@ files['/opt/paperless/paperless.conf'] = {
}, },
} }
files['/opt/paperless/pre-consume.sh'] = {
'mode': '0755',
}
actions['paperless_create_virtualenv'] = { actions['paperless_create_virtualenv'] = {
'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/paperless/venv/', 'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/paperless/venv/',
'unless': 'test -d /opt/paperless/venv/', 'unless': 'test -d /opt/paperless/venv/',

View file

@ -11,6 +11,7 @@ defaults = {
'mariadb-client': {}, 'mariadb-client': {},
'mime-support': {}, 'mime-support': {},
'optipng': {}, 'optipng': {},
'poppler-utils': {},
'python3-wheel': {}, 'python3-wheel': {},
# for OCRmyPDF # for OCRmyPDF
@ -32,6 +33,9 @@ defaults = {
'/mnt/paperless', '/mnt/paperless',
}, },
}, },
'nodejs': {
'version': 18,
},
'postgresql': { 'postgresql': {
'roles': { 'roles': {
'paperless': { 'paperless': {

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,19 +47,18 @@ 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
# generated using mozilla ssl generator, using "old" configuration. # https://ssl-config.mozilla.org/#server=postfix&version=3.7.10&config=intermediate&openssl=3.0.11&guideline=5.7
# we need this to support CentOS 7 systems, sadly ...
# https://ssl-config.mozilla.org/#server=postfix&version=3.5.13&config=old&openssl=1.1.1k&guideline=5.6
smtpd_tls_security_level = may smtpd_tls_security_level = may
smtpd_tls_auth_only = yes smtpd_tls_auth_only = yes
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3 smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_ciphers = medium smtpd_tls_mandatory_ciphers = medium
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA smtpd_tls_dh1024_param_file = /etc/ssl/certs/dhparam.pem
tls_preempt_cipherlist = yes tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
tls_preempt_cipherlist = no
</%text> </%text>
relay_domains = $mydestination, pgsql:/etc/postfix/pgsql/relay_domains.cf relay_domains = $mydestination, pgsql:/etc/postfix/pgsql/relay_domains.cf

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()
@ -65,7 +67,7 @@ svc_systemd = {
actions = { actions = {
'powerdns_reload_zones': { 'powerdns_reload_zones': {
'triggered': True, 'triggered': True,
'command': 'pdns_control rediscover; pdns_control reload; pdns_control notify \*', 'command': r'pdns_control rediscover; pdns_control reload; pdns_control notify \*',
'after': { 'after': {
'svc_systemd:pdns', 'svc_systemd:pdns',
}, },
@ -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)
@ -160,7 +163,7 @@ if node.metadata.get('powerdns/features/pgsql', node.has_bundle('postgresql')):
actions['powerdns_load_pgsql_schema'] = { actions['powerdns_load_pgsql_schema'] = {
'command': node.metadata.get('postgresql/roles/powerdns/password').format_into('PGPASSWORD={} psql -h 127.0.0.1 -d powerdns -U powerdns -w < /usr/share/pdns-backend-pgsql/schema/schema.pgsql.sql'), 'command': node.metadata.get('postgresql/roles/powerdns/password').format_into('PGPASSWORD={} psql -h 127.0.0.1 -d powerdns -U powerdns -w < /usr/share/pdns-backend-pgsql/schema/schema.pgsql.sql'),
'unless': 'sudo -u postgres psql -d powerdns -c "\dt" | grep domains 2>&1 >/dev/null', 'unless': r'sudo -u postgres psql -d powerdns -c "\dt" | grep domains 2>&1 >/dev/null',
'needs': { 'needs': {
'bundle:postgresql', 'bundle:postgresql',
'pkg_apt:pdns-backend-pgsql', 'pkg_apt:pdns-backend-pgsql',

View file

@ -143,11 +143,14 @@ def generate_dns_entries_for_nodes(metadata):
if not ip6 and not ip.is_private: if not ip6 and not ip.is_private:
ip6 = ip ip6 = ip
if not (ip4 or ip6) and found_ips['ipv4']: if not (ip4 or ip6) and (found_ips['ipv4'] or found_ips['ipv6']):
# do it again, but do not filter out private addresses # do it again, but do not filter out private addresses
for ip in sorted(found_ips['ipv4']): for ip in sorted(found_ips['ipv4']):
if not ip4: if not ip4:
ip4 = ip ip4 = ip
for ip in sorted(found_ips['ipv6']):
if not ip6:
ip6 = ip
if ip4: if ip4:
results.add('{} IN A {}'.format(dns_name, ip4)) results.add('{} IN A {}'.format(dns_name, ip4))

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

@ -13,6 +13,9 @@ defaults = {
'python3-wheel': {}, 'python3-wheel': {},
}, },
}, },
'nodejs': {
'version': 18,
},
'users': { 'users': {
'powerdnsadmin': { 'powerdnsadmin': {
'home': '/opt/powerdnsadmin', 'home': '/opt/powerdnsadmin',

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

@ -26,6 +26,9 @@ defaults = {
}, },
}, },
}, },
'nodejs': {
'version': 18,
},
'pretalx': { 'pretalx': {
'database': { 'database': {
'user': 'pretalx', 'user': 'pretalx',

13
bundles/proftpd/items.py Normal file
View file

@ -0,0 +1,13 @@
files['/etc/proftpd/proftpd.conf'] = {
'source': f'{node.name}.conf',
'triggers': {
'svc_systemd:proftpd:restart',
},
}
svc_systemd['proftpd'] = {
'needs': {
'file:/etc/proftpd/proftpd.conf',
'pkg_apt:proftpd-core',
},
}

View file

@ -0,0 +1,26 @@
from bundlewrap.metadata import atomic
defaults = {
'apt': {
'packages': {
'proftpd-core': {},
},
},
}
@metadata_reactor.provides(
'firewall/port_rules',
)
def firewall(metadata):
sources = atomic(metadata.get('mosquitto/restrict-to', set()))
return {
'firewall': {
'port_rules': {
'20/tcp': sources,
'21/tcp': sources,
'49152-50192/tcp': sources,
},
},
}

28
bundles/pyenv/items.py Normal file
View file

@ -0,0 +1,28 @@
from shlex import quote
directories = {
'/opt/pyenv': {},
'/opt/pyenv/install': {},
}
git_deploy = {
'/opt/pyenv/install': {
'repo': 'https://github.com/pyenv/pyenv.git',
'rev': node.metadata.get('pyenv/version'),
'needs': {
'directory:/opt/pyenv/install',
},
},
}
for version in node.metadata.get('pyenv/python_versions', set()):
actions[f'pyenv_install_{version}'] = {
'command': f'PYENV_ROOT=/opt/pyenv /opt/pyenv/install/bin/pyenv install {quote(version)}',
'unless': f'PYENV_ROOT=/opt/pyenv /opt/pyenv/install/bin/pyenv versions --bare | grep -E "^{quote(version)}$"',
'needs': {
'git_deploy:/opt/pyenv/install',
},
'after': {
'pkg_apt:',
},
}

20
bundles/pyenv/metadata.py Normal file
View file

@ -0,0 +1,20 @@
defaults = {
'apt': {
'packages': {
'build-essential': {},
'curl': {},
'libbz2-dev': {},
'libffi-dev': {},
'liblzma-dev': {},
'libncurses-dev': {},
'libreadline-dev': {},
'libsqlite3-dev': {},
'libssl-dev': {},
'libxml2-dev': {},
'libxmlsec1-dev': {},
'tk-dev': {},
'xz-utils': {},
'zlib1g-dev': {},
},
},
}

View file

@ -2,8 +2,8 @@
interface ${interface} interface ${interface}
{ {
AdvSendAdvert on; AdvSendAdvert on;
MinRtrAdvInterval 10; MinRtrAdvInterval 60;
MaxRtrAdvInterval 30; MaxRtrAdvInterval 300;
MinDelayBetweenRAs 10; MinDelayBetweenRAs 10;
prefix ${config.get('prefix', '::/64')} prefix ${config.get('prefix', '::/64')}
{ {
@ -11,7 +11,7 @@ interface ${interface}
AdvAutonomous on; AdvAutonomous on;
AdvRouterAddr on; AdvRouterAddr on;
}; };
% if 'rdnss' in config: % if config.get('rdnss'):
RDNSS ${' '.join(sorted(config['rdnss']))} RDNSS ${' '.join(sorted(config['rdnss']))}
{ {
AdvRDNSSLifetime 900; AdvRDNSSLifetime 900;

View file

@ -1,22 +1,30 @@
disable_overscan=1 disable_overscan=1
hdmi_force_hotplug=1
dtparam=spi=on
dtparam=audio=on dtparam=audio=on
dtoverlay=vc4-fkms-v3d dtoverlay=vc4-kms-v3d
max_framebuffers=2 max_framebuffers=2
hdmi_drive=2
force_turbo=1 force_turbo=1
gpu_mem=${node.metadata['raspberrypi'].get('gpu_mem', 128)} gpu_mem=${node.metadata.get('raspberrypi/gpu_mem', 128)}
% if node.metadata.get('raspberrypi/enable_display'):
display_auto_detect=1
% else:
dtparam=i2c_arm=on
dtparam=i2s=on
dtparam=spi=on
hdmi_drive=2
hdmi_force_hotplug=1
% endif
% if node.os == 'debian': % if node.os == 'debian':
arm_64bit=1 arm_64bit=1
% endif % endif
arm_boost=1
% for item in sorted(node.metadata['raspberrypi'].get('config.txt', set())): % for item in sorted(node.metadata.get('raspberrypi/config.txt', set())):
${item} ${item}
% endfor % endfor
% if node.metadata['raspberrypi'].get('camera', False): % if node.metadata.get('raspberrypi/enable_camera', False):
start_x=1 camera_auto_detect=1
% endif % endif

View file

@ -15,11 +15,11 @@ actions = {
} }
files = { files = {
'/boot/cmdline.txt': { '/boot/firmware/cmdline.txt': {
'content': ' '.join(sorted(node.metadata['raspberrypi']['cmdline'])), 'content': ' '.join(sorted(node.metadata['raspberrypi']['cmdline'])),
**file_perms, **file_perms,
}, },
'/boot/config.txt': { '/boot/firmware/config.txt': {
'content_type': 'mako', 'content_type': 'mako',
'context': node.metadata['raspberrypi'], 'context': node.metadata['raspberrypi'],
**file_perms, **file_perms,

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