Compare commits

...

7 commits

Author SHA1 Message Date
6b0e92447a
left4dead 2022-10-06 14:42:52 +02:00
afe04ae6c8 Merge pull request 'temp130752653' (#6) from temp130752653 into master
Reviewed-on: #6
2022-10-06 14:35:57 +02:00
5bae9ea885
doesnt exist!? 2022-10-06 14:34:51 +02:00
4035ec7fac
bw worker defaults 2022-10-06 14:34:21 +02:00
addbae4b1d
start nginx when network is online 2022-10-06 14:34:21 +02:00
8669124c73
backup timers after online 2022-10-06 14:34:21 +02:00
05eecb72e2
enrv bw workers 2022-10-06 14:34:21 +02:00
16 changed files with 221 additions and 141 deletions

4
.envrc
View file

@ -8,6 +8,8 @@ python3 -m pip install --upgrade pip
rm -rf .cache/bw/git_deploy
export BW_GIT_DEPLOY_CACHE=.cache/bw/git_deploy
export EXPERIMENTAL_UPLOAD_VIA_CAT=1
mkdir -p "$BW_GIT_DEPLOY_CACHE"
export EXPERIMENTAL_UPLOAD_VIA_CAT=1
export BW_ITEM_WORKERS=16
export BW_NODE_WORKERS=32
unset PS1

View file

@ -22,6 +22,9 @@ defaults = {
'command': '/opt/backup/backup_all',
'when': '1:00',
'persistent': True,
'after': {
'network-online.target',
},
},
},
}

View file

@ -0,0 +1,38 @@
hostname "CroneKorkN : ${name}"
sv_contact "admin@sublimity.de"
// assign serevr to steam group
sv_steamgroup "${','.join(steamgroups)}"
// no annoying message of the day
motd_enabled 0
// enable cheats
sv_cheats 1
// allow inconsistent files on clients (weapon mods for example)
sv_consistency 0
// connect from internet
sv_lan 0
// join game at any point
sv_allow_lobby_connect_only 0
// allowed modes
sv_gametypes "coop,realism,survival,versus,teamversus,scavenge,teamscavenge"
// network
sv_minrate 30000
sv_maxrate 60000
sv_mincmdrate 66
sv_maxcmdrate 101
// logging
sv_logsdir "logs-${name}" //Folder in the game directory where server logs will be stored.
log on //Creates a logfile (on | off)
sv_logecho 0 //default 0; Echo log information to the console.
sv_logfile 1 //default 1; Log server information in the log file.
sv_log_onefile 0 //default 0; Log server information to only one file.
sv_logbans 1 //default 0;Log server bans in the server logs.
sv_logflush 0 //default 0; Flush the log files to disk on each write (slow).

View file

@ -1,106 +1,71 @@
assert node.has_bundle('steam') and node.has_bundle('steam-workshop-download')
directories = {
'/opt/left4dead2': {
'/opt/steam/left4dead2/left4dead2/ems/admin system': {
'owner': 'steam',
'group': 'steam',
'mode': '0744',
},
'/opt/left4dead2/ems/admin system': {
'/opt/steam/left4dead2/left4dead2/cfg/server': {
'owner': 'steam',
'group': 'steam',
'purge': True,
},
'/opt/left4dead2/left4dead2/cfg': {
'owner': 'steam',
},
'/opt/left4dead2/left4dead2/addons': {
'/opt/steam/left4dead2/left4dead2/addons': {
'owner': 'steam',
'group': 'steam',
'purge': True,
},
}
files = {
'/opt/left4dead2/ems/admin system/admins.txt': {
'/opt/steam/left4dead2/left4dead2/ems/admin system/admins.txt': {
'owner': 'steam',
'content': '\n'.join(node.metadata.get('left4dead2/admins')),
'content': '\n'.join(sorted(node.metadata.get('left4dead2/admins'))),
}
}
svc_systemd = {
'left4dead2-workshop': {
'running': False,
'needs': [
'svc_systemd:steam-update',
],
},
}
for id in node.metadata.get('left4dead2/workshop'):
directories[f'/opt/left4dead2/left4dead2/addons/{id}'] = {
'owner': 'steam',
'triggers': [
'svc_systemd:left4dead2-workshop:restart',
],
}
server_units = set()
for name, config in node.metadata.get('left4dead2/servers').items():
config.pop('port')
config = {
'hostname': name,
'sv_steamgroup': ','.join(
str(gid) for gid in node.metadata.get('left4dead2/steamgroups')
),
'z_difficulty': 'Impossible',
'sv_gametypes': 'realism',
'sv_region': 3, # europe
'log': 'on',
'sv_logecho': 1,
'sv_logfile': 1,
'sv_log_onefile': 0,
'sv_logbans': 1,
'sv_logflush': 0,
'sv_logsdir': 'logs', # /opt/left4dead2/left4dead2/logs
**config,
}
files[f'/opt/left4dead2/left4dead2/cfg/server-{name}.cfg'] = {
'content': '\n'.join(
f'{key} "{value}"' for key, value in sorted(config.items())
) + '\n',
files[f'/opt/steam/left4dead2/left4dead2/cfg/server/{name}.cfg'] = {
'content_type': 'mako',
'source': 'server.cfg',
'context': {
'name': name,
'steamgroups': node.metadata.get('left4dead2/steamgroups'),
},
'owner': 'steam',
'group': 'steam',
'triggers': [
f'svc_systemd:left4dead2-server-{name}:restart',
f'svc_systemd:left4dead2-{name}.service:restart',
],
}
svc_systemd[f'left4dead2-server-{name}'] = {
svc_systemd[f'left4dead2-{name}.service'] = {
'needs': [
f'file:/usr/local/lib/systemd/system/left4dead2-server-{name}.service',
f'file:/opt/steam/left4dead2/left4dead2/cfg/server/{name}.cfg',
f'file:/usr/local/lib/systemd/system/left4dead2-{name}.service',
],
}
server_units.add(f'left4dead2-server-{name}')
files[f'/opt/steam/left4dead2/left4dead2/addons/readme.txt'] = {
'content_type': 'any',
'owner': 'steam',
'group': 'steam',
}
for id in node.metadata.get('left4dead2/workshop'):
directories[f'/opt/left4dead2/addons/{id}'] = {
files[f'/opt/steam/left4dead2/left4dead2/addons/{id}.vpk'] = {
'content_type': 'any',
'owner': 'steam',
'triggers': [
'svc_systemd:left4dead2-workshop:restart',
],
'group': 'steam',
}
# TIDYUP
find_obsolete_units = (
'find /usr/local/lib/systemd/system -type f -name "left4dead2-server-*.service" ' +
' '.join(f"! -name '{name}.service'" for name in server_units)
)
actions['remove_obsolete_left4dead2_units'] = {
'command': (
f'for unitfile in $({find_obsolete_units}); '
f'do '
f'systemctl stop $(basename "$unitfile"); '
f'systemctl disable $(basename "$unitfile"); '
f'rm "$unitfile"; '
f'systemctl daemon-reload; '
f'done'
),
'unless': (
find_obsolete_units + " | wc -l | grep -q '^0$'"
),
# /opt/steam/steam/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory
symlinks = {
'/opt/steam/steam/.steam/sdk32': {
'target': '/opt/steam/steam/linux32',
'owner': 'steam',
'group': 'steam',
}
}

View file

@ -17,43 +17,20 @@ defaults = {
@metadata_reactor.provides(
'systemd/units',
'steam-workshop-download/left4dead',
)
def workshop(metadata):
command = (
'set -x; '
'for ID in ' + ' '.join(metadata.get('left4dead2/workshop')) + '; '
'do '
'if ! ls /opt/left4dead2/left4dead2/addons/$ID/*.vpk; '
'then '
'cd /opt/left4dead2/left4dead2/addons/$ID; '
'/opt/steam-workshop-downloader https://steamcommunity.com/sharedfiles/filedetails\?id\=$ID; '
'unzip $ID.zip; '
'fi; '
'done'
)
def workshop_download(metadata):
if not metadata.get('left4dead2/workshop'):
return {}
return {
'systemd': {
'units': {
'left4dead2-workshop.service': {
'Unit': {
'Description': 'install workshop items',
'After': 'network.target',
'Requires': 'steam-update.service',
'PartOf': 'steam-update.service'
},
'Service': {
'Type': 'oneshot',
'User': 'steam',
'ExecStart': f'/bin/bash -c {quote(command)}',
},
'Install': {
'WantedBy': {'multi-user.target'},
},
}
}
}
'steam-workshop-download': {
'left4dead': {
'ids': metadata.get('left4dead2/workshop'),
'path': '/opt/steam/left4dead2/left4dead2/addons',
'user': 'steam',
},
},
}
@ -62,19 +39,18 @@ def workshop(metadata):
)
def server_units(metadata):
units = {}
for name, config in metadata.get('left4dead2/servers').items():
units[f'left4dead2-server-{name}.service'] = {
units[f'left4dead2-{name}.service'] = {
'Unit': {
'Description': f'left4dead2 server {name}',
'After': 'network.target',
'Requires': 'steam-update.service',
'After': {'steam.target'},
},
'Service': {
'User': 'steam',
'Group': 'steam',
'WorkingDirectory': '/opt/left4dead2',
'ExecStart': f'/opt/left4dead2/srcds_run -port {config["port"]} -insecure +map {config["map"]} +exec server-{name}.cfg',
'WorkingDirectory': '/opt/steam/left4dead2',
'ExecStart': f'/opt/steam/left4dead2/srcds_run -port {config["port"]} +exec server/{name}.cfg',
'Restart': 'on-failure',
},
'Install': {
@ -87,3 +63,19 @@ def server_units(metadata):
'units': units,
},
}
@metadata_reactor.provides(
'nftables/input',
)
def firewall(metadata):
ports = set(str(server['port']) for server in metadata.get('left4dead2/servers').values())
return {
'nftables': {
'input': {
f"tcp dport {{ {', '.join(ports)} }} accept",
f"udp dport {{ {', '.join(ports)} }} accept",
},
},
}

View file

@ -24,6 +24,15 @@ defaults = {
},
'includes': {},
},
'systemd': {
'units': {
'nginx.service.d/override.conf': {
'Unit': {
'After': {'network-online.target'},
},
},
},
},
}
@metadata_reactor.provides(

View file

@ -0,0 +1,7 @@
files = {
'/opt/steam-workshop-download': {
'content_type': 'download',
'source': 'https://git.sublimity.de/cronekorkn/steam-workshop-downloader/raw/branch/master/steam-workshop-download',
'mode': '755',
},
}

View file

@ -0,0 +1,39 @@
from shlex import quote
defaults = {
'steam-workshop-download': {},
}
@metadata_reactor.provides(
'systemd/units',
)
def workshop(metadata):
units = {}
for name, conf in metadata.get('steam-workshop-download').items():
units[f'steam-workshop-download-{name}.service'] = {
'Unit': {
'Description': 'install workshop items',
'After': {
'network-online.target',
'steam-update.target',
},
'Before': 'steam.target',
},
'Service': {
'Type': 'oneshot',
'User': conf['user'],
'ExecStart': f"/opt/steam-workshop-download {' '.join(quote(str(id)) for id in conf['ids'])} --out {quote(conf['path'])}",
},
'Install': {
'WantedBy': {'multi-user.target'},
},
}
return {
'systemd': {
'units': units,
},
}

View file

@ -22,7 +22,7 @@ for game in node.metadata.get('steam/games'):
'owner': 'steam',
'group': 'steam',
'needed_by': [
'svc_systemd:steam-update',
'svc_systemd:steam-update.service',
],
}
@ -33,22 +33,8 @@ files = {
'owner': 'steam',
'group': 'steam',
},
'/opt/steam/steam/workshop-downloader': {
'content_type': 'download',
'source': 'https://github.com/SegoCode/swd/releases/download/1.1/swd-linux-amd64',
'owner': 'steam',
'group': 'steam',
'mode': '750',
},
}
# symlinks = {
# # /opt/steam/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory
# '/opt/steam/.steam/sdk32': {
# 'target': '/opt/steam/linux32',
# }
# }
actions = {
'extract_steamcmd': {
'command': """su - steam -c 'tar xfvz /opt/steam/steam/steamcmd_linux.tar.gz --directory /opt/steam/steam'""",
@ -59,7 +45,7 @@ actions = {
},
}
svc_systemd['steam-update'] = {
svc_systemd['steam-update.service'] = {
'running': False,
'enabled': False,
'needs': {

View file

@ -10,6 +10,15 @@ defaults = {
'left4dead2': 222860,
},
},
'systemd': {
'units': {
'steam.target': {
'Unit': {
'Description': 'steam is ready',
},
},
},
},
'zfs': {
'datasets': {
'tank/steam': {
@ -31,7 +40,8 @@ def initial_unit(metadata):
'steam-update.service': {
'Unit': {
'Description': 'steam: install and update games',
'After': 'network.target',
'After': 'network-online.target',
'Before': 'steam.target',
},
'Service': {
'Type': 'oneshot',

View file

@ -16,6 +16,7 @@ def systemd(metadata):
f'{name}.timer': {
'Unit':{
'Description': f'{name} timer',
'After': config.get('after', set()),
},
'Timer': {
'OnCalendar': config['when'],

View file

@ -14,7 +14,7 @@ actions = {
'command': 'systemctl daemon-reload',
'cascade_skip': False,
'triggered': True,
},
},
}
for name, unit in node.metadata.get('systemd/units').items():
@ -30,7 +30,7 @@ for name, unit in node.metadata.get('systemd/units').items():
'svc_systemd:systemd-networkd:restart',
],
}
elif extension in ['timer', 'service', 'mount', 'swap']:
elif extension in ['timer', 'service', 'mount', 'swap', 'target']:
path = f'/usr/local/lib/systemd/system/{name}'
dependencies = {
'triggers': [

View file

@ -25,9 +25,6 @@ def units(metadata):
type = name.split('.')[-1]
if type not in ['timer', 'service', 'network', 'netdev', 'mount', 'swap']:
raise Exception(f'unknown type {type}')
if not config.get('Install/WantedBy'):
if type == 'service':
units[name] = {

View file

@ -4,6 +4,9 @@ defaults = {
'command': '/opt/zfs-mirror',
'when': '2:00',
'persistent': True,
'after': {
'network-online.target',
},
},
},
}

View file

@ -0,0 +1,7 @@
{
'bundles': [
'steam',
'steam-workshop-download',
'left4dead2',
],
}

View file

@ -7,6 +7,7 @@
'monitored',
'webserver',
'dnsserver',
'left4dead2',
],
'bundles': [
'bind-acme',
@ -68,6 +69,26 @@
'download-server': {
'hostname': 'dl.sublimity.de',
},
'left4dead2': {
'servers': {
'standard': {
'port': 27020,
},
},
'admins': {
'STEAM_1:0:12376499', # CroneKorkN ☮UKRAINE❤
'STEAM_1:1:169960486', # *RED*
'STEAM_1:1:112940736', # Ðark-AnGe
'STEAM_1:1:34263261', # Alekc
'STEAM_1:1:79349632', # VOID
},
'workshop': {
214630948,
1229957234,
698857882,
},
'steamgroups': {'103582791467869287'},
},
'letsencrypt': {
'domains': {
'ckn.li': {},