How can xinetd services be migrated to a systemd-based setup?

Linux 3 min read

Xinetd is an old-school ‘super server’: it listens on the configured ports, and when a connection arrives, it launches the corresponding program, which communicates with the client via that connection. In this way, even simple programs that merely read from standard input and write to standard output could be turned into network services.

Xinetd has been removed from Red Hat-based systems: on AlmaLinux 9 and 10, it is not available either in the system repositories or in EPEL (during testing, the command dnf info xinetd returned ‘No matching packages’ on both). If you are migrating a service running under xinetd from an old server, you must configure it as a systemd socket. Systemd does exactly the same thing: it listens on the port and starts the program for each connection.

We tested these steps on AlmaLinux 10.2; the process works in exactly the same way on any distribution that uses systemd (Rocky Linux, Ubuntu, Debian).

The default xinetd service

A typical xinetd configuration in the /etc/xinetd.d/directory:

service fontosapp
{
    type        = UNLISTED
    port        = 3662
    socket_type = stream
    protocol    = tcp
    wait        = no
    user        = nobody
    server      = /usr/local/bin/fontosapp
    disable     = no
}

It listens on TCP port 3662; for each connection, it launches the /usr/local/bin/fontosapp program as the nobody, and sends the program’s output to the client. The wait = no setting means that each connection is assigned its own process.

1. The socket file

In systemd, the component that listens on the port is a .socket file, for example /etc/systemd/system/fontosapp.socket:

[Unit]
Description=Sajat alkalmazas socket

[Socket]
ListenStream=3662
Accept=yes

[Install]
WantedBy=sockets.target

Accept=yes is equivalent to the xinetd setting wait = no: a separate service instance is launched for each connection.

2. The service file

The file that starts the program is /etc/systemd/system/fontosapp@.service. The @ in the filename is mandatory: with Accept=yes, systemd launches an instance from this template for each connection, and the filename must match the socket name (fontosapp.socket → fontosapp@.service).

[Unit]
Description=Sajat alkalmazas kiszolgalo

[Service]
ExecStart=-/usr/local/bin/fontosapp
User=nobody
StandardInput=socket
  • ExecStart: the full path to the program. Because of the - at the beginning, systemd does not treat it as an error if the program exits with a non-zero code.
  • User: corresponds to the xinetd user setting. If root privileges are not required, do not grant them; the example runs as the nobody user.
  • StandardInput=socket: the program’s input (and, by default, its output too) will be the network connection, just as it is under xinetd.

3. Enabling and starting

It is not the service but the socket that needs to be enabled and started:

sudo systemctl daemon-reload
sudo systemctl enable --now fontosapp.socket
systemctl status fontosapp.socket

systemd then monitors this port; in the test, the output of sudo ss -tlnp | grep 3662 was *:3662 … users:(("systemd",pid=1,…)).

4. Try it out

A simple test program that displays the computer’s name and the time:

#!/bin/sh
echo "Szia, $(hostname)! Ido: $(date +%T)"

Connecting to the port (using bash’s built-in /dev/tcp option instead of nc, so there’s no need to install anything):

exec 3<>/dev/tcp/127.0.0.1/3662; cat <&3; exec 3<&-

In the test, the response was Szia, vps! Ido: 23:04:07, whilst the systemctl status fontosapp.socket command also displayed the number of accepted connections (Accepted: 1; Connected: 0;).

If you need to access it from outside

The socket listens on all network interfaces. If you are only using the service locally on your machine, enter the local address in the ListenStream line (ListenStream=127.0.0.1:3662). If the service needs to be accessible from outside and firewalld is running, open the port (sudo firewall-cmd --permanent --add-port=3662/tcp, followed by sudo firewall-cmd --reload). If you are using a non-standard port, SELinux may also be involved; see: SELinux: why am I getting a ‘Permission denied’ error?

The article on managing systemd services covers the systemctl command, whilst the journalctl article deals with their logs.

Back: Linux articles (62)