Implementing Systemd Socket Activation for Valheim Dedicated Server

Posted on .

This is a post about how I set up the Valheim dedicated server for socket activation with Systemd, so that it can be started and shut down on demand. This helps it use less resources, keeping the server and the environment happier. If you just want to grab the codes, you might skip directly to the repository, but keep in mind that it requires understanding of Systemd and Linux system administration.

Using Gleam Packages in Your Elixir Project

Posted on .

Using Gleam packages in an Elixir project is not as simple as adding {:lib, "1.2.3"} to your mix.exs, but it's pretty close. There are two issues preventing this simple usage:

  1. Elixir's Mix doesn't know how to compile a Gleam package, which does not have any build setup. It's literally a bunch of Erlang files in a folder. I'm not sure if there is an issue about this.
  2. Gleam writes dev dependencies into the built app.src file, which causes the app to crash on startup, as the dev dependencies aren't there. Gleam issue #3035 deals with this matter.

To circumvent these issues, add your Gleam dependency to mix.exs like this:

{:scriptorium, "~> 2.0.0", app: false, manager: :rebar3}

The first option prevents reading the app file of the dependency entirely. It seems to work for libraries, but I'm not sure of its effects on Gleam projects with startable apps. I believe they won't be automatically started at least. Most Gleam projects at this point are libraries or are explicitly started, so this is likely not an issue for you.

The second tells Mix to use Rebar to build the package. This seems to work even for a plain "Erlang files in a folder" type package that Gleam generates.

You can read more about these options in Mix's documentation.

Once you've gotten your dependency installed, remember that the calling syntax is different from a typical Elixir module. Gleam modules are named according to their path with @ as a separator. For example, to call parse_header from scriptorium/parser/common, use the following:

:scriptorium@parser@common.parse_header("...")

Also note that Gleam custom types map to tuples in Elixir, and more specifically records. In fact you can define a record on the Elixir side to match your Gleam types and operate on them. For example, here's a record from one of my early mixed Elixir/Gleam projects, GeoTherminator:

defmodule GeoTherminator.PumpAPI.Device do
  require Record

  Record.defrecord(:record, :device, [
    :id,
    :device_id,
    :is_online,
    :last_online,
    :created_when,
    :mac_address,
    :name,
    :model,
    :retailer_access
  ])

  # Create idiomatic Elixir type as an alias for Gleam side type
  @type t :: :pump_api@device.device()
end

Now we can use GeoTherminator.PumpAPI.Device.t() in typespecs, and calls like GeoTherminator.PumpAPI.Device.record(my_device, :id) and GeoTherminator.PumpAPI.Device.record(my_device, name: "My Device") to operate on the type in Elixir land.

Minimise Caddy Logging

Posted on .

I've been moving stuff to my new home server and been setting up services with Caddy. It has been a breath of fresh air after my messy Nginx configurations and Let's Encrypt setup. But I found the default logs to contain waaay more information than I needed. So here's a snippet to configure logging to stdout (for Systemd's journald) and remove some extraneous stuff that I don't need to see:

First Time Waxing a Bicycle Chain

Posted on .

I use my bicycles to commute to work year round. The wet, muddy, and slushy seasons really take a toll on the powertrain, and I get tired of the constant need to clean and lubricate the chain. Especially as the oil based lubricants attract grime to the chain. A coworker hinted almost a year ago that he waxes his bike's chain and it has been less work, so I finally decided to try it.

Glossy New Blog

Posted on .

It's a rite of passage for a programmer to write a blog engine. It's lunacy to keep writing blog engines when there was nothing wrong with the previous ones. This blog is now in its fifth incarnation, if I have kept count correctly. Starting in 2015 with a couple of JavaScript based no-backend engines, following up with the Elixir & Phoenix based Mebe, and then with Elixir & Raxx based Mebe 2. Now it's time for Scriptorium.