# Expose a service {#recipes-exposeService} 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. ## Service setup {#recipes-exposeService-service} Let's say our domain name is `example.com`, and we want to reach our service under the `awesome` subdomain: ```nix let domain = "example.com"; subdomain = "awesome"; fqdn = "${subdomain}.${domain}"; listenPort = 9000; dataDir = "/var/lib/awesome"; ldapGroup = "awesome_user"; in ``` We then `enable` the service and explicitly set the `listenPort` and `dataDir`, assuming those options exist: ```nix services.awesome = { enable = true; inherit dataDir listenPort; }; ``` ## SSL Certificate {#recipes-exposeService-ssl} Requesting an SSL certificate from Let's Encrypt is done by adding an entry to the `extraDomains` option: ```nix shb.certs.certs.letsencrypt.${domain}.extraDomains = [ fqdn ]; ``` This assumes the `shb.certs` block has been configured: ```nix shb.certs.certs.letsencrypt.${domain} = { inherit domain; group = "nginx"; reloadServices = [ "nginx.service" ]; adminEmail = "admin@${domain}"; }; ``` ## LDAP group {#recipes-exposeService-ldap} We want only users of the group `calibre_user` to be able to access this subdomain. The following snippet creates the LDAP group: ```nix shb.lldap.ensureGroups = { calibre_user = {}; }; ``` ## Reverse Proxy with Forward Auth {#recipes-exposeService-nginx} 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`: ```nix shb.nginx.vhosts = [ { inherit subdomain domain; ssl = config.shb.certs.certs.letsencrypt.${domain}; upstream = "http://127.0.0.1:${toString listenPort}"; authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; autheliaRules = [{ policy = "one_factor"; subject = [ "group:${ldapGroup}" ]; }]; } ]; ``` ## ZFS support {#recipes-exposeService-zfs} If you use ZFS, you can use SelfHostBlocks to create a dataset for you: ```nix shb.zfs.datasets."safe/awesome".path = config.services.awesome.dataDir; ``` ## Debugging {#recipes-exposeService-debug} 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: ```nix 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. ## Backup {#recipes-exposeService-backup} The following snippet uses the `shb.restic` block to backup the `services.awesome.dataDir` directory: ```nix 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 = config.services.awesome.dataDir; }; shb.sops.secret."awesome" = { request = config.shb.restic.instances.awesome.settings.passphrase.request; }; ``` ## Impermanence {#recipes-exposeService-impermanence} To save the data folder in an impermanence setup, add: ```nix { shb.zfs.datasets."safe/awesome".path = config.services.awesome.dataDir; } ``` ## Application Dashboard {#recipes-exposeService-applicationdashboard} For example using the [Homepage](services-homepage.html) service: ```nix { shb.homepage.servicesGroups.MyServices.services.Awesome = { sortOrder = 1; dashboard.request = { externalUrl = "https://${fqdn}"; internalUrl = "http://127.0.0.1:${toString listenPort}"; }; }; } ```