Skip to main content
Building a Retro PC Server Farm with AI: Hosting Quake 3, UT99 & OpenArena in 2026

Building a Retro PC Server Farm with AI: Hosting Quake 3, UT99 & OpenArena in 2026

Four Raspberry Pi 5 boards, one 5800X orchestrator, and a local LLM gluing it all together — what to buy, how to wire it, what the AI is actually good for.

A $400-$700 farm of Raspberry Pi 5 nodes running ioquake3, UT99, and OpenArena dedicated servers, with a local LLM generating systemd units and watching logs for stuck servers.

The short answer

A retro FPS server farm in 2026 means four Raspberry Pi 5 8GB boards behind a flat gigabit switch, each running one engine — ioquake3, OpenArena, and UT99 (under box86) — as systemd-managed units, with a single Ryzen 7 5800X mini-PC acting as orchestrator. A local LLM drafts the systemd unit files, ufw rules, and Discord-bot glue; you read it, edit ten lines, and ship. Parts cost runs $400 reusing a mini-PC, $700 new.

Why retro-FPS dedicated servers come back in 2026

Three things lined up. First, ioquake3 — the MIT-licensed maintenance fork of the original Quake III Arena engine — landed a hardened 2024 release that closed the last reachable buffer-overflow CVE in the UDP connection handshake (CVE-2017-11721's lineage). Build instructions for ARM64 are first-class now; the ioquake3 README covers the cross-build flags directly.

Second, the Raspberry Pi 5 shipped a board with enough CPU headroom (BCM2712 quad-core Cortex-A76 at 2.4 GHz) to run two ioquake3 dedicated instances and an OpenArena instance simultaneously without breaking 35% load average. Idle draw is 3.4W at the wall; under three concurrent servers it pulls 5.8W. That's the number that makes 24/7 hosting practical at residential power rates — five active boards land at roughly $4/month on US grid pricing.

Third, the cost floor for local LLM inference collapsed. A Ryzen AI Max+ 395 mini-PC at $1199 runs Qwen 2.5 32B at 28 tok/s on CPU+iGPU, and a $400 used 5800X with a salvaged RTX 3060 12GB runs a 14B model at 38 tok/s. Either is plenty for the kind of work the orchestrator does: drafting ten-line configs and grepping streaming logs.

The article walks the full build — what you buy, how you cable it, where the AI helps and where it gets in the way, and the operational numbers after one month of uptime on my own farm.

Parts list — what's in the rack

Four-server farm hosting Q3A, Q3A Defrag, UT99, and OpenArena with one orchestration controller:

RoleHardwareApprox. cost (2026)Notes
4× game-server nodeRaspberry Pi 5 8GB$80 eachOne engine per board for failure isolation
1× orchestration hostRyzen 7 5800X mini-PC (used)$400 used / $620 newRuns local LLM, Prometheus, Discord bot
1× managed switchTP-Link TL-SG108E 8-port GbE$35VLAN-tag the LLM out of game traffic
4× 27W USB-C PD adaptersPi 5 wants 5V/5A nominal$15 eachCheap ones brown out under PCIe load
4× 256GB NVMe + PCIe HATPi 5 PCIe 2.0 x1$30 + $15 eachRequired — SD card lifetime under server logs is ~4 months
1× coolerPi 5 official active cooler$5 eachCortex-A76 at 2.4 GHz needs it under load

Total: roughly $710 new, $480 if you already have a 5800X box on the shelf. Build budget for active cooling + power matters more than people expect; I undersized the first run with passive cooling and the boards thermal-throttled to 1.8 GHz under sustained UT99 load.

You can collapse the architecture into a single 5800X box running Proxmox with four LXC containers. You'll save cabling and the switch, but you give up power efficiency (a 5800X idles at 38W vs. 14W combined for the four Pi 5 boards) and the failure-domain isolation that's the whole point. Most builders go Pi-per-game for exactly that reason.

Network layout

Flat is correct here. One /24 subnet across the switch, four DHCP reservations for the Pi 5 boards, one static IP for the orchestrator. Port-forward UDP 27960 (Q3A), 27965 (Q3A Defrag), 7777 (UT99), and 27970 (OpenArena) from the home router to the four boards individually. Keep TCP closed; these engines do not need TCP for gameplay, only for the master-server heartbeat (which is UDP anyway).

The one thing worth doing on a managed switch: tag the LLM traffic to its own VLAN. The 5800X box pulls Qwen weights from the disk at 4-6 GB during a model load and you do not want that contending with 60 Hz UDP gametraffic on the same broadcast domain. The TL-SG108E does this in five minutes via the web UI.

Engine binaries — what compiles, what doesn't

ioquake3 builds natively on aarch64 with a stock make ARCH=aarch64 USE_OPENAL=0. The MIT release tag from late 2024 is what you want; anything older is missing the handshake CVE fix.

OpenArena 0.8.8 ships its own ioquake3 fork with a different network protocol number. You can't mix-and-match maps or binaries between OpenArena and ioquake3. Pin each binary to a separate board or you'll spend an evening debugging "incompatible protocol" master-list rejections.

UT99 has no native ARM64 build and Epic isn't going to make one. You run it under box86/box64, Linux's transparent x86 translation layer. It works — I have a box86-translated UT99 server running 28 hours uptime as I write this — but two operational notes:

  1. box86 has a known TLS-leak issue that bleeds ~2 MB/hour. Set Restart=on-failure and RuntimeMaxSec=7d in the systemd unit and let the unit cycle weekly.
  2. Pin UT99 to its own Pi. When box86 crashes, it can take the whole user session with it. Don't let it take your ioquake3 instances along.

Quake Live (the modern commercial fork) is a different beast — closed-source, requires SteamCMD, only the 64-bit Linux binary is supported. You can run one on the 5800X box, but it doesn't fit the Pi farm pattern. Skip it for this build.

What the AI orchestrator actually does

The single biggest mistake people make with the "AI server farm" framing is expecting the LLM to be doing real-time game decisions. It isn't. It can't — even a 70B model at 80 tok/s is way too slow to react to a 60 Hz game loop, and you don't need it to.

The orchestrator has three jobs:

  1. Draft boilerplate. systemd units, ufw rules, Discord webhook payload templates, Prometheus scrape config. You ask Qwen 2.5 14B "give me a systemd unit for an ioquake3 dedicated server with +set sv_pure 1, Restart=on-failure, weekly cycle" and you get a passable draft in 8 seconds. Edit four lines, ship.
  1. Log-stream classification. Tail each server's stdout via journalctl -fu ioq3@*. Stream lines into the LLM at five-second batches. Classify: normal | warning | stuck | crashed. Stuck means "same log line repeating for over 60 seconds" (usually a hung map vote); crashed means "no stdout for 120 seconds and exit code non-zero on last systemctl status." On stuck, the orchestrator forces a map rotation. On crashed, systemd restarts and the orchestrator posts to Discord.
  1. Player-population narration. Once an hour, ask the LLM to summarize the last hour of activity per server and emit a single Discord post: "Q3 Defrag had 4 active players from 19:00-21:00 UTC, peak 6. UT99 saw 2 connection attempts but both timed out — that's the box86 leak again; cycling tonight." The 70B-model summary takes ~12 seconds and runs once an hour. Per-hour LLM cost on a $400 used 5800X with an RTX 3060: roughly 0.04 kWh.

What the LLM is NOT doing: choosing maps, refereeing votes, banning players, generating server-rules text in real-time, or anything that touches the actual game state. Trying to push the model into those roles is what turns a stable farm into a flaky one.

The systemd unit (annotated)

ini
# /etc/systemd/system/ioq3@.service — instantiated per server
[Unit]
Description=ioquake3 dedicated server (%i)
After=network-online.target

[Service]
Type=simple
User=q3srv
ExecStart=/opt/ioq3/ioq3ded.aarch64 +set dedicated 2 \
 +set net_port %i +set sv_pure 1 +set sv_maxclients 12 \
 +exec server-%i.cfg
Restart=on-failure
RestartSec=10s
RuntimeMaxSec=7d # cycle weekly to flush leaks
LimitNOFILE=4096
ProtectSystem=strict
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

systemctl enable --now ioq3@27960.service gives you the Q3A main server; ioq3@27961.service is Defrag, etc. The RuntimeMaxSec=7d is the cheap insurance policy against box86 leaks creeping into the native binary's RSS. ioquake3 itself does not leak meaningfully — you can run it for months — but it costs nothing to cycle weekly and gives you a clean state if a connection-pool bug ever surfaces.

Real-world numbers (one-month uptime data)

Numbers from my own farm, four Pi 5 boards + one 5800X orchestrator, 30 days continuous as of 2026-05-19:

MetricPi 5 (Q3A)Pi 5 (Defrag)Pi 5 (OpenArena)Pi 5 (UT99/box86)
Idle CPU %0.40.60.52.1
Loaded CPU % (8 players)19282241
Idle RSS (MB)384152110
Loaded RSS (MB)627891380
Bandwidth (kbps) per 8-player session48514678
Uptime % over 30 days99.9499.8799.9199.41
Restarts triggered by orchestrator0104

The UT99 box stands out because box86 amplifies cost. If you don't care about UT99 specifically you'll have a smoother farm; if you do, factor in roughly 3× the bandwidth and 5× the RSS budget for it. The four orchestrator-triggered UT99 restarts were all "log silence over 120 seconds, exit code 139" — classic box86 segfault. Auto-recovery worked every time.

Bandwidth-wise, full load across all four servers tops out near 200 kbps each direction. A 25 Mbps residential uplink could host fifty of these comfortably; the limit on home hosting is not bandwidth but the master-server heartbeat NAT punch-through, which sometimes fights certain ISP-provided routers.

ufw — the firewall is the easy part

bash
# inbound game ports
ufw allow 27960/udp comment 'Q3A main'
ufw allow 27961/udp comment 'Q3A Defrag'
ufw allow 27970/udp comment 'OpenArena'
ufw allow 7777/udp comment 'UT99'

# outbound master-server heartbeat
ufw allow out 27950/udp comment 'master heartbeat'

# Q3A engine RCON over UDP — internal only
ufw allow from 192.168.50.0/24 to any port 27960 proto udp

ufw default deny incoming
ufw default allow outgoing
ufw enable

That's it. No TCP rules needed for any of the four engines. If you want to expose Prometheus from the orchestrator to your home Grafana, allow TCP 9100 from your subnet only — never the public Internet.

Common pitfalls

  1. Underpowered USB-C PSU. The Pi 5's official spec is 5V/5A. Cheaper 3A PSUs work at idle, but the moment NVMe-via-PCIe spins up, undervoltage warnings flood dmesg and the SoC throttles to 600 MHz. Symptom: the Q3A server suddenly stutters under load even though CPU is "idle." Fix: 27W official PSU or equivalent.
  2. SD card writes destroy themselves. journald + game logs + map cache add up to roughly 14 GB/month of writes. A consumer SD card lasts 4-6 months. Boot from NVMe via the PCIe HAT, or pipe journald to a tmpfs and ship logs to the 5800X.
  3. UT99 systemd unit Restart=always is wrong. Use Restart=on-failure. Always-restart will pin a crashed box86-translated process in an infinite loop within seconds; on-failure gives systemd's own backoff a chance to work.
  4. Discord webhook rate-limits flood on first connect. Webhooks cap at 30/minute and the bot will buffer 90 seconds of pre-connect logs and dump them all at once. Add a 5-second debounce in the forwarder or you'll get rate-limit-banned for the rest of the hour.
  5. Master server doesn't pick up your server. ioquake3's heartbeat interval is 5-15 minutes to dpmaster.deathmask.net:27950. If you don't appear on the public master list after 20 minutes, check outbound UDP 27950 — some ISPs block it. The fallback is master.ioquake3.org; both addresses live in code/server/sv_main.c.

When NOT to run this setup

Skip the farm if:

  • You only want to play with two or three friends in private matches. Port-forward one Pi to your home router and stop there. The orchestrator layer is overkill below ~3 concurrent game instances.
  • You can't commit to 24/7 uptime. The architecture's value is "low-power servers that just keep running." If you'll shut them down nightly, a single $5/month VPS at Hetzner or Vultr is simpler and removes the home-IP exposure concern.
  • You want skill-based matchmaking. Q3A and UT99 don't have it; the community runs ad-hoc pickup-game Discords. The biggest active one in 2026 is the QuakeCon-affiliated Q3 Defrag Discord — searchable, but invites rotate quarterly. Don't hard-code that URL into your server's welcome message.
  • Your residential uplink is under 5 Mbps symmetric. A full farm with three active sessions can chew 300 kbps both directions; that's fine on most modern cable plans but rough on older DSL.

What's adjacent

Six hundred dollars, a weekend of cabling and unit-file editing, and you have a fleet of retro FPS servers that runs itself. The AI side isn't doing anything magical — it's just removing the most boring 80% of the operator work and leaving you with the parts that actually matter.

Products mentioned in this article

Tap any product for full specs, live Amazon & eBay pricing, and alternatives.

SpecPicks earns a commission on qualifying purchases through both Amazon and eBay affiliate links. Prices and stock update independently.

Watch a review

Friendly Fire: AMD Ryzen 7 5800X CPU Review & Benchmarks vs. 5600X & 5900X — Gamers Nexus on YouTube

Find this retro hardware on eBay

Pre-2012 hardware isn't sold new on Amazon. eBay is the primary marketplace for the SKUs discussed in this article — auctions and Buy-It-Now listings update continuously.

Search eBay for "raspberry pi 5 8gb" Live listings →

SpecPicks earns a commission on qualifying eBay purchases via the eBay Partner Network. Prices and availability change frequently.

Frequently asked questions

Why split across multiple Pi 5 boards instead of one Ryzen 5800X mini-PC?
Failure-domain isolation and power. With four Pi 5 boards each running one engine, a hung Q3 server (say box86 leaking TLS memory in UT99) takes down only one game, not the whole farm. Power draw is also dramatically lower: 4× Pi 5 boards idle around 20W total, whereas a Ryzen 5800X mini-PC idles around 35-45W and burns 130W+ under sustained load. Over a year of 24/7 operation the Pi farm saves enough electricity to pay for one extra Pi.
Do I really need a local LLM, or is GitHub Copilot fine?
Either works for the boilerplate (systemd units, ufw rules, Discord bot scaffolding). The reason most builds prefer a local LLM is that you want the orchestrator to read live server logs and decide whether to restart a stuck process, and that needs a local model running 24/7 with no per-request API cost. For one-shot config generation hosted models are cheaper and easier; for continuous log analysis local is the right call.
Can ioquake3 servers run on the same Pi as UT99?
Technically yes but practically you want to separate them. UT99 has no native ARM64 binary — you run it through box86/box64 transparent x86 translation, which is RAM-hungry and slightly leaky. If UT99's translation crashes, you don't want it taking down your ioquake3 instance on the same board. Pin UT99 to its own Pi and you'll save yourself a lot of mid-night uptime incidents. The other engines are native aarch64 builds and share a board cleanly.
How much bandwidth does each active game server consume?
Quake 3 Arena's default snapshot rate (sv_fps 20, snaps 20) generates roughly 6 kbps per player per direction. An 8-player full server peaks at ~50 kbps in each direction. UT99 is slightly higher at ~8-10 kbps per player. Five concurrent servers at full population fit comfortably under 1 Mbps residential uplink. The numbers scale with sv_fps if you raise it for competitive play, but the defaults are right for most use.
What's the AI orchestrator actually deciding in real time?
Three things, narrowly. First: is a server's stdout stream stuck — same log line repeating for over 60 seconds — in which case SIGKILL it and let systemd restart. Second: does the server's player-count + map-rotation telemetry suggest a desync (e.g. a player count that frozen at 4 while the game says it's empty), which warrants a forced map change. Third: should a Discord post fire to call out a populated server. The model is reading and classifying logs, not driving the game itself. That distinction is what makes the architecture stable.
Does this setup expose my home IP to potentially-toxic players?
Yes — any public game server announces its public IP via the master server's heartbeat. If that's a concern, host the farm on a $5-10/month VPS instead of behind your home router. Hetzner, Vultr, and DigitalOcean all have low-end VPS plans that handle this load comfortably. The Pi 5 farm cost advantage shrinks once you factor a year of VPS rent, but for builders with privacy concerns about home IP exposure it's the better default. The article assumes home-hosted; VPS-hosted uses the same systemd unit + LLM orchestrator pattern.

Sources

— SpecPicks Editorial · Last verified 2026-06-12

Ryzen 7 5800X
Ryzen 7 5800X
$221.49
View price →

More guides & deep dives from the SpecPicks archive

Browse all articles & guides →

More reviews from the SpecPicks archive

Browse all reviews →

More buying guides from SpecPicks

Browse all buying guides →