Skip to content
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.git
node_modules
dist
__pycache__
.vscode
server-files

**/*.md
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

# Shell scripts must be LF (important for Docker/Linux)
[*.sh]
end_of_line = lf
29 changes: 22 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# User Settings
PUID=1001
PGID=1001
# Example overrides for indifferentbroccoli/hytale-server-docker
#
# Copy this file to `.env` if you want to override any values:
# cp .env.example .env

# Optional: only needed if you want the container to run as a specific UID/GID
# (by default the image auto-detects a good UID/GID for rootful vs rootless engines)
# your host user id
PUID=
# your host group id
PGID=

# Server Settings
SERVER_NAME=hytale-server-docker
DEFAULT_PORT=5520
MAX_PLAYERS=20

# View Distance (in chunks, 12 chunks = 384 blocks)
# Higher values require more RAM. Recommended max: 12
VIEW_DISTANCE=12

# Authentication Mode (authenticated|offline)
Expand All @@ -20,6 +27,7 @@ AUTH_MODE=authenticated
ENABLE_BACKUPS=false
BACKUP_FREQUENCY=30
BACKUP_MAX_COUNT=5
# BACKUP_DIR=/home/hytale/server-files/backups

# Advanced Settings
DISABLE_SENTRY=true
Expand All @@ -30,11 +38,18 @@ ACCEPT_EARLY_PLUGINS=false
# Adjust based on your server resources and player count
MIN_MEMORY=4G
MAX_MEMORY=8G
# Custom JVM Arguments (optional)
# Example: JVM_ARGS=-XX:+UseG1GC -XX:+ParallelRefProcEnabled
JVM_ARGS=

# Download Settings
# Set to false to skip automatic server download on startup
DOWNLOAD_ON_START=true

# Custom JVM Arguments (optional)
# Example: JVM_ARGS=-XX:+UseG1GC -XX:+ParallelRefProcEnabled
JVM_ARGS=
# Downloader patchline (release|pre-release)
PATCHLINE=release

# Optional GSP token passthrough
SESSION_TOKEN=
IDENTITY_TOKEN=
OWNER_UUID=
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## Ensure Force all files Linux-friendly to LF line endings even when edited on Windows
* text=auto eol=lf
11 changes: 9 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Environment files with sensitive credentials
.env
*.env*
!.env.example

# Server files and data
server-files/
server-files*/

# Docker volumes
*.log
Expand All @@ -18,3 +19,9 @@ Thumbs.db
*.swp
*.swo
*~


# tests
**/*test
test*
*test*/
45 changes: 45 additions & 0 deletions Docker/docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
services:
hytale:
build:
context: ..
dockerfile: Dockerfile
image: indifferentbroccoli/hytale-server-docker
restart: unless-stopped
container_name: hytale
ports:
- 5520:5520/udp
# Optional runtime overrides (image has built-in defaults)
env_file:
- path: ../.env.example
required: false
# those are only neccessary for defaults, overriden by .env file
environment:
- PUID=${PUID}
- PGID=${PGID}
- SERVER_NAME=${SERVER_NAME:-hytale-server-docker}
- DEFAULT_PORT=${DEFAULT_PORT:-5520}
- MAX_PLAYERS=${MAX_PLAYERS:-20}
- VIEW_DISTANCE=${VIEW_DISTANCE:-12}
- AUTH_MODE=${AUTH_MODE:-authenticated}
- ENABLE_BACKUPS=${ENABLE_BACKUPS:-false}
- BACKUP_FREQUENCY=${BACKUP_FREQUENCY:-30}
- BACKUP_MAX_COUNT=${BACKUP_MAX_COUNT:-5}
- DISABLE_SENTRY=${DISABLE_SENTRY:-true}
- USE_AOT_CACHE=${USE_AOT_CACHE:-true}
- ACCEPT_EARLY_PLUGINS=${ACCEPT_EARLY_PLUGINS:-false}
- MIN_MEMORY=${MIN_MEMORY:-4G}
- MAX_MEMORY=${MAX_MEMORY:-8G}
- DOWNLOAD_ON_START=${DOWNLOAD_ON_START:-true}
- PATCHLINE=${PATCHLINE:-release}
volumes:
- ../server-files:/home/hytale/server-files
- ../scripts:/home/hytale/server # use scripts from host dir. # dev only
stdin_open: true
tty: true
develop:
watch:
- action: rebuild
path: .
entrypoint: ["sleep", "infinity"]
# entrypoint: ["/home/hytale/server/init.sh"]
73 changes: 40 additions & 33 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
# BUILD THE HYTALE SERVER IMAGE
FROM eclipse-temurin:25-jdk

# ENVIRONMENT (non user-defined)
ENV HOME=/home/hytale \
USERN=hytale \
SERVER_FILES=/home/hytale/server-files \
SERVER_ROOT=/home/hytale/server \
CONFIG_DIR=/home/hytale/server/hytale-config \
BACKUP_DIR=/home/hytale/server-files/backups \
PATH=/home/hytale/server:${PATH}

RUN apt-get update && apt-get install -y --no-install-recommends \
gettext-base \
procps \
jq \
curl \
gosu \
unzip \
wget \
ca-certificates \
Expand All @@ -18,40 +28,37 @@ LABEL maintainer="support@indifferentbroccoli.com" \
github="https://github.com/indifferentbroccoli/hytale-server-docker" \
dockerhub="https://hub.docker.com/r/indifferentbroccoli/hytale-server-docker"

# Create user/group
RUN userdel -r ubuntu 2>/dev/null || true && \
groupadd -g 1000 hytale && \
useradd -u 1000 -g 1000 -m -d /home/hytale -s /bin/bash hytale

ENV HOME=/home/hytale \
CONFIG_DIR=/hytale-config \
PATH=/home/hytale/server:${PATH} \
DEFAULT_PORT=5520 \
SERVER_NAME=hytale-server \
MAX_PLAYERS=20 \
VIEW_DISTANCE=12 \
ENABLE_BACKUPS=false \
BACKUP_FREQUENCY=30 \
BACKUP_MAX_COUNT=5 \
DISABLE_SENTRY=true \
USE_AOT_CACHE=true \
AUTH_MODE=authenticated \
ACCEPT_EARLY_PLUGINS=false \
DOWNLOAD_ON_START=true \
PATCHLINE=release \
SESSION_TOKEN="" \
IDENTITY_TOKEN="" \
OWNER_UUID=""

COPY ./scripts /home/hytale/server/

COPY branding /branding

RUN mkdir -p /home/hytale/server-files && \
chmod +x /home/hytale/server/*.sh && \
chown -R 1000:1000 /home/hytale

WORKDIR /home/hytale/server

# Create a default user (UID/GID can be adjusted at runtime by init.sh on rootful Docker)
RUN userdel -r ubuntu 2>/dev/null || true \
&& useradd -u 1000 -U -m -s /bin/bash ${USERN} \
&& mkdir -p ${SERVER_ROOT} ${SERVER_FILES} ${BACKUP_DIR} \
&& chown -R ${USERN}:${USERN} ${HOME} \
&& chmod 755 ${HOME}

# Copy some files
COPY --chown=${USERN}:${USERN} ./scripts ${SERVER_ROOT}
COPY --chown=${USERN}:${USERN} branding /branding

# Ensure scripts are executable even if we run as root and later drop privileges.
RUN chmod +x ${SERVER_ROOT}/*.sh \
&& chmod -R a+rX ${SERVER_ROOT}


# Rootless-compatible machine-id persistence
# We cannot write to /etc or /var/lib/dbus when running as non-root.
# Instead we make those paths symlinks to a file stored in the persistent volume.
RUN mkdir -p ${SERVER_FILES}/.machine-id /var/lib/dbus && \
rm -f /etc/machine-id /var/lib/dbus/machine-id && \
ln -s ${SERVER_FILES}/.machine-id/machine-id /etc/machine-id && \
ln -s ${SERVER_FILES}/.machine-id/dbus-machine-id /var/lib/dbus/machine-id

# NOTE: We intentionally do NOT set `USER` here.
# - On rootful Docker, init.sh will drop privileges to match the bind-mounted directory ownership.
# - On rootless Docker (userns), staying as container root ensures files created on a bind mount are owned by the host user.

WORKDIR ${SERVER_ROOT}

# Health check to ensure the server is running
HEALTHCHECK --start-period=5m \
Expand Down
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
[![GitHub Repo stars](https://img.shields.io/github/stars/indifferentbroccoli/hytale-server-docker?style=for-the-badge&color=6aa84f)](https://github.com/indifferentbroccoli/hytale-server-docker)
[![Discord](https://img.shields.io/discord/798321161082896395?style=for-the-badge&label=Discord&labelColor=5865F2&color=6aa84f)](https://discord.gg/indifferentbroccoli)
[![Docker Pulls](https://img.shields.io/docker/pulls/indifferentbroccoli/hytale-server-docker?style=for-the-badge&color=6aa84g)](https://hub.docker.com/r/indifferentbroccoli/hytale-server-docker)
<!-- markdownlint-disable MD060 -->
<!-- markdownlint-disable MD028 -->

Game server hosting

Expand All @@ -27,6 +29,7 @@ A Docker container for running a Hytale dedicated server with automatic download
| Storage | 10GB | 20GB |

> [!NOTE]
>
> - Hytale requires **Java 25** (included in the Docker image)
> - Server resource usage depends heavily on player count and view distance
> - Higher view distances significantly increase RAM usage
Expand All @@ -35,7 +38,7 @@ A Docker container for running a Hytale dedicated server with automatic download

> [!IMPORTANT]
> **First-Time Setup: Authentication Required**
>
>
> On first startup, you'll need to authenticate via your browser. The server will display a URL in the console - just visit it and log in with your Hytale account. You will then need to authorize again from the link that appears once the server has started.

## How to use
Expand Down Expand Up @@ -122,6 +125,21 @@ You can use the following values to change the settings of the server on boot.
| PATCHLINE | release | Selects the patchline for the game (`release` or `pre-release`) |
| DOWNLOAD_ON_START | true | Automatically download/update server files on startup |

## Rootless Docker / file ownership

- **Rootful Docker engine** (normal Docker): the container starts as root and then automatically drops privileges to match the ownership of the mounted `server-files` directory (or `PUID/PGID` if you set them). This prevents creating `root:root` files on your host.
- **Rootless Docker engine** (`dockerd-rootless`): the container detects user-namespace mapping and stays as container root. In rootless mode, container root is mapped to *your* host user, so files created in `server-files` are owned by you.

If you still run into permission issues, ensure the host directory exists and is writable by your user:

```bash

mkdir -p server-files
chmod 755 server-files
```

Also you can edit .env files PUID and PGID to match your host user.

## Port Configuration

Hytale uses the **QUIC protocol over UDP** (not TCP). Make sure to:
Expand All @@ -130,12 +148,11 @@ Hytale uses the **QUIC protocol over UDP** (not TCP). Make sure to:
2. **Forward UDP port 5520** in your router if hosting from home
3. Configure firewall rules for UDP only


## File Structure

After first run, the following structure will be created in your `server-files` directory:

```
``` markdown
server-files/
├── Server/
│ ├── HytaleServer.jar # Main server executable
Expand Down Expand Up @@ -168,36 +185,43 @@ View distance is the primary driver for RAM usage:
- **RAM Impact:** Higher view distances exponentially increase memory requirements

Tune `MAX_MEMORY` and `VIEW_DISTANCE` based on:

- Number of concurrent players
- How spread out players are in the world
- Available server resources

## Useful Commands

### View server logs

```bash
docker logs hytale -f
# or
docker-compose logs -f
```

### Stop the server

```bash
docker-compose down
```

### Restart the server

```bash
docker-compose restart
```

### Update server files

Server files are automatically updated on restart if `DOWNLOAD_ON_START=true`. To force an update:

```bash
docker-compose restart
```

### Send commands to the server console

```bash
# Send a command to the running server
docker exec -u hytale hytale command.sh "/auth status"
Expand All @@ -213,7 +237,6 @@ docker exec -u hytale hytale command.sh "/op add player"
- [Official Hytale Server Manual](https://support.hytale.com/hc/en-us/articles/45326769420827-Hytale-Server-Manual)
- [GitHub Issues](https://github.com/indifferentbroccoli/hytale-server-docker/issues)


## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Loading