156 lines
4.2 KiB
Markdown
156 lines
4.2 KiB
Markdown
<!-- Read these docs at https://shb.skarabox.com -->
|
|
# 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}";
|
|
};
|
|
};
|
|
}
|
|
```
|