What the server asks for
The manual's hardware line is short: any device with Java 25 and no less than 4 GB of RAM, x64 or arm64. Beyond that it names two pressures and tells you to measure. CPU load follows the number of players and entities (NPCs and mobs); memory follows how much of the world is loaded at once, which grows with view distance and with players exploring apart from each other.
| Item | What the manual states |
|---|---|
| Runtime | Java 25; Adoptium Temurin recommended |
| Memory | At least 4 GB; tune the heap with -Xmx |
| Architecture | x64 and arm64 |
| Network | QUIC over UDP, default port 5520, TCP not required |
| CPU load | Rises with player and entity counts |
| Memory load | Rises with loaded world area; view distance is the main factor |
Two details shape sizing. Each world under universe/worlds/ runs on its own main thread and hands parallel work to a shared pool, so one busy world leans on one core. And the manual recommends capping view distance at 12 chunks (384 blocks). It warns that a Java process's real memory need is hard to read without tooling, and that memory pressure typically shows up as extra CPU spent on garbage collection. Our reading: if CPU rises while the heap is close to its -Xmx limit, try a larger heap; if the heap has room, the load more likely comes from players and creatures.
Picking the machine
Every processor on our bare metal game server page clears a PassMark one-thread rating of 2,000, the bar the Satisfactory server documentation sets; Hytale's manual names no score of its own. Entry builds there carry 16 GB or 32 GB, four to eight times the manual's floor, which leaves room for a larger heap and the operating system beside it.
- One community world: the Intel Xeon E3-1585L v5 line, sold in all five cities, 32 GB and an NVMe drive in its entry build.
- Several worlds or servers: a Xeon Gold or EPYC line from the same table, where core count and the 1 TB memory ceiling give each instance its own share.
- A playtest or launch weekend: a ready unit billed by the hour, one-hour minimum, released when the event ends.
A ready server comes online about 30 minutes once its payment is approved; a build to your configuration takes 4 to 24 hours. Pick the city from the test IPs on the locations page: game traffic is mostly small UDP packets, so the city matters more than the port speed. The port is unmetered either way, and the machine has one tenant.
Installing on Ubuntu 24.04
Paste this as root. It sets ufw to write IPv6 rules, allows SSH, switches the firewall on, opens 5520/udp, installs Temurin 25 from Adoptium's apt repository (their published commands, except that the release codename is read by sourcing /etc/os-release rather than with awk), checks that java --version reports 25, creates a hytale system user whose home is /srv/hytale, and fetches and runs the official downloader. The OpenSSH rule assumes SSH on port 22; allow your own port first if you moved it. The block is safe to re-run.
set -o pipefail
sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw && ufw allow OpenSSH && ufw --force enable && ufw allow 5520/udp && \
apt update && apt install -y curl wget apt-transport-https gpg unzip tmux && \
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null && \
. /etc/os-release && echo "deb https://packages.adoptium.net/artifactory/deb ${VERSION_CODENAME} main" | tee /etc/apt/sources.list.d/adoptium.list && \
apt update && apt install -y temurin-25-jdk && \
java --version | head -n 1 | grep -q '^openjdk 25' && \
{ id hytale > /dev/null 2>&1 || useradd --system --create-home --home-dir /srv/hytale --shell /bin/bash hytale; } && \
cd /srv/hytale && sudo -u hytale curl -fLo hytale-downloader.zip https://downloader.hytale.com/hytale-downloader.zip && \
sudo -u hytale unzip -o hytale-downloader.zip -d downloader && \
b=$(ls -d downloader/hytale-downloader* 2>/dev/null | grep -v '\.exe$' | head -n 1) && [ -n "$b" ] && chmod +x "$b" && \
sudo -u hytale "./$b" -download-path game.zip && \
echo "ok - server files in /srv/hytale/game.zip" || echo "STOP - a step above did not finish (no Linux downloader? read downloader/QUICKSTART.md)"
The manual writes the downloader as ./hytale-downloader and says the zip holds Linux and Windows builds; the Linux file may carry a suffix, so the block picks the first non-.exe file of that name, makes it executable and runs it. It signs in with OAuth2: follow the prompt it prints. The manual names no arm64 build of the downloader, so on arm64 use its other route instead: copy HytaleServer.jar from a launcher install into an empty folder, run java -jar HytaleServer.jar --bootstrap, authenticate, then /update setup.
The second block unpacks the archive once (a re-run leaves an existing game/ alone), writes jvm.options if there is none, and starts start.sh inside tmux so the console stays reachable. The heap values are our example for a 16 GB or larger machine; the manual shows -Xms2G and -Xmx4G as samples and says to experiment.
g=/srv/hytale/game
cd /srv/hytale && if [ -e "$g" ]; then echo "game/ exists - not unpacking again"; else sudo -u hytale unzip -q game.zip -d "$g" || echo "STOP - game.zip did not unpack"; fi
[ -f "$g/Assets.zip" ] && [ -f "$g/Server/HytaleServer.jar" ] && [ -f "$g/start.sh" ] && \
{ [ -e "$g/jvm.options" ] || printf '%s\n' -Xms4G -Xmx12G | sudo -u hytale tee "$g/jvm.options" > /dev/null; } && \
sudo -u hytale tmux new-session -d -s hytale "bash $g/start.sh" && \
echo "ok - started; console: sudo -u hytale tmux attach -t hytale" || \
echo "STOP - layout incomplete (see the start.sh note below) or a hytale session is already running"
If it stops because start.sh is missing, run the jar once by hand: cd /srv/hytale/game/Server && sudo -u hytale java -jar HytaleServer.jar --assets ../Assets.zip, type /update setup at its console (the manual says this writes start.sh and start.bat to the parent folder), stop it with Ctrl+C, then paste the second block again.
Signing the server in
The server cannot accept players until it is authenticated against Hytale's services. Attach to the console and authorise it with a device code:
- Attach with
sudo -u hytale tmux attach -t hytaleand type/auth login device. - Open accounts.hytale.com/device on any browser and enter the code shown. The code expires after 900 seconds.
- Once the console reports success, type
/auth persistence Encryptedso the credentials are kept on disk rather than in memory, then/auth statusto confirm. - Detach with Ctrl+B followed by D. The server keeps running.
The Server Provider Authentication Guide lists Memory and Encrypted as the two storage choices; the manual's bootstrap layout shows the stored credentials as auth.enc and auth.key in Server/. Treat those two files as secrets. A running server refreshes its tokens on its own; per that guide, a fresh login is only needed after more than 30 days offline. One game licence covers up to 500 servers.
Updates, and why they cannot wait
Client and server must match the same protocol version exactly, so when Hypixel ships an update, players on the new client cannot join an old server. The built-in updater checks every hour by default and stages a new build in updater/staging/; when the update is applied the server stops with exit code 8, and start.sh copies in the new jar, assets and scripts while leaving config, saves and mods alone, then starts again.
/update check,/update downloadand/update apply --confirmdo it by hand;/update statusshows the running version.AutoApplyModeunderUpdateinconfig.jsonisDisabledby default, so nothing is applied until you act;WhenEmptyapplies once nobody is online, andScheduledapplies afterAutoApplyDelayMinutes(30 by default) with warnings to players.- Edit
config.jsononly with the server stopped: the manual says files changed by hand while it runs are likely to be overwritten.
The wrapper restarts only on exit code 8. A crash or any other exit ends the loop, and nothing here restarts it after a reboot: check sudo -u hytale tmux ls and start it again.
If a fresh update crashes on boot, start.sh points to updater/backup/. The manual's rollback deletes Server/ and Assets.zip first, but Server/ holds universe/, your config and the auth files, so rename it to Server.new (and Assets.zip to Assets.zip.new), move the files back from updater/backup/, then copy universe/, mods/, backups/, the .json files, auth.enc and auth.key from Server.new into Server/ before starting.
Backups off the machine
start.sh already passes --backup --backup-dir backups --backup-frequency 30, and because the wrapper runs the server from Server/, those backups land in /srv/hytale/game/Server/backups every 30 minutes. That folder shares a drive with the live world. As root, this one line packs it with mods/, the JSON config files and jvm.options into a timestamped archive and lists the archive back; it stops if no built-in backup exists yet, and prunes nothing:
`set -o pipefail; d=/root/hytale-archive; mkdir -p -m 700 "$d" && cd /srv/hytale/game/Server && if [ -n "$(ls -A backups 2>/dev/null)" ]; then f="$d/hytale-$(date +%F-%H%M%S).tgz" && tar -czf "$f" $(ls -d backups mods *.json ../jvm.options 2>/dev/null) && tar -tzf "$f" > /dev/null && echo "ok - $f" || echo "STOP - no archive written"; else echo "STOP - no built-in backup yet, the first lands about 30 minutes after start"; fi`
The world travels only inside the built-in backups; the live universe/ is not copied, and auth.enc and auth.key are left out on purpose so the archive holds no credentials. Pull the archives to another machine with scp and delete old ones there on your own schedule.
To put an archive back, stop the server (Ctrl+C at its console), set a= to the archive's name and paste this as root. It checks the archive and that no hytale session runs, unpacks into a dated folder under /root, moves the current backups, mods, JSON files and jvm.options into a dated pre-restore- folder inside Server/, copies the archive in, fixes ownership and starts the server. To roll back, stop it, move those items out of Server/ and move the contents of the pre-restore folder back (jvm.options to game/).
set -o pipefail
a=/root/hytale-archive/hytale-DATE.tgz # put the real archive name here
t=$(date +%F-%H%M%S); g=/srv/hytale/game; s=$g/Server; r=/root/hytale-restore-$t; k=$s/pre-restore-$t
[ -f "$a" ] && tar -tzf "$a" > /dev/null && ! sudo -u hytale tmux has-session -t hytale 2> /dev/null && \
mkdir -m 700 "$r" && tar -xzf "$a" -C "$r" && mkdir "$k" && \
( cd "$s" && for x in backups mods *.json; do [ ! -e "$x" ] || mv "$x" "$k/" || exit 1; done ) && \
{ [ ! -e "$g/jvm.options" ] || mv "$g/jvm.options" "$k/"; } && \
{ [ ! -e "$r/jvm.options" ] || mv "$r/jvm.options" "$g/"; } && \
cp -a "$r"/. "$s"/ && chown -R hytale:hytale "$s" && { [ ! -e "$g/jvm.options" ] || chown hytale:hytale "$g/jvm.options"; } && \
sudo -u hytale tmux new-session -d -s hytale "bash $g/start.sh" && \
echo "ok - restored, previous files in $k" || echo "STOP - not restored: archive name wrong or unreadable, server still running, or a step above stopped"
This restores the built-in backups folder, not the live world. The manual does not describe the format of its backup files or how to restore a world from one, so test that on a spare copy of the install first, and when you do it for real, set the current universe/ aside with mv; never delete it.
Ports, mods and more than one server
Change the port with --bind; start.sh forwards extra arguments, so bash start.sh --bind 0.0.0.0:5521 works, and the ufw rule has to move with it. Running two instances on one box means each gets its own install directory, its own tmux session and its own UDP port. Mods (.zip or .jar) go into Server/mods/. Crash reports go to Sentry; the manual asks plugin developers to pass --disable-sentry so their own development errors are not submitted. For a lighter voxel game that fits this hardware class, see the Luanti server notes.
Questions
How much RAM does a Hytale server need?
The manual's floor is 4 GB, and it gives no per-player figure. Memory follows the loaded world area, so view distance and players spreading out raise it; the manual recommends capping view distance at 12 chunks. Set the heap with -Xmx in jvm.options and watch usage under real load.
Which port does a Hytale server use?
UDP 5520 by default, carrying QUIC. No TCP port is needed. Choose a different one with --bind, then allow the new port through ufw in place of 5520.
Can it run on ARM?
The manual says both x64 and arm64 are supported, given Java 25, but it names no arm64 build of the downloader, so an arm64 install goes through the jar's --bootstrap mode. The setup on this page targets x64 Ubuntu 24.04, which every processor on our game server page runs.
Why can players not join after a game update?
Client and server must be on exactly the same protocol version, so an update to the client locks players out of a server that has not updated. Run /update check, then download and apply, or set AutoApplyMode to WhenEmpty so the server updates once nobody is online.
Does the server need a Hytale account?
Yes. The server must be authenticated, for example with /auth login device, before it accepts players, and the manual limits each game licence to 500 servers. The downloader also signs in with OAuth2 before it fetches files.
Can I rent the machine for a weekend?
A ready unit can be billed by the hour with a one-hour minimum and released when you are done. A build to a different configuration is monthly.