All Guides·FAQ

Deployment · 10 minutes

Raise Your First Gate

From a bare VPS to a public, always-on Diablo & Hellfire game: provision the server, drop in the binary and your MPQs, open one port, and install it as a service that survives reboots.

Beginner friendly Linux VPS systemd

What you need

build
# Build both binaries from the modded source tree
$ cmake -B build-server -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF
$ cmake --build build-server -j$(nproc) --target devilutionx devilutionx-server

1 · Install the files

1

Create a home for the gate

A dedicated user and directory keep things tidy and safe. The server runs fine unprivileged.

root shell
$ useradd -r -m -U -d /opt/devxh -s /usr/sbin/nologin games
$ mkdir -p /opt/devxh/assets /var/lib/devxh /etc/devxh
2

Drop in the binary and your MPQs

Copy devilutionx-server to /opt/devxh and place your MPQ files in /opt/devxh/assets. Then hand ownership to the service user:

root shell
$ cp devilutionx-server /opt/devxh/ && cp *.mpq /opt/devxh/assets/
$ chown -R games:games /opt/devxh /var/lib/devxh /etc/devxh
3

First run — prove it boots

Run it once by hand before wiring up systemd. You should see it bind port 6112 and idle:

shell
$ /opt/devxh/devilutionx-server \
      --data-dir /opt/devxh/assets \
      --save-dir /var/lib/devxh \
      --config-dir /etc/devxh \
      --name "My First Gate"
Hosting game 'My First Gate' on TCP/IP (idle player: Server)

Stop it with Ctrl+C — it shuts down cleanly and saves. That's the whole smoke test.

Firewall

DevXH binds TCP 6112 on all interfaces. Open it in your VPS provider's firewall and the OS firewall: ufw allow 6112/tcp (or the equivalent). For a truly public game, no port-forwarding beyond that is needed.

2 · Run it as a service

Manual runs die when you log out. A systemd unit makes the gate eternal:

/etc/systemd/system/devxh.service
[Unit]
Description=DevXH dedicated server (DevilutionX headless)
After=network-online.target
Wants=network-online.target

[Service]
User=games
ExecStart=/opt/devxh/devilutionx-server \
    --data-dir /opt/devxh/assets \
    --save-dir /var/lib/devxh \
    --config-dir /etc/devxh \
    --name "My First Gate" --server-tcp
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
root shell
$ systemctl daemon-reload
$ systemctl enable --now devxh
$ systemctl status devxh   # should read "active (running)"

Logs land in journald: journalctl -u devxh -f. Watch for Hosting game ... on TCP/IP at startup and Headless resync: ... 100% whenever a player joins — that's the world being handed to them.

3 · Verify from outside

From your own PC, confirm the port answers before round-tripping a game client:

your pc
$ Test-NetConnection your.server.ip -Port 6112   # Windows PowerShell
$ nc -vz your.server.ip 6112                    # Linux / macOS

Then run stock DevilutionX → Multiplayer → TCP/IP → enter your server's IP → join My First Gate. The idle host will be waiting in town. Full client walkthrough: Joining a Public Game.

Flag cheatsheet

FlagWhat it does
--name "..."Game name players see (default server-<pid>).
--password "..."Makes the game private; joiners are prompted.
--port NListen on a different TCP port (default 6112).
--game hellfire|diabloWhich campaign the gate hosts (default hellfire).
--difficulty 0|1|2normal / nightmare / hell. Clients can't change it.
--hero-class ...Idle player class (warrior, rogue, sorcerer, monk…).
--hero-name ...Idle player name (default Server).
--full-questsEnable the full quest set.

Monk, bard, barbarian

The monk class needs hfmonk.mpq; bard and barbarian need hfbard.mpq / hfbarb.mpq — make sure those files are in your assets dir before using those classes.

Your gate is now open. When you're ready to make it visible on the public server list, the membership backend registration is coming soon — meanwhile, share the IP with friends or the world.