If you can't adjust your program's main loop so that it exits after a certain period without socket activity, then you could use systemd-socket-proxyd
, which does have an idle timeout option.
Suppose your service is called thing.service
. It is listening on LISTEN_ADDR. You are going to add a service which sits between thing.socket
and thing.service
and forwards connections from LISTEN_ADDR to PRIVATE_LISTEN_ADDR.
Adjust the configuration for thing
to listen on PRIVATE_LISTEN_ADDR instead of LISTEN_ADDR. This might be done in thing.service
, or perhaps in thing.conf
- it depends on the application.
Configure your service to be stopped if no other unit depends on it. This can be done by setting StopWhenUnneeded=true
in the [Unit]
section of your thing.service
file.
Add thing-proxy.service
. This makes connections to thing.service
via PRIVATE_LISTEN_ADDR. We have configured the idle timeout here to be 10 minutes.
[Unit]
Requires=thing.service
After=thing.service
Requires=thing.socket
After=thing.socket
[Service]
ExecStart=/usr/lib/systemd/systemd-socket-proxyd --exit-idle-time=10min PRIVATE_LISTEN_ADDR
PrivateTmp=yes
PrivateNetwork=yes
Adjust thing.socket
so that it starts thing-proxy.service
instead of thing.service
:
[Socket]
Accept=false
ListenStream=LISTEN_ADDR
Service=thing-proxy.service
[Install]
WantedBy=sockets.target
The values of LISTEN_ADDR and PRIVATE_LISTEN_ADDR could be hostname:port
for TCP services, or UNIX domain socket paths, or perhaps both, depending on what you want, and what the app can do. They just need to be different addresses because now you have two processes listening for connections.