- Shell 87.4%
- Dockerfile 12.6%
| .github/workflows | ||
| .server-package | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.md | ||
About
Simple Docker image of Vintage Story Server for amd64, arm64 and arm v7 architectures.
The build detects the required .NET runtime before docker build starts by reading target framework information from VintagestoryServer.dll. The detected version is passed into the Dockerfile so the runtime stage stays on mcr.microsoft.com/dotnet/runtime:<detected-version>. In GitHub Actions the server package is downloaded once and reused in the build context, and the image build fails if that prepared server package is missing.
If automatic detection from VintagestoryServer.dll ever fails, you can still force the runtime manually with the build arg DOTNET_RUNTIME_VERSION, for example --build-arg DOTNET_RUNTIME_VERSION=8.0.
For local builds, place the extracted server files in .server-package/server/ before running docker build.
Note: Version 1.18.8+ only supports AMD64 architecture. Official ARM builds were discontinued as .NET 8 provides built-in ARM support, but Vintage Story still requires native AMD64 libraries. Consider using x86 emulation (QEMU) on ARM devices for newer versions.
Security: This image runs as a non-root user by default for better security. Legacy installations running as root are automatically detected and supported for backward compatibility. Existing non-root installations that use a custom UID/GID should continue to pass PUID and PGID explicitly.
Quick Start
Get started quickly with a single command:
docker run -d --name vintagestory \
-p 42420:42420/tcp \
-p 42420:42420/udp \
-v ./data:/vintagestory/data \
zsuatem/vintagestory:latest
Your server data will be stored in the ./data directory. Access the console with docker attach vintagestory (detach with Ctrl + P Q).
Tags
latest,stable- latest stable version1.16- latest 1.16.x (stable) version e.g. (1.14, 1.15)1.16.4- 1.16.4 (stable) version e.g. (1.14.10, 1.15.2)
unstable- latest unstable version1.16.5-rc.1- 1.16.5-rc.1 (preview, rc) version e.g. (v1.14.0-pre.11, v1.15.0-pre.8)
How to use
Simple run
Simple run with default settings (not recommended).
docker run --name vintagestory -d -it -p 42420:42420/tcp -p 42420:42420/udp zsuatem/vintagestory:latest
Data folder
If you want to easily change some settings or add mods you can mount the data folder or what you need to folder/file on your server. the data folder is mounted to a randomly named volume by default.
The data folder contains:
.
|-- BackupSaves
|-- Backups
|-- Cache
|-- Logs
|-- Macros
|-- Mods
|-- Playerdata
|-- Saves
|-- WorldEdit
|-- serverconfig.json
`-- servermagicnumbers.json
If you do not want to mount any file or folder you can copy the file from the server to the container using docker cp e.g. docker cp ./serverconfig.json vintagestory:/vintagestory/data/serverconfig.json.
Access to console
You can easily access the console using docker attach vintagestory where "vintagestory" is the container name.
To detach, use the keyboard shortcut Ctrl + P Q.
Run the server (docker run)
Run with the data folder mounted to a local directory (recommended):
docker run --name vintagestory -d -it \
-p 42420:42420/tcp \
-p 42420:42420/udp \
-v ./data:/vintagestory/data \
zsuatem/vintagestory:latest
Or using a named volume:
docker run --name vintagestory -d -it \
-p 42420:42420/tcp \
-p 42420:42420/udp \
-v vsserverdata:/vintagestory/data \
zsuatem/vintagestory:latest
Run the server (docker compose)
Same as above but as docker-compose.yml.
docker-compose.yml file:
services:
vintagestory:
image: zsuatem/vintagestory:latest
container_name: vintagestory
restart: always
ports:
- 42420:42420/tcp
- 42420:42420/udp
volumes:
- ./data:/vintagestory/data
stdin_open: true
tty: true
# Optional: Set custom user/group IDs
# environment:
# - PUID=1000
# - PGID=1000
Environment Variables
| Variable | Description | Default |
|---|---|---|
PUID |
User ID for the container process | 1000 |
PGID |
Group ID for the container process | 1000 |
Set these variables to match your host user/group IDs if you want to force a specific runtime user.
User and Permissions
Default Behavior (Recommended)
By default, the container runs as a non-root user with UID=1000 and GID=1000 for new installations.
docker run -d -p 42420:42420/tcp -p 42420:42420/udp -v vsserverdata:/vintagestory/data zsuatem/vintagestory:latest
# Runs as UID=1000, GID=1000 (non-root)
Custom User/Group IDs
If you need to force specific user/group IDs on your host system (e.g., to avoid permission issues with bind mounts), you can set custom PUID and PGID explicitly:
docker run -d \
-p 42420:42420/tcp \
-p 42420:42420/udp \
-v /path/to/data:/vintagestory/data \
-e PUID=1500 \
-e PGID=1500 \
zsuatem/vintagestory:latest
Or in docker-compose:
services:
vintagestory:
image: zsuatem/vintagestory:latest
environment:
- PUID=1500
- PGID=1500
volumes:
- /path/to/data:/vintagestory/data
Backward Compatibility (Legacy Installations)
If you're upgrading from an older version that stored data as root, the container will automatically detect this and continue running as root for backward compatibility. You'll see a warning message suggesting migration to non-root for better security.
If you're upgrading an existing non-root installation that used a custom UID/GID, keep passing the same PUID and PGID values after the upgrade.
Migration from Root to Non-Root
If you have an existing installation running as root and want to migrate to non-root:
Option 1: On Host (Recommended)
Fix permissions on your host before upgrading:
# Find your data directory (check with docker volume inspect)
sudo chown -R 1000:1000 /var/lib/docker/volumes/vsserverdata/_data
# or for bind mount:
sudo chown -R 1000:1000 /path/to/your/data
# Then run with default settings
docker run -d -v vsserverdata:/vintagestory/data zsuatem/vintagestory:latest
Option 2: Using Temporary Container
docker run --rm -v vsserverdata:/data ubuntu chown -R 1000:1000 /data
docker run -d -v vsserverdata:/vintagestory/data zsuatem/vintagestory:latest
Option 3: Keep Running as Root (Not Recommended)
If you prefer to keep running as root:
docker run -d -e PUID=0 -e PGID=0 -v vsserverdata:/vintagestory/data zsuatem/vintagestory:latest
Note: This bypasses security improvements and is not recommended.
Troubleshooting
Permission Denied Errors
If you see permission errors when the container starts:
-
Check ownership mismatch warning in container logs:
docker logs vintagestory -
Fix ownership on your host to match the user you want the container to run as:
sudo chown -R 1000:1000 /path/to/your/data -
Or set PUID/PGID to match your existing data explicitly:
# Find current ownership ls -ln /path/to/your/data # Set matching PUID/PGID docker run -e PUID=<uid> -e PGID=<gid> ... -
If this is an existing non-root installation with a custom UID/GID, keep passing the matching
PUID/PGIDvalues after upgrading.
Old vsuser startup bug
If you see a startup error like this:
Running with PUID=1000 and PGID=1000
Starting server as vsuser (UID=1000, GID=1000)...
❌ ERROR: User 1000:1000 cannot write to /vintagestory/data!
Current ownership: UID=1000 GID=1000
Fix permissions on your host:
sudo chown -R 1000:1000 /path/to/data
Or set PUID/PGID to match existing data ownership.
then you're likely running an older broken image version.
That error could happen even when the data directory ownership was already correct, because the old image tried to switch to a hard-coded user named vsuser and failed on some base images.
Fix:
- Pull the latest image again:
docker pull zsuatem/vintagestory:latest - Recreate the container with the updated image.
- If your existing data uses a custom non-root UID/GID, keep passing the matching
PUIDandPGIDvalues explicitly.
Container Runs as Root (Security Warning)
If you see warnings about running as root, this means you have data from an older version. For better security, consider migrating to non-root as described in the Migration section.
Healthcheck Causing Restarts
The image includes a healthcheck that verifies the server process is running. If your server takes a long time to start or you experience unexpected restarts, you can disable the healthcheck in docker-compose:
services:
vintagestory:
# ... other config ...
healthcheck:
disable: true
Or in docker run:
docker run --no-healthcheck ...
Useful URLs
- Official game site: Vintage Story
- GitHub repository: zsuatem/VintageStory-Docker
- Docker Hub: zsuatem/vintagestory