fix: use configurable dataDir paths in arr stack and fix sops.secret references

- Replace hardcoded /var/lib/<app> paths with shb.arr.<app>.dataDir in arr.nix
- Fix bazarr config path in test to use cfg.dataDir
- Correct shb.sops.secrets → shb.sops.secret in documentation files
This commit is contained in:
sitrius 2026-02-16 22:53:21 +00:00 committed by Pierre Penninckx
parent 62ea06e57c
commit 5da47a77c7
16 changed files with 73 additions and 70 deletions

View file

@ -250,14 +250,14 @@ shb.nextcloud = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."nextcloud/ldap/admin_password".result;
adminPassword.result = config.shb.sops.secret."nextcloud/ldap/admin_password".result;
};
apps.sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secret.result = config.shb.sops.secrets."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."nextcloud/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."nextcloud/sso/secretForAuthelia".result;
};
};
```
@ -275,15 +275,15 @@ shb.forgejo = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."nextcloud/ldap/admin_password".result;
adminPassword.result = config.shb.sops.secret."nextcloud/ldap/admin_password".result;
};
sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secret.result = config.shb.sops.secrets."forgejo/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."forgejo/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."forgejo/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."forgejo/sso/secretForAuthelia".result;
};
};
```

View file

@ -221,14 +221,14 @@ shb.nextcloud = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."nextcloud/ldap/admin_password".result;
adminPassword.result = config.shb.sops.secret."nextcloud/ldap/admin_password".result;
};
apps.sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secret.result = config.shb.sops.secrets."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."nextcloud/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."nextcloud/sso/secretForAuthelia".result;
};
};
```
@ -246,15 +246,15 @@ shb.forgejo = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."nextcloud/ldap/admin_password".result;
adminPassword.result = config.shb.sops.secret."nextcloud/ldap/admin_password".result;
};
sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secret.result = config.shb.sops.secrets."forgejo/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."forgejo/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."forgejo/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."forgejo/sso/secretForAuthelia".result;
};
};
```

View file

@ -634,8 +634,8 @@ One way to setup secrets management using `sops-nix`:
Setting the default this way makes all sops instances use that same file.
7. Reference the secrets in nix:
```nix
shb.sops.secrets."nextcloud/adminpass".request = config.shb.nextcloud.adminPass.request;
shb.nextcloud.adminPass.result = config.shb.sops.secrets."nextcloud/adminpass".result;
shb.sops.secret."nextcloud/adminpass".request = config.shb.nextcloud.adminPass.request;
shb.nextcloud.adminPass.result = config.shb.sops.secret."nextcloud/adminpass".result;
```
The above snippet uses the [secrets contract](./contracts-secret.html) and
[sops block](./blocks-sops.html) to ease the configuration.

View file

@ -44,31 +44,31 @@ shb.authelia = {
port = 587;
username = "postmaster@mg.example.com";
from_address = "authelia@example.com";
password.result = config.shb.sops.secrets."authelia/smtp_password".result;
password.result = config.shb.sops.secret."authelia/smtp_password".result;
};
secrets = {
jwtSecret.result = config.shb.sops.secrets."authelia/jwt_secret".result;
ldapAdminPassword.result = config.shb.sops.secrets."authelia/ldap_admin_password".result;
sessionSecret.result = config.shb.sops.secrets."authelia/session_secret".result;
storageEncryptionKey.result = config.shb.sops.secrets."authelia/storage_encryption_key".result;
identityProvidersOIDCHMACSecret.result = config.shb.sops.secrets."authelia/hmac_secret".result;
identityProvidersOIDCIssuerPrivateKey.result = config.shb.sops.secrets."authelia/private_key".result;
jwtSecret.result = config.shb.sops.secret."authelia/jwt_secret".result;
ldapAdminPassword.result = config.shb.sops.secret."authelia/ldap_admin_password".result;
sessionSecret.result = config.shb.sops.secret."authelia/session_secret".result;
storageEncryptionKey.result = config.shb.sops.secret."authelia/storage_encryption_key".result;
identityProvidersOIDCHMACSecret.result = config.shb.sops.secret."authelia/hmac_secret".result;
identityProvidersOIDCIssuerPrivateKey.result = config.shb.sops.secret."authelia/private_key".result;
};
};
shb.certs.certs.letsencrypt."example.com".extraDomains = [ "auth.example.com" ];
shb.sops.secrets."authelia/jwt_secret".request = config.shb.authelia.secrets.jwtSecret.request;
shb.sops.secrets."authelia/ldap_admin_password" = {
shb.sops.secret."authelia/jwt_secret".request = config.shb.authelia.secrets.jwtSecret.request;
shb.sops.secret."authelia/ldap_admin_password" = {
request = config.shb.authelia.secrets.ldapAdminPassword.request;
settings.key = "lldap/user_password";
};
shb.sops.secrets."authelia/session_secret".request = config.shb.authelia.secrets.sessionSecret.request;
shb.sops.secrets."authelia/storage_encryption_key".request = config.shb.authelia.secrets.storageEncryptionKey.request;
shb.sops.secrets."authelia/hmac_secret".request = config.shb.authelia.secrets.identityProvidersOIDCHMACSecret.request;
shb.sops.secrets."authelia/private_key".request = config.shb.authelia.secrets.identityProvidersOIDCIssuerPrivateKey.request;
shb.sops.secrets."authelia/smtp_password".request = config.shb.authelia.smtp.password.request;
shb.sops.secret."authelia/session_secret".request = config.shb.authelia.secrets.sessionSecret.request;
shb.sops.secret."authelia/storage_encryption_key".request = config.shb.authelia.secrets.storageEncryptionKey.request;
shb.sops.secret."authelia/hmac_secret".request = config.shb.authelia.secrets.identityProvidersOIDCHMACSecret.request;
shb.sops.secret."authelia/private_key".request = config.shb.authelia.secrets.identityProvidersOIDCIssuerPrivateKey.request;
shb.sops.secret."authelia/smtp_password".request = config.shb.authelia.smtp.password.request;
```
This assumes secrets are setup with SOPS
@ -95,8 +95,8 @@ shb.<service>.sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secret.result = config.shb.sops.secrets."<service>/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."<service>/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."<service>/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."<service>/sso/secretForAuthelia".result;
};
shb.sops.secret."<service>/sso/secret".request = config.shb.<service>.sso.secret.request;
@ -122,7 +122,7 @@ the necessary configuration is:
shb.authelia.oidcClients = [
{
client_id = "<service>";
client_secret.source = shb.sops.secret."<service>/sso/secretForAuthelia".response.path;
client_secret.source = config.shb.sops.secret."<service>/sso/secretForAuthelia".response.path;
scopes = [ "openid" "email" "profile" ];
redirect_uris = [
"<provided by service documentation>"
@ -167,7 +167,7 @@ services.open-webui.environment = {
shb.authelia.oidcClients = [
{
client_id = "open-webui";
client_secret.source = shb.sops.secret."open-webui/sso/secretForAuthelia".response.path;
client_secret.source = config.shb.sops.secret."open-webui/sso/secretForAuthelia".response.path;
scopes = [ "openid" "email" "profile" ];
redirect_uris = [
"<provided by service documentation>"

View file

@ -50,7 +50,7 @@ shb.borgbackup.instances."myservice" = {
settings = {
enable = true;
passphrase.result = shb.sops.secret."passphrase".result;
passphrase.result = config.shb.sops.secret."passphrase".result;
repository = {
path = "/srv/backups/myservice";
@ -71,7 +71,7 @@ shb.borgbackup.instances."myservice" = {
};
shb.sops.secret."passphrase".request =
shb.borgbackup.instances."myservice".settings.passphrase.request;
config.shb.borgbackup.instances."myservice".settings.passphrase.request;
```
### One folder backed up with contract {#blocks-borgbackup-usage-provider-contract}
@ -87,7 +87,7 @@ shb.borgbackup.instances."myservice" = {
settings = {
enable = true;
passphrase.result = shb.sops.secret."passphrase".result;
passphrase.result = config.shb.sops.secret."passphrase".result;
repository = {
path = "/srv/backups/myservice";
@ -108,7 +108,7 @@ shb.borgbackup.instances."myservice" = {
};
shb.sops.secret."passphrase".request =
shb.borgbackup.instances."myservice".settings.passphrase.request;
config.shb.borgbackup.instances."myservice".settings.passphrase.request;
```
### One folder backed up to S3 {#blocks-borgbackup-usage-provider-remote}

View file

@ -142,7 +142,7 @@ set [`shb.lldap.enforceUserMemberships`](#blocks-lldap-options-shb.lldap.enforce
};
shb.sops.secret."dad".request =
shb.lldap.ensureUsers.dad.password.request;
config.shb.lldap.ensureUsers.dad.password.request;
}
```

View file

@ -8,6 +8,7 @@ This block sets up a backup job using [Restic][].
## Provider Contracts {#blocks-restic-contract-provider}
This block provides the following contracts:
- [backup contract](contracts-backup.html) under the [`shb.restic.instances`][instances] option.
@ -25,6 +26,7 @@ a backup Systemd service and a [restore script](#blocks-restic-maintenance) are
## Usage {#blocks-restic-usage}
The following examples assume usage of the [sops block][] to provide secrets
although any blocks providing the [secrets contract][] works too.
@ -33,6 +35,7 @@ although any blocks providing the [secrets contract][] works too.
### One folder backed up manually {#blocks-restic-usage-provider-manual}
The following snippet shows how to configure
the backup of 1 folder to 1 repository.
We assume that the folder `/var/lib/myfolder` of the service `myservice` must be backed up.
@ -50,7 +53,7 @@ shb.restic.instances."myservice" = {
settings = {
enable = true;
passphrase.result = shb.sops.secret."passphrase".result;
passphrase.result = config.shb.sops.secret."passphrase".result;
repository = {
path = "/srv/backups/myservice";
@ -71,7 +74,7 @@ shb.restic.instances."myservice" = {
};
shb.sops.secret."passphrase".request =
shb.restic.instances."myservice".settings.passphrase.request;
config.shb.restic.instances."myservice".settings.passphrase.request;
```
### One folder backed up with contract {#blocks-restic-usage-provider-contract}
@ -87,7 +90,7 @@ shb.restic.instances."myservice" = {
settings = {
enable = true;
passphrase.result = shb.sops.secret."passphrase".result;
passphrase.result = config.shb.sops.secret."passphrase".result;
repository = {
path = "/srv/backups/myservice";
@ -108,7 +111,7 @@ shb.restic.instances."myservice" = {
};
shb.sops.secret."passphrase".request =
shb.restic.instances."myservice".settings.passphrase.request;
config.shb.restic.instances."myservice".settings.passphrase.request;
```
### One folder backed up to S3 {#blocks-restic-usage-provider-remote}

View file

@ -13,7 +13,7 @@ to adapt it to the [secret contract](./contracts-secret.html).
This block provides the following contracts:
- [secret contract][] under the [`shb.sops.secrets`][secret] option.
- [secret contract][] under the [`shb.sops.secret`][secret] option.
It is not yet tested with [contract tests][secret contract tests] but it is used extensively on several machines.
[secret]: #blocks-sops-options-shb.sops.secret
@ -21,7 +21,7 @@ This block provides the following contracts:
[secret contract tests]: @REPO@/test/contracts/secret.nix
As requested by the contract, when asking for a secret with the `shb.sops` module,
the path where the secret will be located can be found under the [`shb.sops.secrets.<name>.result`][result] option.
the path where the secret will be located can be found under the [`shb.sops.secret.<name>.result`][result] option.
[result]: #blocks-sops-options-shb.sops.secret._name_.result

View file

@ -42,12 +42,12 @@ Now, with this contract, a layer on top of `sops` is added which is found under
The configuration then becomes:
```nix
shb.sops.secrets."ldap/user_password" = {
shb.sops.secret."ldap/user_password" = {
request = config.shb.lldap.userPassword.request;
settings.sopsFile = ./secrets.yaml;
};
shb.lldap.userPassword.result = config.shb.sops.secrets."ldap/user_password".result;
shb.lldap.userPassword.result = config.shb.sops.secret."ldap/user_password".result;
```
The issue is now gone as the responsibility falls
@ -63,9 +63,9 @@ sops.defaultSopsFile = ./secrets.yaml;
Then the snippet above is even more simplified:
```nix
shb.sops.secrets."ldap/user_password".request = config.shb.lldap.userPassword.request;
shb.sops.secret."ldap/user_password".request = config.shb.lldap.userPassword.request;
shb.lldap.userPassword.result = config.shb.sops.secrets."ldap/user_password".result;
shb.lldap.userPassword.result = config.shb.sops.secret."ldap/user_password".result;
```
## Contract Reference {#contract-secret-options}

View file

@ -395,7 +395,7 @@ in
services.radarr = {
enable = true;
dataDir = "/var/lib/radarr";
dataDir = shb.arr.radarr.dataDir;
};
systemd.services.radarr.preStart = shb.replaceSecrets {
@ -423,7 +423,7 @@ in
services.sonarr = {
enable = true;
dataDir = "/var/lib/sonarr";
dataDir = shb.arr.sonarr.dataDir;
};
users.users.sonarr = {
extraGroups = [ "media" ];
@ -464,7 +464,7 @@ in
AuthenticationRequired = "DisabledForLocalAddresses";
AuthenticationMethod = "External";
});
resultPath = "/var/lib/bazarr/config.xml";
resultPath = "${config.services.bazarr.dataDir}/config.xml";
generator = apps.bazarr.settingsFormat.generate;
};
@ -479,7 +479,7 @@ in
{
services.readarr = {
enable = true;
dataDir = "/var/lib/readarr";
dataDir = shb.arr.readarr.dataDir;
};
users.users.readarr = {
extraGroups = [ "media" ];
@ -502,7 +502,7 @@ in
{
services.lidarr = {
enable = true;
dataDir = "/var/lib/lidarr";
dataDir = shb.arr.lidarr.dataDir;
};
users.users.lidarr = {
extraGroups = [ "media" ];
@ -529,7 +529,7 @@ in
{
services.jackett = {
enable = true;
dataDir = "/var/lib/jackett";
dataDir = shb.arr.jackett.dataDir;
};
# TODO: avoid implicitly relying on the media group
users.users.jackett = {

View file

@ -39,7 +39,7 @@ shb.firefly-iii = {
port = 587;
username = "postmaster@mg.example.com";
from_address = "firefly-iii@example.com";
password.result = config.shb.sops.secrets."firefly-iii/smtpPassword".result;
password.result = config.shb.sops.secret."firefly-iii/smtpPassword".result;
};
sso = {

View file

@ -34,20 +34,20 @@ shb.forgejo = {
"theadmin" = {
isAdmin = true;
email = "theadmin@example.com";
password.result = config.shb.sops.secrets.forgejoAdminPassword.result;
password.result = config.shb.sops.secret.forgejoAdminPassword.result;
};
"theuser" = {
email = "theuser@example.com";
password.result = config.shb.sops.secrets.forgejoUserPassword.result;
password.result = config.shb.sops.secret.forgejoUserPassword.result;
};
};
};
shb.sops.secrets."forgejo/admin/password" = {
shb.sops.secret."forgejo/admin/password" = {
request = config.shb.forgejo.users."theadmin".password.request;
};
shb.sops.secrets."forgejo/user/password" = {
shb.sops.secret."forgejo/user/password" = {
request = config.shb.forgejo.users."theuser".password.request;
};
```
@ -110,10 +110,10 @@ shb.forgejo.ldap = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."forgejo/ldap/adminPassword".result
adminPassword.result = config.shb.sops.secret."forgejo/ldap/adminPassword".result
};
shb.sops.secrets."forgejo/ldap/adminPassword" = {
shb.sops.secret."forgejo/ldap/adminPassword" = {
request = config.shb.forgejo.ldap.adminPassword.request;
settings.key = "ldap/userPassword";
};

View file

@ -46,7 +46,7 @@ shb.jellyfin = {
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."jellyfin/ldap/adminPassword".result
adminPassword.result = config.shb.sops.secret."jellyfin/ldap/adminPassword".result
};
sso = {
@ -60,7 +60,7 @@ shb.jellyfin = {
shb.sops.secret."jellyfin/adminPassword".request = config.shb.jellyfin.admin.password.request;
shb.sops.secrets."jellyfin/ldap/adminPassword".request = config.shb.jellyfin.ldap.adminPassword.request;
shb.sops.secret."jellyfin/ldap/adminPassword".request = config.shb.jellyfin.ldap.adminPassword.request;
shb.sops.secret."jellyfin/sso_secret".request = config.shb.jellyfin.sso.sharedSecret.request;
shb.sops.secret."jellyfin/authelia/sso_secret" = {

View file

@ -72,10 +72,10 @@ shb.nextcloud = {
domain = "example.com";
subdomain = "n";
defaultPhoneRegion = "US";
adminPass.result = config.shb.sops.secrets."nextcloud/adminpass".result;
adminPass.result = config.shb.sops.secret."nextcloud/adminpass".result;
};
shb.sops.secrets."nextcloud/adminpass".request = config.shb.nextcloud.adminPass.request;
shb.sops.secret."nextcloud/adminpass".request = config.shb.nextcloud.adminPass.request;
```
This assumes secrets are setup with SOPS as mentioned in [the secrets setup section](usage.html#usage-secrets) of the manual.
@ -165,11 +165,11 @@ shb.nextcloud.apps.ldap = {
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminName = "admin";
adminPassword.result = config.shb.sops.secrets."nextcloud/ldap/adminPassword".result
adminPassword.result = config.shb.sops.secret."nextcloud/ldap/adminPassword".result
userGroup = "nextcloud_user";
};
shb.sops.secrets."nextcloud/ldap/adminPassword" = {
shb.sops.secret."nextcloud/ldap/adminPassword" = {
request = config.shb.nextcloud.apps.ldap.adminPassword.request;
settings.key = "ldap/userPassword";
};
@ -216,8 +216,8 @@ shb.nextcloud.apps.sso = {
clientID = "nextcloud";
fallbackDefaultAuth = false;
secret.result = config.shb.sops.secrets."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secrets."nextcloud/sso/secretForAuthelia".result;
secret.result = config.shb.sops.secret."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."nextcloud/sso/secretForAuthelia".result;
};
shb.sops.secret."nextcloud/sso/secret".request = config.shb.nextcloud.apps.sso.secret.request;

View file

@ -28,7 +28,7 @@ shb.vaultwarden = {
port = 8222;
databasePassword.result = config.shb.sops.secrets."vaultwarden/db".result;
databasePassword.result = config.shb.sops.secret."vaultwarden/db".result;
smtp = {
host = "smtp.eu.mailgun.org";

View file

@ -212,7 +212,7 @@ let
radarrCfgFn = cfg: "${cfg.dataDir}/config.xml";
sonarrCfgFn = cfg: "${cfg.dataDir}/config.xml";
bazarrCfgFn = cfg: "/var/lib/bazarr/config.xml";
bazarrCfgFn = cfg: "${cfg.dataDir}/config.xml";
readarrCfgFn = cfg: "${cfg.dataDir}/config.xml";
lidarrCfgFn = cfg: "${cfg.dataDir}/config.xml";
jackettCfgFn = cfg: "${cfg.dataDir}/ServerConfig.json";