Wandering Thoughts archives

2022-07-29

How systemd names instances of templated socket service units

Systemd famously has socket units, which cause systemd itself to listen on something and start a systemd unit when the there's traffic. In other words, systemd can act like (x)inetd. When you do this for a stream-based service (such as a TCP based one), there are two options for what systemd should do when there's a connection, controlled by the Accept= setting.

The default and normal behavior (in systemd) is 'Accept=no', which causes systemd to start the service unit associated with the socket and pass it the listening socket (or sockets) to interact with. If you specify 'Accept=yes', you get xinetd-like behavior where a new instance of the service is spawned for each new connection, and the instance is passed only the connected socket. As the documentation covers, Accept=yes requires that you have a template .service unit; if you have 'oidentd.socket' set with Accept=yes, you have to have an 'oidentd@.service' unit. This service unit will be instantiated with a specific instance name.

You might wonder what the instance name actually is for such a service unit, especially since the systemd documentation is silent about this. For IPv4 connections, the answer turns out to be that the unit names come out like this:

oidentd@<number>-<server-ip>:<server-port>-<client-ip>:<client-port>,service

The number isn't a process ID and it seems to stay constant over multiple instances, so I don't know where it comes from. I suspect that IPv6 connections will look substantially the same, just with IPv6 IP addresses instead of IPv4 ones. I don't know what local stream connections will look like (and I don't feel like experimenting).

Update: looking more closely, the number appears to be a sequence number that increments for each new instance.

On the one hand, this is somewhat convenient for your logs, since you can always tell what the exact connection a given instance was spawned for. On the other hand, this creates rather long service names, probably among the longest server names you have, and if you have anything that's trying to index observed unit names, it's going to be fed lots and lots of units that probably appear only once.

(So Grafana Loki will have another cardinality problem.)

Since this format for socket instance names isn't documented, I would avoid depending on it for anything beyond log parsing. It's probably unlikely to change at this point, but you never know. This implies that the '%i' instance parameter (see systemd.unit's discussion of template and instance units) probably isn't very useful in templated socket service units. You do have the remote (client) IP address and port available in environment variables, although you don't get the server IP or port passed to you.

(Of course you can determine both the local and remote addresses in your code by examining the socket.)

linux/SystemdSocketTemplateServiceNames written at 23:03:29; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.