There are multiple ways to get a service to launch under
We’re going to show two methods which correspond approximately to two of
our generic Fossil server setup methods, the
and standalone HTTP server methods.
A fun thing you can easily do with
systemd that you can’t directly do
with older technologies like
xinetd is to set a server up
as a “user” service.
You can’t listen on TCP port 80 with this method due to security
restrictions on TCP ports in every OS where
systemd runs, but you can
create a listener socket on a high-numbered (≥ 1024) TCP port,
suitable for sharing a Fossil repo to a workgroup on a private LAN.
To do this, write the following in
[Unit] Description=Fossil user server After=network.target [Service] WorkingDirectory=/home/fossil/museum ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil Restart=always RestartSec=3 [Install] WantedBy=sockets.target WantedBy=multi-user.target
xinetd, we don’t need to tell
user and group to run this service as, because we’ve installed it
under the account we’re logged into, which
systemd will use as the
systemd that we want automatic service restarts with
back-off logic, making this much more robust than the by-hand launches
fossil in the platform-independent Fossil server instructions. The
service will stay up until we explicitly tell it to shut down.
A simple and useful modification to the above scheme is to add the
--localhost flags to the
ExecStart line to replace the
fslsrv in the generic SCGI instructions,
giving a much more robust configuration.
Because we’ve set this up as a user service, the commands you give to manipulate the service vary somewhat from the sort you’re more likely to find online:
$ systemctl --user daemon-reload $ systemctl --user enable fossil $ systemctl --user start fossil $ systemctl --user status -l fossil $ systemctl --user stop fossil
That is, we don’t need to talk to
sudo privileges, but
we do need to tell it to look at the user configuration rather than the
This scheme isolates the permissions needed by the Fossil server, which reduces the amount of damage it can do if there is ever a remotely-triggerable security flaw found in Fossil.
systemd based OSes, user services only run while that user is
logged in interactively. This is common on systems aiming to provide
desktop environments, where this is the behavior you often want. To
allow background services to continue to run after logout, say:
$ sudo loginctl enable-linger $USER
You can paste the command just like that into your terminal, since
$USER will expand to your login name.
Another workaround for the problem with user services above is to install the service as a system service instead. This is a better path when you are proxying Fossil with a system-level service, such as nginx.
There are just a small set of changes required:
Install the unit file to one of the persistent system-level unit file directories. Typically, these are:
Group directives to the
[Service] section so
Fossil runs as a normal user, preferrably one with access only to
the Fossil repo files, rather than running as
Another useful method to serve a Fossil repo via
systemd is via a
socket listener, which
systemd calls “socket activation.”
It’s more complicated, but it has some nice properties. It is the
feature that allows
systemd to replace
xinetd, Upstart, and
several other competing technologies.
We first need to define the privileged socket listener by writing
[Unit] Description=Fossil socket [Socket] Accept=yes ListenStream=80 NoDelay=true [Install] WantedBy=sockets.target
Note the change of configuration directory from the
to the system level. We need to start this socket listener at the root
level because of the low-numbered TCP port restriction we brought up
This configuration says more or less the same thing as the socket part
inted entry exemplified elsewhere in this
Next, create the service definition file in that same directory as
[Unit] Description=Fossil socket server After=network.target [Service] WorkingDirectory=/home/fossil/museum ExecStart=/home/fossil/bin/fossil http repo.fossil StandardInput=socket [Install] WantedBy=sockets.target WantedBy=multi-user.target
We’ll explain the “
@” in the file name below.
Notice that we haven’t told
systemd which user and group to run Fossil
under. Since this is a system-level service definition, that means it
will run as root, which then causes Fossil to automatically drop into a
chroot(2) jail rooted at the
we’ve configured above, shortly each
fossil http call starts.
Restart* directives we had in the user service configuration above
are unnecessary for this method, since Fossil isn’t supposed to remain
running under it. Each HTTP hit starts one Fossil instance, which
handles that single client’s request and then immediately shuts down.
Next, you need to tell
systemd to reload its system-level
configuration files and enable the listening socket:
$ sudo systemctl daemon-reload $ sudo systemctl enable fossil.socket
And now you can manipulate the socket listener:
$ sudo systemctl start fossil.socket $ sudo systemctl status -l fossil.socket $ sudo systemctl stop fossil.socket
Notice that we’re working with the socket, not the service. The fact
that we’ve given them the same base name and marked the service as an
instantiated service with the “
@” notation allows
automatically start an instance of the service each time a hit comes in
on the socket that
systemd is monitoring on Fossil’s behalf. To see
this service instantiation at work, visit a long-running Fossil page
/tarball) and then give a command like this:
$ sudo systemctl --full | grep fossil
This will show information about the
fossil socket and service
instances, which should show your
/tarball hit handler, if it’s still
You can feed that service instance description to a
command to stop that single instance without restarting the whole
fossil service, for example.
In all of this, realize that we’re able to manipulate a single socket
listener or single service instance at a time, rather than reload the
whole externally-facing network configuration as with the far more