Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Luanti in docker-compose

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.

Comments