@node Defining Substituters
@section Defining Substituters

@cindex substitutes, implementation
Guix currently only supports downloading substitutes via the HTTP and
HTTPS protocols, and substitutes over IPFS and GNUnet are planned.
An implementation of substitutes over some protocol is called a
‘substituter’.

The API described here is implemented by the @code{(guix scripts substitute)}
module. In order to let the daemon actually find the substituter, the
substituter should be defined in a module @code{(guix scripts substitute name)},
as a variable @var{name}-substituter.

@deffn {Scheme Procedure} make-substituter @var{name} @var{nar-downloader} @
  @var{fetch-narinfos} @var{recognised-uri-schemes}
Return a substituter for the protocols in @var{recognised-uri-schemes},
a list of URI schemes.  @var{fetch-narinfos} will be used finding narinfos
and @var{nar-downloader} to download a substitute.

The procedure @var{nar-downloader} must be a keyword procedure
(@pxref{Optional Arguments, keyword arguments in Guile,, guile, GNU
Guile Reference Manual}).  It accepts two positional arguments
@var{destination} and @var{narinfo}.  @var{destination} is the location
in the file system where the store item should be written to,
and @var{narinfo} is the narinfo describing the substitute to download.

It should return @code{#f} if the substitute is not available
via this method.  If the substitute was available, it should either
return an input port to read the nar from.

@c TODO currently unimplemented, but will be used by the IPFS substituter:
@c or the symbol @code{unpacked}
@c if the substituter wrote the store item to @var{destination} by itself.

The procedure @var{fetch-narinfos} must accept two arguments
@var{url} and @var{paths}, where @var{url} is the URL (as a string)
of a substitute server and @var{paths} is a list of store item names
for which to find a narinfo.

This procedure should return a list of narinfos pertaining to
@var{paths} (possibly empty).  It can be assumed @var{url}
has an URI scheme in @var{recognised-uri-schemes}.

A substituter does not have to verify whether the narinfo and nar
are correctly signed and have a correct hash; this is handled
by @code{(guix scripts substitute)}.  @var{nar-downloader} and
@var{fetch-narinfos} can be @code{#f} if unimplemented by this
substituter.

Likewise, when returning @code{unpacked}, @var{nar-downloader}
does not need to normalize timestamps and file permissions.

@end deffn
