Table of Contents
Let’s see how one can use most of the blocks provided by SelfHostBlocks to make a service accessible through a reverse proxy with LDAP and SSO integration as well as backing up this service and creating a ZFS dataset to store the service’s data.
We’ll use an hypothetical well made service found under services.awesome as our example.
We’re purposely not using a real service to avoid needing to deal with uninteresting particularities.
Let’s say our domain name is example.com,
and we want to reach our service under the awesome subdomain:
let
  domain = "example.com";
  subdomain = "awesome";
  fqdn = "${subdomain}.${domain}";
  listenPort = 9000;
  dataDir = "/var/lib/awesome";
in
We then enable the service and explicitly set the listenPort and dataDir,
assuming those options exist:
services.awesome = {
  enable = true;
  inherit dataDir listenPort;
};
Requesting an SSL certificate from Let’s Encrypt is done by adding an entry to
the extraDomains option:
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ fqdn ];
This assumes the shb.certs block has been configured:
shb.certs.certs.letsencrypt.${domain} = {
  inherit domain;
  group = "nginx";
  reloadServices = [ "nginx.service" ];
  adminEmail = "admin@${domain}";
};
We want only users of the group calibre_user to be able to access this subdomain.
The following snippet creates the LDAP group:
shb.lldap.ensureGroups = {
  calibre_user = {};
};
If our service does not integrate with OIDC, we can still protect it with SSO
with forward authentication by letting the reverse proxy handle authentication.
This is done by adding an entry to shb.nginx.vhosts:
shb.nginx.vhosts = [
  {
    inherit subdomain domain;
    ssl = config.shb.certs.certs.letsencrypt.${domain};
    upstream = "http://127.0.0.1:${toString config.services.calibre-web.listen.port}";
    authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    autheliaRules = [{
      policy = "one_factor";
      subject = [ "group:${config.shb.lldap.ensureGroups.calibre_user.name}" ];
    }];
  }
];
If you use ZFS, you can use SelfHostBlocks to create a dataset for you:
shb.zfs.datasets."safe/awesome".path = config.services.awesome.dataDir;
Usually, the log level of the service can be increased with some option they provide.
With SelfHostBlocks, you can also introspect any HTTP service by adding an
mitmdump instance between the reverse proxy and the awesome service:
shb.mitmdump.awesome = {
  inherit listenPort;
  upstreamPort = listenPort + 1;
};
services.awesome.listenPort = lib.mkForce (listenPort + 1);
This creates a mitmdump-awesome.service systemd service which prints the requests’ and responses’ headers and bodies.
The following snippet uses the shb.restic block to backup the services.awesome.dataDir directory:
shb.restic.instances.awesome = {
  request.user = "awesome";
  request.sourceDirectories = [ dataDir ];
  settings.enable = true;
  settings.passphrase.result = config.shb.sops.secret.awesome.result;
  settings.repository.path = "/srv/backup/awesome";
};
shb.sops.secret."awesome" = {
  request = config.shb.restic.instances.awesome.settings.passphrase.request;
};