From 98b4cc32b6728e57c8da9ce91613c62598689200 Mon Sep 17 00:00:00 2001 From: ibizaman Date: Tue, 16 Sep 2025 21:17:46 +0200 Subject: [PATCH] pinchflat: init --- README.md | 1 + docs/redirects.json | 123 ++++++++++++ docs/services.md | 22 ++- flake.nix | 4 + modules/services/pinchflat.nix | 191 +++++++++++++++++++ modules/services/pinchflat/docs/default.md | 70 +++++++ test/services/pinchflat.nix | 207 +++++++++++++++++++++ 7 files changed, 610 insertions(+), 8 deletions(-) create mode 100644 modules/services/pinchflat.nix create mode 100644 modules/services/pinchflat/docs/default.md create mode 100644 test/services/pinchflat.nix diff --git a/README.md b/README.md index acd2167..3a14e15 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ Also, the stack fits together nicely thanks to [contracts](#contracts). - Hledger - Home-Assistant - Jellyfin +- Pinchflat - Vaultwarden Like explained above, those services all benefit from diff --git a/docs/redirects.json b/docs/redirects.json index 8dc33db..0c4aa7a 100644 --- a/docs/redirects.json +++ b/docs/redirects.json @@ -3320,6 +3320,129 @@ "services-nextcloudserver-usage-version": [ "services-nextcloud.html#services-nextcloudserver-usage-version" ], + "services-pinchflat": [ + "services-pinchflat.html#services-pinchflat" + ], + "services-pinchflat-options": [ + "services-pinchflat.html#services-pinchflat-options" + ], + "services-pinchflat-options-shb.pinchflat.backup": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup" + ], + "services-pinchflat-options-shb.pinchflat.backup.request": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.excludePatterns": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.excludePatterns" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.hooks": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.hooks" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.hooks.afterBackup": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.hooks.afterBackup" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.hooks.beforeBackup": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.hooks.beforeBackup" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.sourceDirectories": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.sourceDirectories" + ], + "services-pinchflat-options-shb.pinchflat.backup.request.user": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.request.user" + ], + "services-pinchflat-options-shb.pinchflat.backup.result": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.result" + ], + "services-pinchflat-options-shb.pinchflat.backup.result.backupService": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.result.backupService" + ], + "services-pinchflat-options-shb.pinchflat.backup.result.restoreScript": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.backup.result.restoreScript" + ], + "services-pinchflat-options-shb.pinchflat.domain": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.domain" + ], + "services-pinchflat-options-shb.pinchflat.enable": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.enable" + ], + "services-pinchflat-options-shb.pinchflat.ldap": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ldap" + ], + "services-pinchflat-options-shb.pinchflat.ldap.enable": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ldap.enable" + ], + "services-pinchflat-options-shb.pinchflat.ldap.userGroup": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ldap.userGroup" + ], + "services-pinchflat-options-shb.pinchflat.mediaDir": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.mediaDir" + ], + "services-pinchflat-options-shb.pinchflat.port": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.port" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.request": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.request" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.request.group": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.request.group" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.request.mode": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.request.mode" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.request.owner": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.request.owner" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.request.restartUnits": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.request.restartUnits" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.result": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.result" + ], + "services-pinchflat-options-shb.pinchflat.secretKeyBase.result.path": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.secretKeyBase.result.path" + ], + "services-pinchflat-options-shb.pinchflat.ssl": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ssl" + ], + "services-pinchflat-options-shb.pinchflat.ssl.paths": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ssl.paths" + ], + "services-pinchflat-options-shb.pinchflat.ssl.paths.cert": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ssl.paths.cert" + ], + "services-pinchflat-options-shb.pinchflat.ssl.paths.key": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ssl.paths.key" + ], + "services-pinchflat-options-shb.pinchflat.ssl.systemdService": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.ssl.systemdService" + ], + "services-pinchflat-options-shb.pinchflat.sso": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.sso" + ], + "services-pinchflat-options-shb.pinchflat.sso.authEndpoint": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.sso.authEndpoint" + ], + "services-pinchflat-options-shb.pinchflat.sso.authorization_policy": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.sso.authorization_policy" + ], + "services-pinchflat-options-shb.pinchflat.sso.enable": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.sso.enable" + ], + "services-pinchflat-options-shb.pinchflat.subdomain": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.subdomain" + ], + "services-pinchflat-options-shb.pinchflat.timeZone": [ + "services-pinchflat.html#services-pinchflat-options-shb.pinchflat.timeZone" + ], + "services-pinchflat-usage": [ + "services-pinchflat.html#services-pinchflat-usage" + ], + "services-pinchflat-usage-backup": [ + "services-pinchflat.html#services-pinchflat-usage-backup" + ], "services-vaultwarden": [ "services-vaultwarden.html#services-vaultwarden" ], diff --git a/docs/services.md b/docs/services.md index 5695593..1fdaec9 100644 --- a/docs/services.md +++ b/docs/services.md @@ -11,14 +11,15 @@ Not all services are yet documented. You can find all available services [in the The following table summarizes for each documented service what features it provides. More information is provided in the respective manual sections. -| Service | Backup | Reverse Proxy | SSO | LDAP | Monitoring | Profiling | -|-----------------------|--------|---------------|-----|-------|------------|-----------| -| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N | -| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N | -| [Jellyfin][] | Y (1) | Y | Y | Y | Y (2) | N | -| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N | -| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) | -| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N | +| Service | Backup | Reverse Proxy | SSO | LDAP | Monitoring | Profiling | +|----------------------|--------|---------------|-----|-------|------------|-----------| +| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N | +| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N | +| [Jellyfin][] | Y (1) | Y | Y | Y | Y (2) | N | +| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N | +| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) | +| [Pinchflat][] | Y | Y | Y | Y (4) | Y (5) | N | +| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N | Legend: **N**: no but WIP; **P**: partial; **Y**: yes @@ -34,6 +35,7 @@ Legend: **N**: no but WIP; **P**: partial; **Y**: yes [Home-Assistant]: services-home-assistant.html [Jellyfin]: services-jellyfin.html [Nextcloud Server]: services-nextcloud.html +[Pinchflat]: services-pinchflat.html [Vaultwarden]: services-vaultwarden.html ```{=include=} chapters html:into-file=//services-arr.html @@ -56,6 +58,10 @@ modules/services/home-assistant/docs/default.md modules/services/nextcloud-server/docs/default.md ``` +```{=include=} chapters html:into-file=//services-pinchflat.html +modules/services/pinchflat/docs/default.md +``` + ```{=include=} chapters html:into-file=//services-vaultwarden.html modules/services/vaultwarden/docs/default.md ``` diff --git a/flake.nix b/flake.nix index 064e7c7..d7f5799 100644 --- a/flake.nix +++ b/flake.nix @@ -81,6 +81,7 @@ self.nixosModules.${system}.assistant self.nixosModules.${system}.jellyfin self.nixosModules.${system}.nextcloud-server + self.nixosModules.${system}.pinchflat self.nixosModules.${system}.vaultwarden ]; }; @@ -114,6 +115,7 @@ nixosModules.assistant = modules/services/home-assistant.nix; nixosModules.jellyfin = modules/services/jellyfin.nix; nixosModules.nextcloud-server = modules/services/nextcloud-server.nix; + nixosModules.pinchflat = modules/services/pinchflat.nix; nixosModules.vaultwarden = modules/services/vaultwarden.nix; packages.manualHtml = pkgs.callPackage ./docs { @@ -142,6 +144,7 @@ "services/home-assistant" = ./modules/services/home-assistant.nix; "services/jellyfin" = ./modules/services/jellyfin.nix; "services/nextcloud-server" = ./modules/services/nextcloud-server.nix; + "services/pinchflat" = ./modules/services/pinchflat.nix; "services/vaultwarden" = ./modules/services/vaultwarden.nix; "contracts/backup" = ./modules/contracts/backup/dummyModule.nix; "contracts/databasebackup" = ./modules/contracts/databasebackup/dummyModule.nix; @@ -257,6 +260,7 @@ // (vm_test "jellyfin" ./test/services/jellyfin.nix) // (vm_test "monitoring" ./test/services/monitoring.nix) // (vm_test "nextcloud" ./test/services/nextcloud.nix) + // (vm_test "pinchflat" ./test/services/pinchflat.nix) // (vm_test "vaultwarden" ./test/services/vaultwarden.nix) // (vm_test "authelia" ./test/blocks/authelia.nix) diff --git a/modules/services/pinchflat.nix b/modules/services/pinchflat.nix new file mode 100644 index 0000000..e9dffda --- /dev/null +++ b/modules/services/pinchflat.nix @@ -0,0 +1,191 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.shb.pinchflat; + + inherit (lib) types; + + contracts = pkgs.callPackage ../contracts {}; + shblib = pkgs.callPackage ../../lib {}; +in +{ + options.shb.pinchflat = { + enable = lib.mkEnableOption "the Pinchflat service."; + + subdomain = lib.mkOption { + type = lib.types.str; + description = "Subdomain under which Pinchflat will be served."; + default = "pinchflat"; + }; + + domain = lib.mkOption { + type = lib.types.str; + description = "domain under which Pinchflat will be served."; + example = "mydomain.com"; + }; + + ssl = lib.mkOption { + description = "Path to SSL files"; + type = lib.types.nullOr contracts.ssl.certs; + default = null; + }; + + port = lib.mkOption { + type = lib.types.port; + description = "Port Pinchflat listens to incoming requests."; + default = 8945; + }; + + secretKeyBase = lib.mkOption { + description = '' + Used to sign/encrypt cookies and other secrets. + + Make sure the secret is at least 64 characters long. + ''; + type = types.submodule { + options = contracts.secret.mkRequester { + restartUnits = [ "pinchflat.service" ]; + }; + }; + }; + + mediaDir = lib.mkOption { + description = "Path where videos are stored."; + type = lib.types.str; + }; + + timeZone = lib.mkOption { + type = lib.types.oneOf [ lib.types.str shblib.secretFileType ]; + description = "Timezone of this instance."; + example = "America/Los_Angeles"; + }; + + ldap = lib.mkOption { + description = '' + Setup LDAP integration. + ''; + default = {}; + type = types.submodule { + options = { + enable = lib.mkEnableOption "LDAP integration." // { + default = cfg.sso.enable; + }; + + userGroup = lib.mkOption { + type = types.str; + description = "Group users must belong to be able to login."; + default = "pinchflat_user"; + }; + }; + }; + }; + + sso = lib.mkOption { + description = '' + Setup SSO integration. + ''; + default = {}; + type = types.submodule { + options = { + enable = lib.mkEnableOption "SSO integration."; + + authEndpoint = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Endpoint to the SSO provider. Leave null to not have SSO configured."; + example = "https://authelia.example.com"; + }; + + authorization_policy = lib.mkOption { + type = types.enum [ "one_factor" "two_factor" ]; + description = "Require one factor (password) or two factor (device) authentication."; + default = "one_factor"; + }; + }; + }; + }; + + backup = lib.mkOption { + description = '' + Backup media directory `shb.mediaDir`. + ''; + default = {}; + type = lib.types.submodule { + options = contracts.backup.mkRequester { + user = "pinchflat"; + sourceDirectories = [ + cfg.mediaDir + ]; + sourceDirectoriesText = "[ config.shb.pinchflat.mediaDir ]"; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '/etc/pinchflat' 0750 root root - -" + ]; + + # Pinchflat relies on the global value so for now this is the only way to pass the option in. + time.timeZone = lib.mkDefault cfg.timeZone; + services.pinchflat = { + inherit (cfg) enable port mediaDir; + secretsFile = "/etc/pinchflat/secrets.env"; + extraConfig = { + ENABLE_PROMETHEUS = true; + # TZ = "as"; # I consider where you live to be sensible so it should be passed as a secret. + }; + }; + + # This should be using a contract instead of setting the option directly. + shb.lldap = lib.mkIf config.shb.ldap.enable { + ensureGroups = { ${cfg.ldap.userGroup} = {}; }; + }; + + systemd.services.pinchflat-pre = { + script = shblib.replaceSecrets { + userConfig = { + SECRET_KEY_BASE.source = cfg.secretKeyBase.result.path; + # TZ = cfg.secretKeyBase.result.path; # Uncomment when PR is merged. + }; + resultPath = "/etc/pinchflat/secrets.env"; + generator = shblib.toEnvVar; + }; + serviceConfig.Type = "oneshot"; + wantedBy = [ "multi-user.target" ]; + before = [ "pinchflat.service" ]; + requiredBy = [ "pinchflat.service" ]; + }; + + shb.nginx.vhosts = [ + { + inherit (cfg) subdomain domain ssl; + inherit (cfg.sso) authEndpoint; + + upstream = "http://127.0.0.1:${toString cfg.port}"; + autheliaRules = lib.optionals (cfg.sso.enable) [ + { + domain = "${cfg.subdomain}.${cfg.domain}"; + policy = cfg.sso.authorization_policy; + subject = [ "group:${cfg.ldap.userGroup}" ]; + } + ]; + } + ]; + + services.prometheus.scrapeConfigs = [ + { + job_name = "pinchflat"; + static_configs = [ + { + targets = ["127.0.0.1:${toString cfg.port}"]; + labels = { + "hostname" = config.networking.hostName; + "domain" = cfg.domain; + }; + } + ]; + } + ]; + }; +} diff --git a/modules/services/pinchflat/docs/default.md b/modules/services/pinchflat/docs/default.md new file mode 100644 index 0000000..0ffc6ad --- /dev/null +++ b/modules/services/pinchflat/docs/default.md @@ -0,0 +1,70 @@ +# Pinchflat Service {#services-pinchflat} + +Defined in [`/modules/services/pinchflat.nix`](@REPO@/modules/services/pinchflat.nix). + +This NixOS module is a service that sets up a [Pinchflat](https://github.com/kieraneglin/pinchflat) instance. + +Compared to the stock module from nixpkgs, +this one sets up, in a fully declarative manner, +LDAP and SSO integration +and has a nicer option for secrets. + +## Usage {#services-pinchflat-usage} + +The following snippet assumes a few blocks have been setup already: + +- the [secrets block](usage.html#usage-secrets) with SOPS, +- the [`shb.ssl` block](blocks-ssl.html#usage), +- the [`shb.lldap` block](blocks-lldap.html#blocks-lldap-global-setup). +- the [`shb.authelia` block](blocks-authelia.html#blocks-sso-global-setup). + +```nix +shb.pinchflat = { + enable = true; + + secretKeyBase.result = config.shb.sops.secret."pinchflat/secretKeyBase".result; + timeZone = "Europe/Brussels"; + mediaDir = "/srv/pinchflat"; + + domain = "example.com"; + subdomain = "pinchflat"; + ssl = config.shb.certs.certs.letsencrypt.${domain}; + + ldap = { + enable = true; + userGroup = "pinchflat_user"; + }; + sso = { + enable = true; + authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; + }; +}; +shb.sops.secret."pinchflat/secretKeyBase".request = config.shb.pinchflat.secretKeyBase.request; +``` + +Secrets can be randomly generated with `nix run nixpkgs#openssl -- rand -hex 64`. + +## Backup {#services-pinchflat-usage-backup} + +Backing up Pinchflat using the [Restic block](blocks-restic.html) is done like so: + +```nix +shb.restic.instances."pinchflat" = { + request = config.shb.pinchflat.backup; + settings = { + enable = true; + }; +}; +``` + +The name `"pinchflat"` in the `instances` can be anything. +The `config.shb.pinchflat.backup` option provides what directories to backup. +You can define any number of Restic instances to backup Pinchflat multiple times. + +## Options Reference {#services-pinchflat-options} + +```{=include=} options +id-prefix: services-pinchflat-options- +list-id: selfhostblocks-service-pinchflat-options +source: @OPTIONS_JSON@ +``` diff --git a/test/services/pinchflat.nix b/test/services/pinchflat.nix new file mode 100644 index 0000000..f6b2370 --- /dev/null +++ b/test/services/pinchflat.nix @@ -0,0 +1,207 @@ +{ pkgs, ... }: +let + testLib = pkgs.callPackage ../common.nix {}; + + commonTestScript = testLib.mkScripts { + hasSSL = { node, ... }: !(isNull node.config.shb.pinchflat.ssl); + waitForServices = { ... }: [ + "pinchflat.service" + "nginx.service" + ]; + waitForPorts = { node, ... }: [ + node.config.shb.pinchflat.port + ]; + }; + + basic = { config, ... }: { + imports = [ + testLib.baseModule + ../../modules/blocks/hardcodedsecret.nix + ../../modules/blocks/lldap.nix + ../../modules/services/pinchflat.nix + ]; + + test = { + subdomain = "p"; + }; + + shb.pinchflat = { + enable = true; + inherit (config.test) subdomain domain; + mediaDir = "/src/pinchflat"; + timeZone = "America/Los_Angeles"; + secretKeyBase.result = config.shb.hardcodedsecret.secretKeyBase.result; + }; + + systemd.tmpfiles.rules = [ + "d '/src/pinchflat' 0750 pinchflat pinchflat - -" + ]; + + # Needed for gitea-runner-local to be able to ping pinchflat. + networking.hosts = { + "127.0.0.1" = [ "${config.test.subdomain}.${config.test.domain}" ]; + }; + + shb.hardcodedsecret.secretKeyBase = { + request = config.shb.pinchflat.secretKeyBase.request; + settings.content = pkgs.lib.strings.replicate 64 "Z"; + }; + }; + + clientLogin = { config, ... }: { + imports = [ + testLib.baseModule + testLib.clientLoginModule + ]; + test = { + subdomain = "p"; + }; + + test.login = { + startUrl = "http://${config.test.fqdn}"; + # There is no login without SSO integration. + testLoginWith = [ + { username = null; password = null; nextPageExpect = [ + "expect(page.get_by_text('Create a media profile')).to_be_visible()" + ]; } + ]; + }; + }; + + https = { config, ... }: { + shb.pinchflat = { + ssl = config.shb.certs.certs.selfsigned.n; + }; + }; + + ldap = { config, ... }: { + shb.pinchflat = { + ldap = { + enable = true; + + userGroup = "user_group"; + }; + }; + }; + + clientLoginSso = { config, ... }: { + imports = [ + testLib.baseModule + testLib.clientLoginModule + ]; + test = { + subdomain = "p"; + }; + + test.login = { + startUrl = "https://${config.test.fqdn}"; + usernameFieldLabelRegex = "Username"; + passwordFieldLabelRegex = "Password"; + loginButtonNameRegex = "[sS]ign [iI]n"; + testLoginWith = [ + { username = "alice"; password = "NotAlicePassword"; nextPageExpect = [ + "expect(page.get_by_text(re.compile('[Ii]ncorrect'))).to_be_visible()" + ]; } + { username = "alice"; password = "AlicePassword"; nextPageExpect = [ + "expect(page.get_by_text(re.compile('[Ii]ncorrect'))).not_to_be_visible()" + "expect(page.get_by_role('button', name=re.compile('Sign In'))).not_to_be_visible()" + "expect(page.get_by_text('Create a media profile')).to_be_visible()" + ]; } + { username = "bob"; password = "NotBobPassword"; nextPageExpect = [ + "expect(page.get_by_text(re.compile('[Ii]ncorrect'))).to_be_visible()" + ]; } + { username = "bob"; password = "BobPassword"; nextPageExpect = [ + "expect(page.get_by_text(re.compile('[Ii]ncorrect'))).not_to_be_visible()" + "expect(page.get_by_role('button', name=re.compile('Sign In'))).not_to_be_visible()" + "expect(page.get_by_text('Create a media profile')).to_be_visible()" + ]; } + ]; + }; + }; + + sso = { config, ... }: { + shb.pinchflat = { + sso = { + enable = true; + authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; + }; + }; + }; +in +{ + basic = pkgs.testers.runNixOSTest { + name = "pinchflat_basic"; + + nodes.client = { + imports = [ + clientLogin + ]; + }; + nodes.server = { + imports = [ + basic + ]; + }; + + testScript = commonTestScript.access; + }; + + backup = pkgs.testers.runNixOSTest { + name = "pinchflat_backup"; + + nodes.server = { config, ... }: { + imports = [ + basic + (testLib.backup config.shb.pinchflat.backup) + ]; + }; + + nodes.client = {}; + + testScript = commonTestScript.backup; + }; + + https = pkgs.testers.runNixOSTest { + name = "pinchflat_https"; + + nodes.client = { + imports = [ + clientLogin + ]; + }; + nodes.server = { + imports = [ + basic + testLib.certs + https + ]; + }; + + testScript = commonTestScript.access; + }; + + sso = pkgs.testers.runNixOSTest { + name = "pinchflat_sso"; + + nodes.client = { + imports = [ + clientLoginSso + ]; + }; + nodes.server = { config, pkgs, ... }: { + imports = [ + basic + testLib.certs + https + testLib.ldap + ldap + (testLib.sso config.shb.certs.certs.selfsigned.n) + sso + ]; + }; + + testScript = commonTestScript.access.override { + redirectSSO = true; + }; + }; +}