The configuration file of the shepherd
command
(see Invoking shepherd
) defines, registers, and possibly starts
services. Each service specifies other services it depends on and
how it is started and stopped. The configuration file contains Scheme
code that uses the programming interface of the (shepherd
service)
module (see Services).
Let’s assume you want to define and register a service to start mcron,
the daemon that periodically executes jobs in the background
(see Introduction in GNU mcron Manual). That service is
started by invoking the mcron
command, after which
shepherd
should monitor the running process, possibly
re-spawning it if it stops unexpectedly. Here’s the configuration file
for this one service:
(define mcron (service '(mcron) ;; Run /usr/bin/mcron without any command-line arguments. #:start (make-forkexec-constructor '("/usr/bin/mcron")) #:stop (make-kill-destructor) #:respawn? #t)) (register-services (list mcron))
You can write the snippet above in the default configuration
file—~/.config/shepherd/init.scm if you run shepherd
as an unprivileged user. When you launch it, shepherd
will
evaluate that configuration; thus it will define and register the
mcron
service, but it will not start it. To start the
service, run:
herd start mcron
Alternatively, if you want mcron
to be started automatically when
shepherd
starts, you can add this snippet at the end of the
configuration file:
(start-in-the-background '(mcron))
Now let’s take another example: sshd
, the secure shell daemon
of the OpenSSH project. We will pass
sshd
the -D option so that it does not “detach”,
making it easy for shepherd
to monitor its process; we also
tell shepherd
to check its PID file to determine once it
has started and is ready to accept connections:
(define sshd (service '(sshd ssh-daemon) ;for convenience, give it two names #:start (make-forkexec-constructor '("/usr/sbin/sshd" "-D") #:pid-file "/etc/ssh/sshd.pid") #:stop (make-kill-destructor) #:respawn? #t)) (register-services (list sshd)) (start-in-the-background '(sshd))
Alternatively, we can start sshd
in inetd mode: in that
case, shepherd
listens for connection and spawns
sshd
only upon incoming connections. The inetd mode is
enabled by passing the -i command-line option:
(define sshd (service '(sshd ssh-daemon) #:start (make-inetd-constructor '("/usr/sbin/sshd" "-D" "-i") (list (endpoint (make-socket-address AF_INET INADDR_ANY 22)) (endpoint (make-socket-address AF_INET6 IN6ADDR_ANY 22))) #:max-connections 10) #:stop (make-inetd-destructor) #:respawn? #t)) (register-services (list sshd)) (start-in-the-background '(sshd))
The make-socket-address
procedure calls above return the
listening addresses (see Network Socket Address in GNU
Guile Reference Manual). In this case, it specifies that
shepherd
will accept connections coming from any network
interface (“0.0.0.0” in IPv4 notation and “::0” for IPv6) on port
22. The endpoint
calls wrap these addresses in endpoint records
(see endpoints). When a client connects, shepherd
accepts
it and spawns sshd -D -i
as a new transient service,
passing it the client connection. The #:max-connections
parameter instructs shepherd
to accept at most 10 simultaneous
client connections.
In these examples, we haven’t discussed dependencies among
services—the #:requires
keyword of <service>
—nor did
we discuss systemd-style services. These are extensions of what we’ve
seen so far. See Services, for details.
If you use Guix System, you will see that it contains a wealth of Shepherd service definitions. The nice thing is that those give you a complete view of what goes into the service—not just how the service is started and stopped, but also what software package is used and what configuration file is provided. See Shepherd Services in GNU Guix Reference Manual, for more info.