Compare commits

...

107 commits

Author SHA1 Message Date
mwiegand
ec26eb548f wip 2022-08-13 15:31:52 +02:00
mwiegand
17181f9df0 wip 2022-08-13 15:31:52 +02:00
mwiegand
3d8deecd68 wip 2022-08-13 15:31:52 +02:00
mwiegand
7f42679f29 wip 2022-08-13 15:31:52 +02:00
mwiegand
a9918735ea wip 2022-08-13 15:31:52 +02:00
mwiegand
ef192700ba wip 2022-08-13 15:31:52 +02:00
mwiegand
83149c197e more grafana 2022-08-12 22:42:53 +02:00
mwiegand
6fef63655c proc ram cpu combined 2022-08-12 18:22:01 +02:00
mwiegand
63b68b8d3e disk_io only partitions 2022-08-12 18:19:19 +02:00
mwiegand
3b257aadab some grafana 2022-08-12 17:42:25 +02:00
mwiegand
88e80f4107 nextcloud update 2022-08-12 01:32:43 +02:00
mwiegand
8dfadbf9c3 typo 2022-08-11 19:31:42 +02:00
mwiegand
0cda286db1 pressure stall graph per ressource 2022-08-11 13:22:44 +02:00
mwiegand
d8de90fa5d pressure stall grafana 2022-08-11 13:18:30 +02:00
mwiegand
e05d987036 telegraf apcups less often 2022-08-11 12:40:28 +02:00
mwiegand
c8b7e34732 apcaccess telegraf: only one call 2022-08-11 12:37:28 +02:00
mwiegand
bb6eeba6fb readme 2022-08-11 12:37:13 +02:00
mwiegand
6c2d4ca69f pressure stall telegraf 2022-08-11 12:37:05 +02:00
mwiegand
706c4028f8 zfs mirror: delete old snapshots and bookmarks 2022-08-09 19:59:24 +02:00
mwiegand
3cd41adeaf smartctl doesnt work here 2022-08-09 19:59:02 +02:00
mwiegand
8a13421577 improve wake on lan 2022-08-09 19:58:47 +02:00
mwiegand
9ff8dce802 ssh multiplexing 2022-08-09 19:58:13 +02:00
mwiegand
49081248ae bundles/backup/files/backup_path_via_zfs: delte old bookmarks and snapshots 2022-08-09 19:57:52 +02:00
mwiegand
116697af9f keep fewer snpashots on backup servers 2022-08-09 19:15:58 +02:00
mwiegand
dc2dd9aa7a more timer readme 2022-08-09 18:13:28 +02:00
mwiegand
495f5537be bin/upgrade_and_restart_all: rename 2022-08-09 17:30:52 +02:00
mwiegand
0e28b18298 htop more delay 2022-08-09 17:02:40 +02:00
mwiegand
8d4abe1ec6 htop process io 2022-08-09 16:59:39 +02:00
mwiegand
ee3625311b htop 2022-08-09 16:50:46 +02:00
mwiegand
1343a85e0b editorconfig 2022-08-09 16:49:48 +02:00
mwiegand
fbe62c8127 monitor timers readme 2022-08-09 00:30:33 +02:00
mwiegand
1387b5f1ae nomodeset on nvidia gpu 2022-07-07 20:17:38 +02:00
mwiegand
e3a1438247 more proc_cpu data 2022-07-07 19:12:59 +02:00
mwiegand
b8cbf4648a influx: remove now-obsolete resolution feature 2022-07-07 19:05:53 +02:00
mwiegand
15f0317fbe massive flux performance increase 2022-07-07 19:00:36 +02:00
mwiegand
e44fc3dc04 further improve swap 2022-07-07 16:16:18 +02:00
mwiegand
f72ee7c85b remove obsolete metadatum 2022-07-07 15:46:15 +02:00
mwiegand
5eac0e8c85 home.server swapfile 2022-07-07 15:46:02 +02:00
mwiegand
fbee9a32df bundle systemd-swap improvements 2022-07-07 15:45:28 +02:00
mwiegand
1bde29bb17 fix pkg name 2022-07-07 15:35:10 +02:00
mwiegand
d10f2b1eb3 picsort: use File Modification Date as alternative 2022-07-07 15:35:01 +02:00
mwiegand
1397e9c9a3 picsort needs exiftool 2022-07-07 13:43:22 +02:00
mwiegand
1b84e84841 picsort heic 2022-07-07 13:29:04 +02:00
mwiegand
c37be21034 home.server more ram 2022-06-28 13:12:40 +02:00
mwiegand
57079a0cbe postgres tuning 2022-06-28 13:12:18 +02:00
mwiegand
cd5b854b00 nextcloud update 2022-06-28 10:18:00 +02:00
mwiegand
04d55caef6 only one ssd pool 2022-06-25 12:58:00 +02:00
mwiegand
8285a12f00 php pm dynamic 2022-06-23 21:35:30 +02:00
mwiegand
9946edc6f3 gitea ssd 2022-06-23 12:55:52 +02:00
mwiegand
a3c7acc399 influx on ssd 2022-06-23 02:52:18 +02:00
mwiegand
4530a34175 home.server more cores 2022-06-23 02:13:47 +02:00
mwiegand
b8100f472b zfs zfs_arc_max 2022-06-23 02:13:06 +02:00
mwiegand
9b104cac25 php pm more procasses 2022-06-23 02:12:33 +02:00
mwiegand
7243ad9e9b storage classes 2022-06-23 02:12:11 +02:00
mwiegand
12268daad6 sort 2022-06-23 01:32:31 +02:00
mwiegand
d4738d762b apt more unique sources lists 2022-06-23 00:26:51 +02:00
mwiegand
72f560809b reinstall home server and backups and many fixes 2022-06-22 22:31:39 +02:00
mwiegand
f55d46281c home server onboard lan 2022-06-20 10:51:37 +02:00
mwiegand
59537a536f grafana rows cpu more everything 2022-06-16 01:34:07 +02:00
mwiegand
ab55ad1020 comment 2022-06-16 01:30:41 +02:00
mwiegand
bb3b4b9bca nextcloud face recognition 2022-06-16 01:30:27 +02:00
mwiegand
f31f86aa21 php.ini as metadata 2022-06-16 01:30:06 +02:00
mwiegand
30b3d570fb nextcloud update 2022-06-16 01:29:45 +02:00
mwiegand
f6baeb328b nextcloud conf: log to syslog, trusted domain 2022-06-16 01:29:40 +02:00
mwiegand
31a4da75aa grafana cpu nice 2022-06-16 01:23:50 +02:00
mwiegand
a51d62f5d2 chatlogger more often 2022-06-11 23:26:38 +02:00
mwiegand
bada714b10 termux autostart 2022-06-01 23:11:55 +02:00
mwiegand
6f9218c5a1 bundle steam-chat-viewer 2022-06-01 20:09:28 +02:00
mwiegand
e6940b151c steam-chat-logger: steamuserimages subdir 2022-06-01 19:51:19 +02:00
mwiegand
5647654135 envrc: empty bw git deploy cache 2022-06-01 19:50:58 +02:00
mwiegand
5fd9452a6c hhtop resets htop config 2022-06-01 14:01:28 +02:00
mwiegand
2a84822cfe zsh namspacing 2022-06-01 13:50:20 +02:00
mwiegand
e62a7781b4 upadte zsh prompt 2022-06-01 13:14:47 +02:00
mwiegand
9f4e304aec upadte zsh prompt 2022-06-01 13:11:20 +02:00
mwiegand
8b2d8d974e upadte zsh prompt 2022-06-01 13:04:45 +02:00
mwiegand
3cddebee11 fix zsh plugins dir permissions plugins 2022-06-01 12:57:12 +02:00
mwiegand
c8b9a46aad update zsh prompt 2022-06-01 12:52:48 +02:00
mwiegand
35d8d4828b global oh-my-zsh 2022-06-01 12:41:45 +02:00
mwiegand
b9ff7e5953 manage global zprofile 2022-06-01 11:34:12 +02:00
mwiegand
8063833950 fix overwrite dicts 2022-06-01 11:33:59 +02:00
mwiegand
34b42832ac zsh prompt show username 2022-06-01 11:33:28 +02:00
mwiegand
52404fe7ce remove .python-version 2022-06-01 11:29:21 +02:00
mwiegand
76a568e8b6 node run wol 2022-06-01 11:11:14 +02:00
mwiegand
6706d04298 ckn user 2022-06-01 10:42:35 +02:00
mwiegand
cf09493486 zsh chown 2022-06-01 10:42:23 +02:00
mwiegand
8cabb029b3 systemd timers be nice 2022-06-01 09:39:17 +02:00
mwiegand
e81f28cf04 envrc add PATH and upgrade pip 2022-06-01 09:38:57 +02:00
mwiegand
df4ffd2d77 readme bw fork 2022-06-01 09:38:42 +02:00
mwiegand
b235ede36d git ignore *.pyc 2022-05-31 17:23:16 +02:00
mwiegand
e5a16b5506 php pm less workers 2022-05-31 17:22:37 +02:00
mwiegand
5e5118215a nicer ux 2022-05-31 17:21:43 +02:00
mwiegand
452c983f63 loadkeys support 2022-05-06 12:43:11 +02:00
mwiegand
c9e565bbde FIXME_dont_touch_sshd seems to be obsolete now? 2022-05-05 15:16:21 +02:00
mwiegand
5ed8f08231 change /etc/locale.gen after installing pkg_apt:locales 2022-05-05 14:21:57 +02:00
mwiegand
7588741b30 debian 12 2022-05-04 20:50:03 +02:00
mwiegand
f416852225 tasmota-charge: fixes + 2022-04-21 23:50:49 +02:00
mwiegand
f5ab497bff tasmota-charge: fixes 2022-04-21 23:32:42 +02:00
mwiegand
f2439dcf66 steam chat logger 2022-04-20 00:37:11 +02:00
mwiegand
b27f07a867 grafana use vhost from documentation 2022-04-09 16:32:34 +02:00
mwiegand
824b10546d grafana set domain 2022-04-09 16:32:08 +02:00
mwiegand
33d973927c dont keep backup snapshots 2022-04-09 16:31:55 +02:00
mwiegand
b528e9b94b wol fix and refactor 2022-04-02 19:30:59 +02:00
mwiegand
8a6c166f16 gutea 1.16.5 2022-04-02 14:39:49 +02:00
mwiegand
49346ba20b move bw managed systemd units to /usr/local/lib 2022-03-31 10:23:57 +02:00
mwiegand
31bf80f771 update nextcloud 2022-03-31 10:23:42 +02:00
mwiegand
1340aaf52e fix path 2022-03-30 10:06:16 +02:00
mwiegand
739c38d1b4 only reboot where necessary 2022-03-29 12:31:04 +02:00
98 changed files with 1795 additions and 468 deletions

22
.editorconfig Normal file
View file

@ -0,0 +1,22 @@
root = true
[*]
end_of_line = lf
[*.py]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
[*.toml]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
[*.yaml]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

4
.envrc
View file

@ -2,7 +2,11 @@
python3 -m venv .venv
source ./.venv/bin/activate
PATH_add .venv/bin
PATH_add bin
python3 -m pip install --upgrade pip
rm -rf .cache/bw/git_deploy
export BW_GIT_DEPLOY_CACHE=.cache/bw/git_deploy
export EXPERIMENTAL_UPLOAD_VIA_CAT=1
mkdir -p "$BW_GIT_DEPLOY_CACHE"

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.secrets.cfg*
.venv
.cache
*.pyc

View file

@ -1 +0,0 @@
3.9.0

View file

@ -12,3 +12,26 @@ Raspberry pi as soundcard
- gadget mode
- OTG g_audio
- https://audiosciencereview.com/forum/index.php?threads/raspberry-pi-as-usb-to-i2s-adapter.8567/post-215824
# install bw fork
pip3 install --editable git+file:///Users/mwiegand/Projekte/bundlewrap-fork#egg=bundlewrap
# monitor timers
```sh
Timer=backup
Triggers=$(systemctl show ${Timer}.timer --property=Triggers --value)
echo $Triggers
if systemctl is-failed "$Triggers"
then
InvocationID=$(systemctl show "$Triggers" --property=InvocationID --value)
echo $InvocationID
ExitCode=$(systemctl show "$Triggers" -p ExecStartEx --value | sed 's/^{//' | sed 's/}$//' | tr ';' '\n' | xargs -n 1 | grep '^status=' | cut -d '=' -f 2)
echo $ExitCode
journalctl INVOCATION_ID="$InvocationID" --output cat
fi
```
telegraf: execd for daemons

View file

@ -7,9 +7,10 @@ from ipaddress import ip_interface
repo = Repository(dirname(dirname(realpath(__file__))))
nodes = [
node
for node in repo.nodes_in_group('debian')
for node in sorted(repo.nodes_in_group('debian'))
if not node.dummy
]
reboot_nodes = []
print('updating nodes:', sorted(node.name for node in nodes))
@ -21,13 +22,16 @@ for node in nodes:
print('--------------------------------------')
repo.libs.wol.wake(node)
print(node.run('DEBIAN_FRONTEND=noninteractive apt update').stdout.decode())
print(node.run('DEBIAN_FRONTEND=noninteractive apt list --upgradable').stdout.decode())
if int(node.run('DEBIAN_FRONTEND=noninteractive apt list --upgradable 2> /dev/null | grep upgradable | wc -l').stdout.decode()):
print(node.run('DEBIAN_FRONTEND=noninteractive apt -y dist-upgrade').stdout.decode())
reboot_nodes.append(node)
# REBOOT IN ORDER
wireguard_servers = [
node
for node in nodes
for node in reboot_nodes
if node.has_bundle('wireguard')
and (
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen <
@ -37,7 +41,7 @@ wireguard_servers = [
wireguard_s2s = [
node
for node in nodes
for node in reboot_nodes
if node.has_bundle('wireguard')
and (
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen ==
@ -47,12 +51,11 @@ wireguard_s2s = [
everything_else = [
node
for node in nodes
for node in reboot_nodes
if not node.has_bundle('wireguard')
]
print('======================================')
print(len(everything_else), len(wireguard_s2s), len(wireguard_servers))
for node in [
*everything_else,
@ -60,4 +63,7 @@ for node in [
*wireguard_servers,
]:
print('rebooting', node.name)
try:
print(node.run('systemctl reboot').stdout.decode())
except Exception as e:
print(e)

9
bin/wake Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env python3
from bundlewrap.repo import Repository
from os.path import realpath, dirname
from sys import argv
repo = Repository(dirname(dirname(realpath(__file__))))
repo.libs.wol.wake(repo.get_node(argv[1]))

View file

@ -21,7 +21,9 @@ for peer in server_node.metadata.get('wireguard/s2s').values():
allowed_ips.append(ip_network(network))
conf = \
f'''[Interface]
f'''>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[Interface]
PrivateKey = {repo.libs.wireguard.privkey(data['peer_id'])}
ListenPort = 51820
Address = {data['peer_ip']}
@ -32,10 +34,12 @@ PublicKey = {repo.libs.wireguard.pubkey(server_node.metadata.get('id'))}
PresharedKey = {repo.libs.wireguard.psk(data['peer_id'], server_node.metadata.get('id'))}
AllowedIPs = {', '.join(str(client_route) for client_route in sorted(allowed_ips))}
Endpoint = {ip_interface(server_node.metadata.get('network/external/ipv4')).ip}:51820
PersistentKeepalive = 10'''
PersistentKeepalive = 10
if input("as test or qrcode? [Tq]: ") in 'Qq':
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'''
print(conf)
if input("print qrcode? [yN]: ").upper() == 'Y':
import pyqrcode
print(pyqrcode.create(conf).terminal(quiet_zone=1))
else:
print(conf)

View file

@ -2,7 +2,9 @@
date=$(date --utc +%s%N)
for metric in TIMELEFT LOADPCT BCHARGE
METRICS=$(apcaccess)
for METRIC in TIMELEFT LOADPCT BCHARGE
do
echo "apcupsd $metric=$(apcaccess -p $metric | cut -d' ' -f1) $date"
echo "apcupsd $METRIC=$(grep $METRIC <<< $METRICS | cut -d ':' -f 2 | xargs | cut -d ' ' -f 1 ) $date"
done

View file

@ -20,6 +20,8 @@ defaults = {
'commands': ["sudo /usr/local/share/telegraf/apcupsd"],
'name_override': "apcupsd",
'data_format': "influx",
'interval': '30s',
'flush_interval': '30s',
}),
},
},

View file

@ -48,8 +48,8 @@ hosts = {}
for source_string in node.metadata.get('apt/sources'):
source = repo.libs.apt.AptSource(source_string)
hosts\
.setdefault(source.url.hostname, set())\
.add(source)
.setdefault(source.url.hostname, list())\
.append(source)
# create sources lists and keyfiles
@ -61,12 +61,13 @@ for host, sources in hosts.items():
source.options['signed-by'] = [destination_path]
files[f'/etc/apt/sources.list.d/{host}.list'] = {
'content': '\n'.join(
str(source) for source in sorted(sources)
).format(
'content': '\n'.join(sorted(set(
str(source).format(
release=node.metadata.get('os_release'),
version=node.os_version[0], # WIP crystal
),
)
for source in sources
))),
'triggers': {
'action:apt_update',
},

View file

@ -44,8 +44,21 @@ fi
if [[ "$?" == "0" ]]
then
# delete old local bookmarks
for destroyable_bookmark in $(zfs list -t bookmark -H -o name "$dataset" | grep "^$dataset#$bookmark_prefix")
do
zfs destroy "$destroyable_bookmark"
done
# delete snapshots from bookmarks (except newest, even of not necessary; maybe for resuming tho)
for destroyable_snapshot in $($ssh sudo zfs list -t snapshot -H -o name "$dataset" | grep "^$dataset@$bookmark_prefix" | grep -v "$new_bookmark")
do
$ssh sudo zfs destroy "$destroyable_snapshot"
done
zfs bookmark "$source_dataset@$new_bookmark" "$source_dataset#$new_bookmark"
#zfs destroy "$source_dataset@$new_bookmark" # keep snapshots?
zfs destroy "$source_dataset@$new_bookmark" # keep snapshots?
echo "SUCCESS"
else
zfs destroy "$source_dataset@$new_bookmark"

View file

@ -114,6 +114,6 @@ for name, conf in node.metadata.get('flask').items():
svc_systemd[name] = {
'needs': [
f'action:flask_{name}_pip_install',
f'file:/etc/systemd/system/{name}.service',
f'file:/usr/local/lib/systemd/system/{name}.service',
],
}

View file

@ -11,10 +11,6 @@ downloads['/usr/local/bin/gitea'] = {
},
}
users['git'] = {
'home': '/home/git',
}
directories['/var/lib/gitea'] = {
'owner': 'git',
'mode': '0700',

View file

@ -1,6 +1,15 @@
database_password = repo.vault.password_for(f'{node.name} postgresql gitea')
defaults = {
'apt': {
'packages': {
'git': {
'needed_by': {
'svc_systemd:gitea',
}
},
},
},
'gitea': {
'database': {
'host': 'localhost',
@ -52,9 +61,25 @@ defaults = {
},
},
},
'users': {
'git': {
'home': '/home/git',
},
},
}
@metadata_reactor.provides(
'zfs/datasets',
)
def zfs(metadata):
if not node.has_bundle('zfs'):
return {}
return {
'zfs': {
'datasets': {
'tank/gitea': {
f"{metadata.get('zfs/storage_classes/ssd')}/gitea": {
'mountpoint': '/var/lib/gitea',
},
},

View file

@ -127,12 +127,16 @@ for dashboard_id, monitored_node in enumerate(monitored_nodes, start=1):
panel['fieldConfig']['defaults']['min'] = panel_config['min']
if 'max' in panel_config:
panel['fieldConfig']['defaults']['max'] = panel_config['max']
if 'soft_max' in panel_config:
panel['fieldConfig']['defaults']['custom']['axisSoftMax'] = panel_config['soft_max']
if 'legend' in panel_config:
panel['options']['legend'].update(panel_config['legend'])
if 'tooltip' in panel_config:
panel['options']['tooltip']['mode'] = panel_config['tooltip']
if panel_config['tooltip'] == 'multi':
panel['options']['tooltip']['sort'] = 'desc'
for query_name, query_config in panel_config['queries'].items():
panel['targets'].append({
@ -142,12 +146,12 @@ for dashboard_id, monitored_node in enumerate(monitored_nodes, start=1):
host=monitored_node.name,
negative=query_config.get('negative', False),
boolean_to_int=query_config.get('boolean_to_int', False),
resolution=query_config.get('resolution', 1) * 4,
minimum=query_config.get('minimum', None),
filters={
'host': monitored_node.name,
**query_config['filters'],
},
exists=query_config.get('exists', []),
function=query_config.get('function', None),
).strip()
})

View file

@ -55,6 +55,20 @@ defaults = {
}
@metadata_reactor.provides(
'grafana/config/server/domain',
)
def domain(metadata):
return {
'grafana': {
'config': {
'server': {
'domain': metadata.get('grafana/hostname'),
},
},
},
}
@metadata_reactor.provides(
'grafana/datasources',
)
@ -115,10 +129,7 @@ def nginx(metadata):
'nginx': {
'vhosts': {
metadata.get('grafana/hostname'): {
'content': 'nginx/proxy_pass.conf',
'context': {
'target': 'http://127.0.0.1:8300',
}
'content': 'grafana/vhost.conf',
},
},
},

5
bundles/grub/files/grub Normal file
View file

@ -0,0 +1,5 @@
GRUB_DEFAULT=0
GRUB_TIMEOUT=1
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="${' '.join(kernel_params)}"
GRUB_CMDLINE_LINUX=""

20
bundles/grub/items.py Normal file
View file

@ -0,0 +1,20 @@
files = {
'/etc/default/grub': {
'content_type': 'mako',
'context': {
'timeout': node.metadata.get('grub/timeout'),
'kernel_params': node.metadata.get('grub/kernel_params'),
},
'mode': '0644',
'triggers': {
'action:update-grub',
},
}
}
actions = {
'update-grub': {
'command': 'update-grub',
'triggered': True,
},
}

6
bundles/grub/metadata.py Normal file
View file

@ -0,0 +1,6 @@
defaults = {
'grub': {
'timeout': 1,
'kernel_params': set(),
},
}

View file

@ -2,6 +2,7 @@ defaults = {
'apt': {
'packages': {
'lm-sensors': {},
'console-data': {}, # leykeys de
},
},
'grafana_rows': {

View file

@ -0,0 +1,39 @@
# Beware! This file is rewritten by htop when settings are changed in the interface.
# The parser is also very primitive, and not human-friendly.
fields=0 48 17 18 38 39 40 2 46 47 109 110 49 1
sort_key=46
sort_direction=-1
tree_sort_key=0
tree_sort_direction=1
hide_kernel_threads=0
hide_userland_threads=0
shadow_other_users=0
show_thread_names=0
show_program_path=1
highlight_base_name=0
highlight_megabytes=1
highlight_threads=1
highlight_changes=0
highlight_changes_delay_secs=5
find_comm_in_cmdline=1
strip_exe_from_cmdline=1
show_merged_command=0
tree_view=0
tree_view_always_by_pid=0
header_margin=1
detailed_cpu_time=0
cpu_count_from_one=1
show_cpu_usage=0
show_cpu_frequency=0
show_cpu_temperature=0
degree_fahrenheit=0
update_process_names=0
account_guest_in_cpu_meter=0
color_scheme=0
enable_mouse=1
delay=20
left_meters=Hostname Tasks DiskIO NetworkIO Blank CPU Memory Swap Blank LeftCPUs${cpus_per_row}
left_meter_modes=2 2 2 2 2 1 1 1 2 1
right_meters=CPU Blank PressureStallCPUSome PressureStallMemorySome PressureStallIOSome Blank RightCPUs${cpus_per_row}
right_meter_modes=3 2 1 1 1 2 1
hide_function_bar=0

8
bundles/htop/items.py Normal file
View file

@ -0,0 +1,8 @@
files = {
'/etc/htoprc.global': {
'content_type': 'mako',
'context': {
'cpus_per_row': 4 if node.metadata.get('vm/threads', node.metadata.get('vm/cores', 1)) > 8 else 2,
},
},
}

7
bundles/htop/metadata.py Normal file
View file

@ -0,0 +1,7 @@
defaults = {
'apt': {
'packages': {
'htop': {},
},
},
}

View file

@ -0,0 +1,13 @@
template Host "generic-host" {
max_check_attempts = 3
check_interval = 1m
retry_interval = 30s
check_command = "hostalive"
}
template Service "generic-service" {
max_check_attempts = 5
check_interval = 1m
retry_interval = 30s
}

View file

@ -0,0 +1,6 @@
const PluginDir = "/usr/lib/nagios/plugins"
const ManubulonPluginDir = "/usr/lib/nagios/plugins"
const PluginContribDir = "/usr/lib/nagios/plugins"
const NodeName = "${domain}"
const ZoneName = NodeName
const TicketSalt = ""

View file

@ -0,0 +1,8 @@
library "db_ido_pgsql"
object IdoPgsqlConnection "ido-pgsql" {
user = "icinga2",
password = "${db_password}",
host = "localhost",
database = "icinga2"
}

View file

@ -0,0 +1,36 @@
<%!
def render_value(key, value):
if isinstance(value, Fault):
return render_value(key, value.value)
elif isinstance(value, type(None)):
return '""'
elif isinstance(value, bool):
return 'true' if value else 'false'
elif isinstance(value, int):
return str(value)
elif isinstance(value, str):
if key.endswith('_interval'):
return value
else:
return f'"{value}"'
elif isinstance(value, (list, set)):
return '[' + ', '.join(render_value(e) for e in sorted(value)) + ']'
else:
raise Exception(f"cant process type '{type(value)}' of value '{value}'")
%>
object Host "${host_name}" {
import "generic-host"
% for key, value in sorted(host_settings.items()):
${key} = ${render_value(key, value)}
% endfor
}
% for service_name, service_config in sorted(services.items(), key=lambda e: [e[1]['vars.bundle'], e[0]]):
object Service "${service_name}" {
import "generic-service"
% for key, value in sorted(service_config.items()):
${key} = ${render_value(key, value)}
% endfor
}
% endfor

View file

@ -0,0 +1,4 @@
include "constants.conf"
include_recursive "features.d"
include_recursive "conf.d"
include_recursive "hosts.d"

68
bundles/icinga2/items.py Normal file
View file

@ -0,0 +1,68 @@
# Git-Hash for Icinga1: b63bb0ef52bf213715e567c81e3ed097024e61af
directories = {
'/etc/icinga2': {
'purge': True,
'owner': 'nagios',
},
'/etc/icinga2/conf.d': {
'purge': True,
'owner': 'nagios',
},
'/etc/icinga2/hosts.d': {
'purge': True,
'owner': 'nagios',
},
'/etc/icinga2/features.d': {
'purge': True,
'owner': 'nagios',
},
}
files = {
'/etc/icinga2/icinga2.conf': {
'owner': 'nagios',
},
'/etc/icinga2/constants.conf': {
'owner': 'nagios',
'context': {
'hostname': node.metadata.get('icinga2/hostname')
},
},
'/etc/icinga2/conf.d/templates.conf': {
'source': 'conf.d/templates.conf',
'owner': 'nagios',
},
'/etc/icinga2/features/ido-pgsql.conf': {
'source': 'features/ido-pgsql.conf',
'content_type': 'mako',
'owner': 'nagios',
'context': {
'db_password': node.metadata.get('postgresql/roles/icinga2/password')
},
'needs': [
'pkg_apt:icinga2-ido-pgsql',
],
},
}
for other_node in repo.nodes:
files[f'/etc/icinga2/hosts.d/{other_node.name}.conf'] = {
'content_type': 'mako',
'source': 'hosts.d/host.conf',
'owner': 'nagios',
'context': {
'host_name': other_node.name,
'host_settings': {},
'services': other_node.metadata.get('monitoring', {}),
},
}
svc_systemd = {
'icinga2': {
'needs': [
'pkg_apt:icinga2-ido-pgsql',
'svc_systemd:postgresql',
],
},
}

View file

@ -0,0 +1,38 @@
from hashlib import sha3_256
defaults = {
'apt': {
'packages': {
'icinga2': {},
'icinga2-ido-pgsql': {},
'icingacli': {},
},
'sources': {
'deb https://packages.icinga.com/debian icinga-{release} main',
},
},
'postgresql': {
'databases': {
'icinga2': {
'owner': 'icinga2',
},
},
'roles': {
'icinga2': {
'password': repo.vault.password_for(f'psql icinga2 on {node.name}'),
},
},
},
'zfs': {
'datasets': {
'tank/icinga2': {
'mountpoint': '/var/lib/icinga2',
'needed_by': {
'pkg_apt:icinga2',
'pkg_apt:icingaweb2',
'pkg_apt:icinga2-ido-pgsql',
},
},
},
},
}

14
bundles/icingadb/items.py Normal file
View file

@ -0,0 +1,14 @@
import yaml, json
from bundlewrap.metadata import MetadataJSONEncoder
files = {
'/etc/icingadb/config.yml': {
'content': yaml.dump(
json.loads(
json.dumps(node.metadata.get('icingadb'), sort_keys=True, cls=MetadataJSONEncoder)
),
),
'mode': '0640',
'owner': 'icingadb',
},
}

View file

@ -0,0 +1,53 @@
defaults = {
'apt': {
'packages': {
'icingadb': {},
'icingadb-redis': {},
'icingadb-web': {},
},
'sources': {
'deb https://packages.icinga.com/debian icinga-{release} main',
'deb https://packages.icinga.com/debian icinga-{release}-snapshots main',
},
},
'postgresql': {
'databases': {
'icingadb': {
'owner': 'icingadb',
},
},
'roles': {
'icingadb': {
'password': repo.vault.password_for(f'psql icingadb on {node.name}'),
},
},
},
'redis': {
'icingadb': {
'port': '6381',
},
},
}
@metadata_reactor.provides(
'icingadb',
)
def config(metadata):
return {
'icingadb': {
'database': {
'type': 'postgresql',
'host': 'localhost',
'port': 3306,
'database': 'icingadb',
'user': 'icingadb',
'password': metadata.get('postgresql/roles/icingadb/password'),
},
'redis': {
'address': 'localhost:6380',
},
'logging': {
'level': 'info',
},
},
}

View file

@ -0,0 +1,6 @@
files = {
'/etc/icingaweb2/setup.token': {
'content': node.metadata.get('icingaweb2/setup_token'),
'owner': 'nagios',
},
}

View file

@ -0,0 +1,67 @@
from hashlib import sha3_256
defaults = {
'apt': {
'packages': {
'icingaweb2': {},
},
'sources': {
'deb https://packages.icinga.com/debian icinga-{release} main',
'deb https://packages.icinga.com/debian icinga-{release}-snapshots main',
},
},
'postgresql': {
'databases': {
'icingaweb2': {
'owner': 'icingaweb2',
},
},
'roles': {
'icingaweb2': {
'password': str(repo.vault.password_for(f'psql icingaweb2 on {node.name}')),
},
},
},
'redis': {
'icingadb': {},
},
}
@metadata_reactor.provides(
'icingaweb2/hostname',
)
def hostname(metadata):
return {
'icingaweb2': {
'hostname': metadata.get('icinga2/hostname'),
},
}
@metadata_reactor.provides(
'icingaweb2/setup_token',
)
def setup_token(metadata):
return {
'icingaweb2': {
'setup_token': sha3_256(metadata.get('id').encode()).hexdigest()[:16],
},
}
@metadata_reactor.provides(
'nginx/vhosts',
)
def nginx(metadata):
return {
'nginx': {
'vhosts': {
metadata.get('icingaweb2/hostname'): {
'content': 'icingaweb2/vhost.conf',
'context': {
},
},
},
},
}

View file

@ -5,7 +5,7 @@ directories['/var/lib/influxdb'] = {
'owner': 'influxdb',
'group': 'influxdb',
'needs': [
'zfs_dataset:tank/influxdb',
f"zfs_dataset:{node.metadata.get('zfs/storage_classes/ssd')}/influxdb",
],
}

View file

@ -4,6 +4,7 @@ defaults = {
'apt': {
'packages': {
'influxdb2': {},
'influxdb2-cli': {},
},
'sources': {
'deb https://repos.influxdata.com/debian {release} stable',
@ -21,15 +22,6 @@ defaults = {
'http-bind-address': ':8200',
},
},
'zfs': {
'datasets': {
'tank/influxdb': {
'mountpoint': '/var/lib/influxdb',
'recordsize': '8192',
'atime': 'off',
},
},
},
}
@metadata_reactor.provides(
@ -45,6 +37,26 @@ def admin_password(metadata):
}
@metadata_reactor.provides(
'zfs/datasets',
)
def zfs(metadata):
if not node.has_bundle('zfs'):
return {}
return {
'zfs': {
'datasets': {
f"{metadata.get('zfs/storage_classes/ssd')}/influxdb": {
'mountpoint': '/var/lib/influxdb',
'recordsize': '8192',
'atime': 'off',
},
},
},
}
@metadata_reactor.provides(
'dns',
)

View file

@ -6,6 +6,7 @@ defaults = {
'version': {
10: 11,
11: 17,
12: 17,
}[node.os_version[0]],
},
}

View file

@ -70,7 +70,7 @@ for name, config in node.metadata.get('left4dead2/servers').items():
}
svc_systemd[f'left4dead2-server-{name}'] = {
'needs': [
f'file:/etc/systemd/system/left4dead2-server-{name}.service',
f'file:/usr/local/lib/systemd/system/left4dead2-server-{name}.service',
],
}
server_units.add(f'left4dead2-server-{name}')
@ -87,7 +87,7 @@ for id in node.metadata.get('left4dead2/workshop'):
# TIDYUP
find_obsolete_units = (
'find /etc/systemd/system -type f -name "left4dead2-server-*.service" ' +
'find /usr/local/lib/systemd/system -type f -name "left4dead2-server-*.service" ' +
' '.join(f"! -name '{name}.service'" for name in server_units)
)
actions['remove_obsolete_left4dead2_units'] = {

View file

@ -10,6 +10,9 @@ files = {
'content': '\n'.join(
f'{locale} {type}' for locale, type in installed_locales
),
'needs': {
'pkg_apt:locales',
},
'triggers': {
'action:locale-gen',
},

View file

@ -1,7 +1,9 @@
#!/bin/bash
USER="$1"
SOURCEPATH="/var/lib/nextcloud/$1/files/$2"
REL_SOURCE_PATH="/$1/files/$2"
ABS_SOURCE_PATH="/var/lib/nextcloud/$1/files/$2"
REL_DEST_PATH="/$1/files/$3"
ABS_DEST_PATH="/var/lib/nextcloud/$1/files/$3"
@ -11,30 +13,41 @@ ABS_UNSORTABLE_PATH="/var/lib/nextcloud/$1/files/$4"
echo "STARTING..."
chown -R www-data:www-data "$SOURCEPATH"
chmod -R 770 "$SOURCEPATH"
chown -R www-data:www-data "$ABS_SOURCE_PATH"
chmod -R 770 "$ABS_SOURCE_PATH"
SCAN="FALSE"
IFS=$'\n'
for f in `find "$SOURCEPATH" -iname *.PNG -o -iname *.JPG -o -iname *.CR2 -o -iname *.CR3 -o -iname *.MP4 -o -iname *.MOV`; do
for f in `find "$ABS_SOURCE_PATH" -iname *.PNG -o -iname *.JPG -o -iname *.JPEG -o -iname *.HEIC -o -iname *.CR2 -o -iname *.CR3 -o -iname *.MP4 -o -iname *.MOV`; do
SCAN="TRUE"
echo "PROCESSING: $f"
DATE=`exiftool "$f" | grep -m 1 "Create Date"`
if ! echo "$DATE" | grep "Create Date" >/dev/null
EXIF=`exiftool "$f"`
if grep -q '^Create Date' <<< $EXIF
then
RELPATH=$(realpath --relative-to="$SOURCEPATH" "$f")
DATETIME=`grep -m 1 "^Create Date" <<< $EXIF | cut -d: -f2- | xargs`
elif grep -q '^File Modification Date' <<< $EXIF
then
DATETIME=`grep -m 1 '^File Modification Date' <<< $EXIF | cut -d: -f2- | xargs`
else
RELPATH=$(realpath --relative-to="$ABS_SOURCE_PATH" "$f")
DIRNAME=$(dirname "$ABS_UNSORTABLE_PATH/$RELPATH")
echo "UNSORTABLE: $f"
mkdir -p "$DIRNAME"
mv "$f" "$DIRNAME"
else
YEAR=`echo $DATE | cut -d':' -f2 | cut -c 2-`
MONTH=`echo $DATE | cut -d':' -f3`
DAY=`echo $DATE | cut -d':' -f4 | cut -d' ' -f1`
HOUR=`echo $DATE | cut -d':' -f4 | cut -d' ' -f2`
MINUTE=`echo $DATE | cut -d':' -f5`
SECOND=`echo $DATE | cut -d':' -f6`
SECOND=`echo $SECOND | cut -d'+' -f1` # remove timezone
continue
fi
DATE=`cut -d' ' -f1 <<< $DATETIME`
TIME=`cut -d' ' -f2 <<< $DATETIME | cut -d'+' -f1`
YEAR=`cut -d':' -f1 <<< $DATE`
MONTH=`cut -d':' -f2 <<< $DATE`
DAY=`cut -d':' -f3 <<< $DATE`
HOUR=`cut -d':' -f1 <<< $TIME`
MINUTE=`cut -d':' -f2 <<< $TIME`
SECOND=`cut -d':' -f3 <<< $TIME`
HASH=`sha256sum "$f" | xxd -r -p | base64 | head -c 3 | tr '/+' '_-'`
EXT=`echo "${f##*.}" | tr '[:upper:]' '[:lower:]'`
if [[ "$EXT" = "cr2" ]] || [[ "$EXT" = "cr3" ]]
@ -47,16 +60,16 @@ for f in `find "$SOURCEPATH" -iname *.PNG -o -iname *.JPG -o -iname *.CR2 -o -in
echo "DESTINATION: $FILE"
mkdir -p "$(dirname "$FILE")"
mv -v "$f" "$FILE"
fi
done
if [ "$SCAN" == "TRUE" ]; then
echo "SCANNING..."
# find "$SOURCEPATH/"* -type d -empty -delete >> /var/echo/nc-picsort.echo # nextcloud app bug when deleting folders
# find "$ABS_SOURCE_PATH/"* -type d -empty -delete >> /var/echo/nc-picsort.echo # nextcloud app bug when deleting folders
chown -R www-data:www-data "$ABS_DEST_PATH"
chown -R www-data:www-data "$ABS_UNSORTABLE_PATH"
chmod -R 770 "$ABS_DEST_PATH"
chmod -R 770 "$ABS_UNSORTABLE_PATH"
sudo -u www-data php /opt/nextcloud/occ files:scan --path "$REL_SOURCE_PATH"
sudo -u www-data php /opt/nextcloud/occ files:scan --path "$REL_UNSORTABLE_PATH"
sudo -u www-data php /opt/nextcloud/occ files:scan --path "$REL_DEST_PATH"
sudo -u www-data php /opt/nextcloud/occ preview:pre-generate

View file

@ -1,6 +1,15 @@
from shlex import quote as q
defaults = {
'apt': {
'packages': {
'libimage-exiftool-perl': {},
},
},
}
@metadata_reactor.provides(
'systemd-timers',
)

View file

@ -28,4 +28,15 @@ $CONFIG = array (
"redis" => [
"host" => "/var/run/redis/nextcloud.sock",
],
'trusted_domains' =>
array (
0 => 'localhost',
1 => '127.0.0.1',
2 => '${hostname}',
),
"log_type" => "syslog",
"syslog_tag" => "nextcloud",
"logfile" => "",
"loglevel" => 3,
"default_phone_region" => "DE",
);

View file

@ -75,6 +75,7 @@ files = {
'mode': '640',
'context': {
'db_password': node.metadata.get('postgresql/roles/nextcloud/password'),
'hostname': node.metadata.get('nextcloud/hostname'),
},
'needs': [
'directory:/etc/nextcloud',
@ -126,7 +127,7 @@ files['/opt/nextcloud_upgrade_status.php'] = {
actions['upgrade_nextcloud'] = {
'command': repo.libs.nextcloud.occ('upgrade'),
'unless': 'sudo -u www-data php /opt/nextcloud/upgrade_status.php; test $? -ne 99',
'unless': 'sudo -u www-data php /opt/nextcloud_upgrade_status.php; test $? -ne 99',
'needs': [
'file:/opt/nextcloud_upgrade_status.php',
'action:install_nextcloud',

View file

@ -5,6 +5,7 @@ defaults = {
'apt': {
'packages': {
'php': {},
'php-redis': {},
'php-fpm': {},
'php-curl': {},
'php-gd': {},
@ -15,6 +16,15 @@ defaults = {
'php-cgi': {},
'php-zip': {},
'php-pgsql': {},
'php-bz2': {}, # face recognition
'php-intl': {},
'php-imagick': {},
'libmagickcore-6.q16-6-extra': {},
'php-gmp': {},
'php-bcmath': {},
},
'sources': {
'deb https://repo.delellis.com.ar {release} {release}', # face recognition
},
},
'archive': {
@ -50,6 +60,11 @@ defaults = {
'env[TMPDIR]': '/tmp',
'env[TEMP]': '/tmp',
},
'php.ini': {
'PHP': {
'memory_limit': '3G', # face recognition requires 2G
},
},
},
'postgresql': {
'roles': {
@ -77,6 +92,11 @@ defaults = {
'when': 'Sun 00:00:00',
'user': 'www-data',
},
'nextcloud-face-recognition': {
'command': '/usr/bin/php -f /opt/nextcloud/occ face:background_job -t 1800',
'when': '*:0/10',
'user': 'www-data',
},
},
'zfs': {
'datasets': {
@ -107,3 +127,16 @@ def vhost(metadata):
},
},
}
@metadata_reactor.provides(
'nginx/vhosts'
)
def pdlib(metadata):
return {
'apt': {
'packages': {
f"php{metadata.get('php/version')}-pdlib": {}, # face recognition
},
},
}

View file

@ -1,110 +0,0 @@
[PHP]
; Only needed for libapache2-mod-php?
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
serialize_precision = -1
ignore_user_abort = Off
zend.enable_gc = On
expose_php = Off
max_execution_time = 300
max_input_time = 600
memory_limit = 1G
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
html_errors = On
error_log = syslog
syslog.ident = php7.4
syslog.filter = ascii
arg_separator.output = "&amp;"
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = ${post_max_size}
default_mimetype = "text/html"
default_charset = "UTF-8"
enable_dl = Off
file_uploads = On
upload_max_filesize = ${post_max_size}
max_file_uploads = 2000
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 10
[CLI Server]
cli_server.color = On
[mail function]
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 32
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 6
[Assertion]
zend.assertions = -1
[Date]
date.timezone = Europe/London
[opcache]
opcache.enable = 1
opcache.interned_strings_buffer = 32
opcache.max_accelerated_files = 20000
opcache.memory_consumption = 1024
opcache.save_comments = 1
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60

View file

@ -1,22 +1,21 @@
version = node.metadata.get('php/version')
from os.path import join
import json
php_ini_context = {
'num_cpus': node.metadata.get('vm/cores'),
'post_max_size': node.metadata.get('php/post_max_size'),
}
from bundlewrap.utils.dicts import merge_dict
version = node.metadata.get('php/version')
files = {
f'/etc/php/{version}/cli/php.ini': {
'content_type': 'mako',
'context': php_ini_context,
'content': repo.libs.ini.dumps(node.metadata.get('php/php.ini')),
'needs': {
f'pkg_apt:php{version}',
f'pkg_apt:php{version}-fpm',
},
},
f'/etc/php/{version}/fpm/php.ini': {
'content_type': 'mako',
'context': php_ini_context,
'content': repo.libs.ini.dumps(node.metadata.get('php/php.ini')),
'needs': {
f'pkg_apt:php{version}',
f'pkg_apt:php{version}-fpm',

View file

@ -1,6 +1,129 @@
defaults = {
}
@metadata_reactor.provides(
'php/php.ini',
)
def php_ini(metadata):
conf = {
'PHP': {
'engine': 'On',
'short_open_tag': 'Off',
'precision': '14',
'output_buffering': '4096',
'zlib.output_compression': 'Off',
'implicit_flush': 'Off',
'serialize_precision': '-1',
'ignore_user_abort': 'Off',
'zend.enable_gc': 'On',
'expose_php': 'Off',
'max_execution_time': '300',
'max_input_time': '600',
'memory_limit': '512M',
'error_reporting': '"E_ALL & ~E_DEPRECATED & ~E_STRICT"',
'display_startup_errors': 'Off',
'log_errors': 'On',
'log_errors_max_len': '1024',
'ignore_repeated_errors': 'Off',
'ignore_repeated_source': 'Off',
'report_memleaks': 'On',
'html_errors': 'On',
'error_log': 'syslog',
'syslog.ident': 'php',
'syslog.filter': 'ascii',
'arg_separator.output': '"&amp;"',
'variables_order': 'GPCS',
'request_order': 'GP',
'register_argc_argv': 'Off',
'auto_globals_jit': 'On',
'post_max_size': '32g',
'default_mimetype': 'text/html',
'default_charset': 'UTF-8',
'enable_dl': 'Off',
'file_uploads': 'On',
'upload_max_filesize': '32g',
'max_file_uploads': '2000',
'allow_url_fopen': 'On',
'allow_url_include': 'Off',
'default_socket_timeout': '10',
},
'CLI Server': {
'cli_server.color': 'On',
},
'mail function': {
'mail.add_x_header': 'Off',
},
'ODBC': {
'odbc.allow_persistent': 'On',
'odbc.check_persistent': 'On',
'odbc.max_persistent': '-1',
'odbc.max_links': '-1',
'odbc.defaultlrl': '4096',
'odbc.defaultbinmode': '1',
},
'PostgreSQL': {
'pgsql.allow_persistent': 'On',
'pgsql.auto_reset_persistent': 'Off',
'pgsql.max_persistent': '-1',
'pgsql.max_links': '-1',
'pgsql.ignore_notice': '0',
'pgsql.log_notice': '0',
},
'bcmath': {
'bcmath.scale': '0',
},
'Session': {
'session.save_handler': 'files',
'session.use_strict_mode': '0',
'session.use_cookies': '1',
'session.use_only_cookies': '1',
'session.name': 'PHPSESSID',
'session.auto_start': '0',
'session.cookie_lifetime': '0',
'session.cookie_path': '/',
'session.cookie_domain': '',
'session.cookie_httponly': '',
'session.cookie_samesite': '',
'session.serialize_handler': 'php',
'session.gc_probability': '1',
'session.gc_divisor': '1000',
'session.gc_maxlifetime': '1440',
'session.referer_check': '',
'session.cache_limiter': 'nocache',
'session.cache_expire': '180',
'session.use_trans_sid': '0',
'session.sid_length': '32',
'session.trans_sid_tags': '"a=href,area=href,frame=src,form="',
'session.sid_bits_per_character': '6',
},
'Assertion': {
'zend.assertions': '-1',
},
'Date': {
'date.timezone': 'Europe/London',
},
'opcache': {
'opcache.enable': '1',
'opcache.interned_strings_buffer': '32',
'opcache.max_accelerated_files': '20000',
'opcache.memory_consumption': '1024',
'opcache.save_comments': '1',
'opcache.validate_timestamps': '1',
'opcache.revalidate_freq': '60',
},
}
return {
'php': {
'post_max_size': '32G',
'php.ini': {
section: {
key: value
for key, value in options.items()
if not metadata.get(f'php/php.ini/{section}/{key}', None)
}
for section, options in conf.items()
}
},
}
@ -9,21 +132,22 @@ defaults = {
'php/www.conf',
)
def www_conf(metadata):
version = metadata.get('php/version')
threads = metadata.get('vm/threads', metadata.get('vm/cores', 4))
return {
'php': {
'www.conf': {
'user': 'www-data',
'group': 'www-data',
'listen': f'/run/php/php{version}-fpm.sock',
'listen': f"/run/php/php{metadata.get('php/version')}-fpm.sock",
'listen.owner': 'www-data',
'listen.group': 'www-data',
'pm': 'dynamic',
'pm.max_children': '60',
'pm.start_servers': '20',
'pm.min_spare_servers': '10',
'pm.max_spare_servers': '20',
'pm.max_requests': '500',
'pm.max_children': int(threads*2),
'pm.start_servers': int(threads),
'pm.min_spare_servers': int(threads/2),
'pm.max_spare_servers': int(threads),
'pm.max_requests': int(threads*32),
},
},
}
@ -33,12 +157,11 @@ def www_conf(metadata):
'apt/packages',
)
def apt(metadata):
version = metadata.get('php/version')
return {
'apt': {
'packages': {
f'php{version}': {},
f'php{version}-fpm': {},
f"php{metadata.get('php/version')}": {},
f"php{metadata.get('php/version')}-fpm": {},
},
},
}

View file

@ -1,12 +1,15 @@
from bundlewrap.utils.dicts import merge_dict
version = node.metadata.get('postgresql/version')
directories = {
'/var/lib/postgresql': {
'owner': 'postgres',
'group': 'postgres',
'needs': [
'pkg_apt:postgresql',
'zfs_dataset:tank/postgresql',
f"zfs_dataset:{node.metadata.get('zfs/storage_classes/ssd')}/postgresql",
],
'needed_by': [
'svc_systemd:postgresql',
@ -14,6 +17,22 @@ directories = {
}
}
files = {
f"/etc/postgresql/{version}/main/conf.d/managed.conf": {
'content': '\n'.join(
f'{key} = {value}'
for key, value in sorted(node.metadata.get('postgresql/conf').items())
) + '\n',
'owner': 'postgres',
'group': 'postgres',
'needed_by': [
'svc_systemd:postgresql',
],
'triggers': [
'svc_systemd:postgresql:restart',
],
},
}
svc_systemd['postgresql'] = {
'needs': [

View file

@ -1,3 +1,6 @@
import builtins
root_password = repo.vault.password_for(f'{node.name} postgresql root')
defaults = {
@ -12,6 +15,7 @@ defaults = {
},
},
'postgresql': {
'conf': {},
'roles': {
'root': {
'password': root_password,
@ -23,15 +27,50 @@ defaults = {
'grafana_rows': set(),
}
if node.has_bundle('zfs'):
defaults['zfs'] = {
@metadata_reactor.provides(
'postgresql/conf',
)
def conf(metadata):
conf = {}
def limit(value, min=float('-inf'), max=float('inf'), unit=None):
result = int(builtins.max([builtins.min([max, value]), min]))
return str(result) + unit if unit else result
ram = metadata.get('vm/ram', None)
if ram:
conf['max_connections'] = limit(ram/50, min=100)
conf['shared_buffers'] = limit(ram/20, min=128, unit='MB')
conf['work_mem'] = limit(ram/500, min=4, max=64, unit='MB')
conf['temp_buffers'] = limit(ram/500, min=8, max=64, unit='MB')
conf['effective_cache_size'] = limit(ram/3, min=4096, unit='MB')
conf['maintenance_work_mem'] = limit(ram/50, min=64, unit='MB')
return {
'postgresql': {
'conf': conf,
},
}
@metadata_reactor.provides(
'zfs/datasets',
)
def zfs(metadata):
if not node.has_bundle('zfs'):
return {}
return {
'zfs': {
'datasets': {
'tank/postgresql': {
f"{metadata.get('zfs/storage_classes/ssd')}/postgresql": {
'mountpoint': '/var/lib/postgresql',
'recordsize': '8192',
'atime': 'off',
},
},
},
}

View file

@ -4,3 +4,6 @@ Host *
GSSAPIAuthentication yes
StrictHostKeyChecking yes
GlobalKnownHostsFile /etc/ssh/ssh_known_hosts
ControlMaster auto
ControlPath ~/.ssh/multiplex-%C
ControlPersist 5m

View file

@ -0,0 +1,48 @@
directories = {
'/opt/steam_chat_logger': {
'owner': 'steam_chat_logger',
},
'/var/lib/steam_chat_logger': {
'owner': 'steam_chat_logger',
'mode': '0755',
'needs': [
'zfs_dataset:tank/steam-chat-logger'
],
},
'/var/lib/steam_chat_logger/steamuserimages': {
'owner': 'steam_chat_logger',
'mode': '0755',
'needs': [
'zfs_dataset:tank/steam-chat-logger'
],
},
}
git_deploy = {
'/opt/steam_chat_logger': {
'repo': 'https://git.sublimity.de/cronekorkn/steam_chat_logger.git',
'rev': 'master',
}
}
pkg_pip = {
'steam': {},
'beautifulsoup4': {},
'pytz': {},
'pg8000': {},
}
# TODO
'''
CREATE TABLE IF NOT EXISTS messages (
id SERIAL PRIMARY KEY,
checksum VARCHAR(64) UNIQUE NOT NULL,
from_url VARCHAR(255) NOT NULL,
from_name VARCHAR(255) NOT NULL,
to_url VARCHAR(255) NOT NULL,
to_name VARCHAR(255) NOT NULL,
date TIMESTAMP WITH TIME ZONE NOT NULL,
message TEXT NOT NULL
)
'''

View file

@ -0,0 +1,51 @@
defaults = {
'apt': {
'packages': {
'python3-pip': {},
},
},
'postgresql': {
'roles': {
'steam_chat_logger': {
'password': repo.vault.password_for(f'{node.name} postgresql steam_chat_logger'),
},
},
'databases': {
'steam_chat_logger': {
'owner': 'steam_chat_logger',
},
},
},
'users': {
'steam_chat_logger': {},
},
'zfs': {
'datasets': {
'tank/steam-chat-logger': {
'mountpoint': '/var/lib/steam_chat_logger',
},
},
},
}
@metadata_reactor.provides(
'systemd-timers/steam-chat-logger',
)
def systemd_timer(metadata):
return {
'systemd-timers': {
f'steam-chat-logger': {
'command': '/opt/steam_chat_logger/steam_chat_logger.py',
'when': 'hourly',
'user': 'steam_chat_logger',
'env': {
'DB_NAME': 'steam_chat_logger',
'DB_USER': 'steam_chat_logger',
'DB_PASSWORD': metadata.get('postgresql/roles/steam_chat_logger/password'),
**metadata.get('steam_chat_logger'),
},
'working_dir': '/var/lib/steam_chat_logger',
},
},
}

View file

@ -0,0 +1,55 @@
from ipaddress import ip_interface
defaults = {
'flask': {
'steam-chat-viewer' : {
'git_url': "https://git.sublimity.de/cronekorkn/steam-chat-viewer.git",
'port': 4001,
'app_module': 'steam_chat_viewer',
'user': 'steam_chat_viewer',
'group': 'steam_chat_viewer',
'timeout': 900,
'env': {
'DB_HOST': 'localhost',
'DB_NAME': 'steam_chat_logger',
'DB_USER': 'steam_chat_logger',
},
},
},
'users': {
'steam_chat_viewer': {},
},
}
@metadata_reactor.provides(
'flask/steam-chat-viewer/env/DB_PASSWORD',
)
def agent_conf(metadata):
return {
'flask': {
'steam-chat-viewer': {
'env': {
'DB_PASSWORD': metadata.get('postgresql/roles/steam_chat_logger/password'),
},
},
},
}
@metadata_reactor.provides(
'nginx/vhosts',
)
def nginx(metadata):
return {
'nginx': {
'vhosts': {
metadata.get('steam-chat-viewer/hostname'): {
'content': 'steam-chat-viewer/vhost.conf',
'context': {
'target': 'http://127.0.0.1:4001',
},
},
},
},
}

View file

@ -54,6 +54,6 @@ actions = {
svc_systemd['steam-update'] = {
'running': False,
'needs': {
'file:/etc/systemd/system/steam-update.service',
'file:/usr/local/lib/systemd/system/steam-update.service',
}
}

View file

@ -1,49 +1,56 @@
size = node.metadata.get('systemd-swap')
assert isinstance(size, int)
size_mb = node.metadata.get('systemd-swap')//1_000_000
actions = {
'stop_swap': {
'command': f'systemctl stop swapfile.swap',
'unless': f'rm /swapfile',
'unless': f'! systemctl is-active swapfile.swap',
'triggered': True,
},
'remove_swapfile': {
'command': f'rm /swapfile',
'unless': f'! test -e /swapfile',
'triggered': True,
'needs': {
'action:stop_swap',
},
},
'create_swapfile': {
'command': f'dd if=/dev/zero of=/swapfile bs={size} count=1',
'unless': f'stat -c %s /swapfile | grep ^{size}$',
'command': f'dd if=/dev/zero of=/swapfile bs=1000000 count={size_mb}',
'unless': f'stat -c %s /swapfile | grep ^{size_mb*1_000_000}$',
'preceded_by': {
'action:stop_swap',
'action:remove_swapfile',
},
'triggers': {
'action:initialize_swapfile',
'svc_systemd:swapfile.swap:restart',
},
},
'swapfile_mode': {
'command': f'chmod 600 /swapfile',
'unless': f'stat -c "%a" /swapfile | grep -q "^600$"',
'needs': {
'action:create_swapfile',
},
'triggers': {
'svc_systemd:swapfile.swap:restart',
},
},
'initialize_swapfile': {
'command': f'mkswap /swapfile',
'triggered': True,
'needs': {
'action:create_swapfile',
'action:swapfile_mode',
}
},
}
files = {
'/swapfile': {
'content_type': 'any',
'mode': '600',
'triggers': {
'svc_systemd:swapfile.swap:restart',
},
}
}
svc_systemd = {
'swapfile.swap': {
'preceded_by': {
'action:initialize_swapfile',
},
'needs': {
'file:/swapfile',
'action:initialize_swapfile',
'action:systemd-reload',
},

View file

@ -30,9 +30,16 @@ def systemd(metadata):
'Service': {
'User': config.get('user', 'root'),
'ExecStart': config['command'],
'Environment': config.get('env'),
'Nice': config.get('nice', 10),
},
},
})
if config.get('working_dir'):
units[f'{name}.service']['Service']['WorkingDirectory'] = config['working_dir']
if config.get('success_exit_status'):
units[f'{name}.service']['Service']['SuccessExitStatus'] = config['success_exit_status']
services[f'{name}.timer'] = {}
return {

View file

@ -1,5 +1,11 @@
# SYSTEMD
## show unit paths
```
systemctl --no-pager --property=UnitPath show | tr ' ' '\n'
```
## metadata
```python

View file

@ -1,5 +1,14 @@
from bundlewrap.utils.dicts import merge_dict
directories = {
'/usr/local/lib/systemd/system': {
'purge': True,
'triggers': [
"action:systemd-reload",
],
},
}
actions = {
'systemd-reload': {
'command': 'systemctl daemon-reload',
@ -22,7 +31,7 @@ for name, unit in node.metadata.get('systemd/units').items():
],
}
elif extension in ['timer', 'service', 'mount', 'swap']:
path = f'/etc/systemd/system/{name}'
path = f'/usr/local/lib/systemd/system/{name}'
dependencies = {
'triggers': [
"action:systemd-reload",

View file

@ -1,14 +1,23 @@
# Phone
- install termux from Play Store
- install termux::api from Play Store
- install termux from F-Droid
- install termux::api from F-Droid
- open termux
- run `pkg update`
- run `pkg install termux-api openssh`
- run `passwd` and set a password
- run `whoami` to get the username
- run `sshd` to start ssh server
- run `su - tasmota-charge -c 'ssh-copy-id -p 8022 u0_a233@10.0.0.175'` on server node
- acquire wakelock for the termux session in notifications
- install termux::boot from F-Droid
- create file ~/.termux/boot/start-sshd:
```shell
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
sshd
```
# Server
- you can run something like `su - tasmota-charge -c 'ssh-copy-id -p 8022 u0_q194@10.0.0.166'`
- you can run something like `su - tasmota-charge -c 'ssh -p 8022 u0_a233@10.0.0.175'`

View file

@ -6,16 +6,26 @@ PLUG_IP=${plug_ip}
MIN=${min}
MAX=${max}
AKKU=$(ssh -p 8022 $PHONE_USER@$PHONE_IP termux-battery-status | jq -r .percentage)
echo "akku is at $AKKU%"
if ! ssh -o 'StrictHostKeyChecking no' -p 8022 $PHONE_USER@$PHONE_IP 'true'
then
echo "ERROR: cant connect to phone via ssh"
exit 51
fi
AKKU=$(ssh -o 'StrictHostKeyChecking no' -p 8022 $PHONE_USER@$PHONE_IP termux-battery-status | jq -r .percentage)
echo "akku is at $AKKU% ($MIN%/$MAX%)"
if ! curl --head --silent --fail "http://$PLUG_IP/cm?cmnd=Power" --output /dev/null
then
echo "ERROR: cant connect to plug via http"
exit 52
fi
PLUG_IS=$(curl -s "http://$PLUG_IP/cm?cmnd=Power" | jq -r .POWER)
echo "plug is $PLUG_IS"
if [[ $AKKU < $MIN ]] && [[ $PLUG_IS = OFF ]]
if [[ $AKKU -lt $MIN ]] && [[ $PLUG_IS = OFF ]]
then
TURN_PLUG=ON
elif [[ $AKKU > $MAX ]] && [[ $PLUG_IS = ON ]]
elif [[ $AKKU -gt $MAX ]] && [[ $PLUG_IS = ON ]]
then
TURN_PLUG=OFF
else
@ -24,4 +34,11 @@ else
fi
echo "turning plug $TURN_PLUG"
curl -s "http://$PLUG_IP/cm?cmnd=Power%20$TURN_PLUG"
if curl --silent "http://$PLUG_IP/cm?cmnd=Power%20$TURN_PLUG" | jq -r .POWER | grep -q "^$TURN_PLUG\$"
then
echo "SUCCESS"
exit 0
else
echo "ERROR"
exit 53
fi

View file

@ -20,6 +20,11 @@ files = {
'source': f"https://dl.sublimity.de/telegraf-procio/telegraf-procio-{node.metadata.get('system/architecture')}-latest",
'mode': '0755',
},
'/usr/local/share/telegraf/pressure_stall': {
'content_type': 'download',
'source': f"https://dl.sublimity.de/telegraf-pressure-stall/telegraf-pressure-stall-{node.metadata.get('system/architecture')}-latest",
'mode': '0755',
},
}
svc_systemd['telegraf'] = {

View file

@ -5,9 +5,6 @@ defaults = {
'packages': {
'telegraf': {},
},
'sources': {
'deb https://repos.influxdata.com/debian {release} stable',
},
},
'telegraf': {
'config': {
@ -48,20 +45,31 @@ defaults = {
'memory_rss',
],
})},
'diskio': {h({})},
'diskio': {h({
'device_tags': ["ID_PART_ENTRY_NUMBER"],
})},
'kernel': {h({})},
'mem': {h({})},
'processes': {h({})},
'swap': {h({})},
'system': {h({})},
'net': {h({})},
'exec': {h({
'exec': {
h({
'commands': [
f'sudo /usr/local/share/telegraf/procio',
],
'data_format': 'influx',
'interval': '20s',
})},
}),
h({
'commands': [
f'/usr/local/share/telegraf/pressure_stall',
],
'data_format': 'influx',
'interval': '10s',
}),
},
},
},
},
@ -71,8 +79,7 @@ defaults = {
'disk_io',
'disk_usage',
'net_io',
'proc_cpu',
'proc_ram',
'proc_cpu_ram',
'proc_io',
},
'sudoers': {
@ -81,6 +88,28 @@ defaults = {
}
@metadata_reactor.provides(
'apt/sources',
)
def apt(metadata):
release = {
'buster': 'buster',
'bullseye': 'bullseye',
'bookworm': 'bullseye',
}[metadata.get('os_release')]
return {
'apt': {
'packages': {
'telegraf': {},
},
'sources': {
f"deb https://repos.influxdata.com/debian {release} stable",
},
},
}
@metadata_reactor.provides(
'telegraf/config/outputs/influxdb_v2',
)

View file

@ -1,40 +1,73 @@
#!/bin/bash
WOKE=$(expr $(journalctl -t systemd-sleep -b 0 -o json MESSAGE="System resumed." -n1 | jq -r .__REALTIME_TIMESTAMP) / 1000000)
NOW=$(date +%s)
UPTIME=$(expr $NOW - $WOKE)
# CHECK UPTIME
RESUMED_TIMESTAMP_MICRO=$(journalctl -t systemd-sleep -b 0 -o json MESSAGE="System resumed." -n1 | jq -r .__REALTIME_TIMESTAMP)
if [[ -z "$RESUMED_TIMESTAMP_MICRO" ]]
then
UPTIME=$(cat /proc/uptime | cut -d' ' -f1 | cut -d'.' -f1)
else
RESUMED_TIMESTAMP=$(expr $RESUMED_TIMESTAMP_MICRO / 1000000)
NOW_TIMESTAMP=$(date +%s)
UPTIME=$(expr $NOW_TIMESTAMP - $RESUMED_TIMESTAMP)
fi
MIN_UPTIME=$(expr 60 \* 15)
if [[ "$UPTIME" -lt "$MIN_UPTIME" ]]
then
echo "ABORT: uptime ($UPTIME s) lower than minimum ($MIN_UPTIME s)"
exit 0
echo "ABORT: uptime of ${UPTIME}s is lower than minimum of ${MIN_UPTIME}s"
exit 75
fi
MY_SERVICE="$2"
# CHECK FOR RUNNING TIMERS
for SERVICE in $(systemctl list-timers --no-pager --no-legend --state active -o json | jq -r '.[] | .activates')
do
if [[ "$SERVICE" = "$MY_SERVICE" ]]
if [[ "$SERVICE" = "$THIS_SERVICE" ]]
then
continue
elif systemctl is-active "$SERVICE" --quiet
then
echo "ABORT: service $SERVICE is running by timer"
exit 0
exit 75
fi
done
LOGINS=$(netstat -tnpa | grep 'ESTABLISHED.*sshd' | wc -l)
if [[ "$LOGINS" -gt 0 ]]
# CHECK FOR ACTIVE LOGINS
LOGINS=$(netstat -tnpa | grep 'ESTABLISHED.*sshd' | tr -s ' ' | cut -d' ' -f5,7-8 | paste -d',' -s | sed 's/,/, /')
if ! [[ -z "$LOGINS" ]]
then
echo "ABORT: $LOGINS user logins"
exit 0
echo "ABORT: users logged in: $LOGINS"
exit 75
fi
if [[ "$1" = now ]]
# SUSPEND!
if [[ "$1" = check ]]
then
echo "SESPENDING"
sleep 60
systemctl suspend
else
echo "WOULD SESPEND"
exit 0
else
echo "SESPENDING AFTER TIMEOUT"
for i in 1 2 3 4 5 6
do
echo "TIMEOUT ${i} success"
sleep 10
# check if condition is still met
if "$0" check
then
continue
else
echo "SESPENSION ABORTED"
exit 75
fi
done
echo "SESPENDING"
systemctl suspend
exit 0
fi

View file

@ -3,7 +3,7 @@ if not waker_node.has_bundle('wol-waker'):
raise Exception(f'waker node {waker_node.name} does not have bundle wol-waker')
files = {
'/opt/suspend_if_idle': {
'/usr/local/bin/suspend_if_idle': {
'mode': '550',
},
}

View file

@ -5,6 +5,8 @@ defaults = {
'apt': {
'packages': {
'jq': {},
'ethtool': {},
'net-tools': {},
},
},
}
@ -14,12 +16,15 @@ defaults = {
'systemd-timers/suspend-if-idle',
)
def timer(metadata):
name = 'suspend-if-idle'#
return {
'systemd-timers': {
name: {
'command': f'/opt/suspend_if_idle now {name}.service',
'suspend-if-idle': {
'command': f'suspend_if_idle',
'when': 'minutely',
'success_exit_status': '75',
'env': {
'THIS_SERVICE': 'suspend-if-idle.service',
},
},
},
}
@ -41,7 +46,6 @@ def wake_command(metadata):
@metadata_reactor.provides(
'apt/packages/ethtool',
'systemd/units/enable-wol.service',
'systemd/services/enable-wol.service',
)
@ -49,11 +53,6 @@ def systemd(metadata):
interface = metadata.get(f"network/{metadata.get('wol-sleeper/network')}/interface")
return {
'apt': {
'packages': {
'ethtool': {},
},
},
'systemd': {
'units': {
'enable-wol.service': {

View file

@ -1,3 +1,11 @@
defaults = {
'apt': {
'packages': {
'wakeonlan': {},
},
},
}
@metadata_reactor.provides(
'users/wol',
)

View file

@ -2,7 +2,7 @@
set -exu
ssh="ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@${server_ip}"
ssh="ssh -o ConnectTimeout=5 root@${server_ip}"
bookmark_prefix="auto-mirror_"
new_bookmark="$bookmark_prefix$(date +"%Y-%m-%d_%H:%M:%S")"
@ -32,6 +32,19 @@ do
if [[ "$?" == "0" ]]
then
# delete old local bookmarks
for destroyable_bookmark in $(zfs list -t bookmark -H -o name "$dataset" | grep "^$dataset#$bookmark_prefix")
do
zfs destroy "$destroyable_bookmark"
done
# delete snapshots from bookmarks (except newest, even of not necessary; maybe for resuming tho)
for destroyable_snapshot in $($ssh sudo zfs list -t snapshot -H -o name "$dataset" | grep "^$dataset@$bookmark_prefix" | grep -v "$new_bookmark")
do
$ssh sudo zfs destroy "$destroyable_snapshot"
done
zfs bookmark "$dataset@$new_bookmark" "$dataset#$new_bookmark"
zfs destroy "$dataset@$new_bookmark"
echo "SUCCESS $dataset"

View file

@ -45,24 +45,6 @@ defaults = {
'when': '*-2,4,6,8,10,12-1 02:00',
'persistent': True,
},
'zfs-auto-snapshot-hourly': {
'command': '/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=hourly --keep=24 //',
'when': 'hourly',
},
'zfs-auto-snapshot-daily': {
'command': '/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=daily --keep=7 //',
'when': 'daily',
},
'zfs-auto-snapshot-weekly': {
'command': '/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=weekly --keep=4 //',
'when': 'weekly',
'persistent': True,
},
'zfs-auto-snapshot-monthly': {
'command': '/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=monthly --keep=24 //',
'when': 'monthly',
'persistent': True,
},
},
'telegraf': {
'config': {
@ -78,9 +60,19 @@ defaults = {
'datasets': {},
'pools': {},
'kernel_params': {},
'storage_classes': {
'ssd': 'tank',
},
'auto_snapshots': {
'hourly': 24,
'daily': 7,
'weekly': 4,
'monthly': 24,
},
},
}
@metadata_reactor.provides(
'zfs/datasets'
)
@ -132,3 +124,62 @@ def headers(metadata):
},
},
}
@metadata_reactor.provides(
'zfs/kernel_params/zfs_arc_max',
)
def arc_size(metadata):
arc_percent = metadata.get('zfs/zfs_arc_max_percent', None)
if arc_percent:
return {
'zfs': {
'kernel_params': {
'zfs_arc_max': str(int(
metadata.get('vm/ram') * 1024 * 1024 * (arc_percent/100)
)),
},
},
}
else:
return {}
@metadata_reactor.provides(
'systemd-timers/zfs-auto-snapshot-hourly',
'systemd-timers/zfs-auto-snapshot-daily',
'systemd-timers/zfs-auto-snapshot-weekly',
'systemd-timers/zfs-auto-snapshot-monthly',
)
def auto_snapshots(metadata):
hourly = metadata.get('zfs/auto_snapshots/hourly')
daily = metadata.get('zfs/auto_snapshots/daily')
weekly = metadata.get('zfs/auto_snapshots/weekly')
monthly = metadata.get('zfs/auto_snapshots/monthly')
# cant be 0
assert hourly > 0 and daily > 0 and weekly > 0 and monthly > 0
return {
'systemd-timers': {
'zfs-auto-snapshot-hourly': {
'command': f'/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=hourly --keep={hourly} //',
'when': 'hourly',
},
'zfs-auto-snapshot-daily': {
'command': f'/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=daily --keep={daily} //',
'when': 'daily',
},
'zfs-auto-snapshot-weekly': {
'command': f'/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=weekly --keep={weekly} //',
'when': 'weekly',
'persistent': True,
},
'zfs-auto-snapshot-monthly': {
'command': f'/usr/sbin/zfs-auto-snapshot --quiet --syslog --label=monthly --keep={monthly} //',
'when': 'monthly',
'persistent': True,
},
},
}

View file

@ -1,4 +1,4 @@
function spwd {
function zsh_spwd {
paths=(${(s:/:)PWD})
cur_path='/'
@ -21,9 +21,20 @@ function spwd {
echo
}
indicator="$(hostname -s)"
local ret_status="%(?:%{$fg_bold[green]%}$indicator:%{$fg_bold[red]%}$indicator)"
PROMPT='${ret_status} %{$fg[cyan]%}$(spwd)%{$reset_color%} $(git_prompt_info)'
function zsh_root_color {
if test "$EUID" -eq 0
then
echo "%{$fg_bold[green]%}"
else
echo "%{$fg_bold[yellow]%}"
fi
}
function zsh_exitcode_color {
echo "%(?:%{$fg_bold[green]%}:%{$fg_bold[red]%})"
}
PROMPT='$(zsh_root_color)$(whoami)%{$reset_color%}@$(zsh_exitcode_color)$(hostname -s) %{$fg[cyan]%}$(zsh_spwd)%{$reset_color%} $(git_prompt_info)'
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "

View file

@ -0,0 +1,22 @@
# /etc/zsh/zprofile: system-wide .zprofile file for zsh(1).
#
# This file is sourced only for login shells (i.e. shells
# invoked with "-" as the first character of argv[0], and
# shells invoked with the -l flag.)
#
# Global Order: zshenv, zprofile, zshrc, zlogin
alias s='sudo su - root -s /usr/bin/zsh'
function hhtop {
mkdir -p ~/.config/htop
cp /etc/htoprc.global ~/.config/htop/htoprc
htop
}
ZSH_THEME=bw
DISABLE_AUTO_UPDATE=true
plugins=(
zsh-autosuggestions
)
source /etc/zsh/oh-my-zsh/oh-my-zsh.sh

View file

@ -1,6 +0,0 @@
export ZSH=~/.zsh/oh-my-zsh
ZSH_THEME=bw
plugins=(
zsh-autosuggestions
)
source $ZSH/oh-my-zsh.sh

View file

@ -1,46 +1,44 @@
from os.path import join
for name, user_config in node.metadata.get('users').items():
if user_config.get('shell', None) != '/usr/bin/zsh':
continue
directories = {
join(user_config['home'], '.zsh'): {
'owner': name,
},
join(user_config['home'], '.zsh/oh-my-zsh'): {
'owner': name,
},
join(user_config['home'], '.zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions'): {
'owner': name,
'/etc/zsh/oh-my-zsh': {},
'/etc/zsh/oh-my-zsh/custom/plugins': {
'mode': '0755',
'needs': [
f"git_deploy:{join(user_config['home'], '.zsh/oh-my-zsh')}",
f"git_deploy:/etc/zsh/oh-my-zsh",
]
},
'/etc/zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions': {
'needs': [
f"git_deploy:/etc/zsh/oh-my-zsh",
]
},
}
git_deploy = {
join(user_config['home'], '.zsh/oh-my-zsh'): {
'/etc/zsh/oh-my-zsh': {
'repo': 'https://github.com/ohmyzsh/ohmyzsh.git',
'rev': 'master',
},
join(user_config['home'], '.zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions'): {
'/etc/zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions': {
'repo': 'https://github.com/zsh-users/zsh-autosuggestions.git',
'rev': 'master',
},
}
files = {
join(user_config['home'], '.zshrc'): {
'owner': name,
'source': 'zshrc',
},
join(user_config['home'], '.zsh/oh-my-zsh/themes/bw.zsh-theme'): {
'owner': name,
'/etc/zsh/zprofile': {},
'/etc/zsh/oh-my-zsh/themes/bw.zsh-theme': {
'needs': [
f"git_deploy:{join(user_config['home'], '.zsh/oh-my-zsh')}",
f"git_deploy:/etc/zsh/oh-my-zsh",
]
},
}
for name, user_config in node.metadata.get('users').items():
if user_config.get('shell', None) != '/usr/bin/zsh':
files[join(user_config['home'], '.zshrc')] = {
'owner': name,
'group': name,
'content': '# bw managed',
}

View file

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.19 (GNU/Linux)
mQGiBFKHzk4RBACSHMIFTtfw4ZsNKAA03Gf5t7ovsKWnS7kcMYleAidypqhOmkGg
0petiYsMPYT+MOepCJFGNzwQwJhZrdLUxxMSWay4Xj0ArgpD9vbvU+gj8Tb02l+x
SqNGP8jXMV5UnK4gZsrYGLUPvx47uNNYRIRJAGOPYTvohhnFJiG402dzlwCg4u5I
1RdFplkp9JM6vNM9VBIAmcED/2jr7UQGsPs8YOiPkskGHLh/zXgO8SvcNAxCLgbp
BjGcF4Iso/A2TAI/2KGJW6kBW/Paf722ltU6s/6mutdXJppgNAz5nfpEt4uZKZyu
oSWf77179B2B/Wl1BsX/Oc3chscAgQb2pD/qPF/VYRJU+hvdQkq1zfi6cVsxyREV
k+IwA/46nXh51CQxE29ayuy1BoIOxezvuXFUXZ8rP6aCh4KaiN9AJoy7pBieCzsq
d7rPEeGIzBjI+yhEu8p92W6KWzL0xduWfYg9I7a2GTk8CaLX2OCLuwnKd7RVDyyZ
yzRjWs0T5U7SRAWspLStYxMdKert9lLyQiRHtLwmlgBPqa0gh7Q+SWNpbmdhIE9w
ZW4gU291cmNlIE1vbml0b3JpbmcgKEJ1aWxkIHNlcnZlcikgPGluZm9AaWNpbmdh
Lm9yZz6IYAQTEQIAIAUCUofOTgIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJ
EMbjGcM0QQaCgSQAnRjXdbsyqziqhmxfAKffNJYuMPwdAKCS/IRCVyQzApFBtIBQ
1xuoym/4C7kCDQRSh85OEAgAvPwjlURCi8z6+7i60no4n16dNcSzd6AT8Kizpv2r
9BmNBff/GNYGnHyob/DMtmO2esEuVG8w62rO9m1wzzXzjbtmtU7NZ1Tg+C+reU2I
GNVu3SYtEVK/UTJHAhLcgry9yD99610tYPN2Fx33Efse94mXOreBfCvDsmFGSc7j
GVNCWXpMR3jTYyGj1igYd5ztOzG63D8gPyOucTTl+RWN/G9EoGBv6sWqk5eCd1Fs
JlWyQX4BJn3YsCZx3uj1DWL0dAl2zqcn6m1M4oj1ozW47MqM/efKOcV6VvCs9SL8
F/NFvZcH4LKzeupCQ5jEONqcTlVlnLlIqId95Z4DI4AV9wADBQf/S6sKA4oH49tD
Yb5xAfUyEp5ben05TzUJbXs0Z7hfRQzy9+vQbWGamWLgg3QRUVPx1e4IT+W5vEm5
dggNTMEwlLMI7izCPDcD32B5oxNVxlfj428KGllYWCFj+edY+xKTvw/PHnn+drKs
LE65Gwx4BPHm9EqWHIBX6aPzbgbJZZ06f6jWVBi/N7e/5n8lkxXqS23DBKemapyu
S1i56sH7mQSMaRZP/iiOroAJemPNxv1IQkykxw2woWMmTLKLMCD/i+4DxejE50tK
dxaOLTc4HDCsattw/RVJO6fwE414IXHMv330z4HKWJevMQ+CmQGfswvCwgeBP9n8
PItLjBQAXIhJBBgRAgAJBQJSh85OAhsMAAoJEMbjGcM0QQaCzpAAmwUNoRyySf9p
5G3/2UD1PMueIwOtAKDVVDXEq5LJPVg4iafNu0SRMwgP0Q==
=icbY
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -0,0 +1,41 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGNBF5qU5ABDAC5P4yAxACWwvknjaREtCjSpqwpVKbP+HCQcaho3ao/ls2mUQ7K
WzqoAknFljZACkoQT6D+9t0Wx+aYhSb8kc/RHDoQQN5w7sAxBCsUS0/unF7PQxZH
px3YTJgTlkl7cB79pbK5mu/Ybj/AhtjLwuu5CO8xPK19K2Xl1TT14sWlfxVmNxJ1
X62w2lPfHuS1GJKw5k32ee3UeZB2FAuwzO84FlvlmoSgiGgOSW+OPLxapZA0glO3
M/FpjF/ergaQqbU3nAaPkj3J7by7+j2r81RJZ49s9RXPUHie8d5TDB53KWaOTHPh
ONF3pssaWeEMP3Ju23s1t9dV1hPtwzdTiXu3lQp+0eZy4X085tEGsz4oYxAXlG2X
gXKR9wO8AhzN6E2UJRDPjiXD8APDh5SDxNreFFTv9orh+dRHjaFQuds0erkDVc9g
CDkczKy8zi14BEdWolPHNp6rVdbtyFKhiCrr9MOQEGJ04FgIB6HDbaAAXEUe7oU4
0v1i0BXFrCVDNx8AEQEAAbQlTWF0aWFzIERlIGxlbGxpcyA8bWF0aTg2ZGxAZ21h
aWwuY29tPokB1AQTAQgAPgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBIMH
yrK2G/QHU3ipTjkheTntPQfbBQJiOGH3BQkHkHVnAAoJEDkheTntPQfbQ28MAIw3
yz+CJWP60ypv/W4ErUif0bhwMsSG+5YPligOcSmgzw9x3xysPSLpBrBR5cpLCx8Z
voqFa5PJbu8cKhmHGQMvH7duVPL6gRX4dQG9t9qtKd9DYmsD9GweyCWFIhVFTId4
VyDeEqx1IWAHyLoJmfnCQAIZHwhPrZKVU2hui8YjqZ4bpuP/xKGBiREgkPP5yv/T
J0GPoH9JOe67V9pDDN71cJzJpbFG7bPwH5LkzhO2fS6StyLKG7rMJHo6y2B9tWET
4V18WKotn1rT2gBunoCE3NsazwnXFf1C/KnHZF8zYAtLZfFa2gz4JgLk4kCgKeUO
vKubOoF44BFad6hgXA2yFiY7LXZmUhydlIdMp9P67jdmosW6Rbjz3st/nqg6pmjM
pMFEoc2jybdbiWkppRmrQlwRD76ir1Fcu71eEDZIPCfHpBNEyMgtdL/zyJnUbtGl
Bp8Jpfg9Y3CqDXtBkUug6KQ77S61zRnaenD91V2NrMnHVQsoiNP42h//7feTiLkB
jQRealOQAQwA2YM6vfJbo+BkFSmjwpuvY65DzVDyz4nRO1NvHBHeuMJKeWgF5pKe
e/TOJWcjlsBT2xwsqi8NhT1O2BpVBXOGN2Ck6YLQ0WPaxfsmAEGCyVFsJIBuWOQ7
j0VXyvbHbUGrcLg5sA3VS0zzqquMf7dAwHI7earp1HsOd8DvRs518leRx18wiDap
6UbPqpu3yFqNY4oeZ7oBpII6olm9YtGGP0mHquPYpWq9ZlN1vjPbLgjY1IPs2OMl
DGE1eaEWeygyL1tRgjAGpgsdLS3BOgF1fY0OpTRyZnez+W8eWqTB12yF17FpErWC
VeO8h6LosfjcQ8Bg2WQnFrzJJgXzVxrvwygbtggvN/feEPzWJg92TEQLzMFRf8I9
rCju5SOR5WBTPmvnq7f9VT/2rg0WSBjkVxGq9wMVyXmOOkYUB6hx5ynDEM9cIzG3
Jmvm+rz1lQiILwnpFXUtTWnQbMuUmdPWFM2f2XKRY0RE0EvJ4K5ve49bz+SvOUip
ewVowQ46z0LZABEBAAGJAbwEGAEIACYCGwwWIQSDB8qythv0B1N4qU45IXk57T0H
2wUCYjhiLwUJB5B1nwAKCRA5IXk57T0H2/7jDACqur/sIYzTSxUEn73yyde6S8za
ZzcnzV9JIIi9vTVd50J5ngWjg06PPYe6NXSf6J/EXxHOp2TKy58FPyMnxBENzycM
P+9GyH4UH3nOK8ywgZ7nkyXYjJKzZ+88F9HcUgO3xSwsMy6kpeIdxXI3fpEOVXBn
lAsHM6CF1Nk5O4oxgJwgbXwf5ntYDeXwcpm6NCdDTorYLy5JvhDg8XiTeMl6fFki
uDSrNF0UNkkhutS/66FVLUlq5grSWH7mYviau6Ju2C2Tq2GijvRcvkQcA37Mx//x
x4ydNydSmu5kxfB6JorgAnK8sLTIHU+RWgmJRly5YY/G6RXm2QsYs+RvObgIablW
k1ZXNcb3qEyn3D91sXUsvp7qMAnQjWp2UkV4KygMc6C4i54JkOTcZiGhynjB6pL9
FgpIgjjhC9B+hToo9uuLC2Ox58TA+7l1sR4JG0XCNW0Z+5swBnWyrlt/ZwWxFqoB
oxYE/j3yxh9TmgHv54/j2ZzU8tiJHW01AGlbbxo=
=cWkh
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -4,6 +4,10 @@ from(bucket: "${bucket}")
<% values = values if isinstance(values, list) else [values] %>\
|> filter(fn: (r) => ${' or '.join(f'r["{key}"] == "{value}"' for value in values)})
% endfor
% for exist in exists:
|> filter(fn: (r) => exists r["${exist}"]) // WTF
% endfor
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) // aggregate early for best performance
% if minimum:
|> filter(fn: (r) => r._value > ${minimum})
% endif
@ -13,7 +17,6 @@ from(bucket: "${bucket}")
% if boolean_to_int:
|> map(fn: (r) => ({r with _value: if r._value == true then 1 else 0 }))
% endif
|> aggregateWindow(every: duration(v: int(v: v.windowPeriod)*${resolution}), fn: mean, createEmpty: false)
% if negative:
|> map(fn: (r) => ({r with _value: r._value * - 1.0}))
% endif

View file

@ -1,13 +1,19 @@
{
'usage': {
'stacked': False,
'stacked': True,
'queries': {
'usage': {
'filters': {
'_measurement': 'cpu',
'cpu': 'cpu-total',
'_field': [
'usage_guest',
'usage_guest_nice',
'usage_iowait',
'usage_irq',
'usage_nice',
'usage_softirq',
'usage_steal',
'usage_system',
'usage_user',
],
@ -16,7 +22,12 @@
},
},
'min': 0,
'max': 100,
'soft_max': 3,
'unit': 'percent',
'tooltip': 'multi',
'legend': {
'displayMode': 'hidden',
},
},
'load': {
'stacked': False,
@ -33,5 +44,40 @@
'function': 'mean',
},
},
'min': 0,
'soft_max': 3,
'unit': 'percent',
'tooltip': 'multi',
'legend': {
'displayMode': 'hidden',
},
},
'pressure_stall': {
'queries': {
'pressure_stall': {
'filters': {
'_measurement': 'pressure_stall',
'resource': [
'cpu',
'io',
'memory',
],
'type': [
'some',
],
'_field': [
'avg10',
],
},
},
},
'min': 0,
'soft_max': 3,
'display_name': '__field.labels.resource',
'unit': 'percent',
'tooltip': 'multi',
'legend': {
'displayMode': 'hidden',
},
},
}

View file

@ -9,11 +9,15 @@
'read_bytes',
],
},
'exists': [
'ID_PART_ENTRY_NUMBER',
],
'function': 'derivative',
},
},
'unit': 'decbytes',
'display_name': '__field.labels.name'
'unit': 'Bps',
'display_name': '__field.labels.name',
'tooltip': 'multi',
},
'write': {
'stacked': True,
@ -25,10 +29,14 @@
'write_bytes',
],
},
'exists': [
'ID_PART_ENTRY_NUMBER',
],
'function': 'derivative',
},
},
'unit': 'decbytes',
'display_name': '__field.labels.name'
'unit': 'Bps',
'display_name': '__field.labels.name',
'tooltip': 'multi',
},
}

View file

@ -16,6 +16,7 @@
},
'min': 0,
'unit': 'bytes',
'tooltip': 'multi',
},
'root_inodes': {
'stacked': True,
@ -33,5 +34,6 @@
},
},
'min': 0,
'tooltip': 'multi',
},
}

View file

@ -16,6 +16,7 @@
},
},
'unit': 'decbytes',
'tooltip': 'multi',
},
'swp': {
'stacked': True,
@ -32,5 +33,6 @@
},
},
'unit': 'decbytes',
'tooltip': 'multi',
},
}

View file

@ -12,8 +12,9 @@
'function': 'derivative',
},
},
'unit': 'decbytes',
'display_name': '__field.labels.interface'
'unit': 'Bps',
'display_name': '__field.labels.interface',
'tooltip': 'multi',
},
'out': {
'stacked': True,
@ -28,7 +29,8 @@
'function': 'derivative',
},
},
'unit': 'decbytes',
'display_name': '__field.labels.interface'
'unit': 'Bps',
'display_name': '__field.labels.interface',
'tooltip': 'multi',
},
}

View file

@ -9,7 +9,7 @@
'length',
],
},
'function': 'mean',
'function': 'max',
},
},
'display_name': '__field.labels.queue'
@ -24,7 +24,7 @@
'size',
],
},
'function': 'mean',
'function': 'max',
},
},
'display_name': '__field.labels.queue'
@ -39,7 +39,7 @@
'age',
],
},
'function': 'mean',
'function': 'max',
},
},
'display_name': '__field.labels.queue'

View file

@ -1,27 +0,0 @@
{
'process_cpu': {
'stacked': True,
'queries': {
'cpu': {
'filters': {
'_measurement': 'procstat',
'_field': [
'cpu_usage',
],
},
'minimum': 1,
'resolution': 2,
},
},
'unit': 'percent',
'display_name': '__field.labels.process_name',
'legend': {
'displayMode': 'table',
'placement': 'right',
'calcs': [
'mean',
'max',
],
},
},
}

View file

@ -0,0 +1,48 @@
{
'cpu': {
'stacked': True,
'queries': {
'cpu': {
'filters': {
'_measurement': 'procstat',
'_field': [
'cpu_usage',
],
},
'minimum': 0.2,
},
},
'unit': 'percent',
'display_name': '__field.labels.process_name',
'legend': {
'displayMode': 'table',
'placement': 'right',
'calcs': [
'last',
],
},
},
'ram': {
'stacked': True,
'queries': {
'ram': {
'filters': {
'_measurement': 'procstat',
'_field': [
'memory_rss',
],
},
'minimum': 10*(10**6),
},
},
'unit': 'bytes',
'display_name': '__field.labels.process_name',
'legend': {
'displayMode': 'table',
'placement': 'right',
'calcs': [
'last',
],
},
},
}

View file

@ -19,8 +19,7 @@
'displayMode': 'table',
'placement': 'right',
'calcs': [
'mean',
'max',
'last',
],
},
},
@ -44,8 +43,7 @@
'displayMode': 'table',
'placement': 'right',
'calcs': [
'mean',
'max',
'last',
],
},
},

View file

@ -1,27 +0,0 @@
{
'process_ram': {
'stacked': True,
'queries': {
'ram': {
'filters': {
'_measurement': 'procstat',
'_field': [
'memory_rss',
],
},
'minimum': 10*(10**6),
'resolution': 2,
},
},
'unit': 'bytes',
'display_name': '__field.labels.process_name',
'legend': {
'displayMode': 'table',
'placement': 'right',
'calcs': [
'mean',
'max',
],
},
},
}

View file

@ -80,6 +80,6 @@
'negative': True,
},
},
'unit': 'bytes',
'unit': 'Bps',
},
}

28
data/grafana/vhost.conf Normal file
View file

@ -0,0 +1,28 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${server_name};
ssl_certificate /var/lib/dehydrated/certs/${server_name}/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/${server_name}/privkey.pem;
location / {
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8300/;
}
# Proxy Grafana Live WebSocket connections.
location /api/live {
rewrite ^/(.*) /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8300/;
}
}

View file

@ -0,0 +1,30 @@
# icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public --config /etc/icingaweb2 --fpm-uri 127.0.0.1:9000
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${server_name};
ssl_certificate /var/lib/dehydrated/certs/${server_name}/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/${server_name}/privkey.pem;
location / {
return 302 /icingaweb2/index.php;
}
location ~ ^/icingaweb2/index\.php(.*)$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/share/icingaweb2/public/index.php;
fastcgi_param ICINGAWEB_CONFIGDIR /etc/icingaweb2;
fastcgi_param REMOTE_USER $remote_user;
}
location ~ ^/icingaweb2(.+)? {
alias /usr/share/icingaweb2/public;
index index.php;
try_files $1 $uri $uri/ /icingaweb2/index.php$is_args$args;
}
}

View file

@ -0,0 +1,20 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${server_name};
ssl_certificate /var/lib/dehydrated/certs/${server_name}/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/${server_name}/privkey.pem;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:4001;
}
location /steamuserimages/ {
root /var/lib/steam_chat_logger/steamuserimages;
rewrite ^/steamuserimages(.*)$ $1 break;
autoindex on;
}
}

20
groups/os/debian-12.py Normal file
View file

@ -0,0 +1,20 @@
{
'supergroups': [
'debian',
],
'metadata': {
'apt': {
'sources': {
'deb http://security.debian.org/ {release}-security main contrib non-free',
},
},
'php': {
'version': '8.1',
},
'postgresql': {
'version': '14',
},
'os_release': 'bookworm',
},
'os_version': (12,),
}

View file

@ -5,6 +5,7 @@
'bundles': [
'hostname',
'hosts',
'htop',
'locale',
'network',
'ssh',
@ -30,9 +31,15 @@
],
},
'users': {
'root': {
'ckn': {
'shell': '/usr/bin/zsh',
'authorized_keys': {
'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEU1l2ijW3ZqzFGZcdWg2ESgTGehdNfBTfafxsjWvWdS mwiegand@macbook',
},
},
},
'sudoers': {
'ckn': {'ALL'},
},
},
}

View file

@ -1,2 +1,5 @@
def node_apply_start(repo, node, interactive=False, **kwargs):
def node_apply_start(repo, node, **kwargs):
repo.libs.wol.wake(node)
def node_run_start(repo, node, cmd, **kwargs):
repo.libs.wol.wake(node)

View file

@ -8,6 +8,7 @@
'monitored',
],
'bundles': [
'grub',
'smartctl',
'wol-sleeper',
'zfs',
@ -17,10 +18,10 @@
'id': '9cf52515-63a1-4659-a8ec-6c3c881727e5',
'network': {
'internal': {
'interface': 'enp1s0',
'interface': 'enp0s31f6',
'ipv4': '10.0.0.5/24',
'gateway4': '10.0.0.1',
'mac': 'd8:cb:8a:e7:be:c6',
'mac': '4c:cc:6a:d5:96:f8',
},
},
'backup-server': {
@ -55,6 +56,12 @@
],
},
},
'auto_snapshots': {
'hourly': 1,
'daily': 7,
'weekly': 4,
'monthly': 24,
},
},
},
}

View file

@ -17,7 +17,6 @@
'zfs',
],
'metadata': {
'FIXME_dont_touch_sshd': True,
'id': '34199b24-4621-42f4-85ae-ec354f9c43e6',
'network': {
'internal': {

View file

@ -16,14 +16,19 @@
'build-agent',
'crystal',
'gitea',
'gollum',
# 'gollum',
'grafana',
'icinga2',
'icingadb',
'icingaweb2',
'influxdb2',
'mirror',
'mosquitto',
'postgresql',
'redis',
'smartctl',
'steam-chat-logger',
'steam-chat-viewer',
'systemd-swap',
'raspberrymatic-cert',
'tasmota-charge',
'wireguard',
@ -34,7 +39,7 @@
'id': 'af96709e-b13f-4965-a588-ef2cd476437a',
'network': {
'internal': {
'interface': 'enp1s0f0',
'interface': 'enp42s0',
'ipv4': '10.0.0.2/24',
'gateway4': '10.0.0.1',
},
@ -54,8 +59,8 @@
'download_server': 'netcup.mails',
},
'gitea': {
'version': '1.16.2',
'sha256': 'ec9b01d119cfe47df44d580c1d321132ce054ff139b05b0a35da91268ca2bcbe',
'version': '1.16.5',
'sha256': 'c0fb4107dc4debf08e6e27fd3383e06dc232ccb410123179c7ae8d7cec60765f',
'domain': 'git.sublimity.de',
},
'gollum': {
@ -67,6 +72,12 @@
'hostname': 'grafana.sublimity.de',
'influxdb_node': 'home.server',
},
'icinga2': {
'hostname': 'icinga.sublimity.de',
},
'icingaweb2': {
'hostname': 'icinga.sublimity.de',
},
'influxdb': {
'hostname': 'influxdb.sublimity.de',
'admin_token': '!decrypt:encrypt$gAAAAABg3z5PcaLYmUpcElJ07s_G-iYwnS8d532TcR8xUYbZfttT-B736zgR6J726mzKAFNYlIfJ7amNLIzi2ETDH5TAXWsOiAKpX8WC_dPBAvG3uXGtcPYENjdeuvllSagZzPt0hCIZQZXg--Z_YvzaX9VzNrVAgGD-sXQnghN5_Vhf9gVxxwP---VB_6iNlsf61Nc4axoS',
@ -81,7 +92,7 @@
},
'nextcloud': {
'hostname': 'cloud.sublimity.de',
'version': '23.0.2',
'version': '24.0.4',
},
'nextcloud-picsort': {
'ckn': {
@ -94,10 +105,22 @@
'domain': 'homematic.ckn.li',
'node': 'home.homematic',
},
'steam_chat_logger': {
'STEAM_USERNAME': 'snake_452',
'STEAM_ID': 'STEAM_0:0:12376499',
'STEAM_PASSWORD': '!decrypt:encrypt$gAAAAABiUzERrXVNxzDaDW_4MgEmPtXkMHlTiz5uqCbu-22-2yKHRHMKvuGqAygpGbnwZucZcmZMox9KM89a6qlVKlE1ZPizTA==',
'IMAP_HOST': 'mail.sublimity.de',
'IMAP_USER': 'i@ckn.li',
'IMAP_PASSWORD': '!decrypt:encrypt$gAAAAABiUzcTVRL-Xb4RDjcwciZawYlmOa9Qy_hKz6sVWDlwZqUFLGRD8ERWoFCOWCM22Sq73Gc4nFuAblBB6wpbH5YEltLA6hmROGKpOFhI63ESLFwNgbY=',
},
'steam-chat-viewer': {
'hostname': 'steam-chats.ckn.li',
},
'systemd-swap': 4_000_000_000,
'tasmota-charge': {
'phone': {
'ip': '10.0.0.166',
'user': 'u0_q194',
'ip': '10.0.0.175',
'user': 'u0_a233',
'password': 'november',
},
'plug': {
@ -107,8 +130,9 @@
},
},
'vm': {
'cores': 2,
'ram': 16192,
'cores': 16,
'threads': 32,
'ram': 49152,
},
'wireguard': {
'my_ip': '172.30.0.2/32',
@ -123,6 +147,10 @@
},
},
'zfs': {
'zfs_arc_max_percent': 80,
'storage_classes': {
'ssd': 'ssd',
},
'pools': {
'tank': {
'type': 'mirror',
@ -131,6 +159,17 @@
'/dev/disk/by-partlabel/zfs-data-2',
],
},
'ssd': {
'devices': [
'/dev/disk/by-id/nvme-SAMSUNG_MZVL22T0HBLB-00B00_S677NF0RA01551-part3',
],
},
},
'datasets': {
'ssd/nextcloud-appdata': {
'mountpoint': '/var/lib/nextcloud/appdata_oci6dw1woodz',
'backup': False,
}
},
},
},

View file

@ -12,8 +12,6 @@
'wpa-supplicant',
],
'metadata': {
'FIXME_dont_touch_sshd': True,
'id': 'dd521b8a-dc03-43f5-b29f-068f948ba3b8',
'network': {
'internal': {

View file

@ -54,11 +54,6 @@
'device': '/dev/disk/by-id/ata-TOSHIBA_MG06ACA10TE_61C0A1B1FKQE',
},
},
'smartctl': {
'/dev/disk/by-id/ata-TOSHIBA_MG06ACA10TE_61C0A1B1FKQE': {
'apm': 1,
},
},
'zfs': {
'pools': {
'tank': {
@ -67,6 +62,12 @@
],
},
},
'auto_snapshots': {
'hourly': 1,
'daily': 1,
'weekly': 4,
'monthly': 24,
},
},
},
}