I migrated my Luanti Mineclonia world from my desktop to a dedicated server. Thankfully, it is very easy to do that! I love Free Software (free as in libre).
I set it up in docker-compose, and I merely copied my entire .minetest
directory to the service account. So it had all my worlds, modes, games, and (the three different categories in the ContentDB for Luanti) already.
Then I set up my service in a docker-compose.yml, and also the venerable mapserver in a separate compose file. Here's what I've got so far.
# File: /home/luanti/game/docker-compose.yml
# Reference:
# https://github.com/linuxserver/docker-luanti
# https://github.com/minetest-mapserver/mapserver/blob/master/docker-compose.yml
# https://github.com/minetest-mapserver/mapserver/blob/master/doc/install.md more useful
---
version: "3.5"
services:
luanti:
image: lscr.io/linuxserver/luanti:latest
container_name: luanti
environment:
- PUID=1009
- PGID=1009
- TZ=Etc/UTC
- "CLI_ARGS=--gameid mineclonia --worldname world1"
volumes:
- /home/luanti/.minetest:/config/.minetest
ports:
- 30000:30000/udp
restart: unless-stopped
...
Yes, I used the linuxserver.io build of a docker image because it came up first in my search. It also took me a while to learn that it configured to use config file .minetest/main-config/minetest.conf
. No biggie, once you know about it.
And then my mapserver is separate, so I can bring it up and down while I'm testing.
# Reference:
# https://github.com/minetest-mapserver/mapserver/blob/master/docker-compose.yml
# https://github.com/minetest-mapserver/mapserver/blob/master/doc/install.md more useful
---
version: "3.5"
services:
mapserver:
image: ghcr.io/minetest-mapserver/mapserver
restart: always
networks:
- default
volumes:
- /home/luanti/.minetest/worlds/world1:/minetest
working_dir: "/minetest"
ports:
- 8086:8080/tcp
...
I had to open up the firewall on the docker host (server4).
sudo firewall-cmd --add-port=8086/tcp --permanent
sudo firewall-cmd --reload
On my https reverse proxy, for which I still don't have websockets quite right but it is somehow functional enough:
# 2025-03-07-6 08:02 for luanti game mineclonia world world1
RewriteEngine on
RewriteRule ^/map-world1$ /map-world1/ [R,L] # not working, but whatever
<Location "/map-world1/">
ProxyPreserveHost On
ProxyPass http://server4:8086/ retry=20 connectiontimeout=300 timeout=300 upgrade=websocket
ProxyPassReverse http://server4:8086/
RequestHeader set X-Script-Name /map-world1
RequestHeader set Upgrade websocket
RequestHeader set Connection upgrade
</Location>
Once I ran the docker-compose up -d
for mapserver, it generated the worlds/world1/mapserver.json
which I customized for my needs.
{
"configversion": 1,
"port": 8080,
"enableprometheus": true,
"enablerendering": true,
"enablesearch": true,
"enableinitialrendering": true,
"enabletransparency": false,
"enablemediarepository": false,
"webdev": false,
"webapi": {
"enablemapblock": false,
"secretkey": "IUEXAMPLELTdht3n"
},
"layers": [
{
"id": 0,
"name": "below1",
"from": -8,
"to": -7
},
{
"id": 1,
"name": "below2",
"from": -7,
"to": -6
},
{
"id": 2,
"name": "below3",
"from": -6,
"to": -5
},
{
"id": 3,
"name": "below4",
"from": -5,
"to": -4
},
{
"id": 4,
"name": "below5",
"from": -4,
"to": -3
},
{
"id": 5,
"name": "below6",
"from": -3,
"to": -2
},
{
"id": 8,
"name": "below7",
"from": -2,
"to": -1
},
{
"id": 6,
"name": "Ground",
"from": -1,
"to": 10
},
{
"id": 7,
"name": "Sky",
"from": 11,
"to": 24
}
],
"renderingfetchlimit": 500,
"renderingjobs": 8,
"renderingqueue": 10,
"incrementalrenderingtimer": "5s",
"mapobjects": {
"areas": true,
"bones": false,
"protector": true,
"xpprotector": true,
"privprotector": true,
"technic_quarry": false,
"technic_switch": false,
"technic_anchor": false,
"technic_reactor": false,
"luacontroller": false,
"digiterms": false,
"digilines": false,
"travelnet": false,
"mapserver_player": true,
"mapserver_poi": true,
"mapserver_label": true,
"mapserver_trainline": false,
"mapserver_border": true,
"tileserverlegacy": true,
"mission": false,
"jumpdrive": false,
"smartshop": false,
"fancyvend": false,
"atm": false,
"train": false,
"trainsignal": false,
"minecart": false,
"locator": false,
"signs": true,
"mapserver_airutils": false,
"phonograph": false,
"um_area_forsale": false
},
"mapblockaccessor": {
"expiretime": "10s",
"purgetime": "15s",
"maxitems": 50
},
"defaultoverlays": [
"mapserver_poi",
"mapserver_label",
"mapserver_player"
],
"skins": {
"enableskinsdb": false,
"skinspath": ""
},
"worldpath": "./",
"datapath": "./",
"colorstxtpath": "./"
}
The initial map tile generation took a while (a few hours?) on my hardware, for a 160MB map.sqlite. It's worth noting that the from and to values in the layers are not node coordinates; they are the mapblock coordinates. You just divide the node coordinates by 16 to get the mapblock coordinates. So in a Mineclonia mapgen v7 world with node Y coord -128 as bedrock, the bottom is just -8. And my colors.txt which shows grass as an ugly brown (for some lame reason) came from my Luanti mapping notes.
I was hoping to investigate adding mod respawn support to mod mapserver but since poi was already supported and is good enough, I didn't bother. I can live with adding crafted blocks in the world for the map to show them.
I haven't yet solved the problem of world backups. I suppose I would want to exclude all the mapserver tile files.