Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
cdf79c2bd8 | |||
13e52027cf | |||
96c2df1c09 | |||
cadb32cffd | |||
8b296ba6db | |||
b1ea126c2a | |||
1bf795c262 | |||
3546633969 | |||
f8f500718b |
119 changed files with 724 additions and 1895 deletions
2
.envrc
2
.envrc
|
@ -1,7 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
PATH_add bin
|
|
||||||
|
|
||||||
source_env ~/.local/share/direnv/pyenv
|
source_env ~/.local/share/direnv/pyenv
|
||||||
source_env ~/.local/share/direnv/venv
|
source_env ~/.local/share/direnv/venv
|
||||||
source_env ~/.local/share/direnv/bundlewrap
|
source_env ~/.local/share/direnv/bundlewrap
|
||||||
|
|
|
@ -37,12 +37,3 @@ fi
|
||||||
telegraf: execd for daemons
|
telegraf: execd for daemons
|
||||||
|
|
||||||
TEST
|
TEST
|
||||||
|
|
||||||
# git signing
|
|
||||||
|
|
||||||
git config --global gpg.format ssh
|
|
||||||
git config --global commit.gpgsign true
|
|
||||||
|
|
||||||
git config user.name CroneKorkN
|
|
||||||
git config user.email i@ckn.li
|
|
||||||
git config user.signingkey "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILMVroYmswD4tLk6iH+2tvQiyaMe42yfONDsPDIdFv6I"
|
|
||||||
|
|
195
bin/dnssec
Executable file
195
bin/dnssec
Executable file
|
@ -0,0 +1,195 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# https://medium.com/iocscan/how-dnssec-works-9c652257be0
|
||||||
|
# https://de.wikipedia.org/wiki/RRSIG_Resource_Record
|
||||||
|
# https://metebalci.com/blog/a-minimum-complete-tutorial-of-dnssec/
|
||||||
|
# https://bind9.readthedocs.io/en/latest/dnssec-guide.html
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
from os.path import realpath, dirname
|
||||||
|
from bundlewrap.repo import Repository
|
||||||
|
from base64 import b64decode, urlsafe_b64encode
|
||||||
|
from cryptography.utils import int_to_bytes
|
||||||
|
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
||||||
|
from struct import pack, unpack
|
||||||
|
from hashlib import sha1, sha256
|
||||||
|
from json import dumps
|
||||||
|
from cache_to_disk import cache_to_disk
|
||||||
|
|
||||||
|
|
||||||
|
def long_to_base64(n):
|
||||||
|
return urlsafe_b64encode(int_to_bytes(n, None)).decode()
|
||||||
|
|
||||||
|
zone = argv[1]
|
||||||
|
repo = Repository(dirname(dirname(realpath(__file__))))
|
||||||
|
|
||||||
|
flags = 256
|
||||||
|
protocol = 3
|
||||||
|
algorithm = 8
|
||||||
|
algorithm_name = 'RSASHA256'
|
||||||
|
|
||||||
|
# ZSK/KSK DNSKEY
|
||||||
|
#
|
||||||
|
# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers
|
||||||
|
# https://crypto.stackexchange.com/a/21104
|
||||||
|
|
||||||
|
def generate_signing_key_pair(zone, salt):
|
||||||
|
privkey = repo.libs.rsa.generate_deterministic_rsa_private_key(
|
||||||
|
b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone)))
|
||||||
|
)
|
||||||
|
|
||||||
|
public_exponent = privkey.private_numbers().public_numbers.e
|
||||||
|
modulo = privkey.private_numbers().public_numbers.n
|
||||||
|
private_exponent = privkey.private_numbers().d
|
||||||
|
prime1 = privkey.private_numbers().p
|
||||||
|
prime2 = privkey.private_numbers().q
|
||||||
|
exponent1 = privkey.private_numbers().dmp1
|
||||||
|
exponent2 = privkey.private_numbers().dmq1
|
||||||
|
coefficient = privkey.private_numbers().iqmp
|
||||||
|
|
||||||
|
dnskey = ''.join(privkey.public_key().public_bytes(
|
||||||
|
crypto_serialization.Encoding.PEM,
|
||||||
|
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
||||||
|
).decode().split('\n')[1:-2])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'dnskey': dnskey,
|
||||||
|
'dnskey_record': f'{zone}. IN DNSKEY {flags} {protocol} {algorithm} {dnskey}',
|
||||||
|
'privkey': privkey,
|
||||||
|
'privkey_file': {
|
||||||
|
'Private-key-format': 'v1.3',
|
||||||
|
'Algorithm': f'{algorithm} ({algorithm_name})',
|
||||||
|
'Modulus': long_to_base64(modulo),
|
||||||
|
'PublicExponent': long_to_base64(public_exponent),
|
||||||
|
'PrivateExponent': long_to_base64(private_exponent),
|
||||||
|
'Prime1': long_to_base64(prime1),
|
||||||
|
'Prime2': long_to_base64(prime2),
|
||||||
|
'Exponent1': long_to_base64(exponent1),
|
||||||
|
'Exponent2': long_to_base64(exponent2),
|
||||||
|
'Coefficient': long_to_base64(coefficient),
|
||||||
|
'Created': 20230428110109,
|
||||||
|
'Publish': 20230428110109,
|
||||||
|
'Activate': 20230428110109,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# DS
|
||||||
|
#
|
||||||
|
# https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a#file-dnskey_to_dsrecord-py-L40
|
||||||
|
|
||||||
|
def _calc_ds(zone, flags, protocol, algorithm, dnskey):
|
||||||
|
if zone.endswith('.') is False:
|
||||||
|
zone += '.'
|
||||||
|
|
||||||
|
signature = bytes()
|
||||||
|
for i in zone.split('.'):
|
||||||
|
signature += pack('B', len(i)) + i.encode()
|
||||||
|
|
||||||
|
signature += pack('!HBB', int(flags), int(protocol), int(algorithm))
|
||||||
|
signature += b64decode(dnskey)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'sha1': sha1(signature).hexdigest().upper(),
|
||||||
|
'sha256': sha256(signature).hexdigest().upper(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def _calc_keyid(flags, protocol, algorithm, dnskey):
|
||||||
|
st = pack('!HBB', int(flags), int(protocol), int(algorithm))
|
||||||
|
st += b64decode(dnskey)
|
||||||
|
|
||||||
|
cnt = 0
|
||||||
|
for idx in range(len(st)):
|
||||||
|
s = unpack('B', st[idx:idx+1])[0]
|
||||||
|
if (idx % 2) == 0:
|
||||||
|
cnt += s << 8
|
||||||
|
else:
|
||||||
|
cnt += s
|
||||||
|
|
||||||
|
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
|
||||||
|
|
||||||
|
def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey):
|
||||||
|
keyid = _calc_keyid(flags, protocol, algorithm, dnskey)
|
||||||
|
ds = _calc_ds(zone, flags, protocol, algorithm, dnskey)
|
||||||
|
|
||||||
|
return[
|
||||||
|
f"{zone}. IN DS {str(keyid)} {str(algorithm)} 1 {ds['sha1'].lower()}",
|
||||||
|
f"{zone}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Result
|
||||||
|
|
||||||
|
#@cache_to_disk(30)
|
||||||
|
def generate_dnssec_for_zone(zone):
|
||||||
|
zsk_data = generate_signing_key_pair(zone, salt='zsk')
|
||||||
|
ksk_data = generate_signing_key_pair(zone, salt='ksk')
|
||||||
|
ds_records = dnskey_to_ds(zone, flags, protocol, algorithm, ksk_data['dnskey'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'zsk_data': zsk_data,
|
||||||
|
'ksk_data': ksk_data,
|
||||||
|
'ds_records': ds_records,
|
||||||
|
}
|
||||||
|
|
||||||
|
print(
|
||||||
|
generate_dnssec_for_zone(zone),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# #########################
|
||||||
|
|
||||||
|
# from dns import rrset, rdatatype, rdata
|
||||||
|
# from dns.rdataclass import IN
|
||||||
|
# from dns.dnssec import sign, make_dnskey
|
||||||
|
# from dns.name import Name
|
||||||
|
# from dns.rdtypes.IN.A import A
|
||||||
|
|
||||||
|
# data = generate_dnssec_for_zone(zone)
|
||||||
|
# zone_name = Name(f'{zone}.'.split('.'))
|
||||||
|
# assert zone_name.is_absolute()
|
||||||
|
|
||||||
|
# # rrset = rrset.from_text_list(
|
||||||
|
# # name=Name(['test']).derelativize(zone_name),
|
||||||
|
# # origin=zone_name,
|
||||||
|
# # relativize=False,
|
||||||
|
# # ttl=60,
|
||||||
|
# # rdclass=IN,
|
||||||
|
# # rdtype=rdatatype.from_text('A'),
|
||||||
|
# # text_rdatas=[
|
||||||
|
# # '100.2.3.4',
|
||||||
|
# # '10.0.0.55',
|
||||||
|
# # ],
|
||||||
|
# # )
|
||||||
|
|
||||||
|
# rrset = rrset.from_rdata_list(
|
||||||
|
# name=Name(['test']).derelativize(zone_name),
|
||||||
|
# ttl=60,
|
||||||
|
# rdatas=[
|
||||||
|
# rdata.from_text(
|
||||||
|
# rdclass=IN,
|
||||||
|
# rdtype=rdatatype.from_text('A'),
|
||||||
|
# origin=zone_name,
|
||||||
|
# tok='1.2.3.4',
|
||||||
|
# relativize=False,
|
||||||
|
# ),
|
||||||
|
# A(IN, rdatatype.from_text('A'), '10.20.30.40')
|
||||||
|
# ],
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # for e in rrset:
|
||||||
|
# # print(e.is_absolute())
|
||||||
|
|
||||||
|
# dnskey = make_dnskey(
|
||||||
|
# public_key=data['zsk_data']['privkey'].public_key(),
|
||||||
|
# algorithm=algorithm,
|
||||||
|
# flags=flags,
|
||||||
|
# protocol=protocol,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# sign(
|
||||||
|
# rrset=rrset,
|
||||||
|
# private_key=data['zsk_data']['privkey'],
|
||||||
|
# signer=Name(f'{zone}.'),
|
||||||
|
# dnskey=dnskey,
|
||||||
|
# lifetime=99999,
|
||||||
|
# )
|
47
bin/test
Executable file
47
bin/test
Executable file
|
@ -0,0 +1,47 @@
|
||||||
|
import dns.zone
|
||||||
|
import dns.rdatatype
|
||||||
|
import dns.rdataclass
|
||||||
|
import dns.dnssec
|
||||||
|
|
||||||
|
# Define the zone name and domain names
|
||||||
|
zone_name = 'example.com.'
|
||||||
|
a_name = 'www.example.com.'
|
||||||
|
txt_name = 'example.com.'
|
||||||
|
mx_name = 'example.com.'
|
||||||
|
|
||||||
|
# Define the DNSKEY algorithm and size
|
||||||
|
algorithm = 8
|
||||||
|
key_size = 2048
|
||||||
|
|
||||||
|
# Generate the DNSSEC key pair
|
||||||
|
keypair = dns.dnssec.make_dnskey(algorithm, key_size)
|
||||||
|
|
||||||
|
# Create the zone
|
||||||
|
zone = dns.zone.Zone(origin=zone_name)
|
||||||
|
|
||||||
|
# Add A record to zone
|
||||||
|
a_rrset = zone.get_rdataset(a_name, rdtype=dns.rdatatype.A, create=True)
|
||||||
|
a_rrset.add(dns.rdataclass.IN, dns.rdatatype.A, '192.0.2.1')
|
||||||
|
|
||||||
|
# Add TXT record to zone
|
||||||
|
txt_rrset = zone.get_rdataset(txt_name, rdtype=dns.rdatatype.TXT, create=True)
|
||||||
|
txt_rrset.add(dns.rdataclass.IN, dns.rdatatype.TXT, 'Hello, world!')
|
||||||
|
|
||||||
|
# Add MX record to zone
|
||||||
|
mx_rrset = zone.get_rdataset(mx_name, rdtype=dns.rdatatype.MX, create=True)
|
||||||
|
mx_rrset.add(dns.rdataclass.IN, dns.rdatatype.MX, '10 mail.example.com.')
|
||||||
|
|
||||||
|
# Create the DNSKEY record for the zone
|
||||||
|
key_name = f'{keypair.name}-K{keypair.fingerprint()}'
|
||||||
|
dnskey_rrset = dns.rrset.RRset(name=keypair.name, rdclass=dns.rdataclass.IN, rdtype=dns.rdatatype.DNSKEY)
|
||||||
|
dnskey_rrset.ttl = 86400
|
||||||
|
dnskey_rrset.add(dns.rdataclass.IN, dns.rdatatype.DNSKEY, keypair.key, key_name=key_name)
|
||||||
|
|
||||||
|
# Add the DNSKEY record to the zone
|
||||||
|
zone.replace_rdataset(keypair.name, dnskey_rrset)
|
||||||
|
|
||||||
|
# Sign the zone with the DNSSEC key pair
|
||||||
|
dns.dnssec.sign_zone(zone, keypair, inception=0, expiration=3600)
|
||||||
|
|
||||||
|
# Print the resulting zone with the RRSIG records
|
||||||
|
print(zone.to_text())
|
|
@ -10,6 +10,7 @@ nodes = [
|
||||||
for node in sorted(repo.nodes_in_group('debian'))
|
for node in sorted(repo.nodes_in_group('debian'))
|
||||||
if not node.dummy
|
if not node.dummy
|
||||||
]
|
]
|
||||||
|
reboot_nodes = []
|
||||||
|
|
||||||
print('updating nodes:', sorted(node.name for node in nodes))
|
print('updating nodes:', sorted(node.name for node in nodes))
|
||||||
|
|
||||||
|
@ -23,13 +24,14 @@ for node in nodes:
|
||||||
print(node.run('DEBIAN_FRONTEND=noninteractive apt update').stdout.decode())
|
print(node.run('DEBIAN_FRONTEND=noninteractive apt update').stdout.decode())
|
||||||
print(node.run('DEBIAN_FRONTEND=noninteractive apt list --upgradable').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()):
|
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 -qy full-upgrade').stdout.decode())
|
print(node.run('DEBIAN_FRONTEND=noninteractive apt -y dist-upgrade').stdout.decode())
|
||||||
|
reboot_nodes.append(node)
|
||||||
|
|
||||||
# REBOOT IN ORDER
|
# REBOOT IN ORDER
|
||||||
|
|
||||||
wireguard_servers = [
|
wireguard_servers = [
|
||||||
node
|
node
|
||||||
for node in nodes
|
for node in reboot_nodes
|
||||||
if node.has_bundle('wireguard')
|
if node.has_bundle('wireguard')
|
||||||
and (
|
and (
|
||||||
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen <
|
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen <
|
||||||
|
@ -39,7 +41,7 @@ wireguard_servers = [
|
||||||
|
|
||||||
wireguard_s2s = [
|
wireguard_s2s = [
|
||||||
node
|
node
|
||||||
for node in nodes
|
for node in reboot_nodes
|
||||||
if node.has_bundle('wireguard')
|
if node.has_bundle('wireguard')
|
||||||
and (
|
and (
|
||||||
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen ==
|
ip_interface(node.metadata.get('wireguard/my_ip')).network.prefixlen ==
|
||||||
|
@ -49,7 +51,7 @@ wireguard_s2s = [
|
||||||
|
|
||||||
everything_else = [
|
everything_else = [
|
||||||
node
|
node
|
||||||
for node in nodes
|
for node in reboot_nodes
|
||||||
if not node.has_bundle('wireguard')
|
if not node.has_bundle('wireguard')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -60,11 +62,8 @@ for node in [
|
||||||
*wireguard_s2s,
|
*wireguard_s2s,
|
||||||
*wireguard_servers,
|
*wireguard_servers,
|
||||||
]:
|
]:
|
||||||
|
print('rebooting', node.name)
|
||||||
try:
|
try:
|
||||||
if node.run('test -e /var/run/reboot-required', may_fail=True).return_code == 0:
|
print(node.run('systemctl reboot').stdout.decode())
|
||||||
print('rebooting', node.name)
|
|
||||||
print(node.run('systemctl reboot').stdout.decode())
|
|
||||||
else:
|
|
||||||
print('not rebooting', node.name)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
|
@ -5,17 +5,9 @@ from os.path import realpath, dirname
|
||||||
from sys import argv
|
from sys import argv
|
||||||
from ipaddress import ip_network, ip_interface
|
from ipaddress import ip_network, ip_interface
|
||||||
|
|
||||||
if len(argv) != 3:
|
|
||||||
print(f'usage: {argv[0]} <node> <client>')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
repo = Repository(dirname(dirname(realpath(__file__))))
|
repo = Repository(dirname(dirname(realpath(__file__))))
|
||||||
|
|
||||||
server_node = repo.get_node(argv[1])
|
server_node = repo.get_node(argv[1])
|
||||||
|
|
||||||
if argv[2] not in server_node.metadata.get('wireguard/clients'):
|
|
||||||
print(f'client {argv[2]} not found in: {server_node.metadata.get("wireguard/clients").keys()}')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
data = server_node.metadata.get(f'wireguard/clients/{argv[2]}')
|
data = server_node.metadata.get(f'wireguard/clients/{argv[2]}')
|
||||||
|
|
||||||
vpn_network = ip_interface(server_node.metadata.get('wireguard/my_ip')).network
|
vpn_network = ip_interface(server_node.metadata.get('wireguard/my_ip')).network
|
||||||
|
@ -28,7 +20,9 @@ for peer in server_node.metadata.get('wireguard/s2s').values():
|
||||||
if not ip_network(network).subnet_of(vpn_network):
|
if not ip_network(network).subnet_of(vpn_network):
|
||||||
allowed_ips.append(ip_network(network))
|
allowed_ips.append(ip_network(network))
|
||||||
|
|
||||||
conf = f'''
|
conf = \
|
||||||
|
f'''>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||||
|
|
||||||
[Interface]
|
[Interface]
|
||||||
PrivateKey = {repo.libs.wireguard.privkey(data['peer_id'])}
|
PrivateKey = {repo.libs.wireguard.privkey(data['peer_id'])}
|
||||||
ListenPort = 51820
|
ListenPort = 51820
|
||||||
|
@ -41,12 +35,11 @@ PresharedKey = {repo.libs.wireguard.psk(data['peer_id'], server_node.metadata.ge
|
||||||
AllowedIPs = {', '.join(str(client_route) for client_route in sorted(allowed_ips))}
|
AllowedIPs = {', '.join(str(client_route) for client_route in sorted(allowed_ips))}
|
||||||
Endpoint = {ip_interface(server_node.metadata.get('network/external/ipv4')).ip}:51820
|
Endpoint = {ip_interface(server_node.metadata.get('network/external/ipv4')).ip}:51820
|
||||||
PersistentKeepalive = 10
|
PersistentKeepalive = 10
|
||||||
'''
|
|
||||||
|
|
||||||
print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'''
|
||||||
|
|
||||||
print(conf)
|
print(conf)
|
||||||
print('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<')
|
|
||||||
|
|
||||||
if input("print qrcode? [Yn]: ").upper() in ['', 'Y']:
|
if input("print qrcode? [yN]: ").upper() == 'Y':
|
||||||
import pyqrcode
|
import pyqrcode
|
||||||
print(pyqrcode.create(conf).terminal(quiet_zone=1))
|
print(pyqrcode.create(conf).terminal(quiet_zone=1))
|
||||||
|
|
|
@ -23,12 +23,12 @@ directories = {
|
||||||
'action:apt_update',
|
'action:apt_update',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# '/etc/apt/listchanges.conf.d': {
|
'/etc/apt/listchanges.conf.d': {
|
||||||
# 'purge': True,
|
'purge': True,
|
||||||
# 'triggers': {
|
'triggers': {
|
||||||
# 'action:apt_update',
|
'action:apt_update',
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
'/etc/apt/preferences.d': {
|
'/etc/apt/preferences.d': {
|
||||||
'purge': True,
|
'purge': True,
|
||||||
'triggers': {
|
'triggers': {
|
||||||
|
@ -50,15 +50,9 @@ files = {
|
||||||
'action:apt_update',
|
'action:apt_update',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'/etc/apt/sources.list': {
|
'/etc/apt/listchanges.conf': {
|
||||||
'content': '# managed by bundlewrap\n',
|
'content': repo.libs.ini.dumps(node.metadata.get('apt/list_changes')),
|
||||||
'triggers': {
|
|
||||||
'action:apt_update',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
# '/etc/apt/listchanges.conf': {
|
|
||||||
# 'content': repo.libs.ini.dumps(node.metadata.get('apt/list_changes')),
|
|
||||||
# },
|
|
||||||
'/usr/lib/nagios/plugins/check_apt_upgradable': {
|
'/usr/lib/nagios/plugins/check_apt_upgradable': {
|
||||||
'mode': '0755',
|
'mode': '0755',
|
||||||
},
|
},
|
||||||
|
@ -66,7 +60,7 @@ files = {
|
||||||
|
|
||||||
actions = {
|
actions = {
|
||||||
'apt_update': {
|
'apt_update': {
|
||||||
'command': 'apt-get update',
|
'command': 'apt-get update -o APT::Update::Error-Mode=any',
|
||||||
'needed_by': {
|
'needed_by': {
|
||||||
'pkg_apt:',
|
'pkg_apt:',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,24 +1,13 @@
|
||||||
defaults = {
|
defaults = {
|
||||||
'apt': {
|
'apt': {
|
||||||
'packages': {
|
|
||||||
'apt-listchanges': {
|
|
||||||
'installed': False,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'config': {
|
'config': {
|
||||||
'DPkg': {
|
'DPkg': {
|
||||||
'Pre-Install-Pkgs': {
|
'Pre-Install-Pkgs': {
|
||||||
'/usr/sbin/dpkg-preconfigure --apt || true',
|
'/usr/sbin/dpkg-preconfigure --apt || true',
|
||||||
},
|
},
|
||||||
'Post-Invoke': {
|
'Post-Invoke': {
|
||||||
# keep package cache empty
|
|
||||||
'/bin/rm -f /var/cache/apt/archives/*.deb || true',
|
'/bin/rm -f /var/cache/apt/archives/*.deb || true',
|
||||||
},
|
},
|
||||||
'Options': {
|
|
||||||
# https://unix.stackexchange.com/a/642541/357916
|
|
||||||
'--force-confold',
|
|
||||||
'--force-confdef',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'APT': {
|
'APT': {
|
||||||
'NeverAutoRemove': {
|
'NeverAutoRemove': {
|
||||||
|
@ -40,13 +29,7 @@ defaults = {
|
||||||
'metapackages',
|
'metapackages',
|
||||||
'tasks',
|
'tasks',
|
||||||
},
|
},
|
||||||
'Move-Autobit-Sections': {
|
'Move-Autobit-Sections': 'oldlibs',
|
||||||
'oldlibs',
|
|
||||||
},
|
|
||||||
'Update': {
|
|
||||||
# https://unix.stackexchange.com/a/653377/357916
|
|
||||||
'Error-Mode': 'any',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'sources': {},
|
'sources': {},
|
||||||
|
@ -133,45 +116,45 @@ def unattended_upgrades(metadata):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# @metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
# 'apt/config',
|
'apt/config',
|
||||||
# 'apt/list_changes',
|
'apt/list_changes',
|
||||||
# )
|
)
|
||||||
# def listchanges(metadata):
|
def listchanges(metadata):
|
||||||
# return {
|
return {
|
||||||
# 'apt': {
|
'apt': {
|
||||||
# 'config': {
|
'config': {
|
||||||
# 'DPkg': {
|
'DPkg': {
|
||||||
# 'Pre-Install-Pkgs': {
|
'Pre-Install-Pkgs': {
|
||||||
# '/usr/bin/apt-listchanges --apt || test $? -lt 10',
|
'/usr/bin/apt-listchanges --apt || test $? -lt 10',
|
||||||
# },
|
},
|
||||||
# 'Tools': {
|
},
|
||||||
# 'Options': {
|
'Tools': {
|
||||||
# '/usr/bin/apt-listchanges': {
|
'Options': {
|
||||||
# 'Version': '2',
|
'/usr/bin/apt-listchanges': {
|
||||||
# 'InfoFD': '20',
|
'Version': '2',
|
||||||
# },
|
'InfoFD': '20',
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# 'Dir': {
|
'Dir': {
|
||||||
# 'Etc': {
|
'Etc': {
|
||||||
# 'apt-listchanges-main': 'listchanges.conf',
|
'apt-listchanges-main': 'listchanges.conf',
|
||||||
# 'apt-listchanges-parts': 'listchanges.conf.d',
|
'apt-listchanges-parts': 'listchanges.conf.d',
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# 'list_changes': {
|
'list_changes': {
|
||||||
# 'apt': {
|
'apt': {
|
||||||
# 'frontend': 'pager',
|
'frontend': 'pager',
|
||||||
# 'which': 'news',
|
'which': 'news',
|
||||||
# 'email_address': 'root',
|
'email_address': 'root',
|
||||||
# 'email_format': 'text',
|
'email_format': 'text',
|
||||||
# 'confirm': 'false',
|
'confirm': 'false',
|
||||||
# 'headers': 'false',
|
'headers': 'false',
|
||||||
# 'reverse': 'false',
|
'reverse': 'false',
|
||||||
# 'save_seen': '/var/lib/apt/listchanges.db',
|
'save_seen': '/var/lib/apt/listchanges.db',
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# },
|
},
|
||||||
# }
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ for dataset in config['datasets']:
|
||||||
|
|
||||||
if snapshot_datetime < two_days_ago:
|
if snapshot_datetime < two_days_ago:
|
||||||
days_ago = (now - snapshot_datetime).days
|
days_ago = (now - snapshot_datetime).days
|
||||||
errors.add(f'dataset "{dataset}" has not been backed up for {days_ago} days')
|
errors.add(f'dataset "{dataset}" has no backups sind {days_ago} days')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
|
|
|
@ -25,8 +25,7 @@ def backup_freshness_check(metadata):
|
||||||
'datasets': {
|
'datasets': {
|
||||||
f"{other_node.metadata.get('id')}/{dataset}"
|
f"{other_node.metadata.get('id')}/{dataset}"
|
||||||
for other_node in repo.nodes
|
for other_node in repo.nodes
|
||||||
if not other_node.dummy
|
if other_node.has_bundle('backup')
|
||||||
and other_node.has_bundle('backup')
|
|
||||||
and other_node.has_bundle('zfs')
|
and other_node.has_bundle('zfs')
|
||||||
and other_node.metadata.get('backup/server') == metadata.get('backup-freshness-check/server')
|
and other_node.metadata.get('backup/server') == metadata.get('backup-freshness-check/server')
|
||||||
for dataset, options in other_node.metadata.get('zfs/datasets').items()
|
for dataset, options in other_node.metadata.get('zfs/datasets').items()
|
||||||
|
|
|
@ -35,7 +35,6 @@ def zfs(metadata):
|
||||||
|
|
||||||
for other_node in repo.nodes:
|
for other_node in repo.nodes:
|
||||||
if (
|
if (
|
||||||
not other_node.dummy and
|
|
||||||
other_node.has_bundle('backup') and
|
other_node.has_bundle('backup') and
|
||||||
other_node.metadata.get('backup/server') == node.name
|
other_node.metadata.get('backup/server') == node.name
|
||||||
):
|
):
|
||||||
|
|
|
@ -1,31 +1,13 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -u
|
set -exu
|
||||||
|
|
||||||
# FIXME: inelegant
|
# FIXME: inelegant
|
||||||
% if wol_command:
|
% if wol_command:
|
||||||
${wol_command}
|
${wol_command}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
exit=0
|
|
||||||
failed_paths=""
|
|
||||||
|
|
||||||
for path in $(jq -r '.paths | .[]' < /etc/backup/config.json)
|
for path in $(jq -r '.paths | .[]' < /etc/backup/config.json)
|
||||||
do
|
do
|
||||||
echo backing up $path
|
|
||||||
/opt/backup/backup_path "$path"
|
/opt/backup/backup_path "$path"
|
||||||
# set exit to 1 if any backup fails
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo ERROR: backing up $path failed >&2
|
|
||||||
exit=5
|
|
||||||
failed_paths="$failed_paths $path"
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $exit -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "ERROR: failed to backup paths: $failed_paths" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $exit
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -eu
|
set -exu
|
||||||
|
|
||||||
path=$1
|
path=$1
|
||||||
uuid=$(jq -r .client_uuid < /etc/backup/config.json)
|
uuid=$(jq -r .client_uuid < /etc/backup/config.json)
|
||||||
|
|
29
bundles/bind/README.md
Normal file
29
bundles/bind/README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
## DNSSEC
|
||||||
|
|
||||||
|
https://wiki.debian.org/DNSSEC%20Howto%20for%20BIND%209.9+#The_signing_part
|
||||||
|
https://blog.apnic.net/2021/11/02/dnssec-provisioning-automation-with-cds-cdnskey-in-the-real-world/
|
||||||
|
https://gist.github.com/wido/4c6288b2f5ba6d16fce37dca3fc2cb4a
|
||||||
|
|
||||||
|
```python
|
||||||
|
import dns.dnssec
|
||||||
|
algorithm = dns.dnssec.RSASHA256
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
import cryptography
|
||||||
|
pk = cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key(key_size=2048, public_exponent=65537)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nomenclature
|
||||||
|
|
||||||
|
### parent
|
||||||
|
|
||||||
|
DNSKEY:
|
||||||
|
the public key
|
||||||
|
|
||||||
|
DS
|
||||||
|
|
||||||
|
### sub
|
||||||
|
|
||||||
|
ZSK/KSK:
|
||||||
|
https://www.cloudflare.com/de-de/dns/dnssec/how-dnssec-works/
|
|
@ -19,7 +19,7 @@ directories[f'/var/lib/bind'] = {
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ files['/etc/default/bind9'] = {
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ files['/etc/bind/named.conf'] = {
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ files['/etc/bind/named.conf.options'] = {
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ files['/etc/bind/named.conf.local'] = {
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ for view_name, view_conf in master_node.metadata.get('bind/views').items():
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ for view_name, view_conf in master_node.metadata.get('bind/views').items():
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,6 @@ actions['named-checkconf'] = {
|
||||||
'unless': 'named-checkconf -z',
|
'unless': 'named-checkconf -z',
|
||||||
'needs': [
|
'needs': [
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
'svc_systemd:bind9:reload',
|
'svc_systemd:bind9:restart',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
from shlex import quote
|
from shlex import quote
|
||||||
|
|
||||||
|
|
||||||
defaults = {
|
|
||||||
'build-ci': {},
|
|
||||||
}
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'users/build-ci/authorized_users',
|
'users/build-ci/authorized_users',
|
||||||
'sudoers/build-ci',
|
'sudoers/build-ci',
|
||||||
|
@ -22,7 +18,7 @@ def ssh_keys(metadata):
|
||||||
},
|
},
|
||||||
'sudoers': {
|
'sudoers': {
|
||||||
'build-ci': {
|
'build-ci': {
|
||||||
f"/usr/bin/chown -R build-ci\\:{quote(ci['group'])} {quote(ci['path'])}"
|
f"/usr/bin/chown -R build-ci\:{quote(ci['group'])} {quote(ci['path'])}"
|
||||||
for ci in metadata.get('build-ci').values()
|
for ci in metadata.get('build-ci').values()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,7 @@ defaults = {
|
||||||
'crystal': {
|
'crystal': {
|
||||||
# https://software.opensuse.org/download.html?project=devel%3Alanguages%3Acrystal&package=crystal
|
# https://software.opensuse.org/download.html?project=devel%3Alanguages%3Acrystal&package=crystal
|
||||||
'urls': {
|
'urls': {
|
||||||
'http://download.opensuse.org/repositories/devel:/languages:/crystal/Debian_Testing/',
|
'https://download.opensuse.org/repositories/devel:/languages:/crystal/Debian_Testing/',
|
||||||
},
|
},
|
||||||
'suites': {
|
'suites': {
|
||||||
'/',
|
'/',
|
||||||
|
|
|
@ -6,7 +6,7 @@ ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')
|
||||||
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/privkey.pem
|
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/privkey.pem
|
||||||
ssl_dh = </etc/dovecot/dhparam.pem
|
ssl_dh = </etc/dovecot/dhparam.pem
|
||||||
ssl_client_ca_dir = /etc/ssl/certs
|
ssl_client_ca_dir = /etc/ssl/certs
|
||||||
mail_location = maildir:${node.metadata.get('mailserver/maildir')}/%u:INDEX=${node.metadata.get('mailserver/maildir')}/index/%u
|
mail_location = maildir:~
|
||||||
mail_plugins = fts fts_xapian
|
mail_plugins = fts fts_xapian
|
||||||
|
|
||||||
namespace inbox {
|
namespace inbox {
|
||||||
|
|
|
@ -20,10 +20,6 @@ directories = {
|
||||||
'owner': 'vmail',
|
'owner': 'vmail',
|
||||||
'group': 'vmail',
|
'group': 'vmail',
|
||||||
},
|
},
|
||||||
'/var/vmail/index': {
|
|
||||||
'owner': 'vmail',
|
|
||||||
'group': 'vmail',
|
|
||||||
},
|
|
||||||
'/var/vmail/sieve': {
|
'/var/vmail/sieve': {
|
||||||
'owner': 'vmail',
|
'owner': 'vmail',
|
||||||
'group': 'vmail',
|
'group': 'vmail',
|
||||||
|
|
6
bundles/download-server/items.py
Normal file
6
bundles/download-server/items.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# directories = {
|
||||||
|
# '/var/lib/downloads': {
|
||||||
|
# 'owner': 'downloads',
|
||||||
|
# 'group': 'www-data',
|
||||||
|
# }
|
||||||
|
# }
|
|
@ -1,23 +0,0 @@
|
||||||
Pg Pass workaround: set manually:
|
|
||||||
|
|
||||||
```
|
|
||||||
root@freescout /ro psql freescout
|
|
||||||
psql (15.6 (Debian 15.6-0+deb12u1))
|
|
||||||
Type "help" for help.
|
|
||||||
|
|
||||||
freescout=# \password freescout
|
|
||||||
Enter new password for user "freescout":
|
|
||||||
Enter it again:
|
|
||||||
freescout=#
|
|
||||||
\q
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# problems
|
|
||||||
|
|
||||||
# check if /opt/freescout/.env is resettet
|
|
||||||
# ckeck `psql -h localhost -d freescout -U freescout -W`with pw from .env
|
|
||||||
# chown -R www-data:www-data /opt/freescout
|
|
||||||
# sudo su - www-data -c 'php /opt/freescout/artisan freescout:clear-cache' -s /bin/bash
|
|
||||||
# javascript funny? `sudo su - www-data -c 'php /opt/freescout/artisan storage:link' -s /bin/bash`
|
|
||||||
# benutzer bilder weg? aus dem backup holen: `/opt/freescout/.zfs/snapshot/zfs-auto-snap_hourly-2024-11-22-1700/storage/app/public/users` `./customers`
|
|
|
@ -1,66 +0,0 @@
|
||||||
# https://github.com/freescout-helpdesk/freescout/wiki/Installation-Guide
|
|
||||||
run_as = repo.libs.tools.run_as
|
|
||||||
php_version = node.metadata.get('php/version')
|
|
||||||
|
|
||||||
|
|
||||||
directories = {
|
|
||||||
'/opt/freescout': {
|
|
||||||
'owner': 'www-data',
|
|
||||||
'group': 'www-data',
|
|
||||||
# chown -R www-data:www-data /opt/freescout
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
actions = {
|
|
||||||
# 'clone_freescout': {
|
|
||||||
# 'command': run_as('www-data', 'git clone https://github.com/freescout-helpdesk/freescout.git /opt/freescout'),
|
|
||||||
# 'unless': 'test -e /opt/freescout/.git',
|
|
||||||
# 'needs': [
|
|
||||||
# 'pkg_apt:git',
|
|
||||||
# 'directory:/opt/freescout',
|
|
||||||
# ],
|
|
||||||
# },
|
|
||||||
# 'pull_freescout': {
|
|
||||||
# 'command': run_as('www-data', 'git -C /opt/freescout fetch origin dist && git -C /opt/freescout reset --hard origin/dist && git -C /opt/freescout clean -f'),
|
|
||||||
# 'unless': run_as('www-data', 'git -C /opt/freescout fetch origin && git -C /opt/freescout status -uno | grep -q "Your branch is up to date"'),
|
|
||||||
# 'needs': [
|
|
||||||
# 'action:clone_freescout',
|
|
||||||
# ],
|
|
||||||
# 'triggers': [
|
|
||||||
# 'action:freescout_artisan_update',
|
|
||||||
# f'svc_systemd:php{php_version}-fpm.service:restart',
|
|
||||||
# ],
|
|
||||||
# },
|
|
||||||
# 'freescout_artisan_update': {
|
|
||||||
# 'command': run_as('www-data', 'php /opt/freescout/artisan freescout:after-app-update'),
|
|
||||||
# 'triggered': True,
|
|
||||||
# 'needs': [
|
|
||||||
# f'svc_systemd:php{php_version}-fpm.service:restart',
|
|
||||||
# 'action:pull_freescout',
|
|
||||||
# ],
|
|
||||||
# },
|
|
||||||
}
|
|
||||||
|
|
||||||
# svc_systemd = {
|
|
||||||
# f'freescout-cron.service': {},
|
|
||||||
# }
|
|
||||||
|
|
||||||
# files = {
|
|
||||||
# '/opt/freescout/.env': {
|
|
||||||
# # https://github.com/freescout-helpdesk/freescout/blob/dist/.env.example
|
|
||||||
# # Every time you are making changes in .env file, in order changes to take an effect you need to run:
|
|
||||||
# # ´sudo su - www-data -c 'php /opt/freescout/artisan freescout:clear-cache' -s /bin/bash´
|
|
||||||
# 'owner': 'www-data',
|
|
||||||
# 'content': '\n'.join(
|
|
||||||
# f'{k}={v}' for k, v in
|
|
||||||
# sorted(node.metadata.get('freescout/env').items())
|
|
||||||
# ) + '\n',
|
|
||||||
# 'needs': [
|
|
||||||
# 'directory:/opt/freescout',
|
|
||||||
# 'action:clone_freescout',
|
|
||||||
# ],
|
|
||||||
# },
|
|
||||||
# }
|
|
||||||
|
|
||||||
#sudo su - www-data -s /bin/bash -c 'php /opt/freescout/artisan freescout:create-user --role admin --firstName M --lastName W --email freescout@freibrief.net --password gyh.jzv2bnf6hvc.HKG --no-interaction'
|
|
||||||
#sudo su - www-data -s /bin/bash -c 'php /opt/freescout/artisan freescout:create-user --role admin --firstName M --lastName W --email freescout@freibrief.net --password gyh.jzv2bnf6hvc.HKG --no-interaction'
|
|
|
@ -1,121 +0,0 @@
|
||||||
from base64 import b64decode
|
|
||||||
|
|
||||||
# hash: SCRAM-SHA-256$4096:tQNfqQi7seqNDwJdHqCHbg==$r3ibECluHJaY6VRwpvPqrtCjgrEK7lAkgtUO8/tllTU=:+eeo4M0L2SowfyHFxT2FRqGzezve4ZOEocSIo11DATA=
|
|
||||||
database_password = repo.vault.password_for(f'{node.name} postgresql freescout').value
|
|
||||||
|
|
||||||
defaults = {
|
|
||||||
'apt': {
|
|
||||||
'packages': {
|
|
||||||
'git': {},
|
|
||||||
'php': {},
|
|
||||||
'php-pgsql': {},
|
|
||||||
'php-fpm': {},
|
|
||||||
'php-mbstring': {},
|
|
||||||
'php-xml': {},
|
|
||||||
'php-imap': {},
|
|
||||||
'php-zip': {},
|
|
||||||
'php-gd': {},
|
|
||||||
'php-curl': {},
|
|
||||||
'php-intl': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'freescout': {
|
|
||||||
'env': {
|
|
||||||
'APP_TIMEZONE': 'Europe/Berlin',
|
|
||||||
'DB_CONNECTION': 'pgsql',
|
|
||||||
'DB_HOST': '127.0.0.1',
|
|
||||||
'DB_PORT': '5432',
|
|
||||||
'DB_DATABASE': 'freescout',
|
|
||||||
'DB_USERNAME': 'freescout',
|
|
||||||
'DB_PASSWORD': database_password,
|
|
||||||
'APP_KEY': 'base64:' + repo.vault.random_bytes_as_base64_for(f'{node.name} freescout APP_KEY', length=32).value
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'php': {
|
|
||||||
'php.ini': {
|
|
||||||
'cgi': {
|
|
||||||
'fix_pathinfo': '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'postgresql': {
|
|
||||||
'roles': {
|
|
||||||
'freescout': {
|
|
||||||
'password_hash': repo.libs.postgres.generate_scram_sha_256(
|
|
||||||
database_password,
|
|
||||||
b64decode(repo.vault.random_bytes_as_base64_for(f'{node.name} postgres freescout', length=16).value.encode()),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'databases': {
|
|
||||||
'freescout': {
|
|
||||||
'owner': 'freescout',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
# 'systemd': {
|
|
||||||
# 'units': {
|
|
||||||
# f'freescout-cron.service': {
|
|
||||||
# 'Unit': {
|
|
||||||
# 'Description': 'Freescout Cron',
|
|
||||||
# 'After': 'network.target',
|
|
||||||
# },
|
|
||||||
# 'Service': {
|
|
||||||
# 'User': 'www-data',
|
|
||||||
# 'Nice': 10,
|
|
||||||
# 'ExecStart': f"/usr/bin/php /opt/freescout/artisan schedule:run"
|
|
||||||
# },
|
|
||||||
# 'Install': {
|
|
||||||
# 'WantedBy': {
|
|
||||||
# 'multi-user.target'
|
|
||||||
# }
|
|
||||||
# },
|
|
||||||
# }
|
|
||||||
# },
|
|
||||||
# },
|
|
||||||
'systemd-timers': {
|
|
||||||
'freescout-cron': {
|
|
||||||
'command': '/usr/bin/php /opt/freescout/artisan schedule:run',
|
|
||||||
'when': '*-*-* *:*:00',
|
|
||||||
'RuntimeMaxSec': '180',
|
|
||||||
'user': 'www-data',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'zfs': {
|
|
||||||
'datasets': {
|
|
||||||
'tank/freescout': {
|
|
||||||
'mountpoint': '/opt/freescout',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'freescout/env/APP_URL',
|
|
||||||
)
|
|
||||||
def freescout(metadata):
|
|
||||||
return {
|
|
||||||
'freescout': {
|
|
||||||
'env': {
|
|
||||||
'APP_URL': 'https://' + metadata.get('freescout/domain') + '/',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'nginx/vhosts',
|
|
||||||
)
|
|
||||||
def nginx(metadata):
|
|
||||||
return {
|
|
||||||
'nginx': {
|
|
||||||
'vhosts': {
|
|
||||||
metadata.get('freescout/domain'): {
|
|
||||||
'content': 'freescout/vhost.conf',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -2,13 +2,10 @@ from os.path import join
|
||||||
from bundlewrap.utils.dicts import merge_dict
|
from bundlewrap.utils.dicts import merge_dict
|
||||||
|
|
||||||
|
|
||||||
version = node.metadata.get('gitea/version')
|
version = version=node.metadata.get('gitea/version')
|
||||||
assert not version.startswith('v')
|
|
||||||
arch = node.metadata.get('system/architecture')
|
|
||||||
|
|
||||||
downloads['/usr/local/bin/gitea'] = {
|
downloads['/usr/local/bin/gitea'] = {
|
||||||
# https://forgejo.org/releases/
|
'url': f'https://dl.gitea.io/gitea/{version}/gitea-{version}-linux-amd64',
|
||||||
'url': f'https://codeberg.org/forgejo/forgejo/releases/download/v{version}/forgejo-{version}-linux-{arch}',
|
|
||||||
'sha256_url': '{url}.sha256',
|
'sha256_url': '{url}.sha256',
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:gitea:restart',
|
'svc_systemd:gitea:restart',
|
||||||
|
@ -48,7 +45,6 @@ files['/etc/gitea/app.ini'] = {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'owner': 'git',
|
'owner': 'git',
|
||||||
'mode': '0600',
|
|
||||||
'context': node.metadata['gitea'],
|
'context': node.metadata['gitea'],
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:gitea:restart',
|
'svc_systemd:gitea:restart',
|
||||||
|
|
|
@ -11,20 +11,7 @@ defaults = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'gitea': {
|
'gitea': {
|
||||||
'conf': {
|
'conf': {},
|
||||||
'DEFAULT': {
|
|
||||||
'WORK_PATH': '/var/lib/gitea',
|
|
||||||
},
|
|
||||||
'database': {
|
|
||||||
'DB_TYPE': 'postgres',
|
|
||||||
'HOST': 'localhost:5432',
|
|
||||||
'NAME': 'gitea',
|
|
||||||
'USER': 'gitea',
|
|
||||||
'PASSWD': database_password,
|
|
||||||
'SSL_MODE': 'disable',
|
|
||||||
'LOG_SQL': 'false',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'postgresql': {
|
'postgresql': {
|
||||||
'roles': {
|
'roles': {
|
||||||
|
@ -96,6 +83,15 @@ def conf(metadata):
|
||||||
'INTERNAL_TOKEN': repo.vault.password_for(f'{node.name} gitea internal_token'),
|
'INTERNAL_TOKEN': repo.vault.password_for(f'{node.name} gitea internal_token'),
|
||||||
'SECRET_KEY': repo.vault.password_for(f'{node.name} gitea security_secret_key'),
|
'SECRET_KEY': repo.vault.password_for(f'{node.name} gitea security_secret_key'),
|
||||||
},
|
},
|
||||||
|
'database': {
|
||||||
|
'DB_TYPE': 'postgres',
|
||||||
|
'HOST': 'localhost:5432',
|
||||||
|
'NAME': 'gitea',
|
||||||
|
'USER': 'gitea',
|
||||||
|
'PASSWD': database_password,
|
||||||
|
'SSL_MODE': 'disable',
|
||||||
|
'LOG_SQL': 'false',
|
||||||
|
},
|
||||||
'service': {
|
'service': {
|
||||||
'NO_REPLY_ADDRESS': f'noreply.{domain}',
|
'NO_REPLY_ADDRESS': f'noreply.{domain}',
|
||||||
},
|
},
|
||||||
|
@ -118,7 +114,7 @@ def nginx(metadata):
|
||||||
'content': 'nginx/proxy_pass.conf',
|
'content': 'nginx/proxy_pass.conf',
|
||||||
'context': {
|
'context': {
|
||||||
'target': 'http://127.0.0.1:3500',
|
'target': 'http://127.0.0.1:3500',
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,20 +26,14 @@ actions['reset_grafana_admin_password'] = {
|
||||||
|
|
||||||
directories = {
|
directories = {
|
||||||
'/etc/grafana': {},
|
'/etc/grafana': {},
|
||||||
'/etc/grafana/provisioning': {
|
'/etc/grafana/provisioning': {},
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
},
|
|
||||||
'/etc/grafana/provisioning/datasources': {
|
'/etc/grafana/provisioning/datasources': {
|
||||||
'purge': True,
|
'purge': True,
|
||||||
},
|
},
|
||||||
'/etc/grafana/provisioning/dashboards': {
|
'/etc/grafana/provisioning/dashboards': {
|
||||||
'purge': True,
|
'purge': True,
|
||||||
},
|
},
|
||||||
'/var/lib/grafana': {
|
'/var/lib/grafana': {},
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
},
|
|
||||||
'/var/lib/grafana/dashboards': {
|
'/var/lib/grafana/dashboards': {
|
||||||
'owner': 'grafana',
|
'owner': 'grafana',
|
||||||
'group': 'grafana',
|
'group': 'grafana',
|
||||||
|
@ -53,8 +47,6 @@ directories = {
|
||||||
files = {
|
files = {
|
||||||
'/etc/grafana/grafana.ini': {
|
'/etc/grafana/grafana.ini': {
|
||||||
'content': repo.libs.ini.dumps(node.metadata.get('grafana/config')),
|
'content': repo.libs.ini.dumps(node.metadata.get('grafana/config')),
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:grafana-server:restart',
|
'svc_systemd:grafana-server:restart',
|
||||||
],
|
],
|
||||||
|
@ -64,8 +56,6 @@ files = {
|
||||||
'apiVersion': 1,
|
'apiVersion': 1,
|
||||||
'datasources': list(node.metadata.get('grafana/datasources').values()),
|
'datasources': list(node.metadata.get('grafana/datasources').values()),
|
||||||
}),
|
}),
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:grafana-server:restart',
|
'svc_systemd:grafana-server:restart',
|
||||||
],
|
],
|
||||||
|
@ -82,8 +72,6 @@ files = {
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:grafana-server:restart',
|
'svc_systemd:grafana-server:restart',
|
||||||
],
|
],
|
||||||
|
@ -172,8 +160,6 @@ for dashboard_id, monitored_node in enumerate(monitored_nodes, start=1):
|
||||||
|
|
||||||
files[f'/var/lib/grafana/dashboards/{monitored_node.name}.json'] = {
|
files[f'/var/lib/grafana/dashboards/{monitored_node.name}.json'] = {
|
||||||
'content': json.dumps(dashboard, indent=4),
|
'content': json.dumps(dashboard, indent=4),
|
||||||
'owner': 'grafana',
|
|
||||||
'group': 'grafana',
|
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:grafana-server:restart',
|
'svc_systemd:grafana-server:restart',
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
https://github.com/home-assistant/supervised-installer?tab=readme-ov-file
|
|
||||||
https://github.com/home-assistant/os-agent/tree/main?tab=readme-ov-file#using-home-assistant-supervised-on-debian
|
|
||||||
https://docs.docker.com/engine/install/debian/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
https://www.home-assistant.io/installation/linux#install-home-assistant-supervised
|
|
||||||
https://github.com/home-assistant/supervised-installer
|
|
||||||
https://github.com/home-assistant/architecture/blob/master/adr/0014-home-assistant-supervised.md
|
|
||||||
|
|
||||||
DATA_SHARE=/usr/share/hassio dpkg --force-confdef --force-confold -i homeassistant-supervised.deb
|
|
||||||
|
|
||||||
neu debian
|
|
||||||
ha installieren
|
|
||||||
gucken ob geht
|
|
||||||
dann bw drüberbügeln
|
|
||||||
|
|
||||||
|
|
||||||
https://www.home-assistant.io/integrations/http/#ssl_certificate
|
|
||||||
|
|
||||||
`wget "$(curl -L https://api.github.com/repos/home-assistant/supervised-installer/releases/latest | jq -r '.assets[0].browser_download_url')" -O homeassistant-supervised.deb && dpkg -i homeassistant-supervised.deb`
|
|
|
@ -1,30 +0,0 @@
|
||||||
from shlex import quote
|
|
||||||
|
|
||||||
|
|
||||||
version = node.metadata.get('homeassistant/os_agent_version')
|
|
||||||
|
|
||||||
directories = {
|
|
||||||
'/usr/share/hassio': {},
|
|
||||||
}
|
|
||||||
|
|
||||||
actions = {
|
|
||||||
'install_os_agent': {
|
|
||||||
'command': ' && '.join([
|
|
||||||
f'wget -O /tmp/os-agent.deb https://github.com/home-assistant/os-agent/releases/download/{quote(version)}/os-agent_{quote(version)}_linux_aarch64.deb',
|
|
||||||
'DEBIAN_FRONTEND=noninteractive dpkg -i /tmp/os-agent.deb',
|
|
||||||
]),
|
|
||||||
'unless': f'test "$(apt -qq list os-agent | cut -d" " -f2)" = "{quote(version)}"',
|
|
||||||
'needs': {
|
|
||||||
'pkg_apt:',
|
|
||||||
'zfs_dataset:tank/homeassistant',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'install_homeassistant_supervised': {
|
|
||||||
'command': 'wget -O /tmp/homeassistant-supervised.deb https://github.com/home-assistant/supervised-installer/releases/latest/download/homeassistant-supervised.deb && apt install /tmp/homeassistant-supervised.deb',
|
|
||||||
'unless': 'apt -qq list homeassistant-supervised | grep -q "installed"',
|
|
||||||
'needs': {
|
|
||||||
'action:install_os_agent',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
defaults = {
|
|
||||||
'apt': {
|
|
||||||
'packages': {
|
|
||||||
# homeassistant-supervised
|
|
||||||
'apparmor': {},
|
|
||||||
'bluez': {},
|
|
||||||
'cifs-utils': {},
|
|
||||||
'curl': {},
|
|
||||||
'dbus': {},
|
|
||||||
'jq': {},
|
|
||||||
'libglib2.0-bin': {},
|
|
||||||
'lsb-release': {},
|
|
||||||
'network-manager': {},
|
|
||||||
'nfs-common': {},
|
|
||||||
'systemd-journal-remote': {},
|
|
||||||
'systemd-resolved': {},
|
|
||||||
'udisks2': {},
|
|
||||||
'wget': {},
|
|
||||||
# docker
|
|
||||||
'docker-ce': {},
|
|
||||||
'docker-ce-cli': {},
|
|
||||||
'containerd.io': {},
|
|
||||||
'docker-buildx-plugin': {},
|
|
||||||
'docker-compose-plugin': {},
|
|
||||||
},
|
|
||||||
'sources': {
|
|
||||||
# docker: https://docs.docker.com/engine/install/debian/#install-using-the-repository
|
|
||||||
'docker': {
|
|
||||||
'urls': {
|
|
||||||
'https://download.docker.com/linux/debian',
|
|
||||||
},
|
|
||||||
'suites': {
|
|
||||||
'{codename}',
|
|
||||||
},
|
|
||||||
'components': {
|
|
||||||
'stable',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'zfs': {
|
|
||||||
'datasets': {
|
|
||||||
'tank/homeassistant': {
|
|
||||||
'mountpoint': '/usr/share/hassio',
|
|
||||||
'needed_by': {
|
|
||||||
'directory:/usr/share/hassio',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'nginx/vhosts',
|
|
||||||
)
|
|
||||||
def nginx(metadata):
|
|
||||||
return {
|
|
||||||
'nginx': {
|
|
||||||
'vhosts': {
|
|
||||||
metadata.get('homeassistant/domain'): {
|
|
||||||
'content': 'homeassistant/vhost.conf',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
20
bundles/homeassistant/items.py
Normal file
20
bundles/homeassistant/items.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
users = {
|
||||||
|
'homeassistant': {
|
||||||
|
'home': '/var/lib/homeassistant',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
directories = {
|
||||||
|
'/var/lib/homeassistant': {
|
||||||
|
'owner': 'homeassistant',
|
||||||
|
},
|
||||||
|
'/var/lib/homeassistant/config': {
|
||||||
|
'owner': 'homeassistant',
|
||||||
|
},
|
||||||
|
'/var/lib/homeassistant/venv': {
|
||||||
|
'owner': 'homeassistant',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# https://wiki.instar.com/de/Software/Linux/Home_Assistant/
|
20
bundles/homeassistant/metadata.py
Normal file
20
bundles/homeassistant/metadata.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
defaults = {
|
||||||
|
'apt': {
|
||||||
|
'packages': {
|
||||||
|
'python3': {},
|
||||||
|
'python3-dev': {},
|
||||||
|
'python3-pip': {},
|
||||||
|
'python3-venv': {},
|
||||||
|
'libffi-dev': {},
|
||||||
|
'libssl-dev': {},
|
||||||
|
'libjpeg-dev': {},
|
||||||
|
'zlib1g-dev': {},
|
||||||
|
'autoconf': {},
|
||||||
|
'build-essential': {},
|
||||||
|
'libopenjp2-7': {},
|
||||||
|
'libtiff5': {},
|
||||||
|
'libturbojpeg0-dev': {},
|
||||||
|
'tzdata': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -13,9 +13,9 @@ apply Notification "mail-icingaadmin" to Host {
|
||||||
user_groups = host.vars.notification.mail.groups
|
user_groups = host.vars.notification.mail.groups
|
||||||
users = host.vars.notification.mail.users
|
users = host.vars.notification.mail.users
|
||||||
|
|
||||||
|
//interval = 2h
|
||||||
|
|
||||||
|
//vars.notification_logtosyslog = true
|
||||||
|
|
||||||
|
|
||||||
assign where host.vars.notification.mail
|
assign where host.vars.notification.mail
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,9 @@ apply Notification "mail-icingaadmin" to Service {
|
||||||
user_groups = host.vars.notification.mail.groups
|
user_groups = host.vars.notification.mail.groups
|
||||||
users = host.vars.notification.mail.users
|
users = host.vars.notification.mail.users
|
||||||
|
|
||||||
|
//interval = 2h
|
||||||
|
|
||||||
|
//vars.notification_logtosyslog = true
|
||||||
|
|
||||||
|
|
||||||
assign where host.vars.notification.mail
|
assign where host.vars.notification.mail
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ svc_systemd = {
|
||||||
'icinga2.service': {
|
'icinga2.service': {
|
||||||
'needs': [
|
'needs': [
|
||||||
'pkg_apt:icinga2-ido-pgsql',
|
'pkg_apt:icinga2-ido-pgsql',
|
||||||
'svc_systemd:postgresql.service',
|
'svc_systemd:postgresql',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ defaults = {
|
||||||
'php-imagick': {},
|
'php-imagick': {},
|
||||||
'php-pgsql': {},
|
'php-pgsql': {},
|
||||||
'icingaweb2': {},
|
'icingaweb2': {},
|
||||||
#'icingaweb2-module-monitoring': {}, # ?
|
'icingaweb2-module-monitoring': {},
|
||||||
},
|
},
|
||||||
'sources': {
|
'sources': {
|
||||||
'icinga': {
|
'icinga': {
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
from json import dumps
|
|
||||||
from bundlewrap.metadata import MetadataJSONEncoder
|
|
||||||
|
|
||||||
files = {
|
|
||||||
'/etc/kea/kea-dhcp4.conf': {
|
|
||||||
'content': dumps(node.metadata.get('kea'), indent=4, sort_keys=True, cls=MetadataJSONEncoder),
|
|
||||||
'triggers': [
|
|
||||||
'svc_systemd:kea-dhcp4-server:restart',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
svc_systemd = {
|
|
||||||
'kea-dhcp4-server': {
|
|
||||||
'needs': [
|
|
||||||
'pkg_apt:kea-dhcp4-server',
|
|
||||||
'file:/etc/kea/kea-dhcp4.conf',
|
|
||||||
'svc_systemd:systemd-networkd:restart',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
from ipaddress import ip_interface, ip_network
|
|
||||||
|
|
||||||
hashable = repo.libs.hashable.hashable
|
|
||||||
|
|
||||||
|
|
||||||
defaults = {
|
|
||||||
'apt': {
|
|
||||||
'packages': {
|
|
||||||
'kea-dhcp4-server': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'kea': {
|
|
||||||
'Dhcp4': {
|
|
||||||
'interfaces-config': {
|
|
||||||
'interfaces': set(),
|
|
||||||
},
|
|
||||||
'lease-database': {
|
|
||||||
'type': 'memfile',
|
|
||||||
'lfc-interval': 3600
|
|
||||||
},
|
|
||||||
'subnet4': set(),
|
|
||||||
'loggers': set([
|
|
||||||
hashable({
|
|
||||||
'name': 'kea-dhcp4',
|
|
||||||
'output_options': [
|
|
||||||
{
|
|
||||||
'output': 'syslog',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'severity': 'INFO',
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'kea/Dhcp4/interfaces-config/interfaces',
|
|
||||||
'kea/Dhcp4/subnet4',
|
|
||||||
)
|
|
||||||
def subnets(metadata):
|
|
||||||
subnet4 = set()
|
|
||||||
interfaces = set()
|
|
||||||
reservations = set(
|
|
||||||
hashable({
|
|
||||||
'hw-address': network_conf['mac'],
|
|
||||||
'ip-address': str(ip_interface(network_conf['ipv4']).ip),
|
|
||||||
})
|
|
||||||
for other_node in repo.nodes
|
|
||||||
for network_conf in other_node.metadata.get('network', {}).values()
|
|
||||||
if 'mac' in network_conf
|
|
||||||
)
|
|
||||||
|
|
||||||
for network_name, network_conf in metadata.get('network').items():
|
|
||||||
dhcp_server_config = network_conf.get('dhcp_server_config', None)
|
|
||||||
|
|
||||||
if dhcp_server_config:
|
|
||||||
_network = ip_network(dhcp_server_config['subnet'])
|
|
||||||
|
|
||||||
subnet4.add(hashable({
|
|
||||||
'subnet': dhcp_server_config['subnet'],
|
|
||||||
'pools': [
|
|
||||||
{
|
|
||||||
'pool': f'{dhcp_server_config['pool_from']} - {dhcp_server_config['pool_to']}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'option-data': [
|
|
||||||
{
|
|
||||||
'name': 'routers',
|
|
||||||
'data': dhcp_server_config['router'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'domain-name-servers',
|
|
||||||
'data': '10.0.10.2',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'reservations': set(
|
|
||||||
reservation
|
|
||||||
for reservation in reservations
|
|
||||||
if ip_interface(reservation['ip-address']).ip in _network
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
|
|
||||||
interfaces.add(network_conf.get('interface', network_name))
|
|
||||||
|
|
||||||
return {
|
|
||||||
'kea': {
|
|
||||||
'Dhcp4': {
|
|
||||||
'interfaces-config': {
|
|
||||||
'interfaces': interfaces,
|
|
||||||
},
|
|
||||||
'subnet4': subnet4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,36 +1,36 @@
|
||||||
hostname "CroneKorkN : ${name}"
|
hostname "CroneKorkN : ${name}"
|
||||||
sv_contact "admin@sublimity.de"
|
sv_contact "admin@sublimity.de"
|
||||||
|
|
||||||
|
// assign serevr to steam group
|
||||||
sv_steamgroup "${','.join(steamgroups)}"
|
sv_steamgroup "${','.join(steamgroups)}"
|
||||||
|
|
||||||
rcon_password "${rcon_password}"
|
rcon_password "${rcon_password}"
|
||||||
|
|
||||||
|
// no annoying message of the day
|
||||||
motd_enabled 0
|
motd_enabled 0
|
||||||
|
|
||||||
|
// enable cheats
|
||||||
sv_cheats 1
|
sv_cheats 1
|
||||||
|
|
||||||
|
// allow inconsistent files on clients (weapon mods for example)
|
||||||
sv_consistency 0
|
sv_consistency 0
|
||||||
|
|
||||||
|
// connect from internet
|
||||||
sv_lan 0
|
sv_lan 0
|
||||||
|
|
||||||
|
// join game at any point
|
||||||
sv_allow_lobby_connect_only 0
|
sv_allow_lobby_connect_only 0
|
||||||
|
|
||||||
|
// allowed modes
|
||||||
sv_gametypes "coop,realism,survival,versus,teamversus,scavenge,teamscavenge"
|
sv_gametypes "coop,realism,survival,versus,teamversus,scavenge,teamscavenge"
|
||||||
|
|
||||||
|
// network
|
||||||
sv_minrate 30000
|
sv_minrate 30000
|
||||||
sv_maxrate 60000
|
sv_maxrate 60000
|
||||||
sv_mincmdrate 66
|
sv_mincmdrate 66
|
||||||
sv_maxcmdrate 101
|
sv_maxcmdrate 101
|
||||||
|
|
||||||
|
// logging
|
||||||
sv_logsdir "logs-${name}" //Folder in the game directory where server logs will be stored.
|
sv_logsdir "logs-${name}" //Folder in the game directory where server logs will be stored.
|
||||||
log on //Creates a logfile (on | off)
|
log on //Creates a logfile (on | off)
|
||||||
sv_logecho 0 //default 0; Echo log information to the console.
|
sv_logecho 0 //default 0; Echo log information to the console.
|
||||||
|
|
|
@ -56,7 +56,6 @@ for domain in node.metadata.get('letsencrypt/domains').keys():
|
||||||
'unless': f'/etc/dehydrated/letsencrypt-ensure-some-certificate {domain} true',
|
'unless': f'/etc/dehydrated/letsencrypt-ensure-some-certificate {domain} true',
|
||||||
'needs': {
|
'needs': {
|
||||||
'file:/etc/dehydrated/letsencrypt-ensure-some-certificate',
|
'file:/etc/dehydrated/letsencrypt-ensure-some-certificate',
|
||||||
'pkg_apt:dehydrated',
|
|
||||||
},
|
},
|
||||||
'needed_by': {
|
'needed_by': {
|
||||||
'svc_systemd:nginx',
|
'svc_systemd:nginx',
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
from shlex import quote
|
|
||||||
|
|
||||||
def generate_sysctl_key_value_pairs_from_json(json_data, parents=[]):
|
|
||||||
if isinstance(json_data, dict):
|
|
||||||
for key, value in json_data.items():
|
|
||||||
yield from generate_sysctl_key_value_pairs_from_json(value, [*parents, key])
|
|
||||||
elif isinstance(json_data, list):
|
|
||||||
raise ValueError(f"List not supported: '{json_data}'")
|
|
||||||
else:
|
|
||||||
# If it's a leaf node, yield the path
|
|
||||||
yield (parents, json_data)
|
|
||||||
|
|
||||||
key_value_pairs = generate_sysctl_key_value_pairs_from_json(node.metadata.get('sysctl'))
|
|
||||||
|
|
||||||
|
|
||||||
files= {
|
|
||||||
'/etc/sysctl.conf': {
|
|
||||||
'content': '\n'.join(
|
|
||||||
sorted(
|
|
||||||
f"{'.'.join(path)}={value}"
|
|
||||||
for path, value in key_value_pairs
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'triggers': [
|
|
||||||
'svc_systemd:systemd-sysctl.service:restart',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
svc_systemd = {
|
|
||||||
'systemd-sysctl.service': {},
|
|
||||||
}
|
|
||||||
|
|
||||||
for path, value in key_value_pairs:
|
|
||||||
actions[f'reload_sysctl.conf_{path}'] = {
|
|
||||||
'command': f"sysctl --values {'.'.join(path)} | grep -q {quote('^'+value+'$')}",
|
|
||||||
'needs': [
|
|
||||||
f'action:systemd-sysctl.service',
|
|
||||||
f'action:systemd-sysctl.service:restart',
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
defaults = {
|
|
||||||
'sysctl': {},
|
|
||||||
}
|
|
|
@ -20,19 +20,18 @@ files = {
|
||||||
}
|
}
|
||||||
|
|
||||||
actions = {
|
actions = {
|
||||||
'systemd-locale': {
|
|
||||||
'command': f'localectl set-locale LANG="{default_locale}"',
|
|
||||||
'unless': f'localectl | grep -Fi "system locale" | grep -Fi "{default_locale}"',
|
|
||||||
'triggers': {
|
|
||||||
'action:locale-gen',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'locale-gen': {
|
'locale-gen': {
|
||||||
'command': 'locale-gen',
|
'command': 'locale-gen',
|
||||||
'triggered': True,
|
'triggered': True,
|
||||||
'needs': {
|
'needs': {
|
||||||
'pkg_apt:locales',
|
'pkg_apt:locales',
|
||||||
'action:systemd-locale',
|
},
|
||||||
|
},
|
||||||
|
'systemd-locale': {
|
||||||
|
'command': f'localectl set-locale LANG="{default_locale}"',
|
||||||
|
'unless': f'localectl | grep -Fi "system locale" | grep -Fi "{default_locale}"',
|
||||||
|
'preceded_by': {
|
||||||
|
'action:locale-gen',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
cd "$OLDPWD"
|
cd "$OLDPWD"
|
||||||
|
|
||||||
export BW_ITEM_WORKERS=$(expr "$(sysctl -n hw.logicalcpu)" '*' 12 '/' 10)
|
export BW_ITEM_WORKERS=$(expr "$(nproc)" '*' 15 '/' 10)
|
||||||
export BW_NODE_WORKERS=$(expr 320 '/' "$BW_ITEM_WORKERS")
|
export BW_NODE_WORKERS=$(expr 320 '/' "$BW_ITEM_WORKERS")
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
|
|
||||||
cd "$OLDPWD"
|
cd "$OLDPWD"
|
||||||
|
|
||||||
PATH_add "/opt/homebrew/opt/gnu-sed/libexec/gnubin"
|
GNU_PATH="$HOME/.local/gnu_bin"
|
||||||
PATH_add "/opt/homebrew/opt/grep/libexec/gnubin"
|
mkdir -p "$GNU_PATH"
|
||||||
|
test -f "$GNU_PATH/sed" || ln -s "$(which gsed)" "$GNU_PATH/sed"
|
||||||
|
PATH_add "$GNU_PATH"
|
||||||
|
|
|
@ -10,7 +10,6 @@ password required pam_deny.so
|
||||||
session required pam_permit.so
|
session required pam_permit.so
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
sudo xcodebuild -license accept
|
|
||||||
xcode-select --install
|
xcode-select --install
|
||||||
|
|
||||||
git -C ~/.zsh/oh-my-zsh pull
|
git -C ~/.zsh/oh-my-zsh pull
|
||||||
|
@ -18,7 +17,7 @@ git -C ~/.zsh/oh-my-zsh pull
|
||||||
brew upgrade
|
brew upgrade
|
||||||
brew upgrade --cask --greedy
|
brew upgrade --cask --greedy
|
||||||
|
|
||||||
pyenv install --skip-existing
|
pyenv install --keep-existing
|
||||||
|
|
||||||
sudo softwareupdate -ia --verbose
|
sudo softwareupdate -ia --verbose
|
||||||
|
|
||||||
|
@ -42,5 +41,3 @@ fi
|
||||||
sudo systemsetup -setremotelogin on # enable ssh
|
sudo systemsetup -setremotelogin on # enable ssh
|
||||||
|
|
||||||
pip install --upgrade pip
|
pip install --upgrade pip
|
||||||
|
|
||||||
# https://sysadmin-journal.com/apache-directory-studio-on-the-apple-m1/
|
|
||||||
|
|
|
@ -5,5 +5,5 @@ cd "$OLDPWD"
|
||||||
if test -f .venv/bin/python && test "$(realpath .venv/bin/python)" != "$(realpath "$(pyenv which python)")"
|
if test -f .venv/bin/python && test "$(realpath .venv/bin/python)" != "$(realpath "$(pyenv which python)")"
|
||||||
then
|
then
|
||||||
echo "rebuilding venv für new python version"
|
echo "rebuilding venv für new python version"
|
||||||
rm -rf .venv .pip_upgrade_timestamp
|
rm -rf .venv
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
cd "$OLDPWD"
|
cd "$OLDPWD"
|
||||||
|
|
||||||
python3 -m venv .venv
|
python3 -m venv .venv
|
||||||
source .venv/bin/activate
|
source ./.venv/bin/activate
|
||||||
PATH_add .venv/bin
|
PATH_add .venv/bin
|
||||||
|
|
||||||
NOW=$(date +%s)
|
NOW=$(date +%s)
|
||||||
|
@ -19,9 +19,5 @@ if test "$DELTA" -gt 86400
|
||||||
then
|
then
|
||||||
python3 -m pip --require-virtualenv install pip wheel --upgrade
|
python3 -m pip --require-virtualenv install pip wheel --upgrade
|
||||||
python3 -m pip --require-virtualenv install -r requirements.txt --upgrade
|
python3 -m pip --require-virtualenv install -r requirements.txt --upgrade
|
||||||
if test -e optional-requirements.txt
|
|
||||||
then
|
|
||||||
python3 -m pip --require-virtualenv install -r optional-requirements.txt --upgrade
|
|
||||||
fi
|
|
||||||
date +%s > .pip_upgrade_timestamp
|
date +%s > .pip_upgrade_timestamp
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
export PATH=~/.bin:$PATH
|
export PATH=~/.bin:$PATH
|
||||||
export PATH=~/.cargo/bin:$PATH
|
|
||||||
|
|
||||||
export ZSH=~/.zsh/oh-my-zsh
|
export ZSH=~/.zsh/oh-my-zsh
|
||||||
export ZSH_HOSTNAME='sm'
|
ZSH_THEME="ckn"
|
||||||
ZSH_THEME="bw"
|
|
||||||
HIST_STAMPS="yyyy/mm/dd"
|
HIST_STAMPS="yyyy/mm/dd"
|
||||||
plugins=(
|
plugins=(
|
||||||
zsh-autosuggestions
|
zsh-autosuggestions
|
||||||
|
@ -13,6 +10,13 @@ source $ZSH/oh-my-zsh.sh
|
||||||
|
|
||||||
ulimit -S -n 24000
|
ulimit -S -n 24000
|
||||||
|
|
||||||
|
sshn() {
|
||||||
|
ssh "$(tr '.' ' ' <<< "$1" | tac -s ' ' | xargs | tr ' ' '.').smhss.de"
|
||||||
|
}
|
||||||
|
pingn() {
|
||||||
|
ping "$(tr '.' ' ' <<< "$1" | tac -s ' ' | xargs | tr ' ' '.').smhss.de"
|
||||||
|
}
|
||||||
|
|
||||||
antivir() {
|
antivir() {
|
||||||
printf 'scanning for viruses' && sleep 1 && printf '.' && sleep 1 && printf '.' && sleep 1 && printf '.' &&
|
printf 'scanning for viruses' && sleep 1 && printf '.' && sleep 1 && printf '.' && sleep 1 && printf '.' &&
|
||||||
sleep 1 && echo '\nyour computer is safe!'
|
sleep 1 && echo '\nyour computer is safe!'
|
||||||
|
@ -22,12 +26,3 @@ eval "$(rbenv init -)"
|
||||||
eval "$(pyenv init -)"
|
eval "$(pyenv init -)"
|
||||||
eval "$(direnv hook zsh)"
|
eval "$(direnv hook zsh)"
|
||||||
eval "$(op completion zsh)"; compdef _op op
|
eval "$(op completion zsh)"; compdef _op op
|
||||||
|
|
||||||
# //S/M
|
|
||||||
|
|
||||||
sshn() {
|
|
||||||
ssh "$(tr '.' ' ' <<< "$1" | tac -s ' ' | xargs | tr ' ' '.').smhss.de"
|
|
||||||
}
|
|
||||||
pingn() {
|
|
||||||
ping "$(tr '.' ' ' <<< "$1" | tac -s ' ' | xargs | tr ' ' '.').smhss.de"
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
# brew install
|
|
||||||
|
|
||||||
actions['brew_install'] = {
|
|
||||||
'command': '/opt/homebrew/bin/brew install ' + ' '.join(node.metadata.get('brew')),
|
|
||||||
'unless': f"""PKGS=$(/opt/homebrew/bin/brew leaves); for p in {' '.join(node.metadata.get('brew'))}; do grep -q "$p" <<< $PKGS || exit 9; done"""
|
|
||||||
}
|
|
||||||
|
|
||||||
# bw init
|
|
||||||
|
|
||||||
directories['/Users/mwiegand/.config/bundlewrap/lock'] = {}
|
directories['/Users/mwiegand/.config/bundlewrap/lock'] = {}
|
||||||
|
|
||||||
# home
|
# home
|
||||||
|
@ -22,12 +13,6 @@ files['/Users/mwiegand/.bin/macbook-update'] = {
|
||||||
'mode': '755',
|
'mode': '755',
|
||||||
}
|
}
|
||||||
|
|
||||||
with open(f'{repo.path}/bundles/zsh/files/bw.zsh-theme') as f:
|
|
||||||
files['/Users/mwiegand/.zsh/oh-my-zsh/themes/bw.zsh-theme'] = {
|
|
||||||
'content': f.read(),
|
|
||||||
'mode': '0644',
|
|
||||||
}
|
|
||||||
|
|
||||||
# direnv
|
# direnv
|
||||||
|
|
||||||
directories['/Users/mwiegand/.local/share/direnv'] = {}
|
directories['/Users/mwiegand/.local/share/direnv'] = {}
|
||||||
|
@ -36,7 +21,6 @@ files['/Users/mwiegand/.local/share/direnv/pyenv'] = {}
|
||||||
files['/Users/mwiegand/.local/share/direnv/venv'] = {}
|
files['/Users/mwiegand/.local/share/direnv/venv'] = {}
|
||||||
files['/Users/mwiegand/.local/share/direnv/bundlewrap'] = {}
|
files['/Users/mwiegand/.local/share/direnv/bundlewrap'] = {}
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
|
|
||||||
for element in [*files.values(), *directories.values()]:
|
for element in [*files.values(), *directories.values()]:
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
defaults = {
|
defaults = {}
|
||||||
'brew': {},
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// https://raw.githubusercontent.com/Radiergummi/autodiscover/master/autodiscover/autodiscover.php
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* Autodiscover responder
|
* Autodiscover responder
|
||||||
|
@ -8,45 +8,45 @@
|
||||||
* This PHP script is intended to respond to any request to http(s)://mydomain.com/autodiscover/autodiscover.xml.
|
* This PHP script is intended to respond to any request to http(s)://mydomain.com/autodiscover/autodiscover.xml.
|
||||||
* If configured properly, it will send a spec-complient autodiscover XML response, pointing mail clients to the
|
* If configured properly, it will send a spec-complient autodiscover XML response, pointing mail clients to the
|
||||||
* appropriate mail services.
|
* appropriate mail services.
|
||||||
* If you use MAPI or ActiveSync, stick with the Autodiscover service your mail server provides for you. But if
|
* If you use MAPI or ActiveSync, stick with the Autodiscover service your mail server provides for you. But if
|
||||||
* you use POP/IMAP servers, this will provide autoconfiguration to Outlook, Apple Mail and mobile devices.
|
* you use POP/IMAP servers, this will provide autoconfiguration to Outlook, Apple Mail and mobile devices.
|
||||||
*
|
*
|
||||||
* To work properly, you'll need to set the service (sub)domains below in the settings section to the correct
|
* To work properly, you'll need to set the service (sub)domains below in the settings section to the correct
|
||||||
* domain names, adjust ports and SSL.
|
* domain names, adjust ports and SSL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//get raw POST data so we can extract the email address
|
||||||
$request = file_get_contents("php://input");
|
$request = file_get_contents("php://input");
|
||||||
|
|
||||||
|
// optional debug log
|
||||||
# file_put_contents( 'request.log', $request, FILE_APPEND );
|
# file_put_contents( 'request.log', $request, FILE_APPEND );
|
||||||
|
|
||||||
|
// retrieve email address from client request
|
||||||
preg_match( "/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $request, $email );
|
preg_match( "/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $request, $email );
|
||||||
|
|
||||||
|
// check for invalid mail, to prevent XSS
|
||||||
if (filter_var($email[1], FILTER_VALIDATE_EMAIL) === false) {
|
if (filter_var($email[1], FILTER_VALIDATE_EMAIL) === false) {
|
||||||
throw new Exception('Invalid E-Mail provided');
|
throw new Exception('Invalid E-Mail provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get domain from email address
|
||||||
$domain = substr( strrchr( $email[1], "@" ), 1 );
|
$domain = substr( strrchr( $email[1], "@" ), 1 );
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* Port and server settings below *
|
* Port and server settings below *
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
|
// IMAP settings
|
||||||
$imapServer = 'imap.' . $domain; // imap.example.com
|
$imapServer = 'imap.' . $domain; // imap.example.com
|
||||||
$imapPort = 993;
|
$imapPort = 993;
|
||||||
$imapSSL = true;
|
$imapSSL = true;
|
||||||
|
|
||||||
|
// SMTP settings
|
||||||
$smtpServer = 'smtp.' . $domain; // smtp.example.com
|
$smtpServer = 'smtp.' . $domain; // smtp.example.com
|
||||||
$smtpPort = 587;
|
$smtpPort = 587;
|
||||||
$smtpSSL = true;
|
$smtpSSL = true;
|
||||||
|
|
||||||
|
//set Content-Type
|
||||||
header( 'Content-Type: application/xml' );
|
header( 'Content-Type: application/xml' );
|
||||||
?>
|
?>
|
||||||
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>
|
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>
|
||||||
|
|
|
@ -33,12 +33,6 @@ defaults = {
|
||||||
'mountpoint': '/var/vmail',
|
'mountpoint': '/var/vmail',
|
||||||
'compression': 'on',
|
'compression': 'on',
|
||||||
},
|
},
|
||||||
'tank/vmail/index': {
|
|
||||||
'mountpoint': '/var/vmail/index',
|
|
||||||
'compression': 'on',
|
|
||||||
'com.sun:auto-snapshot': 'false',
|
|
||||||
'backup': False,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
https://mariadb.com/kb/en/systemd/#configuring-mariadb-to-write-the-error-log-to-syslog
|
|
|
@ -1,11 +0,0 @@
|
||||||
% for section, options in sorted(conf.items()):
|
|
||||||
[${section}]
|
|
||||||
% for key, value in sorted(options.items()):
|
|
||||||
% if value is None:
|
|
||||||
${key}
|
|
||||||
% else:
|
|
||||||
${key} = ${value}
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
% endfor
|
|
|
@ -1,91 +0,0 @@
|
||||||
from shlex import quote
|
|
||||||
|
|
||||||
def mariadb(sql, **kwargs):
|
|
||||||
kwargs_string = ''.join(f" --{k} {v}" for k, v in kwargs.items())
|
|
||||||
return f"mariadb{kwargs_string} -Bsr --execute {quote(sql)}"
|
|
||||||
|
|
||||||
directories = {
|
|
||||||
'/var/lib/mysql': {
|
|
||||||
'owner': 'mysql',
|
|
||||||
'group': 'mysql',
|
|
||||||
'needs': [
|
|
||||||
'zfs_dataset:tank/mariadb',
|
|
||||||
],
|
|
||||||
'needed_by': [
|
|
||||||
'pkg_apt:mariadb-server',
|
|
||||||
'pkg_apt:mariadb-client',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
files = {
|
|
||||||
'/etc/mysql/conf.d/override.conf': {
|
|
||||||
'context': {
|
|
||||||
'conf': node.metadata.get('mariadb/conf'),
|
|
||||||
},
|
|
||||||
'content_type': 'mako',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
svc_systemd = {
|
|
||||||
'mariadb.service': {
|
|
||||||
'needs': [
|
|
||||||
'pkg_apt:mariadb-server',
|
|
||||||
'pkg_apt:mariadb-client',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
actions = {
|
|
||||||
'mariadb_sec_remove_anonymous_users': {
|
|
||||||
'command': mariadb("DELETE FROM mysql.global_priv WHERE User=''"),
|
|
||||||
'unless': mariadb("SELECT count(0) FROM mysql.global_priv WHERE User = ''") + " | grep -q '^0$'",
|
|
||||||
'needs': [
|
|
||||||
'svc_systemd:mariadb.service',
|
|
||||||
],
|
|
||||||
'triggers': [
|
|
||||||
'svc_systemd:mariadb.service:restart',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'mariadb_sec_remove_remote_root': {
|
|
||||||
'command': mariadb("DELETE FROM mysql.global_priv WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')"),
|
|
||||||
'unless': mariadb("SELECT count(0) FROM mysql.global_priv WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')") + " | grep -q '^0$'",
|
|
||||||
'needs': [
|
|
||||||
'svc_systemd:mariadb.service',
|
|
||||||
],
|
|
||||||
'triggers': [
|
|
||||||
'svc_systemd:mariadb.service:restart',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for db, conf in node.metadata.get('mariadb/databases', {}).items():
|
|
||||||
actions[f'mariadb_create_database_{db}'] = {
|
|
||||||
'command': mariadb(f"CREATE DATABASE {db}"),
|
|
||||||
'unless': mariadb(f"SHOW DATABASES LIKE '{db}'") + f" | grep -q '^{db}$'",
|
|
||||||
'needs': [
|
|
||||||
'svc_systemd:mariadb.service',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
actions[f'mariadb_user_{db}_create'] = {
|
|
||||||
'command': mariadb(f"CREATE USER {db}"),
|
|
||||||
'unless': mariadb(f"SELECT User FROM mysql.user WHERE User = '{db}'") + f" | grep -q '^{db}$'",
|
|
||||||
'needs': [
|
|
||||||
f'action:mariadb_create_database_{db}',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
pw = conf['password']
|
|
||||||
actions[f'mariadb_user_{db}_password'] = {
|
|
||||||
'command': mariadb(f"SET PASSWORD FOR {db} = PASSWORD('{conf['password']}')"),
|
|
||||||
'unless': f'echo {quote(pw)} | mariadb -u {db} -e quit -p',
|
|
||||||
'needs': [
|
|
||||||
f'action:mariadb_user_{db}_create',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
actions[f'mariadb_grant_privileges_to_{db}'] = {
|
|
||||||
'command': mariadb(f"GRANT ALL PRIVILEGES ON {db}.* TO '{db}'", database=db),
|
|
||||||
'unless': mariadb(f"SHOW GRANTS FOR {db}") + f" | grep -q '^GRANT ALL PRIVILEGES ON `{db}`.* TO `{db}`@`%`'",
|
|
||||||
'needs': [
|
|
||||||
f'action:mariadb_user_{db}_create',
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
defaults = {
|
|
||||||
'apt': {
|
|
||||||
'packages': {
|
|
||||||
'mariadb-server': {
|
|
||||||
'needs': {
|
|
||||||
'zfs_dataset:tank/mariadb',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'mariadb-client': {
|
|
||||||
'needs': {
|
|
||||||
'zfs_dataset:tank/mariadb',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'mariadb': {
|
|
||||||
'databases': {},
|
|
||||||
'conf': {
|
|
||||||
# https://www.reddit.com/r/zfs/comments/u1xklc/mariadbmysql_database_settings_for_zfs
|
|
||||||
'mysqld': {
|
|
||||||
'skip-innodb_doublewrite': None,
|
|
||||||
'innodb_flush_method': 'fsync',
|
|
||||||
'innodb_doublewrite': '0',
|
|
||||||
'innodb_use_atomic_writes': '0',
|
|
||||||
'innodb_use_native_aio': '0',
|
|
||||||
'innodb_read_io_threads': '10',
|
|
||||||
'innodb_write_io_threads': '10',
|
|
||||||
'innodb_buffer_pool_size': '26G',
|
|
||||||
'innodb_flush_log_at_trx_commit': '1',
|
|
||||||
'innodb_log_file_size': '1G',
|
|
||||||
'innodb_flush_neighbors': '0',
|
|
||||||
'innodb_fast_shutdown': '2',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'zfs': {
|
|
||||||
'datasets': {
|
|
||||||
'tank/mariadb': {
|
|
||||||
'mountpoint': '/var/lib/mysql',
|
|
||||||
'recordsize': '16384',
|
|
||||||
'atime': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -5,89 +5,38 @@ defaults = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'network',
|
|
||||||
)
|
|
||||||
def dhcp(metadata):
|
|
||||||
networks = {}
|
|
||||||
|
|
||||||
for network_name, network_conf in metadata.get('network').items():
|
|
||||||
_interface = ip_interface(network_conf['ipv4'])
|
|
||||||
_ip = _interface.ip
|
|
||||||
_network = _interface.network
|
|
||||||
_hosts = list(_network.hosts())
|
|
||||||
|
|
||||||
if network_conf.get('dhcp_server', False):
|
|
||||||
networks[network_name] = {
|
|
||||||
'dhcp_server_config': {
|
|
||||||
'subnet': str(_network),
|
|
||||||
'pool_from': str(_hosts[len(_hosts)//2]),
|
|
||||||
'pool_to': str(_hosts[-3]),
|
|
||||||
'router': str(_ip),
|
|
||||||
'domain-name-servers': str(_ip),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
'network': networks,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'systemd/units',
|
'systemd/units',
|
||||||
)
|
)
|
||||||
def units(metadata):
|
def units(metadata):
|
||||||
units = {}
|
units = {}
|
||||||
|
|
||||||
for network_name, network_conf in metadata.get('network').items():
|
for type, network in metadata.get('network').items():
|
||||||
interface_type = network_conf.get('type', None)
|
units[f'{type}.network'] = {
|
||||||
|
|
||||||
# network
|
|
||||||
|
|
||||||
units[f'{network_name}.network'] = {
|
|
||||||
'Match': {
|
'Match': {
|
||||||
'Name': network_name if interface_type == 'vlan' else network_conf['interface'],
|
'Name': network['interface'],
|
||||||
},
|
},
|
||||||
'Network': {
|
'Network': {
|
||||||
'DHCP': network_conf.get('dhcp', 'no'),
|
'DHCP': network.get('dhcp', 'no'),
|
||||||
'IPv6AcceptRA': network_conf.get('dhcp', 'no'),
|
'IPv6AcceptRA': network.get('dhcp', 'no'),
|
||||||
'VLAN': set(network_conf.get('vlans', set()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# type
|
|
||||||
|
|
||||||
if interface_type:
|
|
||||||
units[f'{network_name}.network']['Match']['Type'] = interface_type
|
|
||||||
|
|
||||||
# ips
|
|
||||||
|
|
||||||
for i in [4, 6]:
|
for i in [4, 6]:
|
||||||
if network_conf.get(f'ipv{i}', None):
|
if network.get(f'ipv{i}', None):
|
||||||
units[f'{network_name}.network'].update({
|
units[f'{type}.network'].update({
|
||||||
f'Address#ipv{i}': {
|
f'Address#ipv{i}': {
|
||||||
'Address': network_conf[f'ipv{i}'],
|
'Address': network[f'ipv{i}'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if f'gateway{i}' in network_conf:
|
if f'gateway{i}' in network:
|
||||||
units[f'{network_name}.network'].update({
|
units[f'{type}.network'].update({
|
||||||
f'Route#ipv{i}': {
|
f'Route#ipv{i}': {
|
||||||
'Gateway': network_conf[f'gateway{i}'],
|
'Gateway': network[f'gateway{i}'],
|
||||||
'GatewayOnlink': 'yes',
|
'GatewayOnlink': 'yes',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
# as vlan
|
|
||||||
|
|
||||||
if interface_type == 'vlan':
|
|
||||||
units[f"{network_name}.netdev"] = {
|
|
||||||
'NetDev': {
|
|
||||||
'Name': network_name,
|
|
||||||
'Kind': 'vlan',
|
|
||||||
},
|
|
||||||
'VLAN': {
|
|
||||||
'Id': network_conf['id'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'systemd': {
|
'systemd': {
|
||||||
|
|
|
@ -29,8 +29,8 @@ defaults = {
|
||||||
'exclude': [
|
'exclude': [
|
||||||
'^appdata_',
|
'^appdata_',
|
||||||
'^updater-',
|
'^updater-',
|
||||||
'^nextcloud\\.log',
|
'^nextcloud\.log',
|
||||||
'^updater\\.log',
|
'^updater\.log',
|
||||||
'^[^/]+/cache',
|
'^[^/]+/cache',
|
||||||
'^[^/]+/files_versions',
|
'^[^/]+/files_versions',
|
||||||
'^[^/]+/files_trashbin',
|
'^[^/]+/files_trashbin',
|
||||||
|
@ -123,9 +123,9 @@ def config(metadata):
|
||||||
],
|
],
|
||||||
'cache_path': '/var/lib/nextcloud/.cache',
|
'cache_path': '/var/lib/nextcloud/.cache',
|
||||||
'upgrade.disable-web': True,
|
'upgrade.disable-web': True,
|
||||||
'memcache.local': '\\OC\\Memcache\\Redis',
|
'memcache.local': '\OC\Memcache\Redis',
|
||||||
'memcache.locking': '\\OC\\Memcache\\Redis',
|
'memcache.locking': '\OC\Memcache\Redis',
|
||||||
'memcache.distributed': '\\OC\\Memcache\\Redis',
|
'memcache.distributed': '\OC\Memcache\Redis',
|
||||||
'redis': {
|
'redis': {
|
||||||
'host': '/var/run/redis/nextcloud.sock'
|
'host': '/var/run/redis/nextcloud.sock'
|
||||||
},
|
},
|
||||||
|
@ -142,7 +142,6 @@ def config(metadata):
|
||||||
'versions_retention_obligation': 'auto, 90',
|
'versions_retention_obligation': 'auto, 90',
|
||||||
'simpleSignUpLink.shown': False,
|
'simpleSignUpLink.shown': False,
|
||||||
'allow_local_remote_servers': True, # FIXME?
|
'allow_local_remote_servers': True, # FIXME?
|
||||||
'maintenance_window_start': 1, # https://docs.nextcloud.com/server/29/admin_manual/configuration_server/background_jobs_configuration.html#maintenance-window-start
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
pid /var/run/nginx.pid;
|
pid /var/run/nginx.pid;
|
||||||
user www-data;
|
user www-data;
|
||||||
worker_processes ${worker_processes};
|
worker_processes 10;
|
||||||
|
|
||||||
% for module in sorted(modules):
|
% for module in sorted(modules):
|
||||||
load_module modules/ngx_${module}_module.so;
|
load_module modules/ngx_${module}_module.so;
|
||||||
|
@ -21,9 +21,6 @@ http {
|
||||||
server_names_hash_bucket_size 128;
|
server_names_hash_bucket_size 128;
|
||||||
tcp_nopush on;
|
tcp_nopush on;
|
||||||
client_max_body_size 32G;
|
client_max_body_size 32G;
|
||||||
ssl_dhparam "/etc/ssl/certs/dhparam.pem";
|
|
||||||
# dont show nginx version
|
|
||||||
server_tokens off;
|
|
||||||
|
|
||||||
% if node.has_bundle('php'):
|
% if node.has_bundle('php'):
|
||||||
upstream php-handler {
|
upstream php-handler {
|
||||||
|
|
|
@ -32,7 +32,6 @@ files = {
|
||||||
'content_type': 'mako',
|
'content_type': 'mako',
|
||||||
'context': {
|
'context': {
|
||||||
'modules': node.metadata.get('nginx/modules'),
|
'modules': node.metadata.get('nginx/modules'),
|
||||||
'worker_processes': node.metadata.get('vm/cores'),
|
|
||||||
},
|
},
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:nginx:restart',
|
'svc_systemd:nginx:restart',
|
||||||
|
@ -77,7 +76,7 @@ files = {
|
||||||
|
|
||||||
actions = {
|
actions = {
|
||||||
'nginx-generate-dhparam': {
|
'nginx-generate-dhparam': {
|
||||||
'command': 'openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096',
|
'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048',
|
||||||
'unless': 'test -f /etc/ssl/certs/dhparam.pem',
|
'unless': 'test -f /etc/ssl/certs/dhparam.pem',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ def dns(metadata):
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'letsencrypt/domains',
|
'letsencrypt/domains',
|
||||||
|
'letsencrypt/reload_after',
|
||||||
)
|
)
|
||||||
def letsencrypt(metadata):
|
def letsencrypt(metadata):
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from os.path import join, exists
|
|
||||||
from re import sub
|
from re import sub
|
||||||
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
from os.path import join
|
||||||
|
import json
|
||||||
|
|
||||||
|
from bundlewrap.utils.dicts import merge_dict
|
||||||
|
|
||||||
|
|
||||||
version = node.metadata.get('php/version')
|
version = node.metadata.get('php/version')
|
||||||
|
|
||||||
files = {
|
files = {
|
||||||
|
@ -15,7 +21,7 @@ files = {
|
||||||
f'pkg_apt:php{version}-fpm',
|
f'pkg_apt:php{version}-fpm',
|
||||||
},
|
},
|
||||||
'triggers': {
|
'triggers': {
|
||||||
f'svc_systemd:php{version}-fpm.service:restart',
|
f'svc_systemd:php{version}-fpm:restart',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
f'/etc/php/{version}/fpm/pool.d/www.conf': {
|
f'/etc/php/{version}/fpm/pool.d/www.conf': {
|
||||||
|
@ -27,13 +33,13 @@ files = {
|
||||||
f'pkg_apt:php{version}-fpm',
|
f'pkg_apt:php{version}-fpm',
|
||||||
},
|
},
|
||||||
'triggers': {
|
'triggers': {
|
||||||
f'svc_systemd:php{version}-fpm.service:restart',
|
f'svc_systemd:php{version}-fpm:restart',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_systemd = {
|
svc_systemd = {
|
||||||
f'php{version}-fpm.service': {
|
f'php{version}-fpm': {
|
||||||
'needs': {
|
'needs': {
|
||||||
'pkg_apt:',
|
'pkg_apt:',
|
||||||
f'file:/etc/php/{version}/fpm/php.ini',
|
f'file:/etc/php/{version}/fpm/php.ini',
|
||||||
|
|
|
@ -113,7 +113,7 @@ def php_ini(metadata):
|
||||||
'opcache.revalidate_freq': '60',
|
'opcache.revalidate_freq': '60',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'php': {
|
'php': {
|
||||||
'php.ini': {
|
'php.ini': {
|
||||||
|
@ -145,7 +145,7 @@ def www_conf(metadata):
|
||||||
'pm': 'dynamic',
|
'pm': 'dynamic',
|
||||||
'pm.max_children': int(threads*2),
|
'pm.max_children': int(threads*2),
|
||||||
'pm.start_servers': int(threads),
|
'pm.start_servers': int(threads),
|
||||||
'pm.min_spare_servers': max([1, int(threads/2)]),
|
'pm.min_spare_servers': int(threads/2),
|
||||||
'pm.max_spare_servers': int(threads),
|
'pm.max_spare_servers': int(threads),
|
||||||
'pm.max_requests': int(threads*32),
|
'pm.max_requests': int(threads*32),
|
||||||
},
|
},
|
||||||
|
|
|
@ -44,9 +44,7 @@ smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||||
smtpd_restriction_classes = mua_sender_restrictions, mua_client_restrictions, mua_helo_restrictions
|
smtpd_restriction_classes = mua_sender_restrictions, mua_client_restrictions, mua_helo_restrictions
|
||||||
mua_client_restrictions = permit_sasl_authenticated, reject
|
mua_client_restrictions = permit_sasl_authenticated, reject
|
||||||
mua_sender_restrictions = permit_sasl_authenticated, reject
|
mua_sender_restrictions = permit_sasl_authenticated, reject
|
||||||
## MS Outlook, incompatible with reject_non_fqdn_hostname and/or reject_invalid_hostname
|
mua_helo_restrictions = permit_mynetworks, reject_non_fqdn_hostname, reject_invalid_hostname, permit
|
||||||
## https://unix.stackexchange.com/a/91753/357916
|
|
||||||
mua_helo_restrictions = permit_mynetworks, permit
|
|
||||||
|
|
||||||
smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332
|
smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332
|
||||||
non_smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332
|
non_smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332
|
||||||
|
|
|
@ -86,8 +86,6 @@ if node.has_bundle('telegraf'):
|
||||||
'needs': [
|
'needs': [
|
||||||
'pkg_apt:acl',
|
'pkg_apt:acl',
|
||||||
'svc_systemd:postfix',
|
'svc_systemd:postfix',
|
||||||
'svc_systemd:postfix:reload',
|
|
||||||
'svc_systemd:postfix:restart',
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
actions['postfix_setfacl_default_telegraf'] = {
|
actions['postfix_setfacl_default_telegraf'] = {
|
||||||
|
@ -96,7 +94,5 @@ if node.has_bundle('telegraf'):
|
||||||
'needs': [
|
'needs': [
|
||||||
'pkg_apt:acl',
|
'pkg_apt:acl',
|
||||||
'svc_systemd:postfix',
|
'svc_systemd:postfix',
|
||||||
'svc_systemd:postfix:reload',
|
|
||||||
'svc_systemd:postfix:restart',
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ directories = {
|
||||||
'zfs_dataset:tank/postgresql',
|
'zfs_dataset:tank/postgresql',
|
||||||
],
|
],
|
||||||
'needed_by': [
|
'needed_by': [
|
||||||
'svc_systemd:postgresql.service',
|
'svc_systemd:postgresql',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,19 +25,16 @@ files = {
|
||||||
) + '\n',
|
) + '\n',
|
||||||
'owner': 'postgres',
|
'owner': 'postgres',
|
||||||
'group': 'postgres',
|
'group': 'postgres',
|
||||||
'needs': [
|
|
||||||
'pkg_apt:postgresql',
|
|
||||||
],
|
|
||||||
'needed_by': [
|
'needed_by': [
|
||||||
'svc_systemd:postgresql.service',
|
'svc_systemd:postgresql',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:postgresql.service:restart',
|
'svc_systemd:postgresql:restart',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_systemd['postgresql.service'] = {
|
svc_systemd['postgresql'] = {
|
||||||
'needs': [
|
'needs': [
|
||||||
'pkg_apt:postgresql',
|
'pkg_apt:postgresql',
|
||||||
],
|
],
|
||||||
|
@ -46,13 +43,13 @@ svc_systemd['postgresql.service'] = {
|
||||||
for user, config in node.metadata.get('postgresql/roles').items():
|
for user, config in node.metadata.get('postgresql/roles').items():
|
||||||
postgres_roles[user] = merge_dict(config, {
|
postgres_roles[user] = merge_dict(config, {
|
||||||
'needs': [
|
'needs': [
|
||||||
'svc_systemd:postgresql.service',
|
'svc_systemd:postgresql',
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
for database, config in node.metadata.get('postgresql/databases').items():
|
for database, config in node.metadata.get('postgresql/databases').items():
|
||||||
postgres_dbs[database] = merge_dict(config, {
|
postgres_dbs[database] = merge_dict(config, {
|
||||||
'needs': [
|
'needs': [
|
||||||
'svc_systemd:postgresql.service',
|
'svc_systemd:postgresql',
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,11 +6,7 @@ root_password = repo.vault.password_for(f'{node.name} postgresql root')
|
||||||
defaults = {
|
defaults = {
|
||||||
'apt': {
|
'apt': {
|
||||||
'packages': {
|
'packages': {
|
||||||
'postgresql': {
|
'postgresql': {},
|
||||||
'needs': {
|
|
||||||
'zfs_dataset:tank/postgresql',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'backup': {
|
'backup': {
|
||||||
|
@ -58,25 +54,6 @@ def conf(metadata):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'apt/config/APT/NeverAutoRemove',
|
|
||||||
)
|
|
||||||
def apt(metadata):
|
|
||||||
return {
|
|
||||||
'apt': {
|
|
||||||
'config': {
|
|
||||||
'APT': {
|
|
||||||
'NeverAutoRemove': {
|
|
||||||
# https://github.com/credativ/postgresql-common/blob/master/pg_updateaptconfig#L17-L21
|
|
||||||
f"^postgresql.*-{metadata.get('postgresql/version')}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'zfs/datasets',
|
'zfs/datasets',
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
from shlex import quote
|
|
||||||
|
|
||||||
directories = {
|
|
||||||
'/opt/pyenv': {},
|
|
||||||
'/opt/pyenv/install': {},
|
|
||||||
}
|
|
||||||
|
|
||||||
git_deploy = {
|
|
||||||
'/opt/pyenv/install': {
|
|
||||||
'repo': 'https://github.com/pyenv/pyenv.git',
|
|
||||||
'rev': 'master',
|
|
||||||
'needs': {
|
|
||||||
'directory:/opt/pyenv/install',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for version in node.metadata.get('pyenv/versions'):
|
|
||||||
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 -Fxq {quote(version)}',
|
|
||||||
'needs': {
|
|
||||||
'git_deploy:/opt/pyenv/install',
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
defaults = {
|
|
||||||
'apt': {
|
|
||||||
'packages': {
|
|
||||||
'build-essential': {},
|
|
||||||
'libssl-dev': {},
|
|
||||||
'zlib1g-dev': {},
|
|
||||||
'libbz2-dev': {},
|
|
||||||
'libreadline-dev': {},
|
|
||||||
'libsqlite3-dev': {},
|
|
||||||
'curl': {},
|
|
||||||
'libncurses-dev': {},
|
|
||||||
'xz-utils': {},
|
|
||||||
'tk-dev': {},
|
|
||||||
'libxml2-dev': {},
|
|
||||||
'libxmlsec1-dev': {},
|
|
||||||
'libffi-dev': {},
|
|
||||||
'liblzma-dev': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'pyenv': {
|
|
||||||
'versions': set(),
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
- Homematic > Settings > Control panel > Security > SSH > active & set password
|
|
||||||
- ssh to node > `ssh-copy-id -o StrictHostKeyChecking=no root@{homematic}`
|
|
||||||
- Homematic > Settings > Control panel > Security > Automatic forwarding to HTTPS > active
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from shlex import quote
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'letsencrypt/domains',
|
'letsencrypt/domains',
|
||||||
)
|
)
|
||||||
|
@ -17,6 +20,8 @@ def letsencrypt(metadata):
|
||||||
'systemd-timers/raspberrymatic-cert',
|
'systemd-timers/raspberrymatic-cert',
|
||||||
)
|
)
|
||||||
def systemd_timers(metadata):
|
def systemd_timers(metadata):
|
||||||
|
domain = metadata.get('raspberrymatic-cert/domain')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'systemd-timers': {
|
'systemd-timers': {
|
||||||
'raspberrymatic-cert': {
|
'raspberrymatic-cert': {
|
||||||
|
|
|
@ -6,16 +6,80 @@ $config['enable_installer'] = true;
|
||||||
|
|
||||||
/* Local configuration for Roundcube Webmail */
|
/* Local configuration for Roundcube Webmail */
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// SQL DATABASE
|
||||||
|
// ----------------------------------
|
||||||
|
// Database connection string (DSN) for read+write operations
|
||||||
|
// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
|
||||||
|
// Currently supported db_providers: mysql, pgsql, sqlite, mssql or sqlsrv
|
||||||
|
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
|
||||||
|
// NOTE: for SQLite use absolute path: 'sqlite:////full/path/to/sqlite.db?mode=0646'
|
||||||
$config['db_dsnw'] = '${database['provider']}://${database['user']}:${database['password']}@${database['host']}/${database['name']}';
|
$config['db_dsnw'] = '${database['provider']}://${database['user']}:${database['password']}@${database['host']}/${database['name']}';
|
||||||
$config['imap_host'] = 'localhost';
|
|
||||||
$config['smtp_host'] = 'tls://localhost';
|
// ----------------------------------
|
||||||
|
// IMAP
|
||||||
|
// ----------------------------------
|
||||||
|
// The mail host chosen to perform the log-in.
|
||||||
|
// Leave blank to show a textbox at login, give a list of hosts
|
||||||
|
// to display a pulldown menu or set one host as string.
|
||||||
|
// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
|
||||||
|
// Supported replacement variables:
|
||||||
|
// %n - hostname ($_SERVER['SERVER_NAME'])
|
||||||
|
// %t - hostname without the first part
|
||||||
|
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
|
||||||
|
// %s - domain name after the '@' from e-mail address provided at login screen
|
||||||
|
// For example %n = mail.domain.tld, %t = domain.tld
|
||||||
|
// WARNING: After hostname change update of mail_host column in users table is
|
||||||
|
// required to match old user data records with the new host.
|
||||||
|
$config['default_host'] = 'localhost';
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// SMTP
|
||||||
|
// ----------------------------------
|
||||||
|
// SMTP server host (for sending mails).
|
||||||
|
// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
|
||||||
|
// If left blank, the PHP mail() function is used
|
||||||
|
// Supported replacement variables:
|
||||||
|
// %h - user's IMAP hostname
|
||||||
|
// %n - hostname ($_SERVER['SERVER_NAME'])
|
||||||
|
// %t - hostname without the first part
|
||||||
|
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
|
||||||
|
// %z - IMAP domain (IMAP hostname without the first part)
|
||||||
|
// For example %n = mail.domain.tld, %t = domain.tld
|
||||||
|
$config['smtp_server'] = 'tls://localhost';
|
||||||
|
|
||||||
|
// SMTP username (if required) if you use %u as the username Roundcube
|
||||||
|
// will use the current username for login
|
||||||
$config['smtp_user'] = '%u';
|
$config['smtp_user'] = '%u';
|
||||||
|
|
||||||
|
// SMTP password (if required) if you use %p as the password Roundcube
|
||||||
|
// will use the current user's password for login
|
||||||
$config['smtp_pass'] = '%p';
|
$config['smtp_pass'] = '%p';
|
||||||
|
|
||||||
|
// provide an URL where a user can get support for this Roundcube installation
|
||||||
|
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
|
||||||
$config['support_url'] = '';
|
$config['support_url'] = '';
|
||||||
|
|
||||||
|
// this key is used to encrypt the users imap password which is stored
|
||||||
|
// in the session record (and the client cookie if remember password is enabled).
|
||||||
|
// please provide a string of exactly 24 chars.
|
||||||
$config['des_key'] = '${des_key}';
|
$config['des_key'] = '${des_key}';
|
||||||
|
|
||||||
|
// Name your service. This is displayed on the login screen and in the window title
|
||||||
$config['product_name'] = '${product_name}';
|
$config['product_name'] = '${product_name}';
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// PLUGINS
|
||||||
|
// ----------------------------------
|
||||||
|
// List of active plugins (in plugins/ directory)
|
||||||
$config['plugins'] = array(${', '.join(f'"{plugin}"' for plugin in plugins)});
|
$config['plugins'] = array(${', '.join(f'"{plugin}"' for plugin in plugins)});
|
||||||
|
|
||||||
|
// the default locale setting (leave empty for auto-detection)
|
||||||
|
// RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR
|
||||||
$config['language'] = 'de_DE';
|
$config['language'] = 'de_DE';
|
||||||
|
|
||||||
|
|
||||||
|
// https://serverfault.com/a/991304
|
||||||
$config['smtp_conn_options'] = array(
|
$config['smtp_conn_options'] = array(
|
||||||
'ssl' => array(
|
'ssl' => array(
|
||||||
'verify_peer' => false,
|
'verify_peer' => false,
|
||||||
|
|
|
@ -14,4 +14,4 @@ $config['password_dovecotpw'] = '/usr/bin/sudo /usr/bin/doveadm pw';
|
||||||
$config['password_dovecotpw_method'] = 'ARGON2ID';
|
$config['password_dovecotpw_method'] = 'ARGON2ID';
|
||||||
$config['password_dovecotpw_with_method'] = true;
|
$config['password_dovecotpw_with_method'] = true;
|
||||||
$config['password_db_dsn'] = 'pgsql://mailserver:${mailserver_db_password}@localhost/mailserver';
|
$config['password_db_dsn'] = 'pgsql://mailserver:${mailserver_db_password}@localhost/mailserver';
|
||||||
$config['password_query'] = "UPDATE users SET password = %P FROM domains WHERE domains.id = users.domain_id AND domains.name = %d AND users.name = %l";
|
$config['password_query'] = "UPDATE users SET password=%D FROM domains WHERE domains.id = domain_id AND domains.name = %d AND users.name = %l";
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
assert node.has_bundle('php')
|
assert node.has_bundle('php')
|
||||||
assert node.has_bundle('mailserver')
|
assert node.has_bundle('mailserver')
|
||||||
|
|
||||||
roundcube_version = node.metadata.get('roundcube/version')
|
version = node.metadata.get('roundcube/version')
|
||||||
php_version = node.metadata.get('php/version')
|
|
||||||
|
|
||||||
directories = {
|
directories = {
|
||||||
'/opt/roundcube': {
|
'/opt/roundcube': {
|
||||||
|
@ -23,9 +22,9 @@ directories = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
files[f'/tmp/roundcube-{roundcube_version}.tar.gz'] = {
|
files[f'/tmp/roundcube-{version}.tar.gz'] = {
|
||||||
'content_type': 'download',
|
'content_type': 'download',
|
||||||
'source': f'https://github.com/roundcube/roundcubemail/releases/download/{roundcube_version}/roundcubemail-{roundcube_version}-complete.tar.gz',
|
'source': f'https://github.com/roundcube/roundcubemail/releases/download/{version}/roundcubemail-{version}-complete.tar.gz',
|
||||||
'triggered': True,
|
'triggered': True,
|
||||||
}
|
}
|
||||||
actions['delete_roundcube'] = {
|
actions['delete_roundcube'] = {
|
||||||
|
@ -33,18 +32,18 @@ actions['delete_roundcube'] = {
|
||||||
'triggered': True,
|
'triggered': True,
|
||||||
}
|
}
|
||||||
actions['extract_roundcube'] = {
|
actions['extract_roundcube'] = {
|
||||||
'command': f'tar xfvz /tmp/roundcube-{roundcube_version}.tar.gz --strip 1 -C /opt/roundcube',
|
'command': f'tar xfvz /tmp/roundcube-{version}.tar.gz --strip 1 -C /opt/roundcube',
|
||||||
'unless': f'grep -q "Version {roundcube_version}" /opt/roundcube/index.php',
|
'unless': f'grep -q "Version {version}" /opt/roundcube/index.php',
|
||||||
'preceded_by': [
|
'preceded_by': [
|
||||||
'action:delete_roundcube',
|
'action:delete_roundcube',
|
||||||
f'file:/tmp/roundcube-{roundcube_version}.tar.gz',
|
f'file:/tmp/roundcube-{version}.tar.gz',
|
||||||
],
|
],
|
||||||
'needs': [
|
'needs': [
|
||||||
'directory:/opt/roundcube',
|
'directory:/opt/roundcube',
|
||||||
],
|
],
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'action:chown_roundcube',
|
'action:chown_roundcube',
|
||||||
'action:composer_lock_reset',
|
'action:composer_install',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
actions['chown_roundcube'] = {
|
actions['chown_roundcube'] = {
|
||||||
|
@ -65,9 +64,6 @@ files['/opt/roundcube/config/config.inc.php'] = {
|
||||||
'needs': [
|
'needs': [
|
||||||
'action:chown_roundcube',
|
'action:chown_roundcube',
|
||||||
],
|
],
|
||||||
'triggers': [
|
|
||||||
f'svc_systemd:php{php_version}-fpm.service:restart',
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
files['/opt/roundcube/plugins/password/config.inc.php'] = {
|
files['/opt/roundcube/plugins/password/config.inc.php'] = {
|
||||||
'source': 'password.config.inc.php',
|
'source': 'password.config.inc.php',
|
||||||
|
@ -79,16 +75,7 @@ files['/opt/roundcube/plugins/password/config.inc.php'] = {
|
||||||
'action:chown_roundcube',
|
'action:chown_roundcube',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
actions['composer_lock_reset'] = {
|
|
||||||
'command': 'rm /opt/roundcube/composer.lock',
|
|
||||||
'triggered': True,
|
|
||||||
'needs': [
|
|
||||||
'action:chown_roundcube',
|
|
||||||
],
|
|
||||||
'triggers': [
|
|
||||||
'action:composer_install',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
actions['composer_install'] = {
|
actions['composer_install'] = {
|
||||||
'command': "cp /opt/roundcube/composer.json-dist /opt/roundcube/composer.json && su www-data -s /bin/bash -c '/usr/bin/composer -d /opt/roundcube install'",
|
'command': "cp /opt/roundcube/composer.json-dist /opt/roundcube/composer.json && su www-data -s /bin/bash -c '/usr/bin/composer -d /opt/roundcube install'",
|
||||||
'triggered': True,
|
'triggered': True,
|
||||||
|
|
|
@ -21,4 +21,3 @@ ClientAliveInterval 30
|
||||||
ClientAliveCountMax 5
|
ClientAliveCountMax 5
|
||||||
AcceptEnv LANG
|
AcceptEnv LANG
|
||||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||||
HostKey /etc/ssh/ssh_host_managed_key
|
|
||||||
|
|
|
@ -51,14 +51,14 @@ files = {
|
||||||
],
|
],
|
||||||
'skip': dont_touch_sshd,
|
'skip': dont_touch_sshd,
|
||||||
},
|
},
|
||||||
'/etc/ssh/ssh_host_managed_key': {
|
'/etc/ssh/ssh_host_ed25519_key': {
|
||||||
'content': node.metadata.get('ssh/host_key/private') + '\n',
|
'content': node.metadata.get('ssh/host_key/private') + '\n',
|
||||||
'mode': '0600',
|
'mode': '0600',
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:ssh:restart'
|
'svc_systemd:ssh:restart'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'/etc/ssh/ssh_host_managed_key.pub': {
|
'/etc/ssh/ssh_host_ed25519_key.pub': {
|
||||||
'content': node.metadata.get('ssh/host_key/public') + '\n',
|
'content': node.metadata.get('ssh/host_key/public') + '\n',
|
||||||
'mode': '0644',
|
'mode': '0644',
|
||||||
'triggers': [
|
'triggers': [
|
||||||
|
|
|
@ -34,19 +34,18 @@ defaults = {
|
||||||
)
|
)
|
||||||
def systemd_timer(metadata):
|
def systemd_timer(metadata):
|
||||||
return {
|
return {
|
||||||
# steam python login is broken: https://github.com/ValvePython/steam/issues/442
|
'systemd-timers': {
|
||||||
# 'systemd-timers': {
|
f'steam-chat-logger': {
|
||||||
# f'steam-chat-logger': {
|
'command': '/opt/steam_chat_logger/steam_chat_logger.py',
|
||||||
# 'command': '/opt/steam_chat_logger/steam_chat_logger.py',
|
'when': 'hourly',
|
||||||
# 'when': 'hourly',
|
'user': 'steam_chat_logger',
|
||||||
# 'user': 'steam_chat_logger',
|
'env': {
|
||||||
# 'env': {
|
'DB_NAME': 'steam_chat_logger',
|
||||||
# 'DB_NAME': 'steam_chat_logger',
|
'DB_USER': 'steam_chat_logger',
|
||||||
# 'DB_USER': 'steam_chat_logger',
|
'DB_PASSWORD': metadata.get('postgresql/roles/steam_chat_logger/password'),
|
||||||
# 'DB_PASSWORD': metadata.get('postgresql/roles/steam_chat_logger/password'),
|
**metadata.get('steam_chat_logger'),
|
||||||
# **metadata.get('steam_chat_logger'),
|
},
|
||||||
# },
|
'working_dir': '/var/lib/steam_chat_logger',
|
||||||
# 'working_dir': '/var/lib/steam_chat_logger',
|
},
|
||||||
# },
|
},
|
||||||
# },
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
files = {
|
files = {
|
||||||
'/etc/systemd/journald.conf.d/managed.conf': {
|
'/etc/systemd/journald.conf.d/managed.conf': {
|
||||||
'content': repo.libs.systemd.generate_unitfile({
|
'content': repo.libs.systemd.generate_unitfile({
|
||||||
'Journal': node.metadata.get('systemd-journald'),
|
'Jorunal': node.metadata.get('systemd-journald'),
|
||||||
}),
|
}),
|
||||||
'triggers': {
|
'triggers': {
|
||||||
'svc_systemd:systemd-journald:restart',
|
'svc_systemd:systemd-journald:restart',
|
||||||
|
|
|
@ -42,8 +42,6 @@ def systemd(metadata):
|
||||||
units[f'{name}.service']['Service']['SuccessExitStatus'] = config['success_exit_status']
|
units[f'{name}.service']['Service']['SuccessExitStatus'] = config['success_exit_status']
|
||||||
if config.get('kill_mode'):
|
if config.get('kill_mode'):
|
||||||
units[f'{name}.service']['Service']['KillMode'] = config['kill_mode']
|
units[f'{name}.service']['Service']['KillMode'] = config['kill_mode']
|
||||||
if config.get('RuntimeMaxSec'):
|
|
||||||
units[f'{name}.service']['Service']['RuntimeMaxSec'] = config['RuntimeMaxSec']
|
|
||||||
|
|
||||||
services[f'{name}.timer'] = {}
|
services[f'{name}.timer'] = {}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ files = {
|
||||||
node.metadata.get('telegraf/config'),
|
node.metadata.get('telegraf/config'),
|
||||||
cls=MetadataJSONEncoder,
|
cls=MetadataJSONEncoder,
|
||||||
)),
|
)),
|
||||||
sort_keys=True,
|
sort_keys=True
|
||||||
),
|
),
|
||||||
'triggers': [
|
'triggers': [
|
||||||
'svc_systemd:telegraf:restart',
|
'svc_systemd:telegraf:restart',
|
||||||
|
|
|
@ -7,8 +7,6 @@ defaults = {
|
||||||
# needed by crystal plugins:
|
# needed by crystal plugins:
|
||||||
'libgc-dev': {},
|
'libgc-dev': {},
|
||||||
'libevent-dev': {},
|
'libevent-dev': {},
|
||||||
# crystal based (procio, pressure_stall):
|
|
||||||
'libpcre3': {},
|
|
||||||
},
|
},
|
||||||
'sources': {
|
'sources': {
|
||||||
'influxdata': {
|
'influxdata': {
|
||||||
|
@ -58,7 +56,7 @@ defaults = {
|
||||||
'procstat': {h({
|
'procstat': {h({
|
||||||
'interval': '60s',
|
'interval': '60s',
|
||||||
'pattern': '.',
|
'pattern': '.',
|
||||||
'fieldinclude': [
|
'fieldpass': [
|
||||||
'cpu_usage',
|
'cpu_usage',
|
||||||
'memory_rss',
|
'memory_rss',
|
||||||
],
|
],
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
https://developer.wordpress.org/advanced-administration/upgrade/upgrading/
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SITE=$1
|
|
||||||
VERSION=$(php -r "require('/opt/$SITE/wp-includes/version.php'); echo \$wp_version;")
|
|
||||||
STATUS=$(curl -ssL http://api.wordpress.org/core/stable-check/1.0/ | jq -r '.["'$VERSION'"]')
|
|
||||||
|
|
||||||
echo "WordPress $VERSION is '$STATUS'"
|
|
||||||
|
|
||||||
if [[ "$STATUS" == latest ]]
|
|
||||||
then
|
|
||||||
exit 0
|
|
||||||
elif [[ "$STATUS" == outdated ]]
|
|
||||||
then
|
|
||||||
exit 1
|
|
||||||
elif [[ "$STATUS" == insecure ]]
|
|
||||||
then
|
|
||||||
if test -f /etc/nginx/sites/$SITE
|
|
||||||
then
|
|
||||||
rm /etc/nginx/sites/$SITE
|
|
||||||
systemctl restart nginx
|
|
||||||
fi
|
|
||||||
exit 2
|
|
||||||
else
|
|
||||||
exit 2
|
|
||||||
fi
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once '${path}/wp-includes/version.php';
|
|
||||||
|
|
||||||
echo "$wp_version";
|
|
|
@ -1,12 +0,0 @@
|
||||||
files = {
|
|
||||||
'/usr/lib/nagios/plugins/check_wordpress_insecure': {
|
|
||||||
'mode': '0750',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for site, conf in node.metadata.get('wordpress').items():
|
|
||||||
directories[f'/opt/{site}'] = {
|
|
||||||
'owner': 'www-data',
|
|
||||||
'group': 'www-data',
|
|
||||||
'mode': '0755',
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
defaults = {
|
|
||||||
'php': {
|
|
||||||
'php.ini': {
|
|
||||||
'cgi': {
|
|
||||||
'fix_pathinfo': '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'wordpress',
|
|
||||||
)
|
|
||||||
def wordpress(metadata):
|
|
||||||
return {
|
|
||||||
'wordpress': {
|
|
||||||
site: {
|
|
||||||
'db_password': repo.vault.password_for(f"wordpress {site} db").value,
|
|
||||||
}
|
|
||||||
for site in metadata.get('wordpress')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'mariadb/databases',
|
|
||||||
)
|
|
||||||
def mariadb(metadata):
|
|
||||||
return {
|
|
||||||
'mariadb': {
|
|
||||||
'databases': {
|
|
||||||
site: {
|
|
||||||
'password': metadata.get(f'wordpress/{site}/db_password')
|
|
||||||
}
|
|
||||||
for site in metadata.get('wordpress')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'nginx/vhosts'
|
|
||||||
)
|
|
||||||
def vhost(metadata):
|
|
||||||
return {
|
|
||||||
'nginx': {
|
|
||||||
'vhosts': {
|
|
||||||
conf['domain']: {
|
|
||||||
'content': 'wordpress/vhost.conf',
|
|
||||||
'context': {
|
|
||||||
'root': f'/opt/{site}',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for site, conf in metadata.get('wordpress').items()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'zfs/datasets',
|
|
||||||
)
|
|
||||||
def zfs(metadata):
|
|
||||||
return {
|
|
||||||
'zfs': {
|
|
||||||
'datasets': {
|
|
||||||
f'tank/{site}': {
|
|
||||||
'mountpoint': f'/opt/{site}',
|
|
||||||
}
|
|
||||||
for site in metadata.get('wordpress')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
|
||||||
'monitoring/services',
|
|
||||||
)
|
|
||||||
def check_insecure(metadata):
|
|
||||||
return {
|
|
||||||
'monitoring': {
|
|
||||||
'services': {
|
|
||||||
f'wordpress {site} insecure': {
|
|
||||||
'vars.command': f'/usr/lib/nagios/plugins/check_wordpress_insecure {site}',
|
|
||||||
'check_interval': '30m',
|
|
||||||
'vars.sudo': True,
|
|
||||||
}
|
|
||||||
for site in metadata.get('wordpress')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ files = {
|
||||||
'/etc/cron.weekly/zfs-auto-snapshot': {'delete': True, 'needs': {'pkg_apt:zfs-auto-snapshot'}},
|
'/etc/cron.weekly/zfs-auto-snapshot': {'delete': True, 'needs': {'pkg_apt:zfs-auto-snapshot'}},
|
||||||
'/etc/cron.monthly/zfs-auto-snapshot': {'delete': True, 'needs': {'pkg_apt:zfs-auto-snapshot'}},
|
'/etc/cron.monthly/zfs-auto-snapshot': {'delete': True, 'needs': {'pkg_apt:zfs-auto-snapshot'}},
|
||||||
'/etc/modprobe.d/zfs.conf': {
|
'/etc/modprobe.d/zfs.conf': {
|
||||||
'content_type': 'text',
|
|
||||||
'content': '\n'.join(
|
'content': '\n'.join(
|
||||||
f'options zfs {k}={v}'
|
f'options zfs {k}={v}'
|
||||||
for k, v in node.metadata.get('zfs/kernel_params').items()
|
for k, v in node.metadata.get('zfs/kernel_params').items()
|
||||||
|
|
|
@ -122,7 +122,10 @@ def backup(metadata):
|
||||||
'apt/packages'
|
'apt/packages'
|
||||||
)
|
)
|
||||||
def headers(metadata):
|
def headers(metadata):
|
||||||
arch = metadata.get('system/architecture')
|
if node.in_group('raspberry-pi'):
|
||||||
|
arch = 'arm64'
|
||||||
|
else:
|
||||||
|
arch = 'amd64'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'apt': {
|
'apt': {
|
||||||
|
|
|
@ -34,16 +34,7 @@ function zsh_exitcode_color {
|
||||||
echo "%(?:%{$fg_bold[green]%}:%{$fg_bold[red]%})"
|
echo "%(?:%{$fg_bold[green]%}:%{$fg_bold[red]%})"
|
||||||
}
|
}
|
||||||
|
|
||||||
function zsh_hostname {
|
PROMPT='$(zsh_root_color)$(whoami)%{$reset_color%}@$(zsh_exitcode_color)$(hostname -s) %{$fg[cyan]%}$(zsh_spwd)%{$reset_color%} $(git_prompt_info)'
|
||||||
if [ -z "$ZSH_HOSTNAME" ]
|
|
||||||
then
|
|
||||||
hostname -s
|
|
||||||
else
|
|
||||||
echo "$ZSH_HOSTNAME"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
PROMPT='$(zsh_root_color)$(whoami)%{$reset_color%}@$(zsh_exitcode_color)$(zsh_hostname) %{$fg[cyan]%}$(zsh_spwd)%{$reset_color%} $(git_prompt_info)'
|
|
||||||
|
|
||||||
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}"
|
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}"
|
||||||
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
|
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
|
||||||
|
|
|
@ -9,7 +9,6 @@ directories = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'/etc/zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions': {
|
'/etc/zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions': {
|
||||||
'mode': '0755',
|
|
||||||
'needs': [
|
'needs': [
|
||||||
f"git_deploy:/etc/zsh/oh-my-zsh",
|
f"git_deploy:/etc/zsh/oh-my-zsh",
|
||||||
]
|
]
|
||||||
|
@ -28,30 +27,14 @@ git_deploy = {
|
||||||
}
|
}
|
||||||
|
|
||||||
files = {
|
files = {
|
||||||
'/etc/zsh/zprofile': {
|
'/etc/zsh/zprofile': {},
|
||||||
'mode': '0755',
|
|
||||||
},
|
|
||||||
'/etc/zsh/oh-my-zsh/themes/bw.zsh-theme': {
|
'/etc/zsh/oh-my-zsh/themes/bw.zsh-theme': {
|
||||||
'mode': '0755',
|
|
||||||
'needs': [
|
'needs': [
|
||||||
f"git_deploy:/etc/zsh/oh-my-zsh",
|
f"git_deploy:/etc/zsh/oh-my-zsh",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
actions = {
|
|
||||||
'chown_oh_my_zsh': {
|
|
||||||
'command': 'chmod -R 755 /etc/zsh/oh-my-zsh',
|
|
||||||
'triggered': True,
|
|
||||||
'triggered_by': [
|
|
||||||
"git_deploy:/etc/zsh/oh-my-zsh",
|
|
||||||
"git_deploy:/etc/zsh/oh-my-zsh/custom/plugins/zsh-autosuggestions",
|
|
||||||
"file:/etc/zsh/zprofile",
|
|
||||||
"file:/etc/zsh/oh-my-zsh/themes/bw.zsh-theme",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, user_config in node.metadata.get('users').items():
|
for name, user_config in node.metadata.get('users').items():
|
||||||
if user_config.get('shell', None) == '/usr/bin/zsh':
|
if user_config.get('shell', None) == '/usr/bin/zsh':
|
||||||
files[join(user_config['home'], '.zshrc')] = {
|
files[join(user_config['home'], '.zshrc')] = {
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
|
|
||||||
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
|
|
||||||
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
|
|
||||||
=0YYh
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
|
@ -1,41 +1,41 @@
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
mQGNBGTnhmkBDADUE+SzjRRyitIm1siGxiHlIlnn6KO4C4GfEuV+PNzqxvwYO+1r
|
mQGNBGO4aiUBDAC82zo3vUyQH3yTCabQ7ZpospBg/xXBbJWbQNksIbEP/+I12CjB
|
||||||
mcKlGDU0ugo8ohXruAOC77Kwc4keVGNU89BeHvrYbIftz/yxEneuPsCbGnbDMIyC
|
zac1QcMFd27MJlyXpsTqqSo1ZHOisNy0Tmyl/WlqMyoMeChg+LmIHLNbvAK0jPOX
|
||||||
k44UOetRtV9/59Gj5YjNqnsZCr+e5D/JfrHUJTTwKLv88A9eHKxskrlZr7Un7j3i
|
1Pt2OykXJWN9Ru+ZZ4uQNgdKO5nXS6CZtK+McfhRwwghp+vlZFJgqP6aGR2A4cZ7
|
||||||
Ef3NChlOh2Zk9Wfk8IhAqMMTferU4iTIhQk+5fanShtXIuzBaxU3lkzFSG7VuAH4
|
IJpUQIoT/8GY6Fdx5TStTJucVUXjSJ3VqafZe4c0WHrk5Yb0UptYPBj9brZkmC9F
|
||||||
CBLPWitKRMn5oqXUE0FZbRYL/6Qz0Gt6YCJsZbaQ3Am7FCwWCp9+ZHbR9yU+bkK0
|
Uz6BLX6eO0HGLdwvYzoenlN1sD/2dclUtxoKYmfKDgpcG1V4vOClYPgOZ7g6jvwU
|
||||||
Dts4PNx4Wr9CktHIvbypT4Lk2oJEPWjcCJQHqpPQZXbnclXRlK5Ea0NVpaQdGK+v
|
+nW39VGwR7yzbEAmGxVcd93QNUjTaZMfO3xJFm1UG5JwC6VJcd7Wp3hNHJle/y62
|
||||||
JS4HGxFFjSkvTKAZYgwOk93qlpFeDML3TuSgWxuw4NIDitvewudnaWzfl9tDIoVS
|
lw0N2AATqJ7AV6PXKBPNebXvCB0LqkAiC/W//imeMCk9hfREmb5rhf1s83owpJaQ
|
||||||
Bb16nwJ8bMDzovC/RBE14rRKYtMLmBsRzGYHWd0NnX+FitAS9uURHuFxghv9GFPh
|
gScEtJYIVgOqgGoFE8wkCkHFG1slneLykmGK2xAJ2Rk63MIAE4hL9WKLV624LMid
|
||||||
eTaXvc4glM94HBUAEQEAAbQmR3JhZmFuYSBMYWJzIDxlbmdpbmVlcmluZ0BncmFm
|
JqH3YIEA6pR+GlEAEQEAAbQmR3JhZmFuYSBMYWJzIDxlbmdpbmVlcmluZ0BncmFm
|
||||||
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
|
||||||
=J9CI
|
=lSMJ
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
Binary file not shown.
|
@ -1,53 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
root /opt/freescout/public;
|
|
||||||
|
|
||||||
index index.php index.html index.htm;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
|
||||||
}
|
|
||||||
location ~ \.php$ {
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
||||||
fastcgi_pass php-handler;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
include params/fastcgi;
|
|
||||||
}
|
|
||||||
# Uncomment this location if you want to improve attachments downloading speed.
|
|
||||||
# Also make sure to set APP_DOWNLOAD_ATTACHMENTS_VIA=nginx in the .env file.
|
|
||||||
#location ^~ /storage/app/attachment/ {
|
|
||||||
# internal;
|
|
||||||
# alias /var/www/html/storage/app/attachment/;
|
|
||||||
#}
|
|
||||||
location ~* ^/storage/attachment/ {
|
|
||||||
expires 1M;
|
|
||||||
access_log off;
|
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
|
||||||
}
|
|
||||||
location ~* ^/(?:css|js)/.*\.(?:css|js)$ {
|
|
||||||
expires 2d;
|
|
||||||
access_log off;
|
|
||||||
add_header Cache-Control "public, must-revalidate";
|
|
||||||
}
|
|
||||||
# The list should be in sync with /storage/app/public/uploads/.htaccess and /config/app.php
|
|
||||||
location ~* ^/storage/.*\.((?!(jpg|jpeg|jfif|pjpeg|pjp|apng|bmp|gif|ico|cur|png|tif|tiff|webp|pdf|txt|diff|patch|json|mp3|wav|ogg|wma)).)*$ {
|
|
||||||
add_header Content-disposition "attachment; filename=$2";
|
|
||||||
default_type application/octet-stream;
|
|
||||||
}
|
|
||||||
location ~* ^/(?:css|fonts|img|installer|js|modules|[^\\\]+\..*)$ {
|
|
||||||
expires 1M;
|
|
||||||
access_log off;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
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_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_read_timeout 3600;
|
|
||||||
proxy_pass http://127.0.0.1:8123;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
# Upstream to abstract backend connection(s) for php
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
|
|
||||||
server_name ${server_name};
|
|
||||||
root ${root};
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
ssl_certificate /var/lib/dehydrated/certs/${server_name}/fullchain.pem;
|
|
||||||
ssl_certificate_key /var/lib/dehydrated/certs/${server_name}/privkey.pem;
|
|
||||||
|
|
||||||
location = /favicon.ico {
|
|
||||||
log_not_found off;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /robots.txt {
|
|
||||||
allow all;
|
|
||||||
log_not_found off;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
# This is cool because no php is touched for static content.
|
|
||||||
# include the "?$args" part so non-default permalinks doesn't break when using query string
|
|
||||||
try_files $uri $uri/ /index.php?$args;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
|
|
||||||
include params/fastcgi;
|
|
||||||
fastcgi_intercept_errors on;
|
|
||||||
fastcgi_pass php-handler;
|
|
||||||
# The following parameter can be also included in fastcgi_params file
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
|
|
||||||
expires max;
|
|
||||||
log_not_found off;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
'supergroups': [
|
|
||||||
'webserver',
|
|
||||||
],
|
|
||||||
'bundles': [
|
|
||||||
'freescout',
|
|
||||||
'php',
|
|
||||||
'postgresql',
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
'bundles': [
|
|
||||||
'letsencrypt',
|
|
||||||
'mariadb',
|
|
||||||
'nginx',
|
|
||||||
'wordpress',
|
|
||||||
],
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue