docs: add how to expose a service recipe
This commit is contained in:
parent
e0a222f583
commit
fad46e420a
7 changed files with 182 additions and 41 deletions
10
README.md
10
README.md
|
|
@ -171,8 +171,6 @@ is to go to the [All Options][] section of the manual.
|
||||||
|
|
||||||
The services above rely on the following [common blocks][]:
|
The services above rely on the following [common blocks][]:
|
||||||
|
|
||||||
[common blocks]: https://shb.skarabox.com/blocks.html
|
|
||||||
|
|
||||||
- Authelia
|
- Authelia
|
||||||
- BorgBackup
|
- BorgBackup
|
||||||
- Davfs
|
- Davfs
|
||||||
|
|
@ -188,11 +186,11 @@ The services above rely on the following [common blocks][]:
|
||||||
- ZFS
|
- ZFS
|
||||||
|
|
||||||
Those blocks can be used with services
|
Those blocks can be used with services
|
||||||
not provided by SelfHostBlocks.
|
not provided by SelfHostBlocks as shows [in the manual][common blocks].
|
||||||
|
|
||||||
Some blocks do not have an entry yet in the manual.
|
[common blocks]: https://shb.skarabox.com/blocks.html
|
||||||
To know options for those, the only way for now
|
|
||||||
is to go to the [All Options][] section of the manual.
|
The manual also provides documentation for each individual blocks.
|
||||||
|
|
||||||
### Unified Interfaces
|
### Unified Interfaces
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,31 +5,8 @@ Blocks help you self-host apps or services. They implement a specific function l
|
||||||
access through a subdomain. Each block is designed to be usable on its own and to fit nicely with
|
access through a subdomain. Each block is designed to be usable on its own and to fit nicely with
|
||||||
others.
|
others.
|
||||||
|
|
||||||
In practice, most blocks implement a [contract](contracts.html) that must be followed to implement a
|
Not all blocks are documented yet.
|
||||||
specific self-hosting function. It also comes with a unit test and NixOS VM test suite to ensure any
|
You can find all available blocks [in the repository](@REPO@/modules/blocks).
|
||||||
implementation follows the contract.
|
|
||||||
|
|
||||||
As an example, let's take the HTTPS access block which allows for a service to be accessible through
|
|
||||||
a specific subdomain. In Nix terms, this block defines at minimum the inputs:
|
|
||||||
|
|
||||||
- subdomain,
|
|
||||||
- domain,
|
|
||||||
- and upstream address of the service.
|
|
||||||
|
|
||||||
It defines no outputs but has one major side effect:
|
|
||||||
|
|
||||||
- the service should be accessible through HTTPS at `https://subdomain.domain`.
|
|
||||||
|
|
||||||
Anything that provides the inputs and expected outputs and side effects defined by the block can be
|
|
||||||
used to fulfill its contract. In this example, we could use any of Nginx, Caddy, Haproxy or others.
|
|
||||||
|
|
||||||
Self Host Blocks provides at least one implementation for each contract and allows you to use your own
|
|
||||||
implementation if you want to, as long as it passes the tests. You can then use blocks to improve
|
|
||||||
services you already have deployed.
|
|
||||||
|
|
||||||
::: {.note}
|
|
||||||
Not all blocks are yet documented. You can find all available blocks [in the repository](@REPO@/modules/blocks).
|
|
||||||
:::
|
|
||||||
|
|
||||||
```{=include=} chapters html:into-file=//blocks-authelia.html
|
```{=include=} chapters html:into-file=//blocks-authelia.html
|
||||||
modules/blocks/authelia/docs/default.md
|
modules/blocks/authelia/docs/default.md
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ contracts.md
|
||||||
blocks.md
|
blocks.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```{=include=} chapters html:into-file=//recipes.html
|
||||||
|
recipes.md
|
||||||
|
```
|
||||||
|
|
||||||
```{=include=} chapters html:into-file=//demos.html
|
```{=include=} chapters html:into-file=//demos.html
|
||||||
demos.md
|
demos.md
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -92,13 +92,6 @@ To achieve this, Self Host Blocks provides building blocks
|
||||||
which each provide part of what a self hosted app should do (SSO, HTTPS, etc.).
|
which each provide part of what a self hosted app should do (SSO, HTTPS, etc.).
|
||||||
It also provides some services that are already integrated with all those building blocks.
|
It also provides some services that are already integrated with all those building blocks.
|
||||||
|
|
||||||
- You are new to self hosting and want pre-configured services to deploy easily.
|
|
||||||
Look at the [services section](services.html).
|
|
||||||
- You are a seasoned self-hoster but want to enhance some services you deploy already.
|
|
||||||
Go to the [blocks section](blocks.html).
|
|
||||||
- You are a user of Self Host Blocks but would like to use your own implementation for a block.
|
|
||||||
Go to the [contracts section](https://shb.skarabox.com/contracts.html).
|
|
||||||
|
|
||||||
Self Host Blocks uses the full power of NixOS modules to achieve these goals.
|
Self Host Blocks uses the full power of NixOS modules to achieve these goals.
|
||||||
Blocks and service are both NixOS modules.
|
Blocks and service are both NixOS modules.
|
||||||
|
|
||||||
|
|
@ -114,9 +107,14 @@ and also goes over secrets management with [SOPS][].
|
||||||
[deploy-rs]: https://shb.skarabox.com/usage.html#usage-example-deployrs
|
[deploy-rs]: https://shb.skarabox.com/usage.html#usage-example-deployrs
|
||||||
[SOPS]: https://shb.skarabox.com/usage.html#usage-secrets
|
[SOPS]: https://shb.skarabox.com/usage.html#usage-secrets
|
||||||
|
|
||||||
Then, to actually configure services, you can choose which one interests you in
|
Then, depending on what you want to do:
|
||||||
[the services section](https://shb.skarabox.com/services.html) of the manual.
|
|
||||||
Not all services have a corresponding manual page yet.
|
- You are new to self hosting and want pre-configured services to deploy easily.
|
||||||
|
Look at the [services section](services.html).
|
||||||
|
- You are a seasoned self-hoster but want to enhance some services you deploy already.
|
||||||
|
Go to the [blocks section](blocks.html) and the [recipes section](recipes.html).
|
||||||
|
- You are a user of Self Host Blocks but would like to use your own implementation for a block.
|
||||||
|
Go to the [contracts section](https://shb.skarabox.com/contracts.html).
|
||||||
|
|
||||||
Head over to the [matrix channel](https://matrix.to/#/#selfhostblocks:matrix.org)
|
Head over to the [matrix channel](https://matrix.to/#/#selfhostblocks:matrix.org)
|
||||||
for any remaining question, or just to say hi :)
|
for any remaining question, or just to say hi :)
|
||||||
|
|
|
||||||
8
docs/recipes.md
Normal file
8
docs/recipes.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!-- Read these docs at https://shb.skarabox.com -->
|
||||||
|
# Recipes {#recipes}
|
||||||
|
|
||||||
|
This section of the manual gives you easy to follow recipes for common use cases.
|
||||||
|
|
||||||
|
```{=include=} chapters html:into-file=//recipes-exposeService.html
|
||||||
|
recipes/exposeService.md
|
||||||
|
```
|
||||||
129
docs/recipes/exposeService.md
Normal file
129
docs/recipes/exposeService.md
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
<!-- 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";
|
||||||
|
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 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}" ];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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 = "/srv/backup/awesome";
|
||||||
|
};
|
||||||
|
|
||||||
|
shb.sops.secret."awesome" = {
|
||||||
|
request = config.shb.restic.instances.awesome.settings.passphrase.request;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
@ -1643,6 +1643,33 @@
|
||||||
"quick-reference": [
|
"quick-reference": [
|
||||||
"service-implementation-guide.html#quick-reference"
|
"service-implementation-guide.html#quick-reference"
|
||||||
],
|
],
|
||||||
|
"recipes": [
|
||||||
|
"recipes.html#recipes"
|
||||||
|
],
|
||||||
|
"recipes-exposeService": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-backup": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-backup"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-debug": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-debug"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-ldap": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-ldap"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-nginx": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-nginx"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-service": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-service"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-ssl": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-ssl"
|
||||||
|
],
|
||||||
|
"recipes-exposeService-zfs": [
|
||||||
|
"recipes-exposeService.html#recipes-exposeService-zfs"
|
||||||
|
],
|
||||||
"redirect-management": [
|
"redirect-management": [
|
||||||
"service-implementation-guide.html#redirect-management"
|
"service-implementation-guide.html#redirect-management"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue