RE:NODE

Valheim on Pterodactyl: egg, ports and startup variables

By RE:NODE Team
12 min read


Running Valheim on a Pterodactyl panel takes four things: a Valheim egg imported into a nest, a node with two consecutive ports allocated to the server (the game port and the one above it, both reachable over UDP), the startup variables filled in - server name, world name, a password that shares no word with either, and public on or off - and a stop command of ^C, so the panel's Stop button sends SIGINT and the world saves before the container exits. Worlds then sit in the server's file manager under the container's home directory, and mods use a separate BepInEx egg rather than a modified vanilla one. Nearly every problem people hit is one of three: only one port allocated, a password the game rejects, or a world name that does not match the file.

This post is for two kinds of reader: people running their own Pterodactyl panel who are adding Valheim, and people renting a Valheim server from a host built on Pterodactyl who want to understand what the Startup and Network tabs are actually doing.

How Pterodactyl runs a Valheim server#

Pterodactyl has two halves. The panel is the web application where servers, users and settings live. Wings is the daemon on each machine (a node) that creates Docker containers, starts and stops them, streams their console and serves their files. Every game server is one container, with a memory, CPU and disk limit set by the panel, and a volume on the node that holds its files.

What the container does is defined by an egg - a JSON file describing one game. Eggs are grouped in nests. An egg holds:

PartWhat it is for Valheim
Docker imageThe runtime the server runs in, usually a SteamCMD-capable Debian or Ubuntu image
Install scriptRuns once in a separate installer container: SteamCMD downloads app 896660
Startup commandThe valheim_server.x86_64 line, with variables in place of values
VariablesName, world, password, public, and whatever else the egg exposes
Stop command^C, which Wings turns into SIGINT
Done stringA log line that tells the panel the server has finished starting

A good egg means nobody on the panel has to know SteamCMD exists. A bad one means the server reinstalls itself on every start, or gets killed every time it is stopped. Pterodactyl eggs for game servers goes through the format in general; this post sticks to what matters for Valheim. If Pterodactyl itself is new to you, the Pterodactyl panel explained is the background.

Getting and importing the Valheim egg#

Pterodactyl does not ship a Valheim egg. The community eggs repository on GitHub - formerly parkervcp/eggs, now maintained under the pelican-eggs organisation - has a Valheim folder with separate eggs for vanilla, for BepInEx and for Valheim Plus. Use the vanilla one unless you know you need mods; the variants are covered below.

To import it on a Pterodactyl 1.x panel:

  1. Download the egg's .json file from the repository. Read it - it is your server's install script.
  2. In the admin area, open Nests, pick or create a nest (a "Valheim" or "Survival games" nest is tidy), and use Import Egg.
  3. Open the imported egg and check the Docker image list, the startup command and the install script against what you expect.
  4. Create a server with that egg. The panel runs the install script, then the server is ready to start.

The installer container runs the egg's script with the server's volume mounted at /mnt/server, and in the running container the same volume is the home directory, /home/container. The install takes a few minutes the first time - the Valheim server is about 2 GB.

If you run Pelican, the Pterodactyl fork, eggs import in a similar way but the panel's structure differs; follow Pelican's own documentation for where the import lives.

Startup variables and the start line#

The egg's startup command is a template. Variables are written as {{NAME}} and replaced with each server's values at start. A simplified Valheim startup command looks like this - the exact variable names differ between egg versions, so read yours on the egg page or the server's Startup tab:

bash
./valheim_server.x86_64 -nographics -batchmode -name "{{SERVER_NAME}}" \    -port {{SERVER_PORT}} -world "{{WORLD}}" -password "{{PASSWORD}}" \    -public {{PUBLIC_SERVER}}

Real eggs add the environment Valheim needs before that line - LD_LIBRARY_PATH pointing at the server's linux64 folder and SteamAppId=892970 - either in the startup command or in the Docker image's entrypoint. The SteamCMD install guide explains why both are required.

{{SERVER_PORT}} is not an egg variable. It is set by Wings to the server's primary allocation, which is why the port never appears as an editable field. Other built-in values include SERVER_IP and SERVER_MEMORY.

The variables a Valheim egg typically exposes, by role:

VariableMaps toNotes
Server name-nameShown in the community list; must not contain the password
World name-worldThe file name in worlds_local, without extension, case-sensitive
Password-passwordMinimum 5 characters; no word shared with the name or world
Public-public1 lists the server, 0 hides it
Auto update(entrypoint)Runs a SteamCMD update on every start, if the egg has it
Extra argumentsappendedSome eggs have a free-text field for flags such as -crossplay

Each variable has validation rules, written in Laravel's syntax (required|string|min:5, for example), and two flags: whether users can see it and whether they can edit it. As a panel admin you decide which settings belong to the customer. Making the password user-editable with a min:5 rule saves you tickets; leaving the startup command itself locked keeps people from breaking the library path.

Valheim has no config file, so whatever the egg does not expose cannot be changed without editing the egg. If your egg has no field for crossplay, world modifiers or the save interval, an admin can add variables for them, or add a single free-text "additional arguments" variable to the end of the startup command. The flags and their defaults are in the Valheim launch arguments reference.

Allocations: getting both UDP ports right#

In Pterodactyl, a port is an allocation: an IP and port pair created on a node and assigned to one server. Wings publishes each allocation for both TCP and UDP, so there is no protocol setting to get wrong in the panel. There is a count to get wrong.

Valheim binds the game port and the port above it. You tell it the first with -port; the second follows automatically and cannot be set separately. So a Valheim server needs:

  1. A primary allocation on the game port, for example 2456. This becomes SERVER_PORT.
  2. An additional allocation on the very next port, 2457, assigned to the same server.

If the second allocation is missing, the server still starts and still binds 2457 inside the container - but nothing outside can reach it, because Docker never published it. The usual symptom is a server that players can join by IP but that never appears in the community list, because the list talks to the query port. Valheim server not showing in the list has the other causes of that symptom.

For an admin, the sequence is: on the node's Allocation tab, add the IP and a range such as 2456-2465; when creating the server, pick 2456 as primary and add 2457 as an additional allocation. For a second Valheim server on the same node, start at 2458 with 2459 beside it. Keep each server's pair consecutive - an allocation on 2460 does nothing for a server whose game port is 2458.

The node's own firewall must also allow these ports over UDP, and so must any cloud provider firewall in front of it. One trap: Docker writes its own iptables rules for published ports, and traffic to containers does not pass through ufw's normal input rules, so a ufw rule list that looks closed may not be, and one that looks open is not what actually admitted the traffic. Test from outside rather than trusting the rule list. Valheim ports 2456-2458 explained covers the port arithmetic and testing.

Stopping, the done string and saves#

Two lines in the egg's configuration decide whether the panel and Valheim get along.

The stop command is what the panel sends when someone presses Stop or Restart. For most games it is a console command such as stop or quit. Valheim has no stdin console, so its eggs use ^C, which Wings interprets as "send SIGINT to the process". That is the signal Valheim treats as a clean shutdown: it saves the world and exits. If an egg's stop command is anything else, the panel waits, nothing happens, and eventually someone presses Kill - which sends SIGKILL and loses everything since the last save.

The done string is a line from the server's output that the panel watches for to switch the server from "starting" to "running". For Valheim it is usually a line from the end of start-up, such as the one reporting that the game server has connected to Steam. If it never matches, the server works but sits in "starting" forever. The lines Valheim prints, and in which order, are in the Valheim server log explained.

Every Valheim world is held in memory and written every -saveinterval seconds (1800 by default). The panel's buttons, used correctly, give you a clean save:

Panel actionSignalWorld saved
StopEgg stop command (^C gives SIGINT)Yes
RestartStop, then startYes
KillSIGKILLNo
Container hits memory limitKilled by the kernelNo

Upstream Pterodactyl's default lets a container at its memory limit swap rather than be stopped. That keeps the process alive at the price of a server that crawls; either way, size the memory so it is never reached. Realistic figures are in how much RAM a Valheim server needs.

Files: where the world lives in the file manager#

The file manager and SFTP both show the container's volume, which is /home/container from the server's point of view. The game is in that folder. Valheim's save directory, unless the egg passes -savedir, is Unity's default under the home directory:

code
/home/container/.config/unity3d/IronGate/Valheim/    worlds_local/Midgard.db    worlds_local/Midgard.fwl    adminlist.txt    bannedlist.txt    permittedlist.txt

Some eggs set -savedir to a visible folder in the server root to make this easier to find; check your startup line. Dot-folders are easy to miss in file listings, which is why people sometimes conclude a world has vanished when it is sitting in .config.

To upload a world from single-player: stop the server, upload both the .db and .fwl into worlds_local, set the world-name variable to the file name without its extension, then start and watch the console for the world loading by name. Over SFTP, Wings listens on port 2022 by default and the username is your panel username joined to the server's short ID with a dot; the panel shows both on the server's Settings page. The full walkthrough is in uploading a local Valheim world to a server.

Panel backups are archives of the volume, so they include the save directory. Admins can exclude paths with a .pteroignore file in the server root - excluding the 2 GB of game files makes Valheim backups a fraction of the size, since SteamCMD can always download those again.

The BepInEx variant and mods#

Mods do not need a different game server; they need a different way of starting it. BepInEx hooks into Unity through a doorstop loader, configured by environment variables that the BepInExPack's start_server_bepinex.sh sets before launching valheim_server.x86_64. A vanilla egg starts the binary directly and never loads BepInEx, however many mod files you upload.

The community BepInEx egg handles this: its install script downloads the BepInExPack for Valheim alongside the server, and its startup sets the doorstop variables. Switching an existing server to it is done by an admin on the server's Startup settings in the admin area, by changing the egg; check whether the egg change triggers a reinstall on your panel version, and back up first.

Once BepInEx loads - its own lines appear at the top of the console - mods are .dll files dropped into BepInEx/plugins through the file manager or SFTP, with configs appearing in BepInEx/config after the first start. The Valheim Plus egg works the same way with Valheim Plus bundled; check that the build it downloads matches your game version, because Valheim Plus has gone through several forks. The rules for which mods go on the server, the client or both are in Valheim mods with BepInEx on a server. On a modded server, turn off any auto-update variable: a Valheim patch breaks most mods until they are rebuilt.

Schedules: restarts and backups on Pterodactyl#

Pterodactyl schedules take a cron expression and run a list of tasks in order, each with an optional delay: send a console command, perform a power action, or create a backup.

For Valheim, the console-command task is nearly useless - the server reads nothing from stdin, and there is no way to broadcast a warning in game - so a schedule is built from power actions and backups:

TaskActionDelay
1Power action: restart0
2Create backup120 seconds

Run it weekly at a quiet hour - 0 5 * * 1 is Monday at 05:00 in the panel's time zone. The restart stops the server cleanly, so the backup two minutes later captures a freshly saved world. A second schedule with only the backup task, daily, covers the other six days. Restart schedules that help explains why weekly is enough for Valheim, and cron expressions explained covers the syntax.

On RE:NODE#

RE:NODE runs its own panel on top of Pterodactyl and Wings, so everything in this post maps directly. A Valheim server arrives with both UDP ports allocated, crossplay already on and a password generated for you; the Startup tab holds the game variables, and the Network tab is where you add or remove ports. Mods are uploaded through the file manager or SFTP - there is no whitelist. Backup slots come with every plan, and the Schedules tab runs restarts and backups the way described above.

FAQ#

Why does my Valheim server on Pterodactyl not appear in the server list?

Usually because only the game port is allocated. Valheim also needs the port above it for Steam queries, assigned to the same server as an additional allocation. Join by IP to confirm the server itself works, then add the second allocation and restart.

Is Stop on the panel safe for the world?

Yes, if the egg's stop command is ^C. Wings then sends SIGINT and Valheim saves before exiting. Kill skips the save. If Stop seems to hang, check the egg's stop command before reaching for Kill.

Can I enable crossplay with the standard egg?

If the egg exposes a crossplay or extra-arguments variable, yes - add -crossplay. If not, an admin has to add one to the egg. Players then join with the six-digit code printed in the console at each start.

Where do I put Valheim mods on a Pterodactyl server?

In BepInEx/plugins, but only on a server using a BepInEx egg. A vanilla egg never loads BepInEx, so the files are ignored. Switch egg first, confirm BepInEx lines in the console, then upload mods.

Why does the server reinstall or update on every start?

The egg has an auto-update variable switched on, and its entrypoint runs SteamCMD before launching. That is handy for vanilla servers and harmful for modded ones; switch it off on the Startup tab if your egg exposes it.