left4dead

This commit is contained in:
cronekorkn 2022-10-06 14:42:52 +02:00
parent afe04ae6c8
commit 6b0e92447a
Signed by: cronekorkn
SSH key fingerprint: SHA256:v0410ZKfuO1QHdgKBsdQNF64xmTxOF8osF1LIqwTcVw
10 changed files with 164 additions and 140 deletions

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

@ -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

@ -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

@ -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': {},