Knowledge Base

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

Mod for Luanti: lava furnace

I wrote a novel mod for Luanti, specifically for Mineclonia: Lava Furnace.

Go get the code for yourself!

Snippets of the readme

Furnaces powered by being adjacent to lava for Mineclonia. Yes, this breaks balance because it does not need fuel. This is for fun, for large-scale operations in the lategame. Do not install this mod if the imbalance bothers you.

Heavily based on Minetest Game (default/furnace.lua).

Using

Build a lava-powered furnace with a gold block surrounded by 8 cobblestone, or a gold block and a furnace. Lava source or flowing lava must be adjacent (NESWUD) touching this lava furnace.

Configuring

# Speed factor for cooking with lava furnace.
# 1 is a regular furnace, 2 is a blast furnace.
# Requires a restart to take effect.
lava_furnace.factor (Cooking speed factor for lava) float 4.0 0.0 16.0

# Comma-separated list of '<node>,<node>'
# Nodes that can power lava furnace when immediately adjacent
lava_furnace.fuel_nodes (Nodes that power lava furnace) string mcl_core:lava_source,mcl_core:lava_flowing

By default these settings make a lava furnace 4x faster than a regular furnace, and the lava furnace must touch a lava source or flowing lava.

It's a little overpowered for early gameplay, but it makes lategame play easier because you don't have to keep every single furnace stocked with fuel.

Screenshot of lava furnace cooking while in front of flowing lava

Additional credits

Additional notes

Thankfully, I was able to just adapt the existing furnace code. I just disabled consuming the fuel, and made it "fueled" if any of the 6 surface-adjacent nodes is lava source or flowing lava. I also disabled putting fuel in the fuel slot, which is still there in case you want to put a bucket for drying out a wet sponge.

It took me less than a day to build and test this, which means, of course, that it has not been battle-tested beyond my small server. Contributions welcome!

Find xyz of village3 block in Luanti

If you want to find the exact coordinate of your poi block which you buried in a wall or the ground somewhere, use this sqlite3 snippet.

$ sqlite3 mapserver.sqlite
sqlite> select o.* from objects o JOIN object_attributes oa ON o.uid = oa.object_uid where oa.value like '%village3%';
uid|x|y|z|posx|posy|posz|type|mtime
32467ab9-b5fb-4109-bf97-08e77b606b48|-11|28|-1345|-1|1|-85|poi|1746707872

Screenshot of village3 poi block in-game

Chromium: use Debian key to keep google user signed in

For a Devuan user who also uses Chromium, a change within the past year or 2 by Google causes the browser to always require the google user to log back in after starting up the browser.

The current fix for this is to apply the Debian project oauth2 client id and secret from a particular file. In file /etc/chromium.d/oauth2-client:

export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --oauth2-client-id=7718EXAMPLE.apps.googleusercontent.com --oauth2-client-secret=OTJgUEXAMPLE7GsGZq2G4IlT"

References

Weblinks

  1. Ripped directly from Enabling Chromium to sync with Google Account - Stack Overflow

Alternate research

File ~/.config/chromium-flags.conf did not work in my testing, from Arch Linux.

--oauth2-client-id=7718EXAMPLE.apps.googleusercontent.com
--oauth2-client-secret=OTJgUEXAMPLE7GsGZq2G4IlT

Internal files

Rocky Linux 9 and sss ssh knownhosts proxy

Enterprise Linux, even while providing /usr/bin/sss_ssh_knownhostsproxy, still suffers from the same problem I discovered in Devuan GNU+Linux.

The problem lies with how ssh client wants the public keys of the knownhosts available to it, but sssd does not seem to cache it in the way ssh client wants. While /usr/bin/sss_ssh_knownhostsproxy exists, apparently the future intended way to do things is to run sss_ssh_knownhosts. You can cajole sss_ssh_knowhostsproxy to display the right info, in this small script.

# File: /usr/local/bin/sss_stackrpms_knownhosts
for word in ${@} ;
do
   /usr/bin/sss_ssh_knownhostsproxy -k "${word}" | awk -v"w=${word}" '{print w,$0}'
done

I should have used sed for that because it would have been simpler, but I already deployed it so whatever.

sed -r -e "s:^:${word} :"

So the output resembles

$ sss_stackrpms_knownhosts server2
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NEXAMPLEIAO0bzgyjqGKvQKEXAMPLEZhvjWmGE1QTpGa1gt6EB7Y root@server2
server2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjCggwwfNNCmXIpdz/yQPMEXAMPLEv8t/NJ3hi37WmET1d/Sr/VOJI7EXAMPLE3Hvq9KugRmzyOEXAMPLE1cG5MvLGIpu7EXAMPLE1vREf9foa3WzDdo5rv4EHGtunaQnj5BvyQHViQ18IjG4f0C5GbcTEX+2ubDYU1tomAGEXAMPLEYoh7ChhBH+/dSF8TRS3uaZUjmsyyv/ojN4mJtpFZABKfUpBPOIijIApNAC4ENRzlrbj+qpb9eMQO8xJAhsyYvqWFZYudodhybpijEXAMPLEENw0y/xvKv6tXrGPjPS4ZiSUoy9vtcg99Tnjru6NqHCWVrOham6zZhm8Qp8W4DCAAhZOd0pcJ0gcf7i9l4cVX6BywlPb6NGTmLf27JY58XIlJii7x7JA+G7ioEXAMPLEGlbHrPkaiKk4n0ej7zh8xJ+3bjAtgixIZMpVd4dTgPZ8TLUr0ShcPEXAMPLEo5grAPpwdQQJkTtkWDUw/MngXQrc+gNHgHTDmEBcFTs= root@server2
server2 ecdsa-sha2-nistp256 AAAAE2VjEXAMPLEoYTItbmlzdHAyNTYAAAEXAMPLEHAyNTYAAABBBKrIRGEXAMPLEFWNdQIva/usB6zCEXAMPLEOOWDQQEW4oT94REXAMPLEZ5qfsqZ+8VN5ivhEXAMPLEQ14JYRTGM= root@server2

And then you configure ssh client to use it, by completely replacing /etc/ssh/ssh_config.d/04-ipa.conf with the following.

# IPA-related configuration changes to ssh_config
#
PubkeyAuthentication yes
GlobalKnownHostsFile /var/lib/sss/pubconf/known_hosts
#VerifyHostKeyDNS yes

# assumes that if a user does not have shell (/sbin/nologin),
# this will return nonzero exit code and proxy command will be ignored
Match exec true   
    #ProxyCommand /usr/bin/sss_ssh_knownhostsproxy -p %p %h
    KnownHostsCommand /usr/local/bin/sss_stackrpms_knownhosts %H

I deploy using the equivalent of this in my config management (haha).

sudo install -m 0644 -o root -g root /mnt/public/Support/Platforms/Rocky/04-ipa.conf /etc/ssh/ssh_config.d/04-ipa.conf
sudo install -m 0755 -o root -g root /mnt/public/Support/Platforms/Rocky/sss_stackrpms_knownhosts /usr/local/bin/sss_stackrpms_knownhosts

Because it affects ssh client, it gets interpreted fresh for every use, so you don't need to restart any daemons or agents.

If and when EL gets binary /usr/bin/sss_ssh_knownohsts, then this script will be obsolete.

References

  1. FreeIPA on Devuan and sss ssh knownhosts proxy | Knowledge Base
  2. Issue #9536: Client configuration of ssh: Replace sss_ssh_knownhostsproxy with sss_ssh_knownhosts - freeipa - Pagure.io
  3. openssh 8.5 will support KnownHostsCommand · Issue #5518 · SSSD/sssd
  4. Not this problem: sss_ssh_knownhostsproxy prevents connection to machine without reverse address - Red Hat Customer Portal

Use Apache httpd as a reverse proxy for Minetest Mapserver

I use the Luanti Mapserver project for my various worlds, one instance per world. And because I'm old-school, I'm still rocking Apache httpd and still call it httpd like the old Enterprise Linux days and not "apache2" like the Devuanites. And I use httpd as a reverse proxy (for TLS termination, for one thing) for the mapserver.

The webpage works without the websocket upgrade, but the mapserver throws a stack trace complaining about the lack of the upgrade token in the Connection header.

level=error msg=ws-upgrade err="websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header"

After enough Internet research I found the answer! So here is my snippet for mapserver in my httpd config (inside the virtual host) that makes the magic happen.

RewriteEngine on
ProxyPreserveHost On
# mapserver
RewriteRule ^/games/luanti/world3/map$ /games/luanti/world3/map/ [R,L]
<Location "/games/luanti/world3/map/">
   ProxyPreserveHost On
   ProxyPass        http://server4:30011/ retry=20 connectiontimeout=300 timeout=300 upgrade=websocket
   ProxyPassReverse http://server4:30011/
   RequestHeader    set X-Script-Name /games/luanti/world3/map
   RewriteEngine on
   RewriteCond %{HTTP:Connection} Upgrade [NC]
   RewriteCond %{HTTP:Upgrade} websocket [NC]
   RewriteRule /(.*) ws://server4:30011/$1 [P,L]
</Location>

Because not the whole world uses that new-fangled nginx.

References

The secret sauce came from apache - Apache2 can't set headers "Connection" and "Upgrade" - Stack Overflow

Luanti contributions, part 3

Here's a summary of what I've been up to in the Luanti world since the last time.

Luanti serverlist self-hosted in Docker

The official Luanti serverlist is really cool, and is free software! The game client uses this list to show you the public instances. I forked it so I could make it work better with the arbitrary server addresses, and I built a docker container for it. I needed it to accept a server_address = dockerhost.ipa.example.com$30001 so that it would publish that hostname and port, rather than the connected IP address (an internal docker one) of 172.24.0.2 with port 30000 like the container always runs. This means my serverlist trusts the entry coming from the Luanti instance and does not do anything with the actual requester IP address, so it's not as secure.

No, it's not published on hub.docker.com or anywhere else. But it's pretty simple to build.

To build your own docker image with the static files, and no nodejs components, run this command in the repo directory, in my branch. My branch includes the generated servers.js downloaded from the public instance which for some reason took a whole node project to build?! I hate nodepm and never figured out how to use it, and I suppose this docker container is now overkill for just a small Flask project, but it fits nicely with my other docker infrastructure at this point.

docker build . -- tag luantiserverlist

Adjust docker-compose.yml if necessary, and mkdir /home/luanti/serverlist/run. The initial assets will be copied to this volume, for you adjust afterwards. Then you can run docker-compose.

docker-compose up -d

The included docker-compose.yml exposes port 8082.

For an easy reverse proxy in apache httpd, to serve at https://reverseproxy.example.com/games/luantiserverlist which you can place in your minetest.conf variable serverlist_url.

# Inside your virtual host.
ProxyPass        /games/luantiserverlist http://dockerhost.int.example.com:8082/
ProxyPassReverse /games/luantiserverlist http://dockerhost.int.example.com:8082/
<Location "/games/luantiserverlist">
   RequestHeader append X-Forwarded-Prefix "/games/luantiserverlist/"
</Location>

And then you can configure servers and clients to use this value.

serverlist_url = http://webserver.ipa.example.com/games/luantiserverlist/

It's really great to be able to list your own servers with pretty names and descriptions!

Praise the Lord for people who are willing to make FLOSS. I doubt many people will want my modifications, but they're there for anyone who would like it.

References

  1. Dockerizing a Python Flask App: A Step-by-Step Guide to Containerizing Your Web Application | by GeeekFa | Medium

Find exact tag of Docker image

I had a number of old docker images stored locally and didn't have all the tag info. I think I used ":latest" on most of them, but apparently calling an image that does not mean that every time the container restarts (at host reboot), it fetches the latest one. So some of my images were woefully behind, and as part of a good practice to upgrade to current images for everything, I wanted to know exactly which image I had before, in case I need to roll back.

And apparently there's not a good process for determining that. So I had to write a script to do it for me. And then I had to hack it to work with github container registry which operates differently than docker hub, in this case not as efficiently as docker hub.

We'll start with the script and then I'll explain it.

Read more…