yaq-project / yaq-python

Repository for yaq core python packages.
https://yaq.fyi
GNU Lesser General Public License v3.0
6 stars 5 forks source link

Systemd socket activation #1

Open untzag opened 2 years ago

untzag commented 2 years ago

Narrower scope issue stemming from yaqd-core-python#19

Systemd allows for activating daemons on incomming socket communications:

From man 7 daemon:

Socket-Based Activation

   In order to maximize the possible parallelization and robustness and simplify configuration and
   development, it is recommended for all new-style daemons that communicate via listening sockets
   to employ socket-based activation. In a socket-based activation scheme, the creation and
   binding of the listening socket as primary communication channel of daemons to local (and
   sometimes remote) clients is moved out of the daemon code and into the init system. Based on
   per-daemon configuration, the init system installs the sockets and then hands them off to the
   spawned process as soon as the respective daemon is to be started. Optionally, activation of
   the service can be delayed until the first inbound traffic arrives at the socket to implement
   on-demand activation of daemons. However, the primary advantage of this scheme is that all
   providers and all consumers of the sockets can be started in parallel as soon as all sockets
   are established. In addition to that, daemons can be restarted with losing only a minimal
   number of client transactions, or even any client request at all (the latter is particularly
   true for state-less protocols, such as DNS or syslog), because the socket stays bound and
   accessible during the restart, and all requests are queued while the daemon cannot process
   them.

New-style daemons which support socket activation must be able to receive their sockets from the init system instead of creating and binding them themselves. For details about the programming interfaces for this scheme provided by systemd, see sd_listen_fds(3) and sd- daemon(3). For details about porting existing daemons to socket-based activation, see below. With minimal effort, it is possible to implement socket-based activation in addition to traditional internal socket creation in the same codebase in order to support both new-style and old-style init systems from the same daemon binary.

systemd implements socket-based activation via .socket units, which are described in systemd.socket(5). When configuring socket units for socket-based activation, it is essential that all listening sockets are pulled in by the special target unit sockets.target. It is recommended to place a WantedBy=sockets.target directive in the "[Install]" section to automatically add such a dependency on installation of a socket unit. Unless DefaultDependencies=no is set, the necessary ordering dependencies are implicitly created for all socket units. For more information about sockets.target, see systemd.special(7). It is not necessary or recommended to place any additional dependencies on socket units (for example from multi-user.target or suchlike) when one is installed in sockets.target.

Doing this involves a few steps:

https://docs.python.org/3/library/socket.html?highlight=socket#socket.fromfd

I believe this is how it is handed off using the environment variable $LISTEN_FDS_START Which will provid FDs 3, 4, 5, ... for the sockets specified.

Since we may have multiple sockets in one process, we do in fact need to be concerned about the number, and probably should use names to check, especially as we allow disabling of individual ones via the config...