=head1 NAME

nbdkit-service - running nbdkit as a service, and systemd socket activation

=head1 DESCRIPTION

Most people start nbdkit from the command line or run it from another
program (see L<nbdkit-captive(1)>.  It is also possible to run nbdkit
as a standalone service, which is what this page describes.

=head1 SOCKET ACTIVATION

nbdkit supports socket activation (sometimes called systemd socket
activation).  This is a simple protocol where instead of nbdkit itself
opening the listening socket(s), the parent process (typically systemd
or libnbd) passes in pre-opened file descriptors.

One use for socket activation is to serve infrequent NBD requests
using a superserver without needing nbdkit to be running the whole
time.  Another use is to run nbdkit from a controlling libnbd process.

Socket activation is triggered when both the C<LISTEN_FDS> and
C<LISTEN_PID> environment variables are set.  In this mode using
I<-i>, I<-p>, I<--run>, I<-s> or I<-U> flags on the command line will
cause an error.  Also in this mode nbdkit does not fork into the
background (ie. I<-f> is implied).

=head2 Using socket activation with systemd

To use nbdkit with socket activation from systemd, create a unit file
ending in C<.socket> (eg. F</etc/systemd/system/nbdkit.socket>)
containing:

 [Unit]
 Description=NBDKit Network Block Device server

 [Socket]
 ListenStream=10809
 # Optional settings to detect dead clients:
 #KeepAlive=true
 #KeepAliveTimeSec=60
 #KeepAliveIntervalSec=10
 #KeepAliveProbes=5

 [Install]
 WantedBy=sockets.target

There are various formats for the C<ListenStream> key.  See
L<systemd.socket(5)> for more information.

Also create a service unit (eg. F</etc/systemd/system/nbdkit.service>)
containing:

 [Service]
 ExecStart=/usr/sbin/nbdkit file /path/to/serve
 # Optional settings to run as non-root:
 #User=nbd
 #Group=nbd

For more information on systemd and socket activation, see
L<http://0pointer.de/blog/projects/socket-activation.html>

=head2 Using socket activation with libnbd

L<libnbd(3)> L<nbd_connect_systemd_socket_activation(3)> lets you run
nbdkit from a program using libnbd.  An example is:

 struct nbd_handle *nbd = nbd_create ();
 if (nbd == NULL) {
   fprintf (stderr, "%s\n", nbd_get_error ());
   exit (EXIT_FAILURE);
 }
 char *argv[] = {
   "nbdkit", "--exit-with-parent", "memory", "1G", NULL
 };
 if (nbd_connect_systemd_socket_activation (nbd,
                                            args) == -1) {
   fprintf (stderr, "%s\n", nbd_get_error ());
   exit (EXIT_FAILURE);
 }

=head1 INETD AND XINETD

You can run nbdkit from L<inetd(8)> or L<xinetd(8)>.  For inetd use:

 nbd stream tcp nowait root /usr/sbin/nbdkit nbdkit -s file /tmp/disk.img

For xinetd create a file F</etc/xinetd.d/nbdkit> containing:

 service nbd
 {
     socket_type = stream
     wait = no
     user = root
     server = /usr/sbin/nbdkit
     server_args = -s file /tmp/disk.img
 }

=head1 AF_VSOCK

On Linux nbdkit supports the C<AF_VSOCK> address family / protocol.
This allows you to serve NBD devices into virtual machines without
using a regular network connection.

B<Note> that this is different from the usual case where you present
NBD as a virtual block device to a guest (which the guest sees as
something like a SATA or virtio-scsi disk).  With C<AF_VSOCK> the
virtual machine sees a raw NBD socket which it can connect to by
opening an C<AF_VSOCK> connection.  For more about this protocol, see
L<https://wiki.qemu.org/Features/VirtioVsock>

=head2 AF_VSOCK example

To set up an C<AF_VSOCK> server, use for example:

 nbdkit --vsock [--port PORT] memory 1G

The optional I<-p>/I<--port> argument is used to change the
C<AF_VSOCK> port number.  These port numbers exist in a different
namespace from TCP/IP port numbers.  Also unlike TCP, the port numbers
are 32 bit.  The default port is 10809.

The guest that wishes to access nbdkit must be configured for
virtio-vsock.  On the qemu command line use:

 qemu ... -device vhost-vsock-pci,id=vhost-vsock-pci0

For libvirt add this element to the C<<< <devices> >>> section:

 <vsock/>

If you see the error C<unable to open vhost-vsock device> then you may
have to unload the VMCI transport on the host:

 modprobe -r vmw_vsock_vmci_transport

Once nbdkit and the guest are running, from inside the guest you can
connect to nbdkit on the host using libnbd:

 nbdsh -c 'h.connect_vsock(2, 10809)' -c 'print(h.get_size())'

=head1 ENVIRONMENT VARIABLES

=over 4

=item C<LISTEN_FDS>

=item C<LISTEN_PID>

If present in the environment when nbdkit starts up, these trigger
L</SOCKET ACTIVATION>.

=back

=head1 SEE ALSO

L<nbdkit(1)>,
L<nbdkit-client(1)>,
L<nbdkit-exitlast-filter(1)>,
L<nbdkit-exitwhen-filter(1)>,
L<nbdkit-ip-filter(1)>,
L<nbdkit-limit-filter(1)>,
L<systemd(1)>,
L<systemd.socket(5)>,
L<inetd(8)>,
L<xinetd(8)>,
L<syslog(3)>,
L<rsyslogd(8)>,
L<journalctl(1)>,
L<libnbd(3)>,
L<nbd_connect_systemd_socket_activation(3)>,
L<nbdsh(1)>.

=head1 AUTHORS

Eric Blake

Richard W.M. Jones

Pino Toscano

=head1 COPYRIGHT

Copyright Red Hat
