Host a server
Run the same server that hosts the public games. On a Linux server it runs around the clock and updates itself. On your own Windows or Linux PC, you can host straight from the app.
- Players
- 6432 a side. Bots fill every empty slot.
- A full battle
- 4 CPUs, 8 GBNo graphics card needed.
- Game port
- 18451UDP and TCP, IPv4 and IPv6.
- Updates
- AutomaticInstalled once nobody is playing.
Linux server
A dedicated server on a VPS such as Linode, running 24/7 under systemd and updating itself. The best home for a public server.
Follow the Linux guideWindows or Linux PC
Host from the desktop app for your LAN or the world. The server keeps running after you close the game.
Host from the appA dedicated server on Linode
About 20 minutes from a fresh server to a running battle. These steps use Linode and Ubuntu 24.04 LTS, and work the same on any Ubuntu 24.04 server with systemd. Run the server steps as root.
Tested start to finish on a new Linode 8 GB in Atlanta on October 22, 2026, with preview 290.
Create the server
In Linode's Cloud Manager, create a Linode with Ubuntu 24.04 LTS, in the region closest to your players. Choose the Linode 8 GB shared plan (4 CPUs, 8 GB memory) or larger: a full 64-player battle held 60 ticks per second on it in our tests. Add your SSH key, then log in:
ssh root@SERVER_IPReplace
SERVER_IPhere and below with your Linode's IPv4 address.Update it and open the game port
The game port is 18451, over UDP for play and TCP for the server's details.
On the server
apt update && apt -y upgrade ufw allow OpenSSH ufw allow 18451/udp ufw allow 18451/tcp ufw --force enableUsing a Linode Cloud Firewall as well? Allow the same ports there.
Add a service account and Node.js
The server runs as its own user, on Node.js 24 from nodejs.org, checked against its published checksum.
On the server
useradd --system --home-dir /var/lib/bfeserver --shell /usr/sbin/nologin bfeserver install -d -m 755 /opt/bfeserver install -d -m 700 -o bfeserver -g bfeserver /var/lib/bfeserver cd /tmp NODE_URL=https://nodejs.org/dist/latest-v24.x NODE_ARCH=$(uname -m | sed 's/x86_64/x64/; s/aarch64/arm64/') NODE_FILE=$(curl -fsSL $NODE_URL/SHASUMS256.txt | grep -o "node-v[0-9.]*-linux-$NODE_ARCH.tar.xz" | head -1) curl -fsSLO "$NODE_URL/$NODE_FILE" curl -fsSL $NODE_URL/SHASUMS256.txt | grep " $NODE_FILE\$" | sha256sum -c - install -d /opt/bfeserver/node tar -xJf "$NODE_FILE" -C /opt/bfeserver/node --strip-components=1 /opt/bfeserver/node/bin/node --versionCopy your game to the server
On your PC
Copy the folder Steam or GOG installed the game into, the one that holds
GameData, to/opt/bfeserver/retail. It's about 3 GB. Don't create the destination folder first. Run the command for your copy:Steam, from Linux (Steam installs the game through Proton)
rsync -a --info=progress2 "$HOME/.local/share/Steam/steamapps/common/Star Wars Battlefront (Classic 2004)/" root@SERVER_IP:/opt/bfeserver/retail/Steam, from Windows (PowerShell)
scp -r "C:\Program Files (x86)\Steam\steamapps\common\Star Wars Battlefront (Classic 2004)" root@SERVER_IP:/opt/bfeserver/retailGOG, from Linux (installed with Heroic)
rsync -a --info=progress2 "$HOME/Games/Heroic/Star Wars - Battlefront/" root@SERVER_IP:/opt/bfeserver/retail/GOG, from Windows (GOG Galaxy, PowerShell)
scp -r "C:\Program Files (x86)\GOG Galaxy\Games\Star Wars - Battlefront" root@SERVER_IP:/opt/bfeserver/retailInstalled it somewhere else? In Steam, right-click the game and choose Manage, then Browse local files. In GOG Galaxy, choose the settings button beside Play, then Manage installation and Show folder. GOG's offline installer uses
C:\GOG Gamesunless you chose another folder. Then, back on the server, let the server's user read it:On the server
chmod -R a+rX /opt/bfeserver/retail ls /opt/bfeserver/retailYou should see
GameDatain the list.Install the updater from the latest release
The server comes from the same signed releases as the desktop app. Its updater is inside the Linux package, so take it from there without installing the app.
On the server
cd /tmp GET=https://get.battlefronteternal.com/downloads/latest DEB=$(curl -fsSL $GET/SHA256SUMS | grep -o "battlefront-eternal_[^ ]*_$(dpkg --print-architecture)\.deb") curl -fsSLO "$GET/$DEB" curl -fsSL $GET/SHA256SUMS | grep " $DEB\$" | sha256sum -c - install -d /opt/bfeserver/update-bootstrap dpkg-deb --fsys-tarfile "$DEB" | tar -x -C /opt/bfeserver/update-bootstrap --strip-components=6 "./opt/Battlefront Eternal/resources/host-runtime/update" ln -sfn /opt/bfeserver/update-bootstrap /opt/bfeserver/updateThe checksum line must print
OK.Tell it how to update
This sets the release channel, where your game is, and the server it manages, with its ports and memory limit.
On the server
cat > /etc/bfeserver-update.json <<'EOF' { "channel": "development-preview", "retail": "/opt/bfeserver/retail", "jobs": 2, "instances": [ { "name": "main", "unit": true, "healthPort": 18450, "gamePort": 18451, "memoryMax": "2800M" } ] } EOFSet up your server
Name it, describe it and choose its playlist. This one plays six battles from both eras. The configuration reference has every map and setting.
On the server
cat > /var/lib/bfeserver/config.json <<'EOF' { "name": "My Battlefront Eternal server", "description": "Classic battles from both eras. Bots fill both teams.", "location": "Atlanta, US", "engine": "/opt/bfeserver/engine", "data": "/opt/bfeserver/game-data", "maxPlayers": 64, "rotation": [ "swbf1/nab2:rep:conquest", "swbf1/hot1:imp:conquest", "swbf1/kas2:rep:conquest", "swbf1/tat2:imp:conquest", "swbf1/bes2:rep:conquest", "swbf1/end1:imp:conquest" ], "onlineNoticeAccepted": true, "relayPolicy": "never", "honorGlobalBans": true } EOF chown bfeserver:bfeserver /var/lib/bfeserver/config.json chmod 600 /var/lib/bfeserver/config.jsonListing your server publicly."onlineNoticeAccepted": trueputs your server in the in-game browser, and means you accept the online notice: online play processes your IP for connectivity and abuse prevention. Independent hosts and relays process connection metadata. Location sharing remains off. Set it tofalsefor a private server players join by address or over LAN.Start it
This installs the services and starts the first update. The update downloads the newest release, prepares your server's game data from your copy, checks every battle in your playlist, then starts the server.
On the server
/opt/bfeserver/node/bin/node /opt/bfeserver/update/server.js --install-units systemctl start --no-block bfeserver-update.service journalctl -fu bfeserver-updateOn a Linode 8 GB the first run took about five minutes: a 142 MB download, then four minutes preparing the game data. It's ready when the log says
main: runningand the version. Press Ctrl + C to stop watching.Check it's up
On the server
systemctl status bfeserver --no-pager curl -s http://127.0.0.1:18450/healthzFrom your PC,
curl http://SERVER_IP:18451/infoshows what players see. Then open Battlefront Eternal, choose MULTIPLAYER, and find your server in the INTERNET list. You can also join it by address with DIRECT CONNECT.
Host from the app
The desktop app has the server built in. It starts it in the background with your prepared game data, and the server keeps running after you close the game.
Install and prepare
Install Battlefront Eternal and launch it once, so it finds your Steam or GOG copy and prepares the game data.
Open CREATE
Choose MULTIPLAYER, then the CREATE tab, and fill in the form:
Field What it does Server name What players see in the browser. Visibility LAN only, or Public online. Public asks you to accept the online notice once. Map and Side The battle to host. Republic or CIS plays the Clone Wars. Alliance or Empire plays the Galactic Civil War. Human players Up to 64 in total. Bots fill each team to 32, and players replace them. Connection Automatic connects players directly when it can, through a relay when it can't. Relay only and Direct only force one or the other. Host and join
Choose Host and join. The server starts and you join it. Close the game whenever you like: the server keeps running. Open CREATE again to Join running server or Stop server.
Let players in
With Automatic, players who can't reach your PC directly come in through a relay. For direct connections from the Internet, forward UDP and TCP port 18461 on your router to this PC, and allow it through Windows Defender Firewall. In PowerShell, as Administrator:
PowerShell (Administrator)
New-NetFirewallRule -DisplayName "Battlefront Eternal server (UDP)" -Direction Inbound -Protocol UDP -LocalPort 18461 -Action Allow New-NetFirewallRule -DisplayName "Battlefront Eternal server (TCP)" -Direction Inbound -Protocol TCP -LocalPort 18461 -Action Allow New-NetFirewallRule -DisplayName "Battlefront Eternal LAN discovery" -Direction Inbound -Protocol UDP -LocalPort 18452 -Action AllowThe last rule lets players on your LAN find the server. On Linux, open the same ports in your firewall.
The server's settings
A Linux server reads /var/lib/bfeserver/config.json when it starts. After an edit, run systemctl restart bfeserver.
| Setting | What it does |
|---|---|
name | The server's name in the browser, up to 80 characters. |
description | Up to 280 characters shown under the name. |
location | Where it is, such as Atlanta, US, up to 80 characters. |
sponsor | Who pays for it: { "name", "url", "logo" }, with https links. |
rotation | The playlist, played in order and then from the top. Each battle is swbf1/MAP:SIDE:conquest. |
maxPlayers | Human players, up to 64 (32 a side). |
ai | Leave it out for bots that fill the teams. "off" plays with people only. |
autoAssignTeams | true assigns teams instead of letting players pick. |
onlineNoticeAccepted | true lists the server publicly and accepts the online notice. |
relayPolicy | never for a server with a public address. auto behind NAT, which uses a relay when needed. always relays everyone. |
honorGlobalBans | true applies the project's signed ban list as well as your own bans. |
gamePort, bind | Change the game port (18451) or the address it listens on. |
maxPlayersPerAddress | Players allowed from one network, 8 by default. Raise it for a LAN party behind one router. |
stateBytesPerSecond | Upload per player, 100,000 bytes a second by default. Lower it on a slow uplink. |
Maps and eras
The side picks the era: rep or cis for the Clone Wars, imp or all for the Galactic Civil War. All 30 battles:
| Map | Code | Eras |
|---|---|---|
| Bespin: Platforms | bes1 | Both |
| Bespin: Cloud City | bes2 | Both |
| Endor: Bunker | end1 | Galactic Civil War |
| Geonosis: Spire | geo1 | Clone Wars |
| Hoth: Echo Base | hot1 | Galactic Civil War |
| Kamino: Tipoca City | kam1 | Clone Wars |
| Kashyyyk: Islands | kas1 | Both |
| Kashyyyk: Docks | kas2 | Both |
| Naboo: Plains | nab1 | Both |
| Naboo: Theed | nab2 | Both |
| Rhen Var: Harbor | rhn1 | Both |
| Rhen Var: Citadel | rhn2 | Both |
| Tatooine: Dune Sea | tat1 | Both |
| Tatooine: Mos Eisley | tat2 | Both |
| Tatooine: Jabba's Palace | tat3 | Both |
| Yavin 4: Temple | yav1 | Both |
| Yavin 4: Arena | yav2 | Both |
Day to day
The server restarts itself if it stops, starts at boot, and installs each new release once nobody is playing.
Players, kicks, bans and announcements
Open the server's menu as its own user. Choose 9 for live administration: the players on it, kicks, bans, recent stats, a message to everyone and a match restart.
sudo -u bfeserver BFE_STATE_DIR=/var/lib/bfeserver /opt/bfeserver/node/bin/node /opt/bfeserver/server/src/main.jsLogs and status
journalctl -u bfeserver -f
journalctl -u bfeserver-update -n 50
/opt/bfeserver/node/bin/node /opt/bfeserver/update/server.js --statusThe last command shows the running release, one waiting for an empty server, and the last error.
Updates
Every five minutes the updater checks for a new release. It installs and prepares it while the battle goes on, and switches over once nobody is playing. If the new release fails its health check, the old one comes straight back.
To pause updates, add "hold": true to /etc/bfeserver-update.json. To let the machine restart itself for kernel updates once the server is empty, add "rebootWhenRequired": true, and keep upgrades from restarting the server mid-battle:
echo '$nrconf{override_rc}->{qr(^bfeserver)} = 0;' > /etc/needrestart/conf.d/bfeserver.confMore than one server on a machine
Each server gets its own name, playlist, ports and state, and they share one installation. Add it to instances in /etc/bfeserver-update.json with its own ports, open its game port, then run --install-units again. Give it a config.json in /var/lib/bfeserver-NAME with the same gamePort, owned by bfeserver:
"instances": [
{ "name": "main", "unit": true, "healthPort": 18450,
"gamePort": 18451, "memoryMax": "2800M" },
{ "name": "duels", "healthPort": 18453, "gamePort": 18454 }
]Give each server its own game port, and keep clear of 18452, which LAN discovery uses.
When it doesn't come up
The update log says there's no config.json
The server won't start without its settings. Create /var/lib/bfeserver/config.json as in step 7, owned by bfeserver. The next update run, within five minutes, starts it.
Preparing the game data fails
Check that /opt/bfeserver/retail holds GameData directly, not inside another folder, and that it's readable: chmod -R a+rX /opt/bfeserver/retail. The log, journalctl -u bfeserver-update, names the step that failed. A preparation that fails three times waits for the next release.
Players can't see or join the server
From your PC, curl http://SERVER_IP:18451/info must answer. If it doesn't, open UDP and TCP 18451 in ufw and in any cloud firewall. For the public list, onlineNoticeAccepted must be true. Players need the same release as the server: their app updates itself, and so does the server.
It ran out of memory
Naboo: Plains needs the most memory while it loads. Keep memoryMax at 2800M or more for a full server, and use a plan with 8 GB.
The server is free software under GPL-3.0: read its source.
