...
Anton Krinner

How to Setup a Secure Quake III Game Server Which One Can Play On in Your Browser

August 8, 2023
Assorted computer parts symbolizing the technical components involved in setting up a Quake III game server on Kubernetes and DigitalOcean.

In this article, you will learn how to quickly setup a secure Quake III server and client. The emphasis here is on secure i.e. this can be done with https. I wrote another article for setting up the server and client where the connection is also secure but where the costs for running it are even cheaper since it does not rely on a Load Balancer.

Quake III, the legendary first-person shooter from 1999, continues to captivate gamers worldwide. Its open-source release in 2005 sparked various enhancements, and among them is QuakeKube. This adaptation harnesses Kubernetes, allowing players to relive Quake III's action-packed arenas right from their browsers. The creators of QuakeKube have packaged everything you need to play in a Kubernetes cluster, making the setup process straightforward.

A little detour on the technical part. QuakeKube basically runs a dedicated quake server from the ioquake3 project which has been written in C and C++ which communicates with the Java Script web client (taken from QuakeJS) via a proxy. This works smoother than the QuakeJS server because it runs in its original programming language. It also allows both browser-based and real-client gaming. I will create another article in the future to explain how both, browser and real-client users can join the same game. Besides QuakeJS, there exist other ports to run the game in the browser like e.g. ioquake3.js, Quake3 and planet_quake.

Prerequisites:

Step-by-Step Guide:

1. Connect to Your Droplet

Option 1: SSH

Use SSH to access your DigitalOcean droplet:

ssh -i /path/to/your/private/key root@<droplet-ip-address>

Replace /path/to/your/private/key with your private key file path and <droplet-ip-address> with your droplet's IP.

Option 2: DigitalOcean Console

Alternatively, utilize the built-in console by DigitalOcean. Head to the “Droplets” section in your DigitalOcean dashboard, select the droplet you wish to access, and click on “Console”.

2. Install cert-manager

Cert-manager is a Kubernetes add-on to automate the management and issuance of TLS certificates from various issuing sources. We'll use it to secure our Quake server. Install cert-manager by running:

k0s kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml

3. Deploy the Quake Server

Use the following manifest to deploy the Quake servers. This manifest should be in a YAML file. You can create this file by typing nano quake-manifest.yaml and copying and pasting the manifest into the file. Please note, that it is essential to change all the passwords provided in the Quake III Arena server configuration files to ensure security. Close and save with CTRL and X, confirming with a Y.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: quake
spec:
  selector:
    matchLabels:
      run: quake
  replicas: 1
  template:
    metadata:
      labels:
        run: quake
      annotations:
        prometheus.io/scrape: 'true'
        prometheus.io/port: '8080'
    spec:
      containers:
      - command:
        - q3
        - server
        - --config=/config/config.yaml
        - --content-server=http://127.0.0.1:9090
        - --agree-eula
        image: docker.io/criticalstack/quake:latest
        name: server
        ports:
        - containerPort: 8080
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 5
        volumeMounts:
        - name: quake3-server-config
          mountPath: /config
        - name: quake3-content
          mountPath: /assets
      - command:
        - q3
        - content
        - --seed-content-url=http://content.quakejs.com
        image: docker.io/criticalstack/quake:latest
        name: content-server
        ports:
        - containerPort: 9090
        volumeMounts:
        - name: quake3-content
          mountPath: /assets
      volumes:
        - name: quake3-server-config
          configMap:
            name: quake3-server-config
        - name: quake3-content
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: quake
spec:
  type: NodePort
  selector:
    run: quake
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 30001
      name: client
    - port: 27960
      targetPort: 27960
      nodePort: 30003
      name: server
      protocol: UDP
    - port: 9090
      targetPort: 9090
      nodePort: 30002
      name: content
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: quake3-server-config
data:
  config.yaml: |
    fragLimit: 25
    timeLimit: 15m
    bot:
      minPlayers: 3
    game:
      motd: "Welcome"
      type: FreeForAll
      forceRespawn: false
      inactivity: 10m
      quadFactor: 3
      weaponRespawn: 3
      password: Ei&Y2WvF4N
    server:
      hostname: "quakekube"
      maxClients: 20
      password: 4s%qj0iHEs
    commands:
      - addbot sarge 2
    maps:
    - name: q3dm7
      type: FreeForAll
      timeLimit: 10m
    - name: q3dm17
      type: FreeForAll
    - name: q3wctf1
      type: CaptureTheFlag
      captureLimit: 8
    - name: q3tourney2
      type: FreeForAll
    - name: q3wctf3
      type: CaptureTheFlag
      captureLimit: 8
    - name: ztn3tourney1
      type: FreeForAll
                            

Once you've copied the manifest into a file, you can deploy it with kubectl apply -f quake-manifest.yaml.

4. Setup Let's Encrypt for TLS

We'll use Let's Encrypt to secure our Quake servers with TLS.

Use the following manifest to set up Let's Encrypt. This manifest should also be in a YAML file like we have done before nano cluster-issuer.yaml and then execute it with k0s kubectl apply -f cluster-issuer.yaml. Please change the email to your email address.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: youremail.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
                            

5. Setup Ingress

The Ingress basically redirects the traffic to the service and finally to the pod. Copy the manifest, put it in a file nano ingress.yaml and execute it with k0s kubectl apply -f ingress.yaml. Please change the host to your domain name and remember to update your DNS record to point to the Load Balancer.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: quake-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: yourwebsite.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: quake
            port:
              number: 8080
  tls:
  - secretName: quake-tls
    hosts:
    - yourwebsite.com
                            

Verification:

To verify that everything is working correctly, use k0s kubectl get pods to check that all the pods are running. Also, check the logs of the Quake server pods to ensure they are functioning correctly. This is done via the following command:

k0s kubectl logs pod-name

or

k0s kubectl logs -f podname

You get the podname via k0s kubectl get pods.

Wrapping Up:

Congratulations! You've set up a Quake server on a single-node Kubernetes cluster on a DigitalOcean droplet using k0s. Now you can enjoy playing Quake with your friends, hosted on your very own server! Remember, Kubernetes is a powerful tool, and this is just the beginning. The more you play around with it, the more you'll uncover its potential. Happy gaming and exploring!