Hosting a LAN party using Proxmox and Docker

Hosting a LAN party using Proxmox and Docker
Photo by ELLA DON / Unsplash

My girlfriend recently remembered a childhood game she used to play with her sister and wished they could play again: Warcraft III.

So I thought what better way is there to use my homelab than to host LAN sessions and play nostalgic games together!

Now, when I say "host", I mean actually allowing anyone on any device to join the session and play without installing anything but a streaming client. That would for example allow people with MacBooks or old computers to join effortlessly.

In this blog post I layout all the challenges that I had while setting this up, hoping it could help you setup a LAN of your own!

Using the iGPU on the server

I’m running this on a Minisforum MS-01 with an Intel i5-12600H. It has room for a low-profile single-slot GPU, but before adding one, I wanted to try the included integrated Intel Iris Xe graphics. I suspected it would be more than enough for Warcraft III.

As I was already using the iGPU for another virtual machine to do video transcoding, I needed a way to share it with multiple VMs. The technology for that is called SR-IOV. It lets you split PCIe devices into multiple Virtual Functions, which can then be passed through individually to VMs

Proxmox, the hypervisor running on my server, has full support for SR-IOV. But at the time of this writing, support is still in the works in the new xe graphics driver from Intel on Linux. Luckily though, Github user strongtz made a DKMS module with a patched version of the i915 Intel driver with added support for SRIOV.

Quick disclaimer: as the author of this module states, this is very experimental. I wouldn't advise installing it on a production server. It would probably be better to wait for official support in the xe driver.

After following the instructions in the Github repo to install the module on my Proxmox system, I was able to see the Virtual Functions :

We can still see the root device 00:02.0 but we shouldn't use it anymore.

Next, I created an Ubuntu Server 24.04 virtual machine and passed through one of the VFs:

After following the instructions for setting up the DKMS module inside the VM, I was also able to see the iGPU:

Allowing multiple people to play simultaneously on the same server

I first discovered the idea of using a single computer for multiple users to game at the same time when I stumbled on a project called Duo by a developer who goes by Black Seraph. The software is designed for Windows and it allows you to run multiple Sunshine servers in isolation.

Sunshine is a game streaming server with hardware encoding and low-latency. Basically Nvidia GeForce NOW that you can install on your own PC.

I tried running Duo on a Windows 11 machine and multiple-users part worked really well but I encountered other problems though:

  • I found that running Windows in a VM has a lot of overhead. The fan on my server kept screaming the entire time the VM was on (even with no games running).
  • I had a really hard time making old games work well on modern Windows. The integrated compatibility tools are not enough, and each game requires different hacks to get it working.

So I would recommend running Duo, but only on a physical Windows machine.

After that disappointment, I put this project on hold for a few weeks, until I discovered Wolf.

Wolf is part of a bigger project called Games On Whales (like the whale in the Docker logo). It handles the streaming part, like Sunshine, and works with the same client software called Moonlight. You gotta love the naming of these projects 😀.

I highly recommend checking out Wolf's documentation on how the system works. I think it's such an amazing project. The simple version is that Wolf spins up Docker containers on demand as soon as a client connects. These docker containers are custom built to allow running games through Steam, Epic, GOG and others. Wolf then handles sending the video feeds from each container to its corresponding client.

I followed the documentation to setup some requirements and then set up Wolf through Docker Compose (version for Intel GPUs):

services:
  wolf:
    image: ghcr.io/games-on-whales/wolf:stable
    environment:
      - XDG_RUNTIME_DIR=/tmp/sockets
      - HOST_APPS_STATE_FOLDER=/etc/wolf
    volumes:
      - /etc/wolf/:/etc/wolf
      - /tmp/sockets:/tmp/sockets:rw
      - /var/run/docker.sock:/var/run/docker.sock:rw
      - /dev/:/dev/:rw
      - /run/udev:/run/udev:rw
    device_cgroup_rules:
      - 'c 13:* rmw'
    devices:
      - /dev/dri
      - /dev/uinput
      - /dev/uhid
    network_mode: host
    restart: unless-stopped
  • /etc/wolf is where the persisted data for the containers will be stored, as well as the config.toml file for Wolf.
  • /dev/dri gives access to the graphics card
  • /dev/uinput and /dev/uhid allow Wolf to create virtual input devices (mouse, keyboard, gamepad)

After spinning this up with docker compose up -d, a new server will show up in our Moonlight client. You can follow the instructions to pair the client to the server and you're in:

Out of the box, Wolf comes preconfigured (in /etc/wolf/cfg/config.toml) with a few key applications like Emulation Station (retro emulators), Heroic (Epic Games), Steam and Lutris. In the next section I'll focus on the latter and show you how it can help install old games on Linux.

Installing an old game on a modern system

Lutris is a "game preservation platform" according to their website. Simply put, it's a set of tools and a collection of community scripts that allow games to run optimally on modern hardware. It does not provide the games, but rather the toolbelt to run them. So when we search for Warcraft III in Lutris, we find multiple ways to install it. These different scripts could be provided by different people from the community.

In this case, we can either provide the CD if we already have it, or just provide our serial number and let it download the game from Blizzard's servers.

Lutris will then setup the correct Wine configuration and install the game and its updates/patches. A few minutes later and voilà:

This was so easy compared to installing the game myself on the Windows 11 VM and trying to make it work.

Oh and here's the Lutris Docker container running this:

If you noticed that the Docker image for Lutris is a local one, that's because I had to quickly patch games-on-whales' image to add some missing libraries for 32bit games. I'll propose a PR for it on their repository.

The fun part

For me, everything up to this point has already been fun! But let me show you the LAN party side of all this:

And here are the corresponding containers:

One cool thing about this is that the containers are in the same Docker network and can see each other without any more setup.

Remember, these are two devices streaming a game running in parallel on two Docker containers running in an Ubuntu VM on a Proxmox hypervisor, at 60fps and without any noticeable latency.

Finally, here's the network traffic on my server, where we can clearly see the two network ports setup in LAG handling the traffic from 2 different clients:

Special mention

I'd like to mention another project that I found called Cloudypad. This is such a cool piece of software. It allows us to provision cloud GPU instances from most major cloud providers. It automates the configuration of the instance and the installation of Sunshine/Wolf (your choice). You then have a cloud gaming machine at your disposal.

I've tried it on Scaleway using an L4 GPU instance, it works great. Of course this is a much more powerful GPU and more suited for AAA games, and with Wolf, you can even share the instance with multiple people.

Going further

I have two ideas in mind that I'd like to try in the future:

  • Adding a beefier GPU to my server, probably an RTX3050 low-profile single-slot like this one, and trying more recent games locally.
  • Using Tailscale to allow remote sessions to my local Wolf server, though we’d be limited to games that don’t suffer too much from added latency.