games/valheim: init

This creates a valheim game server, using a public image but slightly
nerfing it to be able to run it unprivileged.

We also deploy our first server. The password is Well Known To Those
Versed In Hackerspace Lore.

Change-Id: Ic24262a3b02d3c17d2f00aa2967e240ea4eee7fb
This commit is contained in:
q3k 2021-02-23 23:03:31 +00:00 committed by q3k
parent c97461e844
commit 34d39cc8ed
4 changed files with 218 additions and 0 deletions

10
games/valheim/README.md Normal file
View file

@ -0,0 +1,10 @@
Valheim
=======
This is our (tiny) Valheim game server infrastructure. We run it on prod on k0, using an existing Docker image.
Updating
--------
kubecfg update prod.jsonnet

168
games/valheim/prod.jsonnet Normal file
View file

@ -0,0 +1,168 @@
local kube = import "../../kube/kube.libsonnet";
{
local top = self,
env(ns, name):: {
local env = self,
local cfg = env.cfg,
cfg:: {
name: name,
displayName: name,
image: "mbround18/valheim:latest",
password: error "password must be set",
storageClassName: "waw-hdd-redundant-3",
port: 2456,
},
local named = function(component) "%s-%s" % [name, component],
game: {
local game = self,
pvcs: {
backups: ns.Contain(kube.PersistentVolumeClaim(named("backups"))) {
spec+: {
storageClassName: cfg.storageClassName,
accessModes: ["ReadWriteOnce"],
resources: {
requests: { storage: "10Gi" },
},
},
},
saves: ns.Contain(kube.PersistentVolumeClaim(named("saves"))) {
spec+: {
storageClassName: cfg.storageClassName,
accessModes: ["ReadWriteOnce"],
resources: {
requests: { storage: "10Gi" },
},
},
},
server: ns.Contain(kube.PersistentVolumeClaim(named("server"))) {
spec+: {
storageClassName: cfg.storageClassName,
accessModes: ["ReadWriteOnce"],
resources: {
requests: { storage: "10Gi" },
},
},
},
},
svc: ns.Contain(kube.Service(named("external"))) {
target_pod:: game.deployment.spec.template,
spec+: {
ports: kube.mapToNamedList({
zero: { port: cfg.port, targetPort: cfg.port, protocol: "UDP" },
one: { port: cfg.port+1, targetPort: cfg.port+1, protocol: "UDP" },
two: { port: cfg.port+2, targetPort: cfg.port+2, protocol: "UDP" },
}),
type: "LoadBalancer",
},
},
scripts: ns.Contain(kube.ConfigMap(named("scripts"))) {
data: {
# Based on https://github.com/mbround18/valheim-docker ,
# removed all reliance on running as root (thus removed
# autoupdater/autobackups).
"entrypoint.sh": |||
#!/usr/bin/env bash
log() {
PREFIX="[entrypoint]"
printf "%-16s: %s\n" "${PREFIX}" "$1"
}
line() {
log "==========================================================================="
}
setup_filesystem() {
log "Setting up file systems"
mkdir -p /home/steam/valheim
mkdir -p /home/steam/valheim/logs
mkdir -p /home/steam/backups
mkdir -p /home/steam/scripts
mkdir -p /home/steam/valheim
cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim
}
line
log "Valheim Server - $(date)"
log "Initializing your container..."
line
setup_filesystem
log "Launching the rest of the fucking owl"
cd /home/steam/valheim || exit 1
exec "$@"
|||
},
},
secret: ns.Contain(kube.Secret(named("game"))) {
data_: {
# public game password
public: cfg.password,
},
},
deployment: ns.Contain(kube.Deployment(named("game"))) {
spec+: {
template+: {
spec+: {
containers_: {
default: kube.Container("default") {
image: cfg.image,
command: [
"/bin/bash", "/scripts/entrypoint.sh", "/home/steam/scripts/start_valheim.sh",
],
volumeMounts_: {
backups: { mountPath: "/home/steam/backups" },
saves: { mountPath: "/home/steam/.config/unity3d/IronGate/Valheim" },
server: { mountPath: "/home/steam/valheim" },
scripts: { mountPath: "/scripts" },
},
ports_: {
zero: { containerPort: cfg.port },
one: { containerPort: cfg.port + 1 },
two: { containerPort: cfg.port + 2 },
},
env_: {
PUBLIC: "1",
PASSWORD: kube.SecretKeyRef(game.secret, "public"),
NAME: cfg.displayName,
},
resources: {
requests: {
cpu: "500m",
memory: "2Gi",
},
limits: {
cpu: "1000m",
memory: "4Gi",
},
},
},
},
securityContext: {
runAsUser: 1000,
runAsGroup: 1000,
fsGroup: 1000,
},
volumes_: {
backups: kube.PersistentVolumeClaimVolume(game.pvcs.backups),
saves: kube.PersistentVolumeClaimVolume(game.pvcs.saves),
server: kube.PersistentVolumeClaimVolume(game.pvcs.server),
scripts: kube.ConfigMapVolume(game.scripts),
},
},
},
},
},
},
},
ns: kube.Namespace("valheim") {
},
q3k: top.env(top.ns, "q3k") {
cfg+: {
ns: "valheim",
password: (std.split(importstr "secrets/plain/q3k-public", "\n"))[0],
displayName: "wypierdol z polski xD",
},
},
}

View file

@ -0,0 +1,39 @@
-----BEGIN PGP MESSAGE-----
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
=YmoD
-----END PGP MESSAGE-----

View file

@ -0,0 +1 @@
*