> ## Content Index
> Fetch the complete content index at: https://blog.sudowl.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Running a Hytale Server in Docker With a Web Panel (and Ditching My systemd Unit)
- URL: https://blog.sudowl.com/hytale-server-docker-panel/
- Published: 2026-07-09T10:00:00.000Z
- Updated: 2026-10-11T10:16:27.000Z
- Description: Move a Hytale server from a bare systemd unit into Docker behind a web panel — container layout, UDP ports, console access, and keeping systemd as a fallback.
- Author: Lukas
- Tags: Hytale, Gameserver, Docker

I ran my Hytale server as a plain systemd unit for months and it was fine. Start, stop, `journalctl -f`, done. What finally moved me to Docker with a panel in front wasn't the server — it was everyone else. Every restart, every config tweak, every "can you check the log" went through me and my SSH key. That's a bottleneck with a person in it.

Now the server runs as a container, a panel container manages it, and the people who help me run the thing can restart it and read the console without touching a terminal. The systemd unit still exists — disabled, as a fallback — because I don't fully trust any panel to be the only way into my own server.

**TL;DR — the shape:**

```
panel container   :3000   → web UI, talks to the Docker socket
server container  :5520/udp → the actual Hytale server
volume            ./data   → world, config, logs (lives on the host)

```

If you're standing up Hytale for the first time, start with [/hytale-server-install-guide-prep/](https://blog.sudowl.com/hytale-server-install-guide-prep/) — this post is about what to do once it works and you want it manageable.

## Why a panel and not just `docker compose restart`

Be honest about whether you need one. If you're the only admin, you don't — a compose file and a shell alias beat a panel on every axis. A panel earns its complexity when:

- more than one person needs start/stop/console, and you don't want to hand out SSH,
- you want the console *readable* without teaching people `journalctl`,
- you want a big obvious "restart" button that doesn't `rm -rf` the world folder when someone fat-fingers it.

That's it. It's a permissions and ergonomics tool, not a performance one. The panel doesn't make the server faster; it makes the humans faster.

## The compose file

```yaml
services:
  panel:
    image: ketbom/hytale-panel:latest
    container_name: hytale-panel
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./panel-data:/app/data
    environment:
      - PANEL_SECRET=${PANEL_SECRET}

  server:
    image: hytale-server:latest
    container_name: hytale-server
    restart: unless-stopped
    stop_grace_period: 60s
    ports:
      - "5520:5520/udp"
    volumes:
      - ./data:/data
    stdin_open: true
    tty: true

```

Four lines in there do real work, and three of them are easy to miss.

**`5520:5520/udp`** — Hytale's game traffic is UDP. Omit `/udp` and Docker cheerfully publishes TCP, the port scan looks right, and not a single player connects. This is the single most common "my server is up but nobody can join" cause I've seen.

**`stop_grace_period: 60s`** — the default is 10 seconds, after which Docker sends SIGKILL. A game server killed mid-save leaves you a corrupt world and a bad evening. Give it a full minute to flush.

**`stdin_open: true` \+ `tty: true`** — this is what keeps the server console *attachable*. Without them, `docker attach` gives you nothing and the panel can't send commands into the process. You need both.

**The Docker socket mount.** Understand what you just did: the panel container can now control every container on the host, which is root-equivalent. That's how it starts and stops the server, and it's also why the panel must never be exposed to the internet unauthenticated. More on that below, because it's the part people get wrong.

## The console problem

Hytale's server wants an interactive console — for auth, for admin commands, for anything you'd normally type at the prompt. In a container, "the console" is stdin of PID 1, and getting at it is fiddlier than it looks.

`docker attach hytale-server` works, and then you accidentally hit `Ctrl+C` and kill the server, because attach forwards signals. Detach is `Ctrl+P Ctrl+Q`, which nobody remembers under pressure.

The safer route is a FIFO. Point the server's stdin at a named pipe on the host and write commands into it:

```bash
mkfifo /tmp/hytale-console
# feed the pipe into the container's stdin
docker run -i ... < /tmp/hytale-console

```

Then sending a command is just:

```bash
echo "auth login device" > /tmp/hytale-console

```

Now you can script it, the panel can write to it, and nobody's `Ctrl+C` takes down the server. Read the *output* separately with `docker logs -f hytale-server` — output and input are decoupled, which is exactly what you want.

The device-code auth flow is the one thing that still needs a human: kick it off on the console, watch the logs for the code and URL, approve it in a browser. Once. The token persists in the volume — which is a good reason for the volume to be on the host and in your backups, not in an anonymous Docker volume you'll delete by accident.

## Locking the panel down

The panel talks to the Docker socket. Anyone who gets into the panel effectively has root on the host. So:

**Don't publish :3000 to the world.** Bind it to localhost and reach it through a reverse proxy with TLS and auth:

```yaml
ports:
  - "127.0.0.1:3000:3000"

```

Then front it with nginx ([/nginx-reverse-proxy-setup/](https://blog.sudowl.com/nginx-reverse-proxy-setup/)) or Caddy, add a cert, and put HTTP basic auth in front of the panel's own login as a second layer. Belt and braces — panels are young software and I do not want to be the one who finds their auth bypass.

**Or don't expose it at all.** My preferred setup: the panel binds to a WireGuard address and is only reachable to people on the VPN. Zero public attack surface, and handing someone access is `wg set peer ...` instead of a password they'll reuse.

**Firewall the rest.** Only `5520/udp` should be publicly open. Docker famously writes its own iptables rules and will punch through UFW without asking — a `ports:` mapping is a hole in your firewall whether UFW knows about it or not. Bind to `127.0.0.1` for anything that isn't the game port, and check with `ss -tulnp` what's *actually* listening on the public interface. Trust the socket table, not your rules file.

## Backups, since the container makes it easy

The whole world is in `./data` on the host. So:

```bash
#!/bin/bash
set -euo pipefail
STAMP=$(date +%F-%H%M)
docker exec hytale-server sh -c 'echo "save-all" > /proc/1/fd/0' || true
sleep 10
tar czf "/backup/hytale-$STAMP.tar.gz" -C /opt/hytale data
find /backup -name 'hytale-*.tar.gz' -mtime +7 -delete

```

Flush the world before you tar it, or you're backing up a half-written save. `|| true` so a failed flush doesn't abort the backup entirely — a slightly-stale backup beats no backup. Run it on a timer, not a cron job, if you want the failures to show up in `journalctl`: [/systemd-timers-instead-of-cron/](https://blog.sudowl.com/systemd-timers-instead-of-cron/).

And restore-test it. An untested backup is a folder of hope. I restore into a throwaway container every few weeks; it takes five minutes and it's the only way to know the tarball isn't empty.

## Keep the systemd unit — disabled

This is the bit I'd argue for hardest. When I moved to Docker I didn't delete the old unit. I ran:

```bash
systemctl disable --now hytale

```

It's still there. If the panel breaks, if Docker eats itself, if I upgrade something and the container won't start at 1am, I can `systemctl start hytale` against the same data directory and be back up in thirty seconds while I debug the fancy stuff in daylight.

Two ways to run the same thing, one of them off, both working. That's not indecision — that's the cheapest disaster recovery you'll ever write.

Just don't ever run both at once. They'll both bind `5520/udp` and both write the same world files, and the resulting corruption is entirely your own fault. Ask me how I know that one too.

---

### Related posts

- [How to Install Mods on a Hytale Server (Full Guide)](https://blog.diengdoh.com/install-hytale-mods-plugins-guide/?ref=blog.sudowl.com)
- [How to Set Up a Hytale Dedicated Server (2026 Guide)](https://blog.diengdoh.com/hytale-server-install-guide-prep/?ref=blog.sudowl.com)
- [Bridging a Hytale Forum and Discord Without Making a Mess](https://blog.diengdoh.com/hytale-forum-discord-bridge/?ref=blog.sudowl.com)