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;
};