spawn

What is spawn?

spawn is a suite which provides services to the process spawner of various other daemons, e.g. beng-proxy and Workshop.

The Accessory Daemon

This daemon listens for seqpacket connections on abstract socket @cm4all-spawn and allow clients to create namespaces (protocol definition). The client is usually the process spawner of daemons like beng-proxy and Lukko.

The Reaper Daemon

This daemon watches cgroups below certain scopes; once they run empty, statistics are collected and logged and the cgroup is deleted.

SIGHUP

On systemctl reload cm4all-spawn-reaper (i.e. SIGHUP), the daemon calls the Lua function reload if one was defined. It is up to the Lua script to define the exact meaning of this feature.

Resource Accounting

The file /etc/cm4all/spawn/reaper.lua is a Lua script which is executed at startup. If it defines a function called cgroup_released, then this function will be called every time a cgroup is reaped. The function may for example log its resource usage. Example:

function cgroup_released(cgroup)
  print(cgroup.memory_peak)
end

The following attributes of the cgroup parameter can be queried:

  • path: the cgroup path as noted in /proc/self/cgroup, e.g. /user.slice/user-1000.slice/session-42.scope

  • xattr: A table containing extended attributes of the control group.

  • parent: Information about the parent of this cgroup; it is another object of this type (or nil if there is no parent cgroup).

  • cpu_total, cpu_user, cpu_system: the total, userspace-only or kernel-only CPU usage [in seconds].

  • memory_peak: the peak memory usage [in bytes].

libsodium

There are some libsodium bindings.

Helpers:

bin = sodium.hex2bin("deadbeef") -- returns "\xde\xad\xbe\ef"
hex = sodium.bin2hex("A\0\xff") -- returns "4100ff"

Generating random data:

key = sodium.randombytes(32)

Sealed boxes:

pk, sk = sodium.crypto_box_keypair()
ciphertext = sodium.crypto_box_seal('hello world', pk)
message = sodium.crypto_box_seal_open(ciphertext, pk, sk)

`Point*scalar multiplication <https://doc.libsodium.org/advanced/scalar_multiplication>__:

pk = sodium.crypto_scalarmult_base(sk)

PostgreSQL Client

The Lua script can query a PostgreSQL database. First, a connection should be established during initialization:

db = pg:new('dbname=foo', 'schemaname')

In the handler function, queries can be executed like this (the API is similar to LuaSQL):

local result = assert(db:execute('SELECT id, name FROM bar'))
local row = result:fetch({}, "a")
print(row.id, row.name)

Query parameters are passed to db:execute() as an array after the SQL string:

local result = assert(
  db:execute('SELECT name FROM bar WHERE id=$1', {42}))

The functions pg:encode_array() and pg:decode_array() support PostgreSQL arrays; the former encodes a Lua array to a PostgreSQL array string, and the latter decodes a PostgreSQL array string to a Lua array.

To listen for PostgreSQL notifications, invoke the listen method with a callback function:

db:listen('bar', function()
  print("Received a PostgreSQL NOTIFY")
end)

Network Namespaces

The Debian package cm4all-spawn-netns contains the systemd service template cm4all-spawn-netns@.service which creates a new network namespace connected with the current namespace over a pair of veth devices. This requires a script in /etc/cm4all/spawn/netns/setup.d which sets up the veth device inside the new namespace; its name is passed as command-line argument. The other veth device is expected to be set up with systemd-networkd.

Slice

The Debian package cm4all-slice contains the systemd slice system-cm4all.slice where the scopes of most process spawners live.

NSS-LogName

The Debian package libnss-cm4all-logname contains a glibc NSS module which pretends there is a /etc/passwd entry for the current uid named $LOGNAME. This should be installed in containers spawned by the process spawner.