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
diff --git a/games/valheim/README.md b/games/valheim/README.md
new file mode 100644
index 0000000..cf02ce5
--- /dev/null
+++ b/games/valheim/README.md
@@ -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
+
diff --git a/games/valheim/prod.jsonnet b/games/valheim/prod.jsonnet
new file mode 100644
index 0000000..6c10b8b
--- /dev/null
+++ b/games/valheim/prod.jsonnet
@@ -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",
+ },
+ },
+}
diff --git a/games/valheim/secrets/cipher/q3k-public b/games/valheim/secrets/cipher/q3k-public
new file mode 100644
index 0000000..b95f2a8
--- /dev/null
+++ b/games/valheim/secrets/cipher/q3k-public
@@ -0,0 +1,39 @@
+-----BEGIN PGP MESSAGE-----
+
+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
+=YmoD
+-----END PGP MESSAGE-----
diff --git a/games/valheim/secrets/plain/.gitignore b/games/valheim/secrets/plain/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/games/valheim/secrets/plain/.gitignore
@@ -0,0 +1 @@
+*