diff --git a/bundles/apt/README.md b/bundles/apt/README.md deleted file mode 100644 index ec66fa1..0000000 --- a/bundles/apt/README.md +++ /dev/null @@ -1,13 +0,0 @@ -```python -{ - 'apt': { - 'packages': { - 'apt-transport-https': {}, - }, - 'sources': [ - # place key under data/apt/keys/packages.cloud.google.com.{asc|gpg} - 'deb https://packages.cloud.google.com/apt cloud-sdk main', - ], - }, -} -``` diff --git a/bundles/apt/items.py b/bundles/apt/items.py deleted file mode 100644 index ed992ef..0000000 --- a/bundles/apt/items.py +++ /dev/null @@ -1,95 +0,0 @@ -from os.path import join -from urllib.parse import urlparse -from glob import glob -from os.path import join, basename - -directories = { - '/etc/apt/sources.list.d': { - 'purge': True, - 'triggers': { - 'action:apt_update', - }, - }, - '/etc/apt/trusted.gpg.d': { - 'purge': True, - 'triggers': { - 'action:apt_update', - }, - }, - '/etc/apt/preferences.d': { - 'purge': True, - 'triggers': { - 'action:apt_update', - }, - }, -} - -files = { - '/etc/apt/sources.list': { - 'content': '# managed' - }, -} - -actions = { - 'apt_update': { - 'command': 'apt-get update', - 'needed_by': { - 'pkg_apt:', - }, - 'triggered': True, - 'cascade_skip': False, - }, -} - -hosts = {} - -for source_string in node.metadata.get('apt/sources'): - source = repo.libs.apt.AptSource(source_string) - hosts\ - .setdefault(source.url.hostname, set())\ - .add(source) - -for host, sources in hosts.items(): - keyfile = basename(glob(join(repo.path, 'data', 'apt', 'keys', f'{host}.*'))[0]) - destination_path = f'/etc/apt/trusted.gpg.d/{keyfile}' - - for source in sources: - source.options['signed-by'] = [destination_path] - - files[f'/etc/apt/sources.list.d/{host}.list'] = { - 'content': '\n'.join( - str(source) for source in sorted(sources) - ).format( - release=node.metadata.get('os_release') - ), - 'triggers': { - 'action:apt_update', - }, - } - - files[destination_path] = { - 'source': join(repo.path, 'data', 'apt', 'keys', keyfile), - 'content_type': 'binary', - 'triggers': { - 'action:apt_update', - }, - } - - -for package, options in node.metadata.get('apt/packages', {}).items(): - pkg_apt[package] = options - - if pkg_apt[package].pop('backports', False): - files[f'/etc/apt/preferences.d/{package}'] = { - 'content': '\n'.join([ - f"Package: {package}", - f"Pin: release a={node.metadata.get('os_release')}-backports", - f"Pin-Priority: 900", - ]), - 'needed_by': [ - f'pkg_apt:{package}', - ], - 'triggers': { - 'action:apt_update', - }, - } diff --git a/bundles/apt/metadata.py b/bundles/apt/metadata.py deleted file mode 100644 index f62c8ac..0000000 --- a/bundles/apt/metadata.py +++ /dev/null @@ -1,6 +0,0 @@ -defaults = { - 'apt': { - 'packages': {}, - 'sources': [], - }, -} diff --git a/bundles/archive/README.md b/bundles/archive/README.md deleted file mode 100644 index 4a23ef0..0000000 --- a/bundles/archive/README.md +++ /dev/null @@ -1,12 +0,0 @@ -``` -defaults = { - 'archive': { - '/var/important': { - 'exclude': [ - '\.cache/', - '\.log$', - ], - }, - }, -} -``` diff --git a/bundles/archive/files/archive b/bundles/archive/files/archive deleted file mode 100644 index fab7b27..0000000 --- a/bundles/archive/files/archive +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -if [[ "$1" == 'perform' ]] -then - echo 'NON-DRY RUN' - DRY='' -else - echo 'DRY RUN' - DRY='-n' -fi - -% for path, options in paths.items(): -# ${path} -gsutil ${'\\'} - -m ${'\\'} - -o 'GSUtil:parallel_process_count=${processes}' ${'\\'} - -o 'GSUtil:parallel_thread_count=${threads}' ${'\\'} - rsync ${'\\'} - $DRY ${'\\'} - -r ${'\\'} - -d ${'\\'} - -e ${'\\'} -% if options.get('exclude'): - -x '${'|'.join(options['exclude'])}' ${'\\'} -% endif - '${options['encrypted_path']}' ${'\\'} - 'gs://${bucket}/${node_id}${path}' ${'\\'} - 2>&1 | logger -st gsutil -% endfor diff --git a/bundles/archive/files/get_file b/bundles/archive/files/get_file deleted file mode 100644 index 81f94b7..0000000 --- a/bundles/archive/files/get_file +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -FILENAME=$1 -TMPFILE=$(mktemp /tmp/archive_file.XXXXXXXXXX) -BUCKET=$(cat /etc/gcloud/gcloud.json | jq -r .bucket) -NODE=$(cat /etc/archive/archive.json | jq -r .node_id) -MASTERKEY=$(cat /etc/gocryptfs/masterkey) - -gsutil cat "gs://$BUCKET/$NODE$FILENAME" > "$TMPFILE" -/opt/gocryptfs-inspect/gocryptfs.py --aessiv --config=/etc/gocryptfs/gocryptfs.conf --masterkey="$MASTERKEY" "$TMPFILE" diff --git a/bundles/archive/files/validate_file b/bundles/archive/files/validate_file deleted file mode 100644 index 57da963..0000000 --- a/bundles/archive/files/validate_file +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -FILENAME=$1 - -ARCHIVE=$(/opt/archive/get_file "$FILENAME" | sha256sum) -ORIGINAL=$(cat "$FILENAME" | sha256sum) - -if [[ "$ARCHIVE" == "$ORIGINAL" ]] -then - echo "OK" - exit 0 -else - echo "ERROR" - exit 1 -fi diff --git a/bundles/archive/items.py b/bundles/archive/items.py deleted file mode 100644 index dedf580..0000000 --- a/bundles/archive/items.py +++ /dev/null @@ -1,43 +0,0 @@ -assert node.has_bundle('gcloud') -assert node.has_bundle('gocryptfs') -assert node.has_bundle('gocryptfs-inspect') -assert node.has_bundle('systemd') - -from json import dumps - -directories['/opt/archive'] = {} -directories['/etc/archive'] = {} - -files['/etc/archive/archive.json'] = { - 'content': dumps( - { - 'node_id': node.metadata.get('id'), - **node.metadata.get('archive'), - }, - indent=4, - sort_keys=True - ), -} - -files['/opt/archive/archive'] = { - 'content_type': 'mako', - 'mode': '700', - 'context': { - 'node_id': node.metadata.get('id'), - 'paths': node.metadata.get('archive/paths'), - 'bucket': node.metadata.get('gcloud/bucket'), - 'processes': 4, - 'threads': 4, - }, - 'needs': [ - 'bundle:gcloud', - ], -} - -files['/opt/archive/get_file'] = { - 'mode': '700', -} - -files['/opt/archive/validate_file'] = { - 'mode': '700', -} diff --git a/bundles/archive/metadata.py b/bundles/archive/metadata.py deleted file mode 100644 index 39b9282..0000000 --- a/bundles/archive/metadata.py +++ /dev/null @@ -1,45 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'jq': {}, - }, - }, - 'archive': { - 'paths': {}, - }, -} - - -@metadata_reactor.provides( - 'archive/paths', -) -def paths(metadata): - return { - 'archive': { - 'paths': { - path: { - 'encrypted_path': f'/mnt/archive.enc{path}', - 'exclude': [ - '^\..*', - '/\..*', - ], - } for path in metadata.get('archive/paths') - }, - } - } - - -@metadata_reactor.provides( - 'gocryptfs/paths', -) -def gocryptfs(metadata): - return { - 'gocryptfs': { - 'paths': { - path: { - 'mountpoint': options['encrypted_path'], - 'reverse': True, - } for path, options in metadata.get('archive/paths').items() - }, - } - } diff --git a/bundles/bind/files/db b/bundles/bind/files/db deleted file mode 100644 index a5c1703..0000000 --- a/bundles/bind/files/db +++ /dev/null @@ -1,23 +0,0 @@ -<%! -def column_width(column, table): - return max(map(lambda row: len(row[column]), table)) if table else 0 -%>\ -$TTL 600 -@ IN SOA ns.sublimity.de. admin.sublimity.de. ( - 2020080302 ;Serial - 600 ;Refresh - 300 ;Retry - 1209600 ;Expire - 300 ;Negative response caching TTL -) - -% for record in sorted(records, key=lambda r: (r['name'], r['type'], r['value'])): -${(record['name'] or '@').ljust(column_width('name', records))} \ -IN \ -${record['type'].ljust(column_width('type', records))} \ - % if record['type'] == 'TXT': -(${' '.join('"'+record['value'][i:i+255]+'"' for i in range(0, len(record['value']), 255))}) - % else: -${record['value']} - % endif -% endfor diff --git a/bundles/bind/files/defaults b/bundles/bind/files/defaults deleted file mode 100644 index 9819214..0000000 --- a/bundles/bind/files/defaults +++ /dev/null @@ -1,2 +0,0 @@ -RESOLVCONF=no -OPTIONS="-u bind" diff --git a/bundles/bind/files/named.conf b/bundles/bind/files/named.conf deleted file mode 100644 index 568b28d..0000000 --- a/bundles/bind/files/named.conf +++ /dev/null @@ -1,6 +0,0 @@ -statistics-channels { - inet 127.0.0.1 port 8053; -}; - -include "/etc/bind/named.conf.options"; -include "/etc/bind/named.conf.local"; diff --git a/bundles/bind/files/named.conf.local b/bundles/bind/files/named.conf.local deleted file mode 100644 index 749ce14..0000000 --- a/bundles/bind/files/named.conf.local +++ /dev/null @@ -1,39 +0,0 @@ -% for view in views: -acl "${view['name']}" { - ${' '.join(f'{e};' for e in view['acl'])} -}; -% endfor - -% for view in views: -view "${view['name']}" { - match-clients { ${view['name']}; }; - - % if view['is_internal']: - recursion yes; - % else: - recursion no; - rate-limit { - responses-per-second 2; - window 25; - }; - % endif - - forward only; - forwarders { - 1.1.1.1; - 9.9.9.9; - 8.8.8.8; - }; - - % for zone in zones: - zone "${zone}" { - type master; - file "/var/lib/bind/${view['name']}/db.${zone}"; - }; - % endfor - - include "/etc/bind/named.conf.default-zones"; - include "/etc/bind/zones.rfc1918"; -}; - -% endfor diff --git a/bundles/bind/files/named.conf.options b/bundles/bind/files/named.conf.options deleted file mode 100644 index 8a64abc..0000000 --- a/bundles/bind/files/named.conf.options +++ /dev/null @@ -1,10 +0,0 @@ -options { - directory "/var/cache/bind"; - dnssec-validation auto; - - listen-on-v6 { any; }; - allow-query { any; }; - - max-cache-size 30%; - querylog yes; -}; diff --git a/bundles/bind/items.py b/bundles/bind/items.py deleted file mode 100644 index 16714bc..0000000 --- a/bundles/bind/items.py +++ /dev/null @@ -1,141 +0,0 @@ -from ipaddress import ip_address - -directories[f'/var/lib/bind'] = { - 'purge': True, - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], -} - -files['/etc/default/bind9'] = { - 'source': 'defaults', - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], -} - -files['/etc/bind/named.conf'] = { - 'owner': 'root', - 'group': 'bind', - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], -} -files['/etc/bind/named.conf.options'] = { - 'owner': 'root', - 'group': 'bind', - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], -} - -views = [ - { - 'name': 'internal', - 'is_internal': True, - 'acl': [ - '127.0.0.1', - '10.0.0.0/8', - '169.254.0.0/16', - '172.16.0.0/12', - '192.168.0.0/16', - ] - }, - { - 'name': 'external', - 'is_internal': False, - 'acl': [ - 'any', - ] - }, -] - -files['/etc/bind/named.conf.local'] = { - 'content_type': 'mako', - 'context': { - 'views': views, - 'zones': sorted(node.metadata.get('bind/zones')), - }, - 'owner': 'root', - 'group': 'bind', - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], -} - -def use_record(record, records, view): - if record['type'] in ['A', 'AAAA']: - if view == 'external': - # no internal addresses in external view - if ip_address(record['value']).is_private: - return False - elif view == 'internal': - # external addresses in internal view only, if no internal exists - if ip_address(record['value']).is_global: - for other_record in records: - if ( - record['name'] == other_record['name'] and - record['type'] == other_record['type'] and - ip_address(other_record['value']).is_private - ): - return False - return True - -for view in views: - directories[f"/var/lib/bind/{view['name']}"] = { - 'purge': True, - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], - } - - for zone, records in node.metadata.get('bind/zones').items(): - files[f"/var/lib/bind/{view['name']}/db.{zone}"] = { - 'group': 'bind', - 'source': 'db', - 'content_type': 'mako', - 'context': { - 'view': view['name'], - 'records': list(filter( - lambda record: use_record(record, records, view['name']), - records - )), - }, - 'needs': [ - f"directory:/var/lib/bind/{view['name']}", - ], - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], - } - -svc_systemd['bind9'] = {} - -actions['named-checkconf'] = { - 'command': 'named-checkconf -z', - 'unless': 'named-checkconf -z', - 'needs': [ - 'svc_systemd:bind9', - ] -} diff --git a/bundles/bind/metadata.py b/bundles/bind/metadata.py deleted file mode 100644 index b772f8a..0000000 --- a/bundles/bind/metadata.py +++ /dev/null @@ -1,87 +0,0 @@ -from ipaddress import ip_interface - - -defaults = { - 'apt': { - 'packages': { - 'bind9': {}, - }, - }, - 'bind': { - 'zones': {}, - }, - 'telegraf': { - 'config': { - 'inputs': { - 'bind': [{ - 'urls': ['http://localhost:8053/xml/v3'], - 'gather_memory_contexts': False, - 'gather_views': True, - }], - }, - }, - }, -} - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - return { - 'dns': { - metadata.get('bind/hostname'): repo.libs.dns.get_a_records(metadata), - } - } - - -@metadata_reactor.provides( - 'bind/zones', -) -def collect_records(metadata): - zones = {} - - for other_node in repo.nodes: - for fqdn, records in other_node.metadata.get('dns').items(): - matching_zones = sorted( - filter( - lambda potential_zone: fqdn.endswith(potential_zone), - metadata.get('bind/zones').keys() - ), - key=len, - ) - if matching_zones: - zone = matching_zones[-1] - else: - continue - - name = fqdn[0:-len(zone) - 1] - - for type, values in records.items(): - for value in values: - zones\ - .setdefault(zone, [])\ - .append( - {'name': name, 'type': type, 'value': value} - ) - - return { - 'bind': { - 'zones': zones, - }, - } - - -@metadata_reactor.provides( - 'bind/zones', -) -def ns_records(metadata): - return { - 'bind': { - 'zones': { - zone: [ - {'name': '@', 'type': 'NS', 'value': f"{metadata.get('bind/hostname')}."}, - ] for zone in metadata.get('bind/zones').keys() - }, - }, - } diff --git a/bundles/dovecot/README.md b/bundles/dovecot/README.md deleted file mode 100644 index b40e7f1..0000000 --- a/bundles/dovecot/README.md +++ /dev/null @@ -1,9 +0,0 @@ -DOVECOT -======= - -rescan index: https://doc.dovecot.org/configuration_manual/fts/#rescan - -``` - sudo -u vmail doveadm fts rescan -u 'test@mail2.sublimity.de' - sudo -u vmail doveadm index -u 'test@mail2.sublimity.de' -q '*' -``` diff --git a/bundles/dovecot/files/decode2text.sh b/bundles/dovecot/files/decode2text.sh deleted file mode 100644 index 151fb7c..0000000 --- a/bundles/dovecot/files/decode2text.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/sh - -# Example attachment decoder script. The attachment comes from stdin, and -# the script is expected to output UTF-8 data to stdout. (If the output isn't -# UTF-8, everything except valid UTF-8 sequences are dropped from it.) - -# The attachment decoding is enabled by setting: -# -# plugin { -# fts_decoder = decode2text -# } -# service decode2text { -# executable = script /usr/local/libexec/dovecot/decode2text.sh -# user = dovecot -# unix_listener decode2text { -# mode = 0666 -# } -# } - -libexec_dir=`dirname $0` -content_type=$1 - -# The second parameter is the format's filename extension, which is used when -# found from a filename of application/octet-stream. You can also add more -# extensions by giving more parameters. -formats='application/pdf pdf -application/x-pdf pdf -application/msword doc -application/mspowerpoint ppt -application/vnd.ms-powerpoint ppt -application/ms-excel xls -application/x-msexcel xls -application/vnd.ms-excel xls -application/vnd.openxmlformats-officedocument.wordprocessingml.document docx -application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx -application/vnd.openxmlformats-officedocument.presentationml.presentation pptx -application/vnd.oasis.opendocument.text odt -application/vnd.oasis.opendocument.spreadsheet ods -application/vnd.oasis.opendocument.presentation odp -' - -if [ "$content_type" = "" ]; then - echo "$formats" - exit 0 -fi - -fmt=`echo "$formats" | grep -w "^$content_type" | cut -d ' ' -f 2` -if [ "$fmt" = "" ]; then - echo "Content-Type: $content_type not supported" >&2 - exit 1 -fi - -# most decoders can't handle stdin directly, so write the attachment -# to a temp file -path=`mktemp` -trap "rm -f $path" 0 1 2 3 14 15 -cat > $path - -xmlunzip() { - name=$1 - - tempdir=`mktemp -d` - if [ "$tempdir" = "" ]; then - exit 1 - fi - trap "rm -rf $path $tempdir" 0 1 2 3 14 15 - cd $tempdir || exit 1 - unzip -q "$path" 2>/dev/null || exit 0 - find . -name "$name" -print0 | xargs -0 cat | - $libexec_dir/xml2text -} - -wait_timeout() { - childpid=$! - trap "kill -9 $childpid; rm -f $path" 1 2 3 14 15 - wait $childpid -} - -LANG=en_US.UTF-8 -export LANG -if [ $fmt = "pdf" ]; then - /usr/bin/pdftotext $path - 2>/dev/null& - wait_timeout 2>/dev/null -elif [ $fmt = "doc" ]; then - (/usr/bin/catdoc $path; true) 2>/dev/null& - wait_timeout 2>/dev/null -elif [ $fmt = "ppt" ]; then - (/usr/bin/catppt $path; true) 2>/dev/null& - wait_timeout 2>/dev/null -elif [ $fmt = "xls" ]; then - (/usr/bin/xls2csv $path; true) 2>/dev/null& - wait_timeout 2>/dev/null -elif [ $fmt = "odt" -o $fmt = "ods" -o $fmt = "odp" ]; then - xmlunzip "content.xml" -elif [ $fmt = "docx" ]; then - xmlunzip "document.xml" -elif [ $fmt = "xlsx" ]; then - xmlunzip "sharedStrings.xml" -elif [ $fmt = "pptx" ]; then - xmlunzip "slide*.xml" -else - echo "Buggy decoder script: $fmt not handled" >&2 - exit 1 -fi -exit 0 diff --git a/bundles/dovecot/files/dovecot-sql.conf b/bundles/dovecot/files/dovecot-sql.conf deleted file mode 100644 index 12f6707..0000000 --- a/bundles/dovecot/files/dovecot-sql.conf +++ /dev/null @@ -1,10 +0,0 @@ -connect = host=${host} dbname=${name} user=${user} password=${password} -driver = pgsql -default_pass_scheme = PLAIN-MD5 - -password_query = SELECT CONCAT(users.name, '@', domains.name) AS user, password\ - FROM users \ - LEFT JOIN domains ON users.domain_id = domains.id \ - WHERE redirect IS NULL \ - AND users.name = SPLIT_PART('%u', '@', 1) \ - AND domains.name = SPLIT_PART('%u', '@', 2) diff --git a/bundles/dovecot/files/dovecot.conf b/bundles/dovecot/files/dovecot.conf deleted file mode 100644 index 57daf4e..0000000 --- a/bundles/dovecot/files/dovecot.conf +++ /dev/null @@ -1,134 +0,0 @@ -protocols = imap lmtp sieve -auth_mechanisms = plain login -mail_privileged_group = mail -ssl = required -ssl_cert = - -[session] -PROVIDER = file - -[picture] -DISABLE_GRAVATAR = true -ENABLE_FEDERATED_AVATAR = false - -[log] -MODE = console -LEVEL = warn - -[oauth2] -JWT_SECRET = ${oauth_secret_key} - -[other] -SHOW_FOOTER_BRANDING = true -SHOW_FOOTER_TEMPLATE_LOAD_TIME = false diff --git a/bundles/gitea/items.py b/bundles/gitea/items.py deleted file mode 100644 index 3819d77..0000000 --- a/bundles/gitea/items.py +++ /dev/null @@ -1,45 +0,0 @@ -version = version=node.metadata.get('gitea/version') - -downloads['/usr/local/bin/gitea'] = { - 'url': f'https://dl.gitea.io/gitea/{version}/gitea-{version}-linux-amd64', - 'sha256': node.metadata.get('gitea/sha256'), - 'triggers': { - 'svc_systemd:gitea:restart', - }, - 'preceded_by': { - 'action:stop_gitea', - }, -} - -users['git'] = {} - -directories['/var/lib/gitea'] = { - 'owner': 'git', - 'mode': '0700', - 'triggers': { - 'svc_systemd:gitea:restart', - }, -} - -actions = { - 'chmod_gitea': { - 'command': 'chmod a+x /usr/local/bin/gitea', - 'unless': 'test -x /usr/local/bin/gitea', - 'needs': { - 'download:/usr/local/bin/gitea', - }, - }, - 'stop_gitea': { - 'command': 'systemctl stop gitea', - 'triggered': True, - }, -} - -files['/etc/gitea/app.ini'] = { - 'content_type': 'mako', - 'owner': 'git', - 'context': node.metadata['gitea'], - 'triggers': { - 'svc_systemd:gitea:restart', - }, -} diff --git a/bundles/gitea/metadata.py b/bundles/gitea/metadata.py deleted file mode 100644 index 2c98618..0000000 --- a/bundles/gitea/metadata.py +++ /dev/null @@ -1,94 +0,0 @@ -database_password = repo.vault.password_for(f'{node.name} postgresql gitea') - -defaults = { - 'gitea': { - 'database': { - 'host': 'localhost', - 'port': '5432', - 'username': 'gitea', - 'password': database_password, - 'database': 'gitea', - }, - 'app_name': 'Gitea', - 'lfs_secret_key': repo.vault.password_for(f'{node.name} gitea lfs_secret_key', length=43), - 'security_secret_key': repo.vault.password_for(f'{node.name} gitea security_secret_key'), - 'oauth_secret_key': repo.vault.password_for(f'{node.name} gitea oauth_secret_key', length=43), - 'internal_token': repo.vault.password_for(f'{node.name} gitea internal_token'), - }, - 'postgresql': { - 'roles': { - 'gitea': { - 'password': database_password, - }, - }, - 'databases': { - 'gitea': { - 'owner': 'gitea', - }, - }, - }, - 'systemd': { - 'services': { - 'gitea': { - 'content': { - 'Unit': { - 'Description': 'gitea', - 'After': 'syslog.target', - 'After': 'network.target', - 'Requires': 'postgresql.service', - }, - 'Service': { - 'RestartSec': '2s', - 'Type': 'simple', - 'User': 'git', - 'Group': 'git', - 'WorkingDirectory': '/var/lib/gitea/', - 'ExecStart': '/usr/local/bin/gitea web -c /etc/gitea/app.ini', - 'Restart': 'always', - 'Environment': 'USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea', - }, - 'Install': { - 'WantedBy': 'multi-user.target', - }, - }, - 'needs': [ - 'action:chmod_gitea', - 'download:/usr/local/bin/gitea', - 'file:/etc/systemd/system/gitea.service', - 'file:/etc/gitea/app.ini', - ], - }, - }, - }, - 'zfs': { - 'datasets': { - 'tank/gitea': { - 'mountpoint': '/var/lib/gitea', - }, - }, - }, -} - - -@metadata_reactor.provides( - 'nginx/vhosts', -) -def nginx(metadata): - if not node.has_bundle('nginx'): - raise DoNotRunAgain - - return { - 'nginx': { - 'vhosts': { - metadata.get('gitea/domain'): { - 'proxy': { - '/': { - 'target': 'http://127.0.0.1:22000', - }, - }, - 'website_check_path': '/user/login', - 'website_check_string': 'Sign In', - }, - }, - }, - } diff --git a/bundles/gocryptfs-inspect/items.py b/bundles/gocryptfs-inspect/items.py deleted file mode 100644 index 4466343..0000000 --- a/bundles/gocryptfs-inspect/items.py +++ /dev/null @@ -1,6 +0,0 @@ -directories['/opt/gocryptfs-inspect'] = {} - -git_deploy['/opt/gocryptfs-inspect'] = { - 'repo': 'https://github.com/slackner/gocryptfs-inspect.git', - 'rev': 'ecd296c8f014bf18f5889e3cb9cb64807ff6b9c4', -} diff --git a/bundles/gocryptfs-inspect/metadata.py b/bundles/gocryptfs-inspect/metadata.py deleted file mode 100644 index b12c65d..0000000 --- a/bundles/gocryptfs-inspect/metadata.py +++ /dev/null @@ -1,7 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'python3-pycryptodome': {}, - }, - }, -} diff --git a/bundles/gocryptfs/items.py b/bundles/gocryptfs/items.py deleted file mode 100644 index 43967b9..0000000 --- a/bundles/gocryptfs/items.py +++ /dev/null @@ -1,43 +0,0 @@ -from json import dumps - -directories['/etc/gocryptfs'] = { - 'purge': True, -} - -files['/etc/gocryptfs/masterkey'] = { - 'content': node.metadata.get('gocryptfs/masterkey'), - 'mode': '500', -} - -files['/etc/gocryptfs/gocryptfs.conf'] = { - 'content': dumps({ - 'Version': 2, - 'Creator': 'gocryptfs 1.6.1', - 'ScryptObject': { - 'Salt': node.metadata.get('gocryptfs/salt'), - 'N': 65536, - 'R': 8, - 'P': 1, - 'KeyLen': 32, - }, - 'FeatureFlags': [ - 'GCMIV128', - 'HKDF', - 'PlaintextNames', - 'AESSIV', - ] - }, indent=4, sort_keys=True) -} - -for path, options in node.metadata.get('gocryptfs/paths').items(): - directories[options['mountpoint']] = { - 'owner': None, - 'group': None, - 'mode': None, - 'preceded_by': [ - f'svc_systemd:gocryptfs-{options["id"]}:stop', - ], - 'needed_by': [ - f'svc_systemd:gocryptfs-{options["id"]}', - ], - } diff --git a/bundles/gocryptfs/metadata.py b/bundles/gocryptfs/metadata.py deleted file mode 100644 index aa51819..0000000 --- a/bundles/gocryptfs/metadata.py +++ /dev/null @@ -1,103 +0,0 @@ -from hashlib import sha3_256 -from base64 import b64decode, b64encode -from binascii import hexlify -from uuid import UUID - -defaults = { - 'apt': { - 'packages': { - 'gocryptfs': {}, - 'fuse': {}, - 'socat': {}, - }, - }, - 'gocryptfs': { - 'paths': {}, - }, -} - - -@metadata_reactor.provides( - 'gocryptfs', -) -def config(metadata): - return { - 'gocryptfs': { - 'masterkey': hexlify(b64decode( - str(repo.vault.random_bytes_as_base64_for(metadata.get('id'), length=32)) - )).decode(), - 'salt': b64encode( - sha3_256(UUID(metadata.get('id')).bytes).digest() - ).decode(), - }, - } - - -@metadata_reactor.provides( - 'gocryptfs', -) -def paths(metadata): - paths = {} - - for path, options in metadata.get('gocryptfs/paths').items(): - paths[path] = { - 'id': hexlify(sha3_256(path.encode()).digest()[:8]).decode(), - } - - return { - 'gocryptfs': { - 'paths': paths, - }, - } - - - -@metadata_reactor.provides( - 'systemd/services', -) -def systemd(metadata): - services = {} - - for path, options in metadata.get('gocryptfs/paths').items(): - services[f'gocryptfs-{options["id"]}'] = { - 'content': { - 'Unit': { - 'Description': f'gocryptfs@{path} ({options["id"]})', - 'After': { - 'filesystem.target', - 'zfs.target', - }, - }, - 'Service': { - 'RuntimeDirectory': 'gocryptfs', - 'Environment': { - 'MASTERKEY': metadata.get('gocryptfs/masterkey'), - 'SOCKET': f'/var/run/gocryptfs/{options["id"]}', - 'PLAIN': path, - 'CIPHER': options["mountpoint"] - }, - 'ExecStart': [ - '/usr/bin/gocryptfs -fg -plaintextnames -reverse -masterkey $MASTERKEY -ctlsock $SOCKET $PLAIN $CIPHER', - ], - 'ExecStopPost': [ - '/usr/bin/umount $CIPHER' - ], - }, - }, - 'needs': [ - 'pkg_apt:gocryptfs', - 'pkg_apt:fuse', - 'pkg_apt:socat', - 'file:/etc/gocryptfs/masterkey', - 'file:/etc/gocryptfs/gocryptfs.conf', - ], - 'triggers': [ - f'svc_systemd:gocryptfs-{options["id"]}:restart', - ], - } - - return { - 'systemd': { - 'services': services, - }, - } diff --git a/bundles/grafana/README.md b/bundles/grafana/README.md deleted file mode 100644 index 61e9ffc..0000000 --- a/bundles/grafana/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# metadata - -```python -{ - 'hostname': 'example.com', - 'influxdb_node': 'htz.influx', -} -``` - -# links - - -https://github.com/grafana/influxdb-flux-datasource/issues/42 -https://community.grafana.com/t/no-alias-by-when-using-flux/15575/6 diff --git a/bundles/grafana/items.py b/bundles/grafana/items.py deleted file mode 100644 index 3f41725..0000000 --- a/bundles/grafana/items.py +++ /dev/null @@ -1,150 +0,0 @@ -assert node.has_bundle('redis') -assert node.has_bundle('postgresql') - -from mako.template import Template -from shlex import quote -from copy import deepcopy -from itertools import count -import yaml -import json - -svc_systemd['grafana-server'] = { - 'needs': [ - 'pkg_apt:grafana', - ], -} - -admin_password = node.metadata.get('grafana/config/security/admin_password') -port = node.metadata.get('grafana/config/server/http_port') -actions['reset_grafana_admin_password'] = { - 'command': f"grafana-cli admin reset-admin-password {quote(admin_password)}", - 'unless': f"curl http://admin:{quote(admin_password)}@localhost:{port}/api/org", - 'needs': [ - 'svc_systemd:grafana-server', - ], -} - -directories = { - '/etc/grafana': { - }, - '/etc/grafana/provisioning': { - }, - '/etc/grafana/provisioning/datasources': { - 'purge': True, - }, - '/etc/grafana/provisioning/dashboards': { - 'purge': True, - }, - '/var/lib/grafana': {}, - '/var/lib/grafana/dashboards': {}, -} - -files = { - '/etc/grafana/grafana.ini': { - 'content': repo.libs.ini.dumps(node.metadata.get('grafana/config')), - 'triggers': [ - 'svc_systemd:grafana-server:restart', - ], - }, - '/etc/grafana/provisioning/datasources/managed.yaml': { - 'content': yaml.dump({ - 'apiVersion': 1, - 'datasources': list(node.metadata.get('grafana/datasources').values()), - }), - 'triggers': [ - 'svc_systemd:grafana-server:restart', - ], - }, - '/etc/grafana/provisioning/dashboards/managed.yaml': { - 'content': yaml.dump({ - 'apiVersion': 1, - 'providers': [{ - 'name': 'Default', - 'folder': 'Generated', - 'type': 'file', - 'options': { - 'path': '/var/lib/grafana/dashboards', - }, - }], - }), - 'triggers': [ - 'svc_systemd:grafana-server:restart', - ], - }, -} - -# DASHBOARDS - -with open(repo.path.join([f'data/grafana/dashboard.py'])) as file: - dashboard_template = eval(file.read()) -with open(repo.path.join([f'data/grafana/panel.py'])) as file: - panel_template = eval(file.read()) -with open(repo.path.join([f'data/grafana/flux.mako'])) as file: - flux_template = Template(file.read()) - -bucket = repo.get_node(node.metadata.get('grafana/influxdb_node')).metadata.get('influxdb/bucket') - -monitored_nodes = [ - other_node - for other_node in repo.nodes - if other_node.metadata.get('telegraf/influxdb_node', None) == node.metadata.get('grafana/influxdb_node') -] - -for dashboard_id, monitored_node in enumerate(monitored_nodes, start=1): - dashboard = deepcopy(dashboard_template) - dashboard['id'] = dashboard_id - dashboard['title'] = monitored_node.name - dashboard['uid'] = monitored_node.metadata.get('id') - panel_id = count(start=1) - - for row_id, row_name in enumerate(sorted(monitored_node.metadata.get('grafana_rows')), start=1): - with open(repo.path.join([f'data/grafana/rows/{row_name}.py'])) as file: - row = eval(file.read()) - - for panel_in_row, (panel_name, panel_config) in enumerate(row.items()): - panel = deepcopy(panel_template) - panel['id'] = next(panel_id) - panel['title'] = f'{row_name} {panel_name}' - panel['gridPos']['w'] = 24 // len(row) - panel['gridPos']['x'] = (24 // len(row)) * panel_in_row - panel['gridPos']['y'] = (row_id - 1) * panel['gridPos']['h'] - - if 'display_name' in panel_config: - panel['fieldConfig']['defaults']['displayName'] = '${'+panel_config['display_name']+'}' - - if panel_config.get('stacked'): - panel['fieldConfig']['defaults']['custom']['stacking']['mode'] = 'normal' - - if 'unit' in panel_config: - panel['fieldConfig']['defaults']['unit'] = panel_config['unit'] - - if 'min' in panel_config: - panel['fieldConfig']['defaults']['min'] = panel_config['min'] - if 'max' in panel_config: - panel['fieldConfig']['defaults']['max'] = panel_config['max'] - - - for query_name, query_config in panel_config['queries'].items(): - panel['targets'].append({ - 'refId': query_name, - 'query': flux_template.render( - bucket=bucket, - host=monitored_node.name, - negative=query_config.get('negative', False), - filters={ - 'host': monitored_node.name, - **query_config['filters'], - }, - function=query_config.get('function', None), - ).strip() - }) - - dashboard['panels'].append(panel) - - files[f'/var/lib/grafana/dashboards/{monitored_node.name}.json'] = { - 'content': json.dumps(dashboard, indent=4), - 'triggers': [ - 'svc_systemd:grafana-server:restart', - ] - } - diff --git a/bundles/grafana/metadata.py b/bundles/grafana/metadata.py deleted file mode 100644 index 6e3cd28..0000000 --- a/bundles/grafana/metadata.py +++ /dev/null @@ -1,107 +0,0 @@ -from mako.template import Template - -postgres_password = repo.vault.password_for(f'{node.name} postgres role grafana') - -defaults = { - 'apt': { - 'packages': { - 'grafana': {}, - }, - 'sources': [ - 'deb https://packages.grafana.com/oss/deb stable main', - ], - }, - 'grafana': { - 'config': { - 'server': { - 'http_port': 8300, - }, - 'database': { - 'url': f'postgres://grafana:{postgres_password}@localhost:5432/grafana', - }, - 'remote_cache': { - 'type': 'redis', - 'connstr': 'addr=127.0.0.1:6379', - }, - 'security': { - 'admin_user': 'admin', - 'admin_password': str(repo.vault.password_for(f'{node.name} grafana admin')), - }, - 'users': { - 'allow_signup': False, - }, - }, - 'datasources': {}, - }, - 'postgresql': { - 'databases': { - 'grafana': { - 'owner': 'grafana', - }, - }, - 'roles': { - 'grafana': { - 'password': postgres_password, - }, - }, - }, - 'zfs': { - 'datasets': { - 'tank/grafana': { - 'mountpoint': '/var/lib/grafana' - }, - }, - }, -} - - -@metadata_reactor.provides( - 'grafana/datasources', -) -def influxdb2(metadata): - influxdb_metadata = repo.get_node(metadata.get('grafana/influxdb_node')).metadata.get('influxdb') - - return { - 'grafana': { - 'datasources': { - f"influxdb@{influxdb_metadata['hostname']}": { - 'type': 'influxdb', - 'url': f"http://{influxdb_metadata['hostname']}:{influxdb_metadata['port']}", - 'jsonData': { - 'version': 'Flux', - 'organization': influxdb_metadata['org'], - 'defaultBucket': influxdb_metadata['bucket'], - }, - 'secureJsonData': { - 'token': str(influxdb_metadata['readonly_token']), - }, - 'editable': False, - 'isDefault': True, - }, - }, - }, - } - - -@metadata_reactor.provides( - 'grafana/datasources', -) -def datasource_key_to_name(metadata): - return { - 'grafana': { - 'datasources': { - name: {'name': name} for name in metadata.get('grafana/datasources').keys() - }, - }, - } - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - return { - 'dns': { - metadata.get('grafana/hostname'): repo.libs.dns.get_a_records(metadata), - } - } diff --git a/bundles/hetzner-cloud/metadata.py b/bundles/hetzner-cloud/metadata.py deleted file mode 100644 index e73592c..0000000 --- a/bundles/hetzner-cloud/metadata.py +++ /dev/null @@ -1,8 +0,0 @@ -# defaults = { -# 'network': { -# 'external': { -# 'gateway4': '172.31.1.1', -# 'gateway6': 'fe80::1', -# }, -# }, -# } diff --git a/bundles/influxdb2/README.md b/bundles/influxdb2/README.md deleted file mode 100644 index ac2b112..0000000 --- a/bundles/influxdb2/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# setup - -1. apply influxdb to server -2. write `admin`, `readonly` and `writeonly` token into influxdb metadata: - `influx auth list --json | jq -r '.[] | select (.description == "NAME") | .token'` -3. apply clients - -# metadata - -```python -{ - 'hostname': 'example.com', - 'admin_token': 'Wawbd5n...HJS76ez', - 'readonly_token': '5v235b3...6wbnuzz', - 'writeonly_token': '8w4cnos...fn849zg', -} -``` - -# reset password - -Opening /var/lib/influxdb/influxd.bolt with https://github.com/br0xen/boltbrowser might help diff --git a/bundles/influxdb2/items.py b/bundles/influxdb2/items.py deleted file mode 100644 index 525a67c..0000000 --- a/bundles/influxdb2/items.py +++ /dev/null @@ -1,77 +0,0 @@ -from tomlkit import dumps -from shlex import quote - -directories['/var/lib/influxdb'] = { - 'owner': 'influxdb', - 'group': 'influxdb', - 'needs': [ - 'zfs_dataset:tank/influxdb', - ], -} - -directories['/etc/influxdb'] = { - 'purge': True, -} -files['/etc/influxdb/config.toml'] = { - 'content': dumps(node.metadata.get('influxdb/config')), - 'triggers': [ - 'svc_systemd:influxdb:restart', - ] -} - -svc_systemd['influxdb'] = { - 'needs': [ - 'directory:/var/lib/influxdb', - 'file:/etc/influxdb/config.toml', - 'pkg_apt:influxdb2', - ] -} - -actions['wait_for_influxdb_start'] = { - 'command': 'sleep 15', - 'triggered': True, - 'triggered_by': [ - 'svc_systemd:influxdb', - 'svc_systemd:influxdb:restart', - ] -} - -actions['setup_influxdb'] = { - 'command': 'influx setup --username={username} --password={password} --org={org} --bucket={bucket} --token={token} --retention=0 --force'.format( - username=node.metadata.get('influxdb/username'), - password=quote(str(node.metadata.get('influxdb/password'))), - org=node.metadata.get('influxdb/org'), - bucket=node.metadata.get('influxdb/bucket'), - token=str(node.metadata.get('influxdb/admin_token')), - ), - 'unless': 'influx bucket list', - 'needs': [ - 'action:wait_for_influxdb_start', - ], -} - -files['/root/.influxdbv2/configs'] = { - 'content': dumps({ - node.metadata.get('influxdb/bucket'): { - 'url': f"http://localhost:{node.metadata.get('influxdb/port')}", - 'token': str(node.metadata.get('influxdb/admin_token')), - 'org': node.metadata.get('influxdb/org'), - 'active': True, - }, - }), - 'needs': [ - 'action:setup_influxdb', - ], -} - -for description, permissions in { - 'readonly': '--read-buckets', - 'writeonly': '--write-buckets --read-telegrafs', -}.items(): - actions[f'influxdb_{description}_token'] = { - 'command': f'influx auth create --description {description} {permissions}', - 'unless': f'''influx auth list --json | jq -r '.[] | select (.description == "{description}") | .token' | wc -l | grep -q ^1$''', - 'needs': [ - 'file:/root/.influxdbv2/configs', - ], - } diff --git a/bundles/influxdb2/metadata.py b/bundles/influxdb2/metadata.py deleted file mode 100644 index be179e0..0000000 --- a/bundles/influxdb2/metadata.py +++ /dev/null @@ -1,53 +0,0 @@ -from ipaddress import ip_interface - -defaults = { - 'apt': { - 'packages': { - 'influxdb2': {}, - }, - 'sources': [ - 'deb https://repos.influxdata.com/debian {release} stable', - ], - }, - 'influxdb': { - 'port': '8200', - 'username': 'admin', - 'org': 'default', - 'bucket': 'default', - 'config': { - 'bolt-path': '/var/lib/influxdb/influxd.bolt', - 'engine-path': '/var/lib/influxdb/engine', - 'reporting-disabled': True, - 'http-bind-address': ':8200', - }, - }, - 'zfs': { - 'datasets': { - 'tank/influxdb': { - 'mountpoint': '/var/lib/influxdb' - }, - }, - }, -} - -@metadata_reactor.provides( - 'influxdb/password', -) -def admin_password(metadata): - return { - 'influxdb': { - 'password': repo.vault.password_for(f"{metadata.get('id')} influxdb admin"), - 'admin_token': repo.vault.random_bytes_as_base64_for(f"{metadata.get('id')} influxdb default token", length=64), - }, - } - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - return { - 'dns': { - metadata.get('influxdb/hostname'): repo.libs.dns.get_a_records(metadata), - } - } diff --git a/bundles/l4d2/files/l4d2.service b/bundles/l4d2/files/l4d2.service deleted file mode 100644 index 06cc1fd..0000000 --- a/bundles/l4d2/files/l4d2.service +++ /dev/null @@ -1,13 +0,0 @@ -GNU nano 4.8 /etc/systemd/system/l4d2-server-a.service -[Unit] -Description=l4d2 Server A -After=network.target steam-update.service - -[Service] -User=steam -WorkingDirectory=/home/steam/steam/l4d2 -ExecStart=/home/steam/steam/l4d2/srcds_run -port 27001 -secure +exec server_a.cfg -Restart=on-failure - -[Install] -WantedBy=multi-user.target diff --git a/bundles/l4d2/files/update_addons b/bundles/l4d2/files/update_addons deleted file mode 100644 index 6025c5b..0000000 --- a/bundles/l4d2/files/update_addons +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -/home/steam/steam_workshop_downloader/workshop.py -o /home/steam/steam/l4d2/left4dead2/addons 2283884609 -chown -R steam:steam /home/steam/steam/l4d2/left4dead2/addons diff --git a/bundles/l4d2/metadata.py b/bundles/l4d2/metadata.py deleted file mode 100644 index c3b4514..0000000 --- a/bundles/l4d2/metadata.py +++ /dev/null @@ -1,7 +0,0 @@ -@metadata_reactor.provides() -def steam(metadata): - return { - 'steam': { - '222860': 'l4d2', - }, - } diff --git a/bundles/letsencrypt/files/config b/bundles/letsencrypt/files/config deleted file mode 100644 index 2d4b2b6..0000000 --- a/bundles/letsencrypt/files/config +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_D=/etc/dehydrated/conf.d -BASEDIR=/var/lib/dehydrated -WELLKNOWN="${BASEDIR}/acme-challenges" -DOMAINS_TXT="/etc/dehydrated/domains.txt" -HOOK="/etc/dehydrated/hook.sh" diff --git a/bundles/letsencrypt/files/domains.txt b/bundles/letsencrypt/files/domains.txt deleted file mode 100644 index ea7e427..0000000 --- a/bundles/letsencrypt/files/domains.txt +++ /dev/null @@ -1,3 +0,0 @@ -% for domain, aliases in sorted(node.metadata.get('letsencrypt/domains', {}).items()): -${domain} ${' '.join(sorted(aliases))} -% endfor diff --git a/bundles/letsencrypt/files/hook.sh b/bundles/letsencrypt/files/hook.sh deleted file mode 100644 index 4cdf79d..0000000 --- a/bundles/letsencrypt/files/hook.sh +++ /dev/null @@ -1,37 +0,0 @@ -deploy_cert() {<%text> - local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}" -% for service, config in node.metadata.get('letsencrypt/concat_and_deploy', {}).items(): - - # concat_and_deploy ${service} - if [ "$DOMAIN" = "${config['match_domain']}" ]; then - cat $KEYFILE > ${config['target']} - cat $FULLCHAINFILE >> ${config['target']} -% if 'chown' in config: - chown ${config['chown']} ${config['target']} -% endif -% if 'chmod' in config: - chmod ${config['chmod']} ${config['target']} -% endif -% if 'commands' in config: -% for command in config['commands']: - ${command} -% endfor -% endif - fi -% endfor -} - - -exit_hook() {<%text> - local ERROR="${1:-}" - -% for service in sorted(node.metadata.get('letsencrypt/reload_after', set())): - systemctl reload-or-restart ${service} -% endfor -} - -<%text> -HANDLER="$1"; shift -if [[ "${HANDLER}" =~ ^(deploy_cert|exit_hook)$ ]]; then - "$HANDLER" "$@" -fi diff --git a/bundles/letsencrypt/files/letsencrypt-ensure-some-certificate b/bundles/letsencrypt/files/letsencrypt-ensure-some-certificate deleted file mode 100644 index e0248cb..0000000 --- a/bundles/letsencrypt/files/letsencrypt-ensure-some-certificate +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -domain=$1 -just_check=$2 - -cert_path="/var/lib/dehydrated/certs/$domain" - -already_exists=false -if [ -f "$cert_path/privkey.pem" -a -f "$cert_path/fullchain.pem" -a -f "$cert_path/chain.pem" ] -then - already_exists=true -fi - -if [ "$just_check" = true ] -then - if [ "$already_exists" = true ] - then - exit 0 - else - exit 1 - fi -fi - -if [ "$already_exists" != true ] -then - rm -r "$cert_path" - mkdir -p "$cert_path" - openssl req -x509 -newkey rsa:4096 -nodes -days 3650 -subj "/CN=$domain" -keyout "$cert_path/privkey.pem" -out "$cert_path/fullchain.pem" - chmod 0600 "$cert_path/privkey.pem" - cp "$cert_path/fullchain.pem" "$cert_path/chain.pem" -fi diff --git a/bundles/letsencrypt/items.py b/bundles/letsencrypt/items.py deleted file mode 100644 index 9b86c36..0000000 --- a/bundles/letsencrypt/items.py +++ /dev/null @@ -1,50 +0,0 @@ -assert node.has_bundle('nginx') - -directories = { - '/etc/dehydrated/conf.d': {}, - '/var/lib/dehydrated/acme-challenges': {}, -} - -files = { - '/etc/dehydrated/domains.txt': { - 'content_type': 'mako', - 'triggers': { - 'action:letsencrypt_update_certificates', - }, - }, - '/etc/dehydrated/config': { - 'triggers': { - 'action:letsencrypt_update_certificates', - }, - }, - '/etc/dehydrated/hook.sh': { - 'content_type': 'mako', - 'mode': '0755', - }, - '/etc/dehydrated/letsencrypt-ensure-some-certificate': { - 'mode': '0755', - }, -} - -actions['letsencrypt_update_certificates'] = { - 'command': 'dehydrated --cron --accept-terms --challenge http-01', - 'triggered': True, - 'needs': { - 'svc_systemd:nginx', - }, -} - -for domain, _ in node.metadata.get('letsencrypt/domains').items(): - actions['letsencrypt_ensure-some-certificate_{}'.format(domain)] = { - 'command': '/etc/dehydrated/letsencrypt-ensure-some-certificate {}'.format(domain), - 'unless': '/etc/dehydrated/letsencrypt-ensure-some-certificate {} true'.format(domain), - 'needs': { - 'file:/etc/dehydrated/letsencrypt-ensure-some-certificate', - }, - 'needed_by': { - 'svc_systemd:nginx', - }, - 'triggers': { - 'action:letsencrypt_update_certificates', - }, - } diff --git a/bundles/letsencrypt/metadata.py b/bundles/letsencrypt/metadata.py deleted file mode 100644 index d735ccb..0000000 --- a/bundles/letsencrypt/metadata.py +++ /dev/null @@ -1,16 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'dehydrated': {}, - }, - }, - 'cron': { - 'letsencrypt_renew': '{} 4 * * * root /usr/bin/dehydrated --cron --accept-terms --challenge http-01 > /dev/null'.format((node.magic_number % 60)), - 'letsencrypt_cleanup': '{} 4 * * 0 root /usr/bin/dehydrated --cleanup > /dev/null'.format((node.magic_number % 60)), - }, - 'pacman': { - 'packages': { - 'dehydrated': {}, - }, - }, -} diff --git a/bundles/mailserver/items.py b/bundles/mailserver/items.py deleted file mode 100644 index 14527b7..0000000 --- a/bundles/mailserver/items.py +++ /dev/null @@ -1,79 +0,0 @@ -assert node.has_bundle('postfix') -assert node.has_bundle('opendkim') -assert node.has_bundle('dovecot') -assert node.has_bundle('letsencrypt') -assert node.has_bundle('roundcube') -assert node.has_bundle('rspamd') -assert node.has_bundle('redis') - -from hashlib import md5 -from shlex import quote - -db_data = node.metadata.get('mailserver/database') -test_password = str(node.metadata.get('mailserver/test_password')) -setup = f""" - CREATE TABLE domains ( - "id" BIGSERIAL PRIMARY KEY, - "name" varchar(255) UNIQUE NOT NULL - ); - CREATE INDEX ON domains ("name"); - - CREATE TABLE users ( - "id" BIGSERIAL PRIMARY KEY, - "name" varchar(255) NOT NULL, - "domain_id" BIGSERIAL REFERENCES domains(id), - "password" varchar(255) NULL, - "redirect" varchar(255) DEFAULT NULL - ); - CREATE UNIQUE INDEX ON users ("name", "domain_id") WHERE "redirect" IS NULL; - - -- OWNERSHIPS - - ALTER TABLE domains OWNER TO {db_data['user']}; - ALTER TABLE users OWNER TO {db_data['user']}; - - -- TEST DATA - - INSERT INTO domains (name) VALUES ('example.com'); - - INSERT INTO users (name, domain_id, password) - SELECT 'bw_test_user', domains.id, MD5('{test_password}') - FROM domains - WHERE domains.name = 'example.com'; - - INSERT INTO users (name, domain_id, redirect) - SELECT 'bw_test_alias', domains.id, 'somewhere@example.com' - FROM domains - WHERE domains.name = 'example.com'; -""" - -actions['initialize_mailserver_db'] = { - 'command': f"psql -d {db_data['name']} -c {quote(setup)}", - 'unless': f"psql -At -d {db_data['name']} -c \"SELECT to_regclass(\'public.users\')\" | grep -q '^users$'", - 'needs': [ - 'postgres_db:mailserver', - ], -} - -# testuser - -test_password_md5 = md5(str(test_password).encode()).hexdigest() -check_query = """ - SELECT password - FROM users - WHERE name = 'bw_test_user' - AND domain_id = (SELECT id FROM domains WHERE name = 'example.com') -""" -update_query = f""" - UPDATE users - SET password = MD5('{test_password}') - WHERE name = 'bw_test_user' - AND domain_id = (SELECT id FROM domains WHERE name = 'example.com') -""" -actions['mailserver_update_test_pw'] = { - 'command': f"psql -d {db_data['name']} -c {quote(update_query)}", - 'unless': f"psql -At -d {db_data['name']} -c {quote(check_query)} | grep -q '^{test_password_md5}$\'", - 'needs': [ - 'action:initialize_mailserver_db', - ], -} diff --git a/bundles/mailserver/metadata.py b/bundles/mailserver/metadata.py deleted file mode 100644 index 99c539b..0000000 --- a/bundles/mailserver/metadata.py +++ /dev/null @@ -1,66 +0,0 @@ -from ipaddress import ip_interface - -database_password = repo.vault.password_for(f'{node.name} db mailserver') - -defaults = { - 'mailserver': { - 'maildir': '/var/vmail', - 'database': { - 'host': '127.0.0.1', # dont use localhost - 'name': 'mailserver', - 'user': 'mailserver', - 'password': database_password, - }, - 'test_password': repo.vault.password_for(f'{node.name} test_pw mailserver'), - 'domains': [], - }, - 'postgresql': { - 'roles': { - 'mailserver': { - 'password': database_password, - }, - }, - 'databases': { - 'mailserver': { - 'owner': 'mailserver', - }, - }, - }, - 'zfs': { - 'datasets': { - 'tank/vmail': { - 'mountpoint': '/var/vmail', - 'compression': 'on', - }, - }, - }, -} - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - dns = {} - - for domain in metadata.get('mailserver/domains'): - dns[domain] = { - 'MX': [f'5 {domain}.'], - 'TXT': ['v=spf1 a mx -all'], - } - - return { - 'dns': dns, - } - -@metadata_reactor.provides( - 'letsencrypt/domains', -) -def letsencrypt(metadata): - return { - 'letsencrypt': { - 'domains': { - metadata.get('mailserver/hostname'): set(), - }, - }, - } diff --git a/bundles/mirror/metadata.py b/bundles/mirror/metadata.py deleted file mode 100644 index 8f444ca..0000000 --- a/bundles/mirror/metadata.py +++ /dev/null @@ -1,17 +0,0 @@ -defaults = { - 'mirror': {}, -} - - -@metadata_reactor.provides( - 'systemd-timers', -) -def timers(metadata): - return { - 'systemd-timers': { - f'mirror-{name}': { - 'command': f"/usr/bin/scp -r -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '{config['from']}' '{config['to']}'", - 'when': 'hourly', - } for name, config in metadata.get('mirror').items() - } - } diff --git a/bundles/network/metadata.py b/bundles/network/metadata.py deleted file mode 100644 index bd97df3..0000000 --- a/bundles/network/metadata.py +++ /dev/null @@ -1,46 +0,0 @@ -from ipaddress import ip_interface - -defaults = { - 'network': { - } -} - - -@metadata_reactor.provides( - 'systemd-networkd/networks', -) -def systemd_networkd(metadata): - units = {} - - for type, network in metadata.get('network').items(): - units[type] = { - 'Match': { - 'Name': network['interface'], - }, - 'Network': { - 'DHCP': 'no', - 'IPv6AcceptRA': 'no', - } - } - - for i in [4, 6]: - if network.get(f'ipv{i}', None): - units[type].update({ - f'Address#ipv{i}': { - 'Address': network[f'ipv{i}'], - }, - }) - if f'gateway{i}' in network: - units[type].update({ - f'Route#ipv{i}': { - 'Gateway': network[f'gateway{i}'], - 'GatewayOnlink': 'yes', - } - }) - - - return { - 'systemd-networkd': { - 'networks': units, - } - } diff --git a/bundles/nextcloud/README.md b/bundles/nextcloud/README.md deleted file mode 100644 index 4d51f9c..0000000 --- a/bundles/nextcloud/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# downloads[f'/tmp/nextcloud-{version}.tar.bz2'] = { -# 'url': f'https://download.nextcloud.com/server/releases/nextcloud-{version}.tar.bz2', -# 'sha256_url': '{url}.sha256', -# 'triggered': True, -# } -# actions['delete_nextcloud'] = { -# 'command': 'rm -rf /opt/nextcloud/*', -# 'triggered': True, -# } -# actions['extract_nextcloud'] = { -# 'command': f'tar xfvj /tmp/nextcloud-{version}.tar.bz2 --strip 1 -C /opt/nextcloud nextcloud', -# 'unless': f"""php -r 'include "/opt/nextcloud/version.php"; echo "$OC_VersionString";' | grep -q '^{version}$'""", -# 'preceded_by': [ -# 'action:delete_nextcloud', -# f'download:/tmp/nextcloud-{version}.tar.bz2', -# ], -# 'needs': [ -# 'directory:/opt/nextcloud', -# ], -# } - - -# git_deploy = { -# '/opt/nextcloud': { -# 'repo': 'git://github.com/nextcloud/server.git', -# 'rev': f"v{node.metadata.get('nextcloud/version')}", -# 'needs': { -# 'directory:/opt/nextcloud', -# }, -# }, -# '/opt/nextcloud/3rdparty': { -# 'repo': 'git://github.com/nextcloud/3rdparty.git', -# 'rev': f"v{node.metadata.get('nextcloud/version')}", -# 'needs': { -# 'git_deploy:/opt/nextcloud', -# }, -# }, -# } diff --git a/bundles/nextcloud/files/managed.config.php b/bundles/nextcloud/files/managed.config.php deleted file mode 100644 index e186d1b..0000000 --- a/bundles/nextcloud/files/managed.config.php +++ /dev/null @@ -1,24 +0,0 @@ - "nextcloud", - "dbpassword" => "${db_password}", - "dbname" => "nextcloud", - "dbhost" => "localhost", - "dbtype" => "pgsql", - "datadirectory" => "/var/lib/nextcloud", - "dbport" => "5432", - "apps_paths" => [ - [ - "path" => "/opt/nextcloud/apps", - "url" => "/apps", - "writable" => false, - ], - [ - "path" => "/var/lib/nextcloud/.userapps", - "url" => "/userapps", - "writable" => true, - ], - ], - "cache_path" => "/var/lib/nextcloud/.cache", -); diff --git a/bundles/nextcloud/items.py b/bundles/nextcloud/items.py deleted file mode 100644 index 38fcb0c..0000000 --- a/bundles/nextcloud/items.py +++ /dev/null @@ -1,144 +0,0 @@ -assert node.has_bundle('php') - -from shlex import quote -from os.path import join -from mako.template import Template - -version = node.metadata.get('nextcloud/version') - -directories = { - '/opt/nextcloud': {}, - '/etc/nextcloud': { - 'owner': 'www-data', - 'group': 'www-data', - }, - '/var/lib/nextcloud': { - 'owner': 'www-data', - 'group': 'www-data', - 'mode': '770', - }, - '/var/lib/nextcloud/.userapps': { - 'owner': 'www-data', - 'group': 'www-data', - }, - '/var/lib/nextcloud/.cache': { - 'owner': 'www-data', - 'group': 'www-data', - }, -} - -downloads[f'/tmp/nextcloud-{version}.tar.bz2'] = { - 'url': f'https://download.nextcloud.com/server/releases/nextcloud-{version}.tar.bz2', - 'sha256_url': '{url}.sha256', - 'triggered': True, -} -actions['delete_nextcloud'] = { - 'command': 'rm -rf /opt/nextcloud/*', - 'triggered': True, -} -actions['extract_nextcloud'] = { - 'command': f'tar xfvj /tmp/nextcloud-{version}.tar.bz2 --strip 1 -C /opt/nextcloud nextcloud', - 'unless': f"""php -r 'include "/opt/nextcloud/version.php"; echo "$OC_VersionString";' | grep -q '^{version}$'""", - 'preceded_by': [ - 'action:delete_nextcloud', - f'download:/tmp/nextcloud-{version}.tar.bz2', - ], - 'needs': [ - 'directory:/opt/nextcloud', - ], -} - -symlinks = { - '/opt/nextcloud/config': { - 'target': '/etc/nextcloud', - 'owner': 'www-data', - 'group': 'www-data', - 'needs': [ - 'action:extract_nextcloud', - ], - }, - '/opt/nextcloud/userapps': { - 'target': '/var/lib/nextcloud/.userapps', - 'owner': 'www-data', - 'group': 'www-data', - 'needs': [ - 'action:extract_nextcloud', - ], - }, -} - -files = { - '/etc/nextcloud/CAN_INSTALL': { - 'content': '', - 'owner': 'www-data', - 'group': 'www-data', - 'mode': '640', - 'needs': [ - 'directory:/etc/nextcloud', - ], - }, - '/etc/nextcloud/managed.config.php': { - 'content_type': 'mako', - 'owner': 'www-data', - 'group': 'www-data', - 'mode': '640', - 'context': { - 'db_password': node.metadata.get('postgresql/roles/nextcloud/password'), - }, - 'needs': [ - 'directory:/etc/nextcloud', - ], - }, -} - -# SETUP - -actions['install_nextcloud'] = { - 'command': repo.libs.nextcloud.occ( - 'maintenance:install', - no_interaction=None, - database='pgsql', - database_name='nextcloud', - database_host='localhost', - database_user='nextcloud', - database_pass=node.metadata.get('postgresql/roles/nextcloud/password'), - admin_user='admin', - admin_pass=node.metadata.get('nextcloud/admin_pass'), - data_dir='/var/lib/nextcloud', - ), - 'unless': repo.libs.nextcloud.occ('status') + ' | grep -q "installed: true"', - 'needs': [ - 'directory:/etc/nextcloud', - 'directory:/opt/nextcloud', - 'directory:/var/lib/nextcloud', - 'directory:/var/lib/nextcloud/.userapps', - 'directory:/var/lib/nextcloud/.cache', - 'symlink:/opt/nextcloud/config', - 'symlink:/opt/nextcloud/userapps', - 'action:extract_nextcloud', - 'file:/etc/nextcloud/CAN_INSTALL', - 'file:/etc/nextcloud/managed.config.php', - 'postgres_db:nextcloud', - ], -} - -# UPGRADE - -actions['upgrade_nextcloud'] = { - 'command': repo.libs.nextcloud.occ('upgrade'), - 'unless': "! " + repo.libs.nextcloud.occ('status') + ' | grep -q "Nextcloud or one of the apps require upgrade"', - 'needs': [ - 'action:install_nextcloud', - ], -} - -actions['nextcloud_add_missing_inidces'] = { - 'command': repo.libs.nextcloud.occ('db:add-missing-indices'), - 'needs': [ - 'action:upgrade_nextcloud', - ], - 'triggered': True, - 'triggered_by': [ - f'action:extract_nextcloud', - ], -} diff --git a/bundles/nextcloud/metadata.py b/bundles/nextcloud/metadata.py deleted file mode 100644 index d4bfe11..0000000 --- a/bundles/nextcloud/metadata.py +++ /dev/null @@ -1,83 +0,0 @@ -import string -from uuid import UUID - -defaults = { - 'apt': { - 'packages': { - 'php': {}, - 'php-curl': {}, - 'php-gd': {}, - 'php-json': {}, - 'php-xml': {}, - 'php-mbstring': {}, - 'php-cli': {}, - 'php-cgi': {}, - 'php-zip': {}, - 'php-pgsql': {}, - }, - }, - 'archive': { - 'paths': { - '/var/lib/nextcloud': { - 'exclude': [ - '^appdata_', - '^updater-', - '^nextcloud\.log', - '^updater\.log', - '^[^/]+/cache', - '^[^/]+/files_versions', - '^[^/]+/files_trashbin', - ], - }, - }, - }, - 'backup': { - 'paths': [ - '/etc/nextcloud/config.php', - ], - }, - 'nextcloud': { - 'admin_user': 'admin', - 'admin_pass': repo.vault.password_for(f'{node.name} nextcloud admin pw'), - }, - 'postgresql': { - 'roles': { - 'nextcloud': { - 'password': repo.vault.password_for(f'{node.name} nextcloud db pw'), - }, - }, - 'databases': { - 'nextcloud': { - 'owner': 'nextcloud', - }, - }, - }, - 'zfs': { - 'datasets': { - 'tank/nextcloud': { - 'mountpoint': '/var/lib/nextcloud', - 'needed_by': [ - 'bundle:nextcloud', - ], - }, - }, - }, -} - - -@metadata_reactor.provides( - 'nginx/vhosts' -) -def vhost(metadata): - return { - 'nginx': { - 'vhosts': { - metadata.get('nextcloud/hostname'): { - 'root': '/opt/nextcloud', - 'include': [ - 'php.conf', - ], - }, - }, - }, - } diff --git a/bundles/nginx/files/fastcgi.conf b/bundles/nginx/files/fastcgi.conf deleted file mode 100644 index bd151a6..0000000 --- a/bundles/nginx/files/fastcgi.conf +++ /dev/null @@ -1,27 +0,0 @@ -fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; -fastcgi_param QUERY_STRING $query_string; -fastcgi_param REQUEST_METHOD $request_method; -fastcgi_param CONTENT_TYPE $content_type; -fastcgi_param CONTENT_LENGTH $content_length; - -fastcgi_param SCRIPT_NAME $fastcgi_script_name; -fastcgi_param REQUEST_URI $request_uri; -fastcgi_param DOCUMENT_URI $document_uri; -fastcgi_param DOCUMENT_ROOT $document_root; -fastcgi_param SERVER_PROTOCOL $server_protocol; -fastcgi_param REQUEST_SCHEME $scheme; -fastcgi_param HTTPS $https if_not_empty; - -fastcgi_param GATEWAY_INTERFACE CGI/1.1; -fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - -fastcgi_param REMOTE_ADDR $remote_addr; -fastcgi_param REMOTE_PORT $remote_port; -fastcgi_param SERVER_ADDR $server_addr; -fastcgi_param SERVER_PORT $server_port; -fastcgi_param SERVER_NAME $server_name; - -fastcgi_param REDIRECT_STATUS 200; - -# This is the only thing that's different to the debian default. -fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; diff --git a/bundles/nginx/items.py b/bundles/nginx/items.py deleted file mode 100644 index b8cc63c..0000000 --- a/bundles/nginx/items.py +++ /dev/null @@ -1,88 +0,0 @@ -from datetime import datetime, timedelta - -directories = { - '/etc/nginx/sites': { - 'purge': True, - 'triggers': { - 'svc_systemd:nginx:restart', - }, - }, - '/etc/nginx/ssl': { - 'purge': True, - 'triggers': { - 'svc_systemd:nginx:restart', - }, - }, - '/var/www': {}, -} - -files = { - '/etc/nginx/nginx.conf': { - 'content': repo.libs.nginx.render_config(node.metadata.get('nginx/config')), - 'triggers': { - 'svc_systemd:nginx:restart', - }, - }, - '/etc/nginx/fastcgi.conf': { - 'triggers': { - 'svc_systemd:nginx:restart', - }, - }, - '/etc/nginx/sites-available': { - 'delete': True, - }, - '/etc/nginx/sites-enabled': { - 'delete': True, - }, -} - -actions = { - 'nginx-generate-dhparam': { - 'command': 'openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048', - 'unless': 'test -f /etc/ssl/certs/dhparam.pem', - }, -} - -svc_systemd = { - 'nginx': { - 'needs': { - 'action:nginx-generate-dhparam', - 'pkg_apt:nginx', - }, - }, -} - -for name, config in node.metadata.get('nginx/includes').items(): - files[f'/etc/nginx/{name}.conf'] = { - 'content': repo.libs.nginx.render_config(config), - 'needed_by': { - 'svc_systemd:nginx', - 'svc_systemd:nginx:restart', - }, - 'triggers': { - 'svc_systemd:nginx:restart', - }, - } - -for name, config in { - **node.metadata.get('nginx/default_vhosts'), - **node.metadata.get('nginx/vhosts'), -}.items(): - files[f'/etc/nginx/sites/{name}'] = { - 'content': repo.libs.nginx.render_config({ - 'server': config, - }), - 'needs': [], - 'needed_by': { - 'svc_systemd:nginx', - 'svc_systemd:nginx:restart', - }, - 'triggers': { - 'svc_systemd:nginx:restart', - }, - } - - if name in node.metadata.get('letsencrypt/domains'): - files[f'/etc/nginx/sites/{name}']['needs'].append( - f'action:letsencrypt_ensure-some-certificate_{name}', - ) diff --git a/bundles/nginx/metadata.py b/bundles/nginx/metadata.py deleted file mode 100644 index 3f1030c..0000000 --- a/bundles/nginx/metadata.py +++ /dev/null @@ -1,126 +0,0 @@ -from ipaddress import ip_interface - -defaults = { - 'apt': { - 'packages': { - 'nginx': {}, - }, - }, - 'nginx': { - 'config': { - 'user': 'www-data', - 'worker_processes': 10, - 'pid': '/var/run/nginx.pid', - 'events': { - 'worker_connections': 768, - }, - 'http': { - 'include': [ - '/etc/nginx/mime.types', - '/etc/nginx/sites/*', - ], - 'default_type': 'application/octet-stream', - 'sendfile': 'on', - 'tcp_nopush': 'on', - 'server_names_hash_bucket_size': 128, - 'access_log': '/var/log/nginx/access.log', - 'error_log': '/var/log/nginx/error.log', - }, - }, - 'default_vhosts': { - '80': { - 'listen': [ - '80', - '[::]:80', - ], - 'location /.well-known/acme-challenge/': { - 'alias': '/var/lib/dehydrated/acme-challenges/', - }, - 'location /': { - 'return': '301 https://$host$request_uri', - }, - }, - 'stub_status': { - 'listen': '127.0.0.1:22999 default_server', - 'server_name': '_', - 'stub_status': '', - }, - }, - 'vhosts': {}, - 'includes': {}, - }, -} - -@metadata_reactor.provides( - 'nginx/includes/php', -) -def php(metadata): - return { - 'nginx': { - 'includes': { - 'php': { - 'location ~ \.php$': { - 'include': 'fastcgi.conf', - 'fastcgi_split_path_info': '^(.+\.php)(/.+)$', - 'fastcgi_pass': f"unix:/run/php/php{metadata.get('php/version')}-fpm.sock", - }, - }, - }, - }, - } - - -@metadata_reactor.provides( - 'nginx/vhosts', -) -def vhosts(metadata): - vhosts = {} - - for name, config in metadata.get('nginx/vhosts').items(): - vhosts[name] = { - 'server_name': name, - 'listen': [ - '443 ssl http2', - '[::]:443 ssl http2', - ], - 'ssl_certificate': f'/var/lib/dehydrated/certs/{name}/fullchain.pem', - 'ssl_certificate_key': f'/var/lib/dehydrated/certs/{name}/privkey.pem', - 'location /.well-known/acme-challenge/': { - 'alias': '/var/lib/dehydrated/acme-challenges/', - }, - } - - return { - 'nginx': { - 'vhosts': vhosts, - } - } - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - return { - 'dns': { - domain: repo.libs.dns.get_a_records(metadata) - for domain in metadata.get('nginx/vhosts') - }, - } - - -@metadata_reactor.provides( - 'letsencrypt/domains', - 'letsencrypt/reload_after', -) -def letsencrypt(metadata): - return { - 'letsencrypt': { - 'domains': { - domain: {} for domain in metadata.get('nginx/vhosts') - }, - 'reload_after': { - 'nginx', - }, - }, - } diff --git a/bundles/opendkim/files/key_table b/bundles/opendkim/files/key_table deleted file mode 100644 index d669afe..0000000 --- a/bundles/opendkim/files/key_table +++ /dev/null @@ -1,3 +0,0 @@ -% for domain in domains: -mail._domainkey.${domain} ${domain}:mail:/etc/opendkim/keys/${domain}/mail.private -% endfor diff --git a/bundles/opendkim/files/opendkim.conf b/bundles/opendkim/files/opendkim.conf deleted file mode 100644 index 6f2ef79..0000000 --- a/bundles/opendkim/files/opendkim.conf +++ /dev/null @@ -1,15 +0,0 @@ -Mode sv -SignatureAlgorithm rsa-sha256 -Canonicalization relaxed/simple -KeyTable refile:/etc/opendkim/key_table -SigningTable refile:/etc/opendkim/signing_table - -UMask 007 -UserID opendkim:opendkim -PidFile /run/opendkim/opendkim.pid -Socket inet:8891@localhost - -Syslog yes -SyslogSuccess Yes -SyslogFacility mail -LogWhy Yes diff --git a/bundles/opendkim/files/signing_table b/bundles/opendkim/files/signing_table deleted file mode 100644 index 90bf076..0000000 --- a/bundles/opendkim/files/signing_table +++ /dev/null @@ -1,3 +0,0 @@ -% for domain in domains: -*@${domain} mail._domainkey.${domain} -% endfor diff --git a/bundles/opendkim/items.py b/bundles/opendkim/items.py deleted file mode 100644 index 5d10151..0000000 --- a/bundles/opendkim/items.py +++ /dev/null @@ -1,86 +0,0 @@ -file_attributes = { - 'owner': 'opendkim', - 'group': 'opendkim', - 'mode': '700', - 'triggers': [ - 'svc_systemd:opendkim:restart', - ], -} - -groups['opendkim'] = {} -users['opendkim'] = {} - -directories = { - '/etc/opendkim': { - **file_attributes, - 'purge' : True, - }, - '/etc/opendkim/keys': { - **file_attributes, - 'purge' : True, - }, -} - -files = { - '/etc/opendkim.conf': { - **file_attributes, - }, - '/etc/defaults/opendkim': { - # https://metadata.ftp-master.debian.org/changelogs//main/o/opendkim/testing_opendkim.NEWS - 'delete': True, - }, - '/etc/opendkim/key_table': { - 'content_type': 'mako', - 'context': { - 'domains': node.metadata.get('mailserver/domains'), - }, - **file_attributes, - }, - '/etc/opendkim/signing_table': { - 'content_type': 'mako', - 'context': { - 'domains': node.metadata.get('mailserver/domains'), - }, - **file_attributes, - }, -} - -for domain in node.metadata.get('mailserver/domains'): - directories[f'/etc/opendkim/keys/{domain}'] = { - **file_attributes, - 'purge': True, - } - files[f'/etc/opendkim/keys/{domain}/mail.private'] = { - **file_attributes, - 'content': node.metadata.get(f'opendkim/keys/{domain}/private'), - } - # files[f'/etc/opendkim/keys/{domain}/mail.txt'] = { - # **file_attributes, - # 'content_type': 'any', - # } - # actions[f'generate_{domain}_dkim_key'] = { - # 'command': ( - # f'sudo --user opendkim' - # f' opendkim-genkey' - # f' --selector=mail' - # f' --directory=/etc/opendkim/keys/{domain}' - # f' --domain={domain}' - # ), - # 'unless': f'test -f /etc/opendkim/keys/{domain}/mail.private', - # 'needs': [ - # 'svc_systemd:opendkim', - # f'directory:/etc/opendkim/keys/{domain}', - # ], - # 'triggers': [ - # 'svc_systemd:opendkim:restart', - # ], - # } - -svc_systemd['opendkim'] = { - 'needs': [ - 'pkg_apt:opendkim', - 'file:/etc/opendkim.conf', - 'file:/etc/opendkim/key_table', - 'file:/etc/opendkim/signing_table', - ], -} diff --git a/bundles/opendkim/metadata.py b/bundles/opendkim/metadata.py deleted file mode 100644 index 2f4bb9e..0000000 --- a/bundles/opendkim/metadata.py +++ /dev/null @@ -1,93 +0,0 @@ -from os.path import join, exists -from re import sub -from cryptography.hazmat.primitives import serialization as crypto_serialization -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.backends import default_backend as crypto_default_backend - - -defaults = { - 'apt': { - 'packages': { - 'opendkim': {}, - 'opendkim-tools': {}, - }, - }, - 'opendkim': { - 'keys': {}, - }, - 'dns': { - 'mail._domainkey.mail2.sublimity.de': { - 'TXT': [ - - ] - } - } -} - - -@metadata_reactor.provides( - 'opendkim/keys', -) -def keys(metadata): - keys = {} - - for domain in metadata.get('mailserver/domains'): - if domain in metadata.get(f'opendkim/keys'): - continue - - pubkey_path = join(repo.path, 'data', 'dkim', f'{domain}.pubkey') - privkey_path = join(repo.path, 'data', 'dkim', f'{domain}.privkey.enc') - - if not exists(pubkey_path) or not exists(privkey_path): - key = rsa.generate_private_key( - backend=crypto_default_backend(), - public_exponent=65537, - key_size=2048 - ) - with open(pubkey_path, 'w') as file: - file.write( - key.public_key().public_bytes( - crypto_serialization.Encoding.OpenSSH, - crypto_serialization.PublicFormat.OpenSSH - ).decode() - ) - with open(privkey_path, 'w') as file: - file.write( - repo.vault.encrypt( - key.private_bytes( - crypto_serialization.Encoding.PEM, - crypto_serialization.PrivateFormat.PKCS8, - crypto_serialization.NoEncryption() - ).decode(), - ) - ) - - with open(pubkey_path, 'r') as pubkey: - with open(privkey_path, 'r') as privkey: - keys[domain] = { - 'public': pubkey.read(), - 'private': repo.vault.decrypt(privkey.read()), - } - - return { - 'opendkim': { - 'keys': keys, - } - } - - -@metadata_reactor.provides( - 'dns', -) -def dns(metadata): - dns = {} - - for domain, keys in metadata.get('opendkim/keys').items(): - raw_key = sub('^ssh-rsa ', '', keys['public']) - dns[f'mail._domainkey.{domain}'] = { - 'TXT': [f'v=DKIM1; k=rsa; p={raw_key}'], - } - - return { - 'dns': dns, - } diff --git a/bundles/php/files/php.ini b/bundles/php/files/php.ini deleted file mode 100644 index d06e97f..0000000 --- a/bundles/php/files/php.ini +++ /dev/null @@ -1,102 +0,0 @@ -[PHP] -; Only needed for libapache2-mod-php? -engine = On -short_open_tag = Off -precision = 14 -output_buffering = 4096 -zlib.output_compression = Off -implicit_flush = Off -serialize_precision = -1 -disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals -ignore_user_abort = Off -zend.enable_gc = On -expose_php = Off - -max_execution_time = 30 -max_input_time = 60 -memory_limit = 256M - -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT -display_startup_errors = Off -log_errors = On -log_errors_max_len = 1024 -ignore_repeated_errors = Off -ignore_repeated_source = Off -report_memleaks = On -html_errors = On -error_log = syslog -syslog.ident = php7.4 -syslog.filter = ascii - -arg_separator.output = "&" -variables_order = "GPCS" -request_order = "GP" -register_argc_argv = Off -auto_globals_jit = On -post_max_size = ${post_max_size}M -default_mimetype = "text/html" -default_charset = "UTF-8" - -enable_dl = Off -file_uploads = On -upload_max_filesize = ${post_max_size}M -max_file_uploads = 20 - -allow_url_fopen = On -allow_url_include = Off -default_socket_timeout = 10 - -[CLI Server] -cli_server.color = On - -[mail function] -mail.add_x_header = Off - -[ODBC] -odbc.allow_persistent = On -odbc.check_persistent = On -odbc.max_persistent = -1 -odbc.max_links = -1 -odbc.defaultlrl = 4096 -odbc.defaultbinmode = 1 - -[PostgreSQL] -pgsql.allow_persistent = On -pgsql.auto_reset_persistent = Off -pgsql.max_persistent = -1 -pgsql.max_links = -1 -pgsql.ignore_notice = 0 -pgsql.log_notice = 0 - -[bcmath] -bcmath.scale = 0 - -[Session] -session.save_handler = files -session.use_strict_mode = 0 -session.use_cookies = 1 -session.use_only_cookies = 1 -session.name = PHPSESSID -session.auto_start = 0 -session.cookie_lifetime = 0 -session.cookie_path = / -session.cookie_domain = -session.cookie_httponly = -session.cookie_samesite = -session.serialize_handler = php -session.gc_probability = 1 -session.gc_divisor = 1000 -session.gc_maxlifetime = 1440 -session.referer_check = -session.cache_limiter = nocache -session.cache_expire = 180 -session.use_trans_sid = 0 -session.sid_length = 32 -session.trans_sid_tags = "a=href,area=href,frame=src,form=" -session.sid_bits_per_character = 6 - -[Assertion] -zend.assertions = -1 - -[Date] -date.timezone = Europe/London diff --git a/bundles/php/items.py b/bundles/php/items.py deleted file mode 100644 index 9d36098..0000000 --- a/bundles/php/items.py +++ /dev/null @@ -1,37 +0,0 @@ -version = node.metadata.get('php/version') - -php_ini_context = { - 'num_cpus': node.metadata.get('vm/cores'), - 'post_max_size': node.metadata.get('php/post_max_size', 10), -} - -files = { - f'/etc/php/{version}/fpm/php.ini': { - 'content_type': 'mako', - 'context': php_ini_context, - 'needs': { - # "all php packages" - 'pkg_apt:' - }, - 'triggers': { - f'svc_systemd:php{version}-fpm:restart', - }, - }, - f'/etc/php/{version}/cli/php.ini': { - 'content_type': 'mako', - 'context': php_ini_context, - 'needs': { - # "all php packages" - 'pkg_apt:' - }, - }, -} - -svc_systemd = { - f'php{version}-fpm': { - 'needs': { - 'pkg_apt:', - f'file:/etc/php/{version}/fpm/php.ini', - }, - }, -} diff --git a/bundles/php/metadata.py b/bundles/php/metadata.py deleted file mode 100644 index f658c87..0000000 --- a/bundles/php/metadata.py +++ /dev/null @@ -1,7 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'php': {}, - }, - }, -} diff --git a/bundles/postfix/files/main.cf b/bundles/postfix/files/main.cf deleted file mode 100644 index fb307a0..0000000 --- a/bundles/postfix/files/main.cf +++ /dev/null @@ -1,53 +0,0 @@ -smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) -biff = no -append_dot_mydomain = no -readme_directory = no -compatibility_level = 2 -smtpd_use_tls=yes -<%text> -smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache -smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache - -smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination -myhostname = debian-2gb-nbg1-1 -alias_maps = hash:/etc/aliases -alias_database = hash:/etc/aliases -myorigin = /etc/mailname -mydestination = $myhostname, debian-2gb-nbg1-1, localhost.localdomain, localhost -relayhost = -mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 -mailbox_size_limit = 0 -recipient_delimiter = + -inet_interfaces = all -inet_protocols = all - -virtual_mailbox_domains = pgsql:/etc/postfix/virtual_mailbox_domains.cf -virtual_mailbox_maps = pgsql:/etc/postfix/virtual_mailbox_maps.cf -virtual_alias_maps = pgsql:/etc/postfix/virtual_alias_maps.cf,pgsql:/etc/postfix/virtual_mailbox_maps.cf -smtpd_sender_login_maps = pgsql:/etc/postfix/virtual_alias_maps.cf -virtual_transport = lmtp:unix:private/dovecot-lmtp - -smtpd_sasl_type = dovecot -smtpd_sasl_path = private/auth -smtpd_sasl_auth_enable = yes - -smtpd_tls_security_level = may -smtpd_tls_auth_only = yes -smtpd_tls_cert_file = /var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/fullchain.pem -smtpd_tls_key_file = /var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/privkey.pem -smtp_tls_security_level = may - -smtpd_restriction_classes = mua_sender_restrictions, mua_client_restrictions, mua_helo_restrictions -mua_client_restrictions = permit_sasl_authenticated, reject -mua_sender_restrictions = permit_sasl_authenticated, reject -mua_helo_restrictions = permit_mynetworks, reject_non_fqdn_hostname, reject_invalid_hostname, permit - -smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332 -non_smtpd_milters = inet:localhost:8891 inet:127.0.0.1:11332 - -# opendkim -milter_protocol = 6 -milter_default_action = accept - -# rspamd -milter_mail_macros = "i {mail_addr} {client_addr} {client_name} {auth_authen}" diff --git a/bundles/postfix/files/master.cf b/bundles/postfix/files/master.cf deleted file mode 100644 index f9d8b21..0000000 --- a/bundles/postfix/files/master.cf +++ /dev/null @@ -1,55 +0,0 @@ -# ========================================================================== -# service type private unpriv chroot wakeup maxproc command + args -# (yes) (yes) (no) (never) (100) -# ========================================================================== -smtp inet n - y - - smtpd -pickup unix n - y 60 1 pickup -cleanup unix n - y - 0 cleanup -qmgr unix n - n 300 1 qmgr -tlsmgr unix - - y 1000? 1 tlsmgr -rewrite unix - - y - - trivial-rewrite -bounce unix - - y - 0 bounce -defer unix - - y - 0 bounce -trace unix - - y - 0 bounce -verify unix - - y - 1 verify -flush unix n - y 1000? 0 flush -proxymap unix - - n - - proxymap -proxywrite unix - - n - 1 proxymap -smtp unix - - y - - smtp -relay unix - - y - - smtp - -o syslog_name=postfix/$service_name -showq unix n - y - - showq -error unix - - y - - error -retry unix - - y - - error -discard unix - - y - - discard -local unix - n n - - local -virtual unix - n n - - virtual -lmtp unix - - y - - lmtp -anvil unix - - y - 1 anvil -scache unix - - y - 1 scache -postlog unix-dgram n - n - 1 postlogd -maildrop unix - n n - - pipe - flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} -uucp unix - n n - - pipe - flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) -ifmail unix - n n - - pipe - flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) -bsmtp unix - n n - - pipe - flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient -scalemail-backend unix - n n - 2 pipe - flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} -mailman unix - n n - - pipe - flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py - ${nexthop} ${user} -submission inet n - y - - smtpd - -o syslog_name=postfix/submission - -o smtpd_tls_security_level=encrypt - -o smtpd_sasl_auth_enable=yes - -o smtpd_tls_auth_only=yes - -o smtpd_reject_unlisted_recipient=no - -o smtpd_client_restrictions=$mua_client_restrictions - -o smtpd_helo_restrictions=$mua_helo_restrictions - -o smtpd_sender_restrictions=$mua_sender_restrictions - -o smtpd_recipient_restrictions= - -o smtpd_relay_restrictions=permit_sasl_authenticated,reject - -o milter_macro_daemon_name=ORIGINATING diff --git a/bundles/postfix/files/virtual_alias_maps.cf b/bundles/postfix/files/virtual_alias_maps.cf deleted file mode 100644 index fe427cd..0000000 --- a/bundles/postfix/files/virtual_alias_maps.cf +++ /dev/null @@ -1,5 +0,0 @@ -hosts = ${host} -dbname = ${name} -user = ${user} -password = ${password} -query = SELECT redirect FROM users LEFT JOIN domains ON users.domain_id = domains.id WHERE redirect IS NOT NULL AND users.name = '%u' AND domains.name = '%d' diff --git a/bundles/postfix/files/virtual_mailbox_domains.cf b/bundles/postfix/files/virtual_mailbox_domains.cf deleted file mode 100644 index 3741a2b..0000000 --- a/bundles/postfix/files/virtual_mailbox_domains.cf +++ /dev/null @@ -1,5 +0,0 @@ -hosts = ${host} -dbname = ${name} -user = ${user} -password = ${password} -query = SELECT name FROM domains WHERE name='%s' diff --git a/bundles/postfix/files/virtual_mailbox_maps.cf b/bundles/postfix/files/virtual_mailbox_maps.cf deleted file mode 100644 index 32c21eb..0000000 --- a/bundles/postfix/files/virtual_mailbox_maps.cf +++ /dev/null @@ -1,5 +0,0 @@ -hosts = ${host} -dbname = ${name} -user = ${user} -password = ${password} -query = SELECT CONCAT(users.name, '@', domains.name) AS email FROM users LEFT JOIN domains ON users.domain_id = domains.id WHERE redirect IS NULL AND users.name = '%u' AND domains.name = '%d' diff --git a/bundles/postfix/items.py b/bundles/postfix/items.py deleted file mode 100644 index 723bb37..0000000 --- a/bundles/postfix/items.py +++ /dev/null @@ -1,73 +0,0 @@ -assert node.has_bundle('mailserver') - -file_options = { - 'triggers': [ - 'svc_systemd:postfix:restart', - ], - 'needed_by': [ - 'svc_systemd:postfix', - ], -} - -files = { - '/etc/postfix/main.cf': { - 'content_type': 'mako', - **file_options, - }, - '/etc/postfix/master.cf': { - **file_options, - }, - '/etc/postfix/virtual_mailbox_domains.cf': { - 'content_type': 'mako', - 'context': node.metadata.get('mailserver/database'), - **file_options, - }, - '/etc/postfix/virtual_mailbox_maps.cf': { - 'content_type': 'mako', - 'context': node.metadata.get('mailserver/database'), - **file_options, - }, - '/etc/postfix/virtual_alias_maps.cf': { - 'content_type': 'mako', - 'context': node.metadata.get('mailserver/database'), - **file_options, - }, -} - -svc_systemd['postfix'] = { - 'needs': [ - 'postgres_db:mailserver', - ], -} - -actions['test_postfix_config'] = { - 'command': 'false', - 'unless': "postconf check | grep -v 'symlink leaves directory' | wc -l | grep -q '^0$'", - 'needs': [ - 'svc_systemd:postfix', - ], -} -actions['test_virtual_mailbox_domains'] = { - 'command': 'false', - 'unless': "postmap -q example.com pgsql:/etc/postfix/virtual_mailbox_domains.cf | grep -q '^example.com$'", - 'needs': [ - 'svc_systemd:postfix', - 'action:mailserver_update_test_pw', - ], -} -actions['test_virtual_mailbox_maps'] = { - 'command': 'false', - 'unless': "postmap -q bw_test_user@example.com pgsql:/etc/postfix/virtual_mailbox_maps.cf | grep -q '^bw_test_user@example.com$'", - 'needs': [ - 'svc_systemd:postfix', - 'action:mailserver_update_test_pw', - ], -} -actions['test_virtual_alias_maps'] = { - 'command': 'false', - 'unless': "postmap -q bw_test_alias@example.com pgsql:/etc/postfix/virtual_alias_maps.cf | grep -q '^somewhere@example.com$'", - 'needs': [ - 'svc_systemd:postfix', - 'action:mailserver_update_test_pw', - ], -} diff --git a/bundles/postfix/metadata.py b/bundles/postfix/metadata.py deleted file mode 100644 index 5f3e8df..0000000 --- a/bundles/postfix/metadata.py +++ /dev/null @@ -1,25 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'postfix': {}, - 'postfix-pgsql': {}, - } - }, - 'backup': { - 'paths': [ - '/var/vmail', - ], - }, - 'letsencrypt': { - 'reload_after': { - 'postfix', - }, - }, - 'telegraf': { - 'config': { - 'inputs': { - 'postfix': [{}], - }, - }, - }, -} diff --git a/bundles/postgresql/items.py b/bundles/postgresql/items.py deleted file mode 100644 index 3589587..0000000 --- a/bundles/postgresql/items.py +++ /dev/null @@ -1,22 +0,0 @@ -from bundlewrap.utils.dicts import merge_dict - - -svc_systemd['postgresql'] = { - 'needs': [ - 'pkg_apt:postgresql', - ], -} - -for user, config in node.metadata.get('postgresql/roles').items(): - postgres_roles[user] = merge_dict(config, { - 'needs': [ - 'svc_systemd:postgresql', - ], - }) - -for database, config in node.metadata.get('postgresql/databases').items(): - postgres_dbs[database] = merge_dict(config, { - 'needs': [ - 'svc_systemd:postgresql', - ], - }) diff --git a/bundles/postgresql/metadata.py b/bundles/postgresql/metadata.py deleted file mode 100644 index d41513a..0000000 --- a/bundles/postgresql/metadata.py +++ /dev/null @@ -1,52 +0,0 @@ -root_password = repo.vault.password_for(f'{node.name} postgresql root') - -defaults = { - 'apt': { - 'packages': { - 'postgresql': {}, - }, - }, - 'backup': { - 'paths': [ - '/var/lib/postgresql', - ], - }, - 'postgresql': { - 'roles': { - 'root': { - 'password': root_password, - 'superuser': True, - }, - }, - 'databases': {}, - }, - 'grafana_rows': [], -} - -if node.has_bundle('zfs'): - defaults['zfs'] = { - 'datasets': { - 'tank/postgresql': { - 'mountpoint': '/var/lib/postgresql', -# 'recordsize': '16384', - }, - }, - } - - -@metadata_reactor.provides( - 'telegraf/config/inputs/postgresql', -) -def telegraf(metadata): - return { - 'telegraf': { - 'config': { - 'inputs': { - 'postgresql': [{ - 'address': f'postgres://root:{root_password}@localhost:5432/postgres', - 'databases': sorted(list(node.metadata.get('postgresql/databases').keys())), - }], - }, - }, - }, - } diff --git a/bundles/redis/metadata.py b/bundles/redis/metadata.py deleted file mode 100644 index ad287c2..0000000 --- a/bundles/redis/metadata.py +++ /dev/null @@ -1,7 +0,0 @@ -defaults = { - 'apt': { - 'packages': { - 'redis-server': {}, - }, - }, -} diff --git a/bundles/roundcube/files/config.inc.php b/bundles/roundcube/files/config.inc.php deleted file mode 100644 index bcaef07..0000000 --- a/bundles/roundcube/files/config.inc.php +++ /dev/null @@ -1,79 +0,0 @@ - range(start: v.timeRangeStart, stop: v.timeRangeStop) -% for key, values in filters.items(): -<% values = values if isinstance(values, list) else [values] %>\ - |> filter(fn: (r) => ${' or '.join(f'r["{key}"] == "{value}"' for value in values)}) -% endfor -% if function == 'derivative': - |> derivative() -% else: - |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) -% endif -% if negative: - |> map(fn: (r) => ({r with _value: r._value * - 1.0})) -% endif - |> yield(name: "mean") diff --git a/data/grafana/panel.py b/data/grafana/panel.py deleted file mode 100644 index 4c652bd..0000000 --- a/data/grafana/panel.py +++ /dev/null @@ -1,66 +0,0 @@ -{ -# 'id': 1, -# 'title': 'TBD', - "gridPos": { -# "x": 0, -# "y": 0, - "h": 8, -# "w": 24 - }, - 'type': 'timeseries', - 'transformations': [], - 'description': '', - 'fieldConfig': { - 'defaults': { - 'custom': { - 'drawStyle': 'line', - 'lineInterpolation': 'smooth', - 'barAlignment': 0, - 'lineWidth': 1, - 'fillOpacity': 40, - 'gradientMode': 'opacity', - 'spanNulls': False, - 'showPoints': 'never', - 'pointSize': 5, - 'stacking': { - 'mode': 'none', - 'group': 'A' - }, - 'axisLabel': '', - 'scaleDistribution': { - 'type': 'linear' - }, - 'hideFrom': { - 'tooltip': False, - 'viz': False, - 'legend': False - }, - 'thresholdsStyle': { - 'mode': 'off', - }, - 'lineStyle': { - 'fill': 'solid', - }, - }, - 'color': { - 'mode': 'palette-classic', - }, - 'mappings': [], - 'displayName': '${__field.name}', - }, - 'overrides': [], - }, - 'options': { - 'tooltip': { - 'mode': 'single', - }, - 'legend': { - 'displayMode': 'list', - 'placement': 'bottom', - 'calcs': [], - }, - }, - 'targets': [], - 'transparent': True, - 'datasource': None, -} diff --git a/data/grafana/rows/cpu.py b/data/grafana/rows/cpu.py deleted file mode 100644 index ba3e44e..0000000 --- a/data/grafana/rows/cpu.py +++ /dev/null @@ -1,37 +0,0 @@ -{ - 'usage': { - 'stacked': False, - 'queries': { - 'usage': { - 'filters': { - '_measurement': 'cpu', - 'cpu': 'cpu-total', - '_field': [ - 'usage_iowait', - 'usage_system', - 'usage_user', - ], - }, - 'function': 'mean', - }, - }, - 'min': 0, - 'max': 100, - }, - 'load': { - 'stacked': False, - 'queries': { - 'load': { - 'filters': { - '_measurement': 'system', - '_field': [ - 'load1', - 'load5', - 'load15', - ], - }, - 'function': 'mean', - }, - }, - }, -} diff --git a/data/grafana/rows/disk_io.py b/data/grafana/rows/disk_io.py deleted file mode 100644 index deca33d..0000000 --- a/data/grafana/rows/disk_io.py +++ /dev/null @@ -1,34 +0,0 @@ -{ - 'read': { - 'stacked': True, - 'queries': { - 'usage': { - 'filters': { - '_measurement': 'diskio', - '_field': [ - 'read_bytes', - ], - }, - 'function': 'derivative', - }, - }, - 'unit': 'decbytes', - 'display_name': '__field.labels.name' - }, - 'write': { - 'stacked': True, - 'queries': { - 'load': { - 'filters': { - '_measurement': 'diskio', - '_field': [ - 'write_bytes', - ], - }, - 'function': 'derivative', - }, - }, - 'unit': 'decbytes', - 'display_name': '__field.labels.name' - }, -} diff --git a/data/grafana/rows/mem.py b/data/grafana/rows/mem.py deleted file mode 100644 index 1fcaf57..0000000 --- a/data/grafana/rows/mem.py +++ /dev/null @@ -1,36 +0,0 @@ -{ - 'memory': { - 'stacked': True, - 'queries': { - 'memory': { - 'filters': { - '_measurement': 'mem', - '_field': [ - 'used', - 'cached', - 'buffered', - 'free', - ], - }, - 'function': 'mean', - }, - }, - 'unit': 'decbytes', - }, - 'swp': { - 'stacked': True, - 'queries': { - 'memory': { - 'filters': { - '_measurement': 'mem', - '_field': [ - 'swap_cached', - 'swap_free', - ], - }, - 'function': 'mean', - }, - }, - 'unit': 'decbytes', - }, -} diff --git a/data/grafana/rows/net_io.py b/data/grafana/rows/net_io.py deleted file mode 100644 index cb8fc63..0000000 --- a/data/grafana/rows/net_io.py +++ /dev/null @@ -1,34 +0,0 @@ -{ - 'in': { - 'stacked': True, - 'queries': { - 'in': { - 'filters': { - '_measurement': 'net', - '_field': [ - 'bytes_recv', - ], - }, - 'function': 'derivative', - }, - }, - 'unit': 'decbytes', - 'display_name': '__field.labels.interface' - }, - 'out': { - 'stacked': True, - 'queries': { - 'out': { - 'filters': { - '_measurement': 'net', - '_field': [ - 'bytes_sent', - ], - }, - 'function': 'derivative', - }, - }, - 'unit': 'decbytes', - 'display_name': '__field.labels.interface' - }, -} diff --git a/data/network.py b/data/network.py deleted file mode 100644 index 2e3a6e8..0000000 --- a/data/network.py +++ /dev/null @@ -1,19 +0,0 @@ -{ - 'networks': [ - '10.0.0.0/24', - '10.0.2.0/24', - '10.0.9.0/24', - '10.0.10.0/24', - ], - 'routers': { - '10.0.0.1': { - '10.0.0.0/24': None, - '10.0.0.2/24': None, - '10.0.0.9/24': None, - }, - '10.0.0.2': { - '10.0.0.0/24': 'internal', - '10.0.10.0/24': 'wg0', - }, - }, -} diff --git a/groups/all.py b/groups/all.py index 294c47c..679d8db 100644 --- a/groups/all.py +++ b/groups/all.py @@ -1,13 +1,12 @@ { 'bundles': [ 'users', - 'zsh', + 'backup', ], 'metadata': { - 'dns': {}, - 'nameservers': [ - '10.0.10.2', - ], + 'backup': { + 'server': 'home.backups', + }, 'users': { 'root': { 'shell': '/usr/bin/zsh', diff --git a/groups/applications/archive.py b/groups/applications/archive.py deleted file mode 100644 index 237d004..0000000 --- a/groups/applications/archive.py +++ /dev/null @@ -1,10 +0,0 @@ -{ - 'supergroups': [ - 'gcloud', - ], - 'bundles': [ - 'archive', - 'gocryptfs', - 'gocryptfs-inspect', - ], -} diff --git a/groups/applications/backup-server.py b/groups/applications/backup-server.py deleted file mode 100644 index 1dd9a2f..0000000 --- a/groups/applications/backup-server.py +++ /dev/null @@ -1,6 +0,0 @@ -{ - 'bundles': [ - 'backup-server', - 'zfs', - ], -} diff --git a/groups/applications/backup.py b/groups/applications/backup.py deleted file mode 100644 index 369925e..0000000 --- a/groups/applications/backup.py +++ /dev/null @@ -1,10 +0,0 @@ -{ - 'bundles': [ - 'backup', - ], - 'metadata': { - 'backup': { - 'server': 'home.backups', - }, - } -} diff --git a/groups/applications/dnsserver.py b/groups/applications/dnsserver.py deleted file mode 100644 index 68c889c..0000000 --- a/groups/applications/dnsserver.py +++ /dev/null @@ -1,5 +0,0 @@ -{ - 'bundles': [ - 'bind', - ], -} diff --git a/groups/applications/gcloud.py b/groups/applications/gcloud.py deleted file mode 100644 index 33f29af..0000000 --- a/groups/applications/gcloud.py +++ /dev/null @@ -1,12 +0,0 @@ -{ - 'bundles': [ - 'gcloud', - ], - 'metadata': { - 'gcloud': { - 'service_account': 'backup', - 'bucket': 'sublimity-backup', - 'project': 'sublimity-182017', - }, - }, -} diff --git a/groups/applications/mailserver.py b/groups/applications/mailserver.py deleted file mode 100644 index c154897..0000000 --- a/groups/applications/mailserver.py +++ /dev/null @@ -1,14 +0,0 @@ -{ - 'bundles': [ - 'opendkim', - 'dovecot', - 'letsencrypt', - 'mailserver', - 'php', - 'postfix', - 'postgresql', - 'redis', - 'roundcube', - 'rspamd', - ], -} diff --git a/groups/applications/monitored.py b/groups/applications/monitored.py deleted file mode 100644 index ccf4ee8..0000000 --- a/groups/applications/monitored.py +++ /dev/null @@ -1,10 +0,0 @@ -{ - 'bundles': [ - 'telegraf', - ], - 'metadata': { - 'telegraf': { - 'influxdb_node': 'home.server', - }, - }, -} diff --git a/groups/applications/nextcloud.py b/groups/applications/nextcloud.py deleted file mode 100644 index 626a331..0000000 --- a/groups/applications/nextcloud.py +++ /dev/null @@ -1,6 +0,0 @@ -{ - 'bundles': [ - 'nextcloud', - 'php', - ], -} diff --git a/groups/applications/webserver.py b/groups/applications/webserver.py deleted file mode 100644 index 70fb0e8..0000000 --- a/groups/applications/webserver.py +++ /dev/null @@ -1,6 +0,0 @@ -{ - 'bundles': [ - 'nginx', - 'letsencrypt', - ], -} diff --git a/groups/hardware/hetzner-cloud.py b/groups/hardware/hetzner-cloud.py deleted file mode 100644 index eb1d2a4..0000000 --- a/groups/hardware/hetzner-cloud.py +++ /dev/null @@ -1,5 +0,0 @@ -{ - 'bundles': [ - 'hetzner-cloud', - ], -} diff --git a/groups/os/debian-10.py b/groups/os/debian-10.py deleted file mode 100644 index 6f72004..0000000 --- a/groups/os/debian-10.py +++ /dev/null @@ -1,20 +0,0 @@ -{ - 'supergroups': [ - 'debian', - ], - 'metadata': { - 'apt': { - 'sources': [ - 'deb http://security.debian.org/debian-security {release}/updates main contrib non-free', - ], - }, - 'php': { - 'version': '7.3', - }, - 'postgresql': { - 'version': '11', - }, - 'os_release': 'buster', - }, - 'os_version': (10,), -} diff --git a/groups/os/debian-11.py b/groups/os/debian-11.py deleted file mode 100644 index 731b69c..0000000 --- a/groups/os/debian-11.py +++ /dev/null @@ -1,20 +0,0 @@ -{ - 'supergroups': [ - 'debian', - ], - 'metadata': { - 'apt': { - 'sources': [ - 'deb http://security.debian.org/ {release}-security main contrib non-free', - ], - }, - 'php': { - 'version': '7.4', - }, - 'postgresql': { - 'version': '13', - }, - 'os_release': 'bullseye', - }, - 'os_version': (11,), -} diff --git a/groups/os/debian.py b/groups/os/debian.py deleted file mode 100644 index 7f80d9f..0000000 --- a/groups/os/debian.py +++ /dev/null @@ -1,22 +0,0 @@ -{ - 'supergroups': [ - 'linux', - ], - 'bundles': [ - 'apt', - ], - 'metadata': { - 'apt': { - 'sources': [ - 'deb http://deb.debian.org/debian {release} main non-free contrib', - 'deb http://deb.debian.org/debian {release}-updates main contrib non-free', - 'deb http://deb.debian.org/debian {release}-backports main contrib non-free', - ], - 'packages': { - 'mtr-tiny': {}, - }, - }, - }, - 'os': 'debian', - 'pip_command': 'pip3', -} diff --git a/groups/os/linux.py b/groups/os/linux.py deleted file mode 100644 index b632300..0000000 --- a/groups/os/linux.py +++ /dev/null @@ -1,11 +0,0 @@ -{ - 'supergroups': [ - 'all', - ], - 'bundles': [ - 'network', - 'systemd', - 'systemd-networkd', - 'systemd-timers', - ], -} diff --git a/libs/apt.py b/libs/apt.py deleted file mode 100644 index 0798c41..0000000 --- a/libs/apt.py +++ /dev/null @@ -1,70 +0,0 @@ -# https://manpages.debian.org/jessie/apt/sources.list.5.de.html -from urllib.parse import urlparse -from re import search, sub -from functools import total_ordering - - -@total_ordering -class AptSource(): - def __init__(self, string): - if search(r'\[.*\]', string): - self.options = { - k:v.split(',') for k,v in ( - e.split('=') for e in search(r'\[(.*)\]', string)[1].split() - ) - } - else: - self.options = {} - - parts = sub(r'\[.*\]', '', string).split() - self.type = parts[0] - self.url = urlparse(parts[1]) - self.suite = parts[2] - self.components = parts[3:] - - def __str__(self): - parts = [ - self.type, - self.url.geturl(), - self.suite, - ' '.join(self.components), - ] - - if self.options: - parts.insert( - 1, - "[{}]".format( - ' '.join( - '{}={}'.format( - k, - ','.join(v) - ) for k,v in self.options.items() - ) - ) - ) - - return ' '.join(parts) - - - def __eq__(self, other): - return str(self) == str(other) - - def __lt__(self, other): - return str(self) < str(other) - - def __hash__(self): - return hash(str(self)) - - def __repr__(self): - return f"{type(self).__name__}('{str(self)}')" - - -# source = AptSource('deb [arch=amd64 trusted=true] http://deb.debian.org/debian buster-backports main contrib non-free') -# print(repr(source)) -# print(source.type) -# print(source.options) -# source.options['test'] = ['was', 'ist', 'das'] -# print(source.url) -# print(source.suite) -# print(source.components) -# print(str(source)) diff --git a/libs/derive_string.py b/libs/derive_string.py deleted file mode 100644 index 828103c..0000000 --- a/libs/derive_string.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -from hashlib import sha3_256 -from itertools import count, islice -from Crypto.Cipher import ChaCha20 -from math import floor, ceil -from time import sleep -from os import environ -from sys import stderr - -def debug(*args): - if 'DEBUG' in environ: - print(*args, file=stderr) - -def chacha_bits(input, bit_count): - zerobyte = (0).to_bytes(length=1, byteorder='big') - cipher = ChaCha20.new(key=sha3_256(input).digest(), nonce=zerobyte*8) - i = 0 - - while True: - debug(f'--- BITS {i} ---') - start_bit = bit_count * i - start_byte = start_bit // 8 - start_padding = start_bit % 8 - debug('start_bit', start_bit) - debug('start_byte', start_byte) - debug('start_padding', start_padding) - - end_bit = bit_count * i + bit_count - end_byte = end_bit // 8 - end_padding = 8 - (end_bit % 8) - debug('end_bit', end_bit) - debug('end_byte', end_byte) - debug('end_padding', end_padding) - - byte_count = (end_byte - start_byte) + 1 - debug('byte_count', byte_count) - - cipher.seek(start_byte) - cipherint = int.from_bytes(cipher.encrypt(zerobyte*byte_count), byteorder='big') - debug('ciphertext', bin(cipherint)) - shifted_cipherint = cipherint >> end_padding - debug('shifted_ciphertext', bin(shifted_cipherint)) - - bit_mask = int('1'*bit_count, 2) - debug('bit_mask', bin(bit_mask)) - masked_cipherint = shifted_cipherint & bit_mask - debug('masked_ciphertext', bin(masked_cipherint)) - - debug('') - yield masked_cipherint - i += 1 - - -def chacha_chracter(input, choices): - get_bits = chacha_bits(input, len(choices).bit_length()) - - while True: - key = next(get_bits) - if key < len(choices): - yield choices[key] - - -def derive_string(input, length, choices): - sorted_choices = bytes(sorted(choices)) - get_character = chacha_chracter(input, sorted_choices) - return bytes(islice(get_character, length)) - -# print( -# derive_string(b'12344', length=100, choices=b'abcdefghijklmnopqrstuvwxyz0123456789') -# ) diff --git a/libs/dns.py b/libs/dns.py deleted file mode 100644 index 7af9cf3..0000000 --- a/libs/dns.py +++ /dev/null @@ -1,15 +0,0 @@ -from ipaddress import ip_interface - -def get_a_records(metadata): - return { - 'A': [ - str(ip_interface(network['ipv4']).ip) - for network in metadata.get('network').values() - if 'ipv4' in network - ], - 'AAAA': [ - str(ip_interface(network['ipv6']).ip) - for network in metadata.get('network').values() - if 'ipv6' in network - ], - } diff --git a/libs/grafana.py b/libs/grafana.py deleted file mode 100644 index 73dc1ec..0000000 --- a/libs/grafana.py +++ /dev/null @@ -1,29 +0,0 @@ -from mako.template import Template -from copy import deepcopy - - -def generate_flux(bucket, host, field, data): - return Template(flux_template).render( - bucket=bucket, - host=host, - field=field, - data=data - ).strip() - - -def generate_panel(bucket, host, title, targets, min=None, max=None): - panel = deepcopy(panel_template) - panel['title'] = title - - if min: - panel['fieldConfig']['defaults']['min'] = min - if max: - panel['fieldConfig']['defaults']['max'] = max - - panel['targets'] = [ - { - 'hide': False, - 'refId': field, - 'query': generate_flux(bucket, host, field, data), - } for field, data in targets.items() - ] diff --git a/libs/ini.py b/libs/ini.py deleted file mode 100644 index 792e52b..0000000 --- a/libs/ini.py +++ /dev/null @@ -1,24 +0,0 @@ -from configparser import ConfigParser - -def parse(text): - config = ConfigParser() - config.read_string(text) - - return { - section: dict(config.items(section)) - for section in config.sections() - } - -class Writable(): - data = '' - - def write(self, line): - self.data += line - -def dumps(dict): - config = ConfigParser() - config.read_dict(dict) - writable = Writable() - config.write(writable) - - return writable.data diff --git a/libs/keys.py b/libs/keys.py deleted file mode 100644 index 427a85f..0000000 --- a/libs/keys.py +++ /dev/null @@ -1,15 +0,0 @@ -import base64 -from nacl.public import PrivateKey -from nacl.encoding import Base64Encoder -from bundlewrap.utils import Fault - -def gen_privkey(repo, identifier): - return repo.vault.random_bytes_as_base64_for(identifier) - -def get_pubkey_from_privkey(identifier, privkey): - # FIXME this assumes the privkey is always a base64 encoded string - def derive_pubkey(): - pub_key = PrivateKey(base64.b64decode(str(privkey))).public_key - return pub_key.encode(encoder=Base64Encoder).decode('ascii') - - return Fault(f'pubkey from privkey {identifier}', derive_pubkey) diff --git a/libs/nextcloud.py b/libs/nextcloud.py deleted file mode 100644 index 78e4086..0000000 --- a/libs/nextcloud.py +++ /dev/null @@ -1,2 +0,0 @@ -def occ(command, *args, **kwargs): - return f"""sudo -u www-data php /opt/nextcloud/occ {command} {' '.join(args)} {' '.join(f'--{name.replace("_", "-")}' + (f'={value}' if value else '') for name, value in kwargs.items())}""" diff --git a/libs/nginx.py b/libs/nginx.py deleted file mode 100644 index dc83e25..0000000 --- a/libs/nginx.py +++ /dev/null @@ -1,27 +0,0 @@ -def render_config(config): - return '\n'.join(render_lines(config)) - -def render_lines(config, indent=0): - lines = [] - blocks = [] - - for key, value in sorted(config.items()): - if isinstance(value, dict): - blocks.extend([ - '', - key+' {', - *render_lines(value, indent=4), - '}', - ]) - elif isinstance(value, list): - lines.extend([ - f'{key} {_value};' for _value in value - ]) - else: - lines.append( - f'{key} {value};' - ) - - return [ - f"{' '*indent}{line}" for line in lines+blocks - ] diff --git a/libs/systemd.py b/libs/systemd.py deleted file mode 100644 index b52bb88..0000000 --- a/libs/systemd.py +++ /dev/null @@ -1,27 +0,0 @@ -from mako.template import Template - -template = ''' -% for segment, options in data.items(): - -% if '#' in segment: -# ${segment.split('#', 2)[1]} -% endif -[${segment.split('#')[0]}] -% for option, value in options.items(): -% if isinstance(value, dict): -% for k, v in value.items(): -${option}=${k}=${v} -% endfor -% elif isinstance(value, (list, set, tuple)): -% for item in sorted(value): -${option}=${item} -% endfor -% else: -${option}=${str(value)} -% endif -% endfor -% endfor -''' - -def generate_unitfile(data): - return Template(template).render(data=data).lstrip() diff --git a/libs/tools.py b/libs/tools.py deleted file mode 100644 index d96feec..0000000 --- a/libs/tools.py +++ /dev/null @@ -1,88 +0,0 @@ -from ipaddress import ip_address, ip_network, IPv4Address, IPv4Network - -from bundlewrap.exceptions import NoSuchGroup, NoSuchNode, BundleError -from bundlewrap.utils.text import bold, red -from bundlewrap.utils.ui import io - -def resolve_identifier(repo, identifier): - """ - Try to resolve an identifier (group or node). Return a set of ip - addresses valid for this identifier. - """ - try: - nodes = {repo.get_node(identifier)} - except NoSuchNode: - try: - nodes = repo.nodes_in_group(identifier) - except NoSuchGroup: - try: - ip = ip_network(identifier) - - if isinstance(ip, IPv4Network): - return {'ipv4': {ip}, 'ipv6': set()} - else: - return {'ipv4': set(), 'ipv6': {ip}} - except Exception as e: - io.stderr('{x} {t} Exception while resolving "{i}": {e}'.format( - x=red('✘'), - t=bold('libs.tools.resolve_identifier'), - i=identifier, - e=str(e), - )) - raise - - found_ips = set() - for node in nodes: - for interface, config in node.metadata.get('interfaces', {}).items(): - for ip in config.get('ips', set()): - if '/' in ip: - found_ips.add(ip_address(ip.split('/')[0])) - else: - found_ips.add(ip_address(ip)) - - if node.metadata.get('external_ipv4', None): - found_ips.add(ip_address(node.metadata.get('external_ipv4'))) - - ip_dict = { - 'ipv4': set(), - 'ipv6': set(), - } - - for ip in found_ips: - if isinstance(ip, IPv4Address): - ip_dict['ipv4'].add(ip) - else: - ip_dict['ipv6'].add(ip) - - return ip_dict - - -def remove_more_specific_subnets(input_subnets) -> list: - final_subnets = [] - - for subnet in sorted(input_subnets): - source = ip_network(subnet) - - if not source in final_subnets: - subnet_found = False - - for dest_subnet in final_subnets: - if source.subnet_of(dest_subnet): - subnet_found = True - - if not subnet_found: - final_subnets.append(source) - - out = [] - for net in final_subnets: - out.append(str(net)) - - return out - - -def require_bundle(node, bundle, hint=''): - # It's considered bad style to use assert statements outside of tests. - # That's why this little helper function exists, so we have an easy - # way of defining bundle requirements in other bundles. - if not node.has_bundle(bundle): - raise BundleError(f'{node.name} requires bundle {bundle}, but wasn\'t found! {hint}') diff --git a/nodes/home.backups.py b/nodes/home.backups.py index 3e5c9df..889e250 100644 --- a/nodes/home.backups.py +++ b/nodes/home.backups.py @@ -1,35 +1,15 @@ { 'hostname': '10.0.0.5', - 'groups': [ - 'debian-10', - 'backup-server', - 'monitored', - ], 'bundles': [ - 'zfs', + 'backup-server', + ], + 'groups': [ + 'all', ], 'metadata': { 'id': '9cf52515-63a1-4659-a8ec-6c3c881727e5', 'backup-server': { 'hostname': 'backups.sublimity.de', }, - 'network': { - 'internal': { - 'interface': 'enp1s0', - 'ipv4': '10.0.0.5/24', - 'gateway4': '10.0.0.1', - }, - }, - 'zfs': { - 'pools': { - 'tank': { - 'raidz': [ - '/dev/disk/by-id/ata-HGST_HDN726040ALE614_K3GV6TPL', - '/dev/disk/by-id/ata-HGST_HDN726040ALE614_K4KAJXEB', - '/dev/disk/by-id/ata-TOSHIBA_HDWQ140_19VZK0EMFAYG', - ], - }, - }, - }, }, } diff --git a/nodes/home.server.py b/nodes/home.server.py index 375ad72..03dd064 100644 --- a/nodes/home.server.py +++ b/nodes/home.server.py @@ -1,85 +1,9 @@ { 'hostname': '10.0.0.2', 'groups': [ - 'archive', - 'backup', - 'debian-10', -# 'nextcloud', - 'monitored', - ], - 'bundles': [ - 'gitea', - 'grafana', - 'influxdb2', - 'mirror', - 'postgresql', - 'redis', - 'wireguard', - 'zfs', + 'all', ], 'metadata': { 'id': 'af96709e-b13f-4965-a588-ef2cd476437a', - 'mirror': { - 'certs': { - 'from': '10.0.10.2:/var/lib/dehydrated/certs', - 'to': '/var/lib/dehydrated/certs', - }, - }, - 'network': { - 'internal': { - 'interface': 'enp1s0f0', - 'ipv4': '10.0.0.2/24', - 'gateway4': '10.0.0.1', - }, - }, - 'gitea': { - 'version': '1.14.2', - 'sha256': '0d11d87ce60d5d98e22fc52f2c8c6ba2b54b14f9c26c767a46bf102c381ad128', - 'domain': 'git.sublimity.de', - }, - 'grafana': { - 'hostname': 'grafana.sublimity.de', - 'influxdb_node': 'home.server', - }, - 'influxdb': { - 'hostname': 'influxdb.sublimity.de', - 'admin_token': '!decrypt:encrypt$gAAAAABg3z5PcaLYmUpcElJ07s_G-iYwnS8d532TcR8xUYbZfttT-B736zgR6J726mzKAFNYlIfJ7amNLIzi2ETDH5TAXWsOiAKpX8WC_dPBAvG3uXGtcPYENjdeuvllSagZzPt0hCIZQZXg--Z_YvzaX9VzNrVAgGD-sXQnghN5_Vhf9gVxxwP---VB_6iNlsf61Nc4axoS', - 'readonly_token': '!decrypt:encrypt$gAAAAABg3z1-0hnUdzsfivocxhJm58YnPLn96OUvnHiPaehdRhKd6TZBgEPc5YyR07t2-GEUfOvEwoie-O6QsVhWYxrwxNTBXux_iUSx7W6e-fLQA_3MgWf5G97q_3kx_wCgQ6V0iKRyxH988TpNSMACfS4WhCXdSes1CaMpic4VV3S3ox_gCrSHxO7yVXQkJDnOW0MixY5T', - 'writeonly_token': '!decrypt:encrypt$gAAAAABg3z6fGrOy2tNdo03RoYAXmpJoJYkfhBfpblPh_wxYfqmdjtABaD7XyV9mSh9xl8oWQlTAtCk9KndVCDQy7BJ-ju7S3HCKJ0k244Y5YKxUnQtqt9fc9nnm8XD-NOJqLKyfy0QhL_I8dFT02pygoJeCUR5NkZcTKf6julb-iGXI6vWcQgolJTYrW643pHObd-Z-vIEl', - }, - 'nextcloud': { - 'hostname': 'cloud.sublimity.de', - 'version': '21.0.1', - }, - 'users': { - 'root': { - 'shell': '/usr/bin/zsh', - }, - }, - 'vm': { - 'cores': 2, - 'ram': 16192, - }, - 'wireguard': { - 'my_ip': '172.30.0.2/24', - 'peers': { - 'htz.mails': { - 'route': [ - '10.0.10.0/24', - '10.0.11.0/24', - ], - }, - }, - }, - 'zfs': { - 'pools': { - 'tank': { - 'mirrors': [ - '/dev/disk/by-partlabel/zfs-data-1', - '/dev/disk/by-partlabel/zfs-data-2', - ], - }, - }, - }, }, } diff --git a/nodes/htz.games.py b/nodes/htz.games.py index ad7c720..729d94a 100644 --- a/nodes/htz.games.py +++ b/nodes/htz.games.py @@ -1,12 +1,7 @@ { 'dummy': True, 'groups': [ - 'backup', - 'debian-10', - ], - 'bundles': [ - 'steam', - 'l4d2', + 'all', ], 'metadata': { 'id': '353bb086-f3ce-4f36-8533-e91786c91ed9', diff --git a/nodes/htz.mails.py b/nodes/htz.mails.py index e6ab74f..edf1d73 100644 --- a/nodes/htz.mails.py +++ b/nodes/htz.mails.py @@ -1,129 +1,9 @@ { 'hostname': '162.55.188.157', 'groups': [ - 'archive', - 'backup', - 'hetzner-cloud', - 'debian-10', - 'mailserver', - 'monitored', - 'webserver', - 'dnsserver', - ], - 'bundles': [ - 'nextcloud', - 'wireguard', - 'zfs', + 'all', ], 'metadata': { - 'systemd-timers': { - 'test1': { - 'when': 'weekly', - 'command': '/bin/ls', - }, - }, - 'nextcloud': { - 'hostname': 'cloud.sublimity.de', - 'version': '21.0.0', - }, 'id': 'ea29bdf0-0b47-4bf4-8346-67d60c9dc4ae', - 'bind': { - 'hostname': 'ns.sublimity.de', - 'zones': { - 'sublimity.de': [], - 'freibrief.net': [], - 'nadenau.net': [], - 'naeder.net': [], - 'rolfwerner.eu': [], - 'wettengl.net': [], - 'wingl.de': [], - 'woodpipe.de': [], - 'ckn.li': [], - 'islamicstate.eu': [], - }, - }, - 'dns': { - 'islamicstate.eu': { - 'A': ['1.2.3.4'], - }, - 'test.islamicstate.eu': { - 'AAAA': ['::1337'], - }, - }, - 'network': { - 'internal': { - 'interface': 'ens10', - 'ipv4': '10.0.10.2/24', - }, - 'external': { - 'interface': 'eth0', - 'ipv4': '162.55.188.157/32', - 'ipv6': '2a01:4f8:1c1c:4121::2/64', - 'gateway4': '172.31.1.1', - 'gateway6': 'fe80::1', - } - }, - 'mailserver': { - 'hostname': 'mail.sublimity.de', - 'admin_email': 'postmaster@sublimity.de', - 'domains': [ - 'mail3.sublimity.de', - 'islamicstate.eu', - # 'sublimity.de', - # 'freibrief.net', - # 'nadenau.net', - # 'naeder.net', - # 'rolfwerner.eu', - # 'wettengl.net', - # 'wingl.de', - # 'woodpipe.de', - ], - }, - 'roundcube': { - 'product_name': 'Sublimity Mail', - 'version': '1.4.11', - 'installer': True, - }, - 'users': { - 'root': { - 'authorized_users': [ - 'root@home.server', - ], - }, - }, - 'vm': { - 'cores': 2, - 'ram': 8096, - }, - 'wireguard': { - # ip r add 10.0.0.0/24 via 172.19.136.2 dev wg0 - 'my_ip': '172.30.0.1/24', - 'peers': { - 'home.server': { - 'route': [ - '10.0.0.0/24', - '10.0.2.0/24', - '10.0.9.0/24', - ], - }, - 'netcup.secondary': { - 'route': [ - '10.0.11.0/24', - ], - }, - }, - }, - 'zfs': { - 'pools': { - 'tank': { - 'device': '/dev/disk/by-id/scsi-0HC_Volume_11764264', - }, - }, - }, - 'archive': { - 'paths': { - '/var/test': {}, - }, - }, }, } diff --git a/nodes/netcup.secondary.py b/nodes/netcup.secondary.py index ff520e6..c0141c4 100644 --- a/nodes/netcup.secondary.py +++ b/nodes/netcup.secondary.py @@ -1,38 +1,9 @@ { 'hostname': '46.38.240.85', 'groups': [ - 'debian-10', - ], - 'bundles': [ - 'wireguard', + 'all', ], 'metadata': { 'id': '890848b2-a900-4f74-ad5b-b811fbb4f0bc', - 'network': { - 'external': { - 'interface': 'eth0', - 'ipv4': '46.38.240.85/22', - 'gateway4': '46.38.240.1', - 'ipv6': '2a03:4000:7:534::2/64', - 'gateway6': 'fe80::1', - }, - 'internal': { - 'interface': 'eth1', - 'ipv4': '10.0.11.2', - }, - }, - 'wireguard': { - 'my_ip': '172.30.0.3/24', - 'peers': { - 'htz.mails': { - 'route': [ - '10.0.0.0/24', - '10.0.2.0/24', - '10.0.9.0/24', - '10.0.10.0/24', - ], - }, - }, - }, }, }