Drahkar Posted December 4, 2025 Report Posted December 4, 2025 (edited) Dedicated Server Docker Image Vintage Story Dedicated Server Docker Image, built on Debian 13 is based on the official Vintage Story server installation instructions, and extracted from server.sh for better Docker compatibility. Docker Image References Docker Hub: ralnoc/vintagestory Github: ghcr.io/darkmatterproductions/vintagestory Links Github Repository: https://github.com/DarkMatterProductions/vintagestory Usage To run the Vintage Story Dedicated Server Docker container, use the following command: docker run -d \ --name vintagestory-server \ -p 42420:42420/tcp \ -p 42420:42420/udp \ -v /path/to/your/vs/data:/vintagestory/data \ --restart unless-stopped \ ghcr.io/darkmatterproductions/vintagestory Note: Replace /path/to/your/vs/data with the path to the directory on your server, where you want to persist your Vintage Story server data. This is critical to ensure that your world data, configurations, and mods are not lost when upgrading, which results in the container being removed. When starting the server, remember to map the data directory to a persistent volume on your host machine to ensure that your server data is not lost when the container is removed. If you leverage our published docker image at ghcr.io/darkmatterproductions/vintagestory or ralnoc/vintagestory, it will always install the latest version of Vintage Story server. This will dramatically simplify the upgrade process, and removes any issues with the in place upgrade, as you are replacing the image, not upgrading in place. Configuration There are four options for handling configuration of the Vintage Story server: Use the default configuration, as defined within the Docker image. This is not recommended for production use. Pre-create the serverconfig.json configuration file in your mapped data directory. This file will be used by the server on first run. Create an updated server-config.yaml and mount it into the container at /vintagestory/server-config.yaml. This will cause the server to generate a serverconfig.json file based on the provided YAML configuration. Use environment variables to override specific configuration options. See the list of supported environment variables below. Environment Variables You can enable additional logging by setting one of the following environment variables: ENABLE_DEBUG_LOGGING=true - Enables debug level logging ENABLE_CHAT_LOGGING=true - Enables chat logging VS_CFG_SERVER_NAME - Set the server name VS_CFG_SERVER_URL - Set the server URL VS_CFG_SERVER_DESCRIPTION - Set the server description VS_CFG_WELCOME_MESSAGE - Set the welcome message VS_CFG_ALLOW_CREATIVE_MODE - Enable or disable Allow Creative Mode VS_CFG_SERVER_IP - Set the server IP VS_CFG_SERVER_PORT - Set the server port VS_CFG_SERVER_UPNP - Enable or disable UPNP VS_CFG_SERVER_COMPRESS_PACKETS - Enable or disable packet compression VS_CFG_ADVERTISE_SERVER - Enable or disable server advertisement VS_CFG_MAX_CLIENTS - Set the maximum number of clients VS_CFG_PASS_TIME_WHEN_EMPTY - Enable or disable pass time when empty VS_CFG_SERVER_PASSWORD - Set the server password VS_CFG_MAX_CHUNK_RADIUS - Set the maximum chunk radius VS_CFG_SERVER_LANGUAGE - Set the server language VS_CFG_ONLY_WHITELISTED - Enable or disable only whitelisted players VS_CFG_ANTIABUSE - Enable or disable anti-abuse VS_CFG_ALLOW_PVP - Enable or disable PvP VS_CFG_HOSTED_MODE - Enable or disable hosted mode VS_CFG_HOSTED_MODE_ALLOW_MODS - Enable or disable hosted mode mods Example of running the container with environment variable overrides: docker run -d \ --name vintagestory-server \ -p 42420:42420/tcp \ -p 42420:42420/udp \ -v /path/to/your/vs/data:/vintagestory/data \ -e ENABLE_DEBUG_LOGGING=true \ -e ENABLE_CHAT_LOGGING=true \ -e VS_CFG_SERVER_NAME="My Vintage Story Server" \ --restart unless-stopped \ ghcr.io/darkmatterproductions/vintagestory Viewing Logs The Vintage Story server logs are routed to standard output and standard error. The can then be viewed using the command: docker logs vintagestory-server. Building the Docker Image To build the Docker image locally, use the following command: docker build -t vintagestory:1.21.5 --build-arg VS_VERSION=1.21.5 --build-arg DOTNET_VERSION=8.0 . This command builds the Docker image and tags it as vintagestory:1.21.5. You can replace 1.21.5 with the desired version of Vintage Story by changing the VS_VERSION build argument. If building on a linux server, you can use an environment variable to set the version: export VS_VERSION=1.21.5 export DOTNET_VERSION=8.0 docker build -t vintagestory:$VS_VERSION --build-arg VS_VERSION=$VS_VERSION --build-arg DOTNET_VERSION=$DOTNET_VERSION . This will build the Docker image with the specified version of Vintage Story and .NET SDK. Docker Compose You can also use Docker Compose to manage the Vintage Story server container. Below is an example docker-compose.yml file: version: '3.8' services: vintagestory-server: image: ghcr.io/ralnoc/vintagestory:latest container_name: vintagestory-server ports: - "42420:42420/tcp" - "42420:42420/udp" volumes: - /path/to/your/vs/data:/vintagestory/data environment: - ENABLE_DEBUG_LOGGING=true - ENABLE_CHAT_LOGGING=true - VS_CFG_SERVER_NAME=My Vintage Story Server restart: unless-stopped To start the server using Docker Compose, run the following command in the directory where your docker-compose.yml file is located: docker-compose up -d This command will start the Vintage Story server container in detached mode. Docker Compose Build If you want to build the Docker image using Docker Compose, you can add a build section to the docker-compose.yml file: version: '3.8' services: vintagestory-server: build: context: . args: VS_VERSION: 1.21.5 DOTNET_VERSION: 8.0 image: vintagestory:1.21.5 container_name: vintagestory-server ports: - "42420:42420/tcp" - "42420:42420/udp" volumes: - /path/to/your/vs/data:/vintagestory/data environment: - ENABLE_DEBUG_LOGGING=true - ENABLE_CHAT_LOGGING=true - VS_CFG_SERVER_NAME=My Vintage Story Server restart: unless-stopped Edited January 15 by Drahkar Updating the formatting and placement of the image references to help people leverage the pre-built images better.
Alexander Wilhelm Benedictus Posted December 5, 2025 Report Posted December 5, 2025 This is so useful when trying to set up a Vintage Story server on an opensuse. In theory it should be quite stable even on tumbleweed. I couldn't get the docker get the image form ghcr.io/darkmatterproductions/vintagestory, it just gave unauthorized error even if I was logged in ghcr.io on docker. Maybe it's private or not pushed there? However, I did manage to get it working by pulling the repo from github and then just building the image locally. Thank you!
Drahkar Posted December 5, 2025 Author Report Posted December 5, 2025 I'm glad this has been helpful! It was one of the first things I ran into, when I started playing. I generally don't play on my local machine, opting to instead host it on a another one. That way if friends want to play, they can do so without being at my schedule's mercy. Also, thank you for letting me know about the access issue on the packages at the Github Registry. I've fixed that, and it should work fine now. The repository permissions got mixed up when I switched the repo public, after getting the image to build and run correctly. I'm currently working on finding a way to detect when a new version and new build version of the server is available, so that I can automatically kick off the build process for the images. But even without that, I plan to keep the images up to date for those who don't have the ability to run the docker build process themselves. I should have the current build version posted to the registry tonight.
SneakyHomeless Posted January 15 Report Posted January 15 (edited) Hey, I can't manage to get it to work, getting an error saying it can't locate package `aspnetcore-runtime-8`. This is on your latest version, I will submit an Issue on github as I really don't know my stuff around this, would be glad if you could help! Thanks for the work. Edit: I got it working by using `apt-get dotnet-sdk-${DOTNET_VERSION}.0` Instead of the previous aspnetcore Edited January 15 by SneakyHomeless
Drahkar Posted January 15 Author Report Posted January 15 Thank you for calling the issue out. I'm assuming that your actively building the image, instead of just using the published on. I'll get online tonight to update the Dockerfile. The pre-built images work as is.
bughazard Posted January 18 Report Posted January 18 Howdy, I've somewhat recently switched to Linux (Debian 13) and I'm not particularly familiar with Docker, so please bear with me if you think I have missed something obvious here. I've been trying to get a dedicated server working with my computer for a few weeks now. I ran the provided command to run the Docker container, pointing the file path towards a new empty directory (empty other than a config file). It doesn't throw any errors and the logs show that the server is active, but when I try to connect to it with my IP address it just times out. I'm imagining I was supposed to do something major before running this but I'm not really sure what it is... Please help me out there, haha. Thank you for your help.
Drahkar Posted January 19 Author Report Posted January 19 Hey there! Can you paste the exact command you are using? And the docker-compose.yaml file, if you are using it.
bughazard Posted January 19 Report Posted January 19 Yes, here is the command I am using: docker run -d \ --name vintagestory-server \ -p 42420:42420/tcp \ -p 42420:42420/udp \ -v /home/username/Server \ -e ENABLE_DEBUG_LOGGING=true \ -e ENABLE_CHAT_LOGGING=true \ -e VS_CFG_SERVER_NAME="My Vintage Story Server" \ --restart unless-stopped \ ghcr.io/darkmatterproductions/vintagestory [I have replaced my username with "username" as it contains my full name] I used a serverconfig.json file, which I copied from the one that is in the singleplayer game files and mildly edited to disable the whitelist, specify the port, and added a temporary password (I planned on editing this in more depth after I got the server working). I placed in the home/username/Server folder: Spoiler { "FileEditWarning": "PLEASE NOTE: This file is also loaded when you start a single player world. If you want to run a dedicated server without affecting single player, we recommend you install the game into a different folder and run the server from there.", "ConfigVersion": "1.9", "ServerName": "My Vintage Story Server", "ServerUrl": null, "ServerDescription": "Welcome to my server", "WelcomeMessage": "Welcome {0}, may you survive well and prosper", "Ip": null, "Port": 42420, "Upnp": false, "CompressPackets": true, "AdvertiseServer": false, "MaxClients": 5, "MaxClientsInQueue": 0, "PassTimeWhenEmpty": false, "MasterserverUrl": "http://masterserver.vintagestory.at/api/v1/servers/", "ModDbUrl": "https://mods.vintagestory.at/", "ClientConnectionTimeout": 150, "EntityDebugMode": false, "Password": "password", "MapSizeX": 1024000, "MapSizeY": 256, "MapSizeZ": 1024000, "ServerLanguage": "en", "MaxChunkRadius": 12, "TickTime": 33.333332, "SpawnCapPlayerScaling": 0.5, "BlockTickChunkRange": 5, "MaxMainThreadBlockTicks": 10000, "RandomBlockTicksPerChunk": 16, "BlockTickInterval": 300, "SkipEveryChunkRow": 0, "SkipEveryChunkRowWidth": 0, "Roles": [ { "Code": "suvisitor", "PrivilegeLevel": -1, "Name": "Survival Visitor", "Description": "Can only visit this world and chat but not use/place/break anything", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "chat" ], "RuntimePrivileges": [], "DefaultGameMode": 1, "Color": "Green", "LandClaimAllowance": 0, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 3, "AutoGrant": false }, { "Code": "crvisitor", "PrivilegeLevel": -1, "Name": "Creative Visitor", "Description": "Can only visit this world, chat and fly but not use/place/break anything", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "chat" ], "RuntimePrivileges": [], "DefaultGameMode": 2, "Color": "DarkGray", "LandClaimAllowance": 0, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 3, "AutoGrant": false }, { "Code": "limitedsuplayer", "PrivilegeLevel": -1, "Name": "Limited Survival Player", "Description": "Can use/place/break blocks only in permitted areas (priv level -1), create/manage player groups and chat", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "chat", "build", "useblock", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 1, "Color": "White", "LandClaimAllowance": 0, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 3, "AutoGrant": false }, { "Code": "limitedcrplayer", "PrivilegeLevel": -1, "Name": "Limited Creative Player", "Description": "Can use/place/break blocks in only in permitted areas (priv level -1), create/manage player groups, chat, fly and set his own game mode (= allows fly and change of move speed)", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "chat", "build", "useblock", "gamemode", "freemove", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 2, "Color": "LightGreen", "LandClaimAllowance": 0, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 3, "AutoGrant": false }, { "Code": "suplayer", "PrivilegeLevel": 0, "Name": "Survival Player", "Description": "Can use/place/break blocks in unprotected areas (priv level 0), create/manage player groups and chat. Can claim an area of up to 8 chunks.", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "chat", "areamodify", "build", "useblock", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 1, "Color": "White", "LandClaimAllowance": 262144, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 3, "AutoGrant": false }, { "Code": "crplayer", "PrivilegeLevel": 100, "Name": "Creative Player", "Description": "Can use/place/break blocks in all areas (priv level 100), create/manage player groups, chat, fly and set his own game mode (= allows fly and change of move speed). Can claim an area of up to 40 chunks.", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "chat", "areamodify", "build", "useblock", "gamemode", "freemove", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 2, "Color": "LightGreen", "LandClaimAllowance": 1310720, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 6, "AutoGrant": false }, { "Code": "sumod", "PrivilegeLevel": 200, "Name": "Survival Moderator", "Description": "Can use/place/break blocks everywhere (priv level 200), create/manage own/other player groups, chat, kick/ban players and do serverwide announcements. Can claim an area of up to 4 chunks.", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "manageotherplayergroups", "chat", "areamodify", "build", "useblock", "buildblockseverywhere", "useblockseverywhere", "kick", "ban", "announce", "readlists", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 1, "Color": "Cyan", "LandClaimAllowance": 1310720, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 60, "AutoGrant": false }, { "Code": "crmod", "PrivilegeLevel": 500, "Name": "Creative Moderator", "Description": "Can use/place/break blocks everywhere (priv level 500), create/manage own/other player groups, chat, kick/ban players, fly and set his own or other players game modes (= allows fly and change of move speed). Can claim an area of up to 40 chunks.", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "controlplayergroups", "manageplayergroups", "manageotherplayergroups", "chat", "areamodify", "build", "useblock", "buildblockseverywhere", "useblockseverywhere", "kick", "ban", "gamemode", "freemove", "commandplayer", "announce", "readlists", "attackcreatures", "attackplayers", "selfkill" ], "RuntimePrivileges": [], "DefaultGameMode": 2, "Color": "Cyan", "LandClaimAllowance": 1310720, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 60, "AutoGrant": false }, { "Code": "admin", "PrivilegeLevel": 99999, "Name": "Admin", "Description": "Has all privileges, including giving other players admin status.", "DefaultSpawn": null, "ForcedSpawn": null, "Privileges": [ "build", "useblock", "buildblockseverywhere", "useblockseverywhere", "attackplayers", "attackcreatures", "freemove", "gamemode", "pickingrange", "chat", "kick", "ban", "whitelist", "setwelcome", "announce", "readlists", "give", "areamodify", "setspawn", "controlserver", "tp", "time", "grantrevoke", "root", "commandplayer", "controlplayergroups", "manageplayergroups", "selfkill", "manageotherplayergroups", "worldedit" ], "RuntimePrivileges": [], "DefaultGameMode": 1, "Color": "LightBlue", "LandClaimAllowance": 2147483647, "LandClaimMinSize": { "X": 5, "Y": 5, "Z": 5 }, "LandClaimMaxAreas": 99999, "AutoGrant": true } ], "DefaultRoleCode": "suplayer", "ModPaths": [ "Mods", "/home" ], "AntiAbuse": 0, "WorldConfig": { "Seed": "1821141230", "SaveFileLocation": "/home/vsserver", "WorldName": "Awesome Village Lands", "AllowCreativeMode": true, "PlayStyle": "surviveandbuild", "PlayStyleLangCode": "preset-surviveandbuild", "WorldType": "standard", "WorldConfiguration": { "gameMode": "survival", "playerlives": "-1", "startingClimate": "temperate", "spawnRadius": "50", "graceTimer": "0", "deathPunishment": "keep", "droppedItemsTimer": "600", "seasons": "enabled", "daysPerMonth": "9", "harshWinters": "true", "blockGravity": "sandgravel", "caveIns": "off", "allowFallingBlocks": true, "allowFireSpread": true, "lightningFires": false, "allowUndergroundFarming": false, "noLiquidSourceTransport": false, "playerHealthPoints": "15", "playerHealthRegenSpeed": "1", "playerHungerSpeed": "1", "lungCapacity": "40000", "bodyTemperatureResistance": "0", "playerMoveSpeed": "1.5", "creatureHostility": "aggressive", "creatureStrength": "1", "creatureSwimSpeed": "2", "foodSpoilSpeed": "1", "saplingGrowthRate": "1", "toolDurability": "1", "toolMiningSpeed": "1", "propickNodeSearchRadius": "6", "microblockChiseling": "stonewood", "allowCoordinateHud": true, "allowMap": true, "colorAccurateWorldmap": false, "loreContent": true, "clutterObtainable": "ifrepaired", "temporalStability": true, "temporalStorms": "sometimes", "tempstormDurationMul": "1", "temporalRifts": "visible", "temporalGearRespawnUses": "20", "temporalStormSleeping": "0", "worldClimate": "realistic", "landcover": "0.975", "oceanscale": "5", "upheavelCommonness": "0.5", "geologicActivity": "0.05", "landformScale": "1.0", "worldWidth": "1024000", "worldLength": "1024000", "worldEdge": "traversable", "polarEquatorDistance": "100000", "storyStructuresDistScaling": "1", "globalTemperature": "1", "globalPrecipitation": "1", "globalForestation": "0", "globalDepositSpawnRate": "1", "surfaceCopperDeposits": "0.12", "surfaceTinDeposits": "0.007", "snowAccum": "true", "allowLandClaiming": true, "classExclusiveRecipes": true, "auctionHouse": true }, "MapSizeY": 256, "CreatedByPlayerName": "bughazard", "DisabledMods": [], "RepairMode": false }, "NextPlayerGroupUid": 10, "GroupChatHistorySize": 20, "MaxOwnedGroupChannelsPerUser": 10, "OnlyWhitelisted": false, "WhitelistMode": 0, "VerifyPlayerAuth": true, "DefaultSpawn": null, "AllowPvP": true, "AllowFireSpread": true, "AllowFallingBlocks": true, "HostedMode": false, "HostedModeAllowMods": false, "VhIdentifier": null, "StartupCommands": null, "RepairMode": false, "AnalyzeMode": false, "CorruptionProtection": true, "RegenerateCorruptChunks": false, "ChatRateLimitMs": 1000, "DieBelowDiskSpaceMb": 400, "ModIdBlackList": null, "ModIdWhiteList": null, "ServerIdentifier": "d31ba0e7-8c5e-4f15-bce4-f42d692c0d22", "LogBlockBreakPlace": false, "LogFileSplitAfterLine": 500000, "DieAboveErrorCount": 100000, "LoginFloodProtection": false, "TemporaryIpBlockList": false, "DisableModSafetyCheck": false, "DieAboveMemoryUsageMb": 50000 }
Fat_Lizardman Posted 20 hours ago Report Posted 20 hours ago Hey! I just made a fork of your project and added this mod to auto install https://mods.vintagestory.at/vintagercon so that the server has a means of remote communications, i also added ttyd to handle the exposure of the rcon server so now the console is accessible via http. check it out! https://github.com/JoshEvans-Weber/casaos-store/tree/ff130cc42fe8a93582401eb1e16af357f5bc41c1/Apps/vintagestory-custom this container also has been put into a repository that is accessible via CasaOS's appstore using the instructions in the readme.md
Recommended Posts