add vm tests for jellyfin and regroup ldap and sso options
This commit is contained in:
parent
97f213a137
commit
e80cc0d3aa
4 changed files with 439 additions and 78 deletions
|
@ -100,6 +100,7 @@
|
|||
};
|
||||
}
|
||||
// (vm_test "authelia" ./test/vm/authelia.nix)
|
||||
// (vm_test "jellyfin" ./test/vm/jellyfin.nix)
|
||||
// (vm_test "ldap" ./test/vm/ldap.nix)
|
||||
// (vm_test "lib" ./test/vm/lib.nix)
|
||||
// (vm_test "postgresql" ./test/vm/postgresql.nix)
|
||||
|
|
|
@ -22,9 +22,9 @@ rec {
|
|||
''
|
||||
set -euo pipefail
|
||||
set -x
|
||||
mkdir -p $(dirname ${templatePath})
|
||||
ln -fs ${file} ${templatePath}
|
||||
rm -f ${resultPath}
|
||||
${pkgs.gnused}/bin/sed ${sedPatterns} ${templatePath}
|
||||
${pkgs.gnused}/bin/sed ${sedPatterns} ${templatePath} > ${resultPath}
|
||||
'';
|
||||
|
||||
|
|
|
@ -30,62 +30,94 @@ in
|
|||
default = null;
|
||||
};
|
||||
|
||||
ldapHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "host serving the LDAP server";
|
||||
example = "127.0.0.1";
|
||||
ldap = lib.mkOption {
|
||||
description = "LDAP configuration.";
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "LDAP";
|
||||
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Host serving the LDAP server.";
|
||||
example = "127.0.0.1";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "Port where the LDAP server is listening.";
|
||||
example = 389;
|
||||
};
|
||||
|
||||
dcdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "DC domain for LDAP.";
|
||||
example = "dc=mydomain,dc=com";
|
||||
};
|
||||
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "LDAP user group";
|
||||
default = "jellyfin_user";
|
||||
};
|
||||
|
||||
adminGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "LDAP admin group";
|
||||
default = "jellyfin_admin";
|
||||
};
|
||||
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the LDAP admin password.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ldapPort = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "port where the LDAP server is listening";
|
||||
example = 389;
|
||||
};
|
||||
sso = lib.mkOption {
|
||||
description = "SSO configuration.";
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "SSO";
|
||||
|
||||
dcdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "dc domain for ldap";
|
||||
example = "dc=mydomain,dc=com";
|
||||
};
|
||||
provider = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC provider name";
|
||||
default = "Authelia";
|
||||
};
|
||||
|
||||
oidcProvider = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC provider name";
|
||||
default = "Authelia";
|
||||
};
|
||||
endpoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC endpoint for SSO";
|
||||
example = "https://authelia.example.com";
|
||||
};
|
||||
|
||||
authEndpoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC endpoint for SSO";
|
||||
example = "https://authelia.example.com";
|
||||
};
|
||||
clientID = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Client ID for the OIDC endpoint";
|
||||
default = "jellyfin";
|
||||
};
|
||||
|
||||
oidcClientID = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Client ID for the OIDC endpoint";
|
||||
default = "jellyfin";
|
||||
};
|
||||
adminUserGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC admin group";
|
||||
default = "jellyfin_admin";
|
||||
};
|
||||
|
||||
oidcAdminUserGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC admin group";
|
||||
default = "jellyfin_admin";
|
||||
};
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC user group";
|
||||
default = "jellyfin_user";
|
||||
};
|
||||
|
||||
oidcUserGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC user group";
|
||||
default = "jellyfin_user";
|
||||
};
|
||||
|
||||
ldapPasswordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the LDAP admin password.";
|
||||
};
|
||||
|
||||
ssoSecretFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the SSO shared secret.";
|
||||
secretFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the OIDC shared secret.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -107,6 +139,8 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
|
||||
# Take advice from https://jellyfin.org/docs/general/networking/nginx/ and https://nixos.wiki/wiki/Plex
|
||||
services.nginx.virtualHosts."${fqdn}" = {
|
||||
forceSSL = !(isNull cfg.ssl);
|
||||
|
@ -238,17 +272,17 @@ in
|
|||
ldapConfig = pkgs.writeText "LDAP-Auth.xml" ''
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PluginConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<LdapServer>${cfg.ldapHost}</LdapServer>
|
||||
<LdapPort>${builtins.toString cfg.ldapPort}</LdapPort>
|
||||
<LdapServer>${cfg.ldap.host}</LdapServer>
|
||||
<LdapPort>${builtins.toString cfg.ldap.port}</LdapPort>
|
||||
<UseSsl>false</UseSsl>
|
||||
<UseStartTls>false</UseStartTls>
|
||||
<SkipSslVerify>false</SkipSslVerify>
|
||||
<LdapBindUser>uid=admin,ou=people,${cfg.dcdomain}</LdapBindUser>
|
||||
<LdapBindUser>uid=admin,ou=people,${cfg.ldap.dcdomain}</LdapBindUser>
|
||||
<LdapBindPassword>%LDAP_PASSWORD%</LdapBindPassword>
|
||||
<LdapBaseDn>ou=people,${cfg.dcdomain}</LdapBaseDn>
|
||||
<LdapSearchFilter>(memberof=cn=jellyfin_user,ou=groups,${cfg.dcdomain})</LdapSearchFilter>
|
||||
<LdapAdminBaseDn>ou=people,${cfg.dcdomain}</LdapAdminBaseDn>
|
||||
<LdapAdminFilter>(memberof=cn=jellyfin_admin,ou=groups,${cfg.dcdomain})</LdapAdminFilter>
|
||||
<LdapBaseDn>ou=people,${cfg.ldap.dcdomain}</LdapBaseDn>
|
||||
<LdapSearchFilter>(memberof=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain})</LdapSearchFilter>
|
||||
<LdapAdminBaseDn>ou=people,${cfg.ldap.dcdomain}</LdapAdminBaseDn>
|
||||
<LdapAdminFilter>(memberof=cn=${cfg.ldap.adminGroup},ou=groups,${cfg.ldap.dcdomain})</LdapAdminFilter>
|
||||
<EnableLdapAdminFilterMemberUid>false</EnableLdapAdminFilterMemberUid>
|
||||
<LdapSearchAttributes>uid, cn, mail, displayName</LdapSearchAttributes>
|
||||
<LdapClientCertPath />
|
||||
|
@ -271,22 +305,22 @@ in
|
|||
<OidConfigs>
|
||||
<item>
|
||||
<key>
|
||||
<string>${cfg.oidcProvider}</string>
|
||||
<string>${cfg.sso.provider}</string>
|
||||
</key>
|
||||
<value>
|
||||
<PluginConfiguration>
|
||||
<OidEndpoint>${cfg.authEndpoint}</OidEndpoint>
|
||||
<OidClientId>${cfg.oidcClientID}</OidClientId>
|
||||
<OidEndpoint>${cfg.sso.endpoint}</OidEndpoint>
|
||||
<OidClientId>${cfg.sso.clientID}</OidClientId>
|
||||
<OidSecret>%SSO_SECRET%</OidSecret>
|
||||
<Enabled>true</Enabled>
|
||||
<EnableAuthorization>true</EnableAuthorization>
|
||||
<EnableAllFolders>true</EnableAllFolders>
|
||||
<EnabledFolders />
|
||||
<AdminRoles>
|
||||
<string>${cfg.oidcAdminUserGroup}</string>
|
||||
<string>${cfg.sso.adminUserGroup}</string>
|
||||
</AdminRoles>
|
||||
<Roles>
|
||||
<string>${cfg.oidcUserGroup}</string>
|
||||
<string>${cfg.sso.userGroup}</string>
|
||||
</Roles>
|
||||
<EnableFolderRoles>false</EnableFolderRoles>
|
||||
<FolderRoleMappings />
|
||||
|
@ -305,15 +339,15 @@ in
|
|||
brandingConfig = pkgs.writeText "branding.xml" ''
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<BrandingOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<LoginDisclaimer><a href="https://${cfg.subdomain}.${cfg.domain}/SSO/OID/p/${cfg.oidcProvider}" class="raised cancel block emby-button authentik-sso">
|
||||
Sign in with ${cfg.oidcProvider}&nbsp;
|
||||
<LoginDisclaimer><a href="https://${cfg.subdomain}.${cfg.domain}/SSO/OID/p/${cfg.sso.provider}" class="raised cancel block emby-button authentik-sso">
|
||||
Sign in with ${cfg.sso.provider}&nbsp;
|
||||
<img alt="OpenID Connect (authentik)" title="OpenID Connect (authentik)" class="oauth-login-image" src="https://raw.githubusercontent.com/goauthentik/authentik/master/web/icons/icon.png">
|
||||
</a>
|
||||
<a href="https://${cfg.subdomain}.${cfg.domain}/SSOViews/linking" class="raised cancel block emby-button authentik-sso">
|
||||
Link ${cfg.oidcProvider} config&nbsp;
|
||||
Link ${cfg.sso.provider} config&nbsp;
|
||||
</a>
|
||||
<a href="${cfg.authEndpoint}" class="raised cancel block emby-button authentik-sso">
|
||||
${cfg.oidcProvider} config&nbsp;
|
||||
<a href="${cfg.sso.endpoint}" class="raised cancel block emby-button authentik-sso">
|
||||
${cfg.sso.provider} config&nbsp;
|
||||
</a>
|
||||
</LoginDisclaimer>
|
||||
<CustomCss>
|
||||
|
@ -348,36 +382,36 @@ in
|
|||
</BrandingOptions>
|
||||
'';
|
||||
in
|
||||
shblib.replaceSecretsScript {
|
||||
lib.strings.optionalString cfg.ldap.enable (shblib.replaceSecretsScript {
|
||||
file = ldapConfig;
|
||||
resultPath = "/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml";
|
||||
replacements = {
|
||||
"%LDAP_PASSWORD%" = "$(cat ${cfg.ldapPasswordFile})";
|
||||
"%LDAP_PASSWORD%" = "$(cat ${cfg.ldap.passwordFile})";
|
||||
};
|
||||
}
|
||||
+ shblib.replaceSecretsScript {
|
||||
})
|
||||
+ lib.strings.optionalString cfg.sso.enable (shblib.replaceSecretsScript {
|
||||
file = ssoConfig;
|
||||
resultPath = "/var/lib/jellyfin/plugins/configurations/SSO-Auth.xml";
|
||||
replacements = {
|
||||
"%SSO_SECRET%" = "$(cat ${cfg.ssoSecretFile})";
|
||||
"%SSO_SECRET%" = "$(cat ${cfg.sso.secretFile})";
|
||||
};
|
||||
}
|
||||
+ shblib.replaceSecretsScript {
|
||||
})
|
||||
+ lib.strings.optionalString cfg.sso.enable (shblib.replaceSecretsScript {
|
||||
file = brandingConfig;
|
||||
resultPath = "/var/lib/jellyfin/config/branding.xml";
|
||||
replacements = {
|
||||
"%a%" = "%a%";
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
shb.authelia.oidcClients = [
|
||||
shb.authelia.oidcClients = lib.lists.optionals (!(isNull cfg.sso)) [
|
||||
{
|
||||
id = cfg.oidcClientID;
|
||||
id = cfg.sso.clientID;
|
||||
description = "Jellyfin";
|
||||
secret.source = cfg.ssoSecretFile;
|
||||
secret.source = cfg.sso.secretFile;
|
||||
public = false;
|
||||
authorization_policy = "one_factor";
|
||||
redirect_uris = [ "https://${cfg.subdomain}.${cfg.domain}/sso/OID/r/${cfg.oidcProvider}" ];
|
||||
redirect_uris = [ "https://${cfg.subdomain}.${cfg.domain}/sso/OID/r/${cfg.sso.provider}" ];
|
||||
}
|
||||
];
|
||||
|
||||
|
|
326
test/vm/jellyfin.nix
Normal file
326
test/vm/jellyfin.nix
Normal file
|
@ -0,0 +1,326 @@
|
|||
{ pkgs, lib, ... }:
|
||||
{
|
||||
basic = pkgs.nixosTest {
|
||||
name = "jellyfin-basic";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
shb.authelia = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
../../modules/services/jellyfin.nix
|
||||
];
|
||||
|
||||
shb.jellyfin = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "j";
|
||||
};
|
||||
# Nginx port.
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
# TODO: Test login
|
||||
testScript = { nodes, ... }: ''
|
||||
import json
|
||||
|
||||
def curl(target, format, endpoint):
|
||||
return json.loads(target.succeed(
|
||||
"curl --fail-with-body --silent --show-error --output /dev/null --location"
|
||||
+ " --connect-to j.example.com:443:server:443"
|
||||
+ " --connect-to j.example.com:80:server:80"
|
||||
+ f" --write-out '{format}'"
|
||||
+ " " + endpoint
|
||||
))
|
||||
|
||||
start_all()
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_for_open_port(8096)
|
||||
|
||||
response = curl(client, """{"code":%{response_code}}""", "http://j.example.com")
|
||||
|
||||
if response['code'] != 200:
|
||||
raise Exception(f"Code is {response['code']}")
|
||||
'';
|
||||
};
|
||||
|
||||
ldap = pkgs.nixosTest {
|
||||
name = "jellyfin-ldap";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
shb.authelia = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
../../modules/blocks/ldap.nix
|
||||
../../modules/services/jellyfin.nix
|
||||
];
|
||||
|
||||
shb.ldap = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "ldap";
|
||||
ldapPort = 3890;
|
||||
webUIListenPort = 17170;
|
||||
dcdomain = "dc=example,dc=com";
|
||||
ldapUserPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
|
||||
};
|
||||
|
||||
shb.jellyfin = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "j";
|
||||
|
||||
ldap = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
port = config.shb.ldap.ldapPort;
|
||||
dcdomain = config.shb.ldap.dcdomain;
|
||||
passwordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
};
|
||||
};
|
||||
# Nginx port.
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
# TODO: Test login with ldap user
|
||||
testScript = { nodes, ... }: ''
|
||||
import json
|
||||
|
||||
def curl(target, format, endpoint):
|
||||
return json.loads(target.succeed(
|
||||
"curl --fail-with-body --silent --show-error --output /dev/null --location"
|
||||
+ " --connect-to j.example.com:443:server:443"
|
||||
+ " --connect-to j.example.com:80:server:80"
|
||||
+ f" --write-out '{format}'"
|
||||
+ " " + endpoint
|
||||
))
|
||||
|
||||
start_all()
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_for_unit("lldap.service")
|
||||
server.wait_for_open_port(8096)
|
||||
|
||||
response = curl(client, """{"code":%{response_code}}""", "http://j.example.com")
|
||||
|
||||
if response['code'] != 200:
|
||||
raise Exception(f"Code is {response['code']}")
|
||||
'';
|
||||
};
|
||||
|
||||
cert = pkgs.nixosTest {
|
||||
name = "jellyfin_cert";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
shb.authelia = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
../../modules/blocks/nginx.nix
|
||||
../../modules/blocks/postgresql.nix
|
||||
../../modules/blocks/ssl.nix
|
||||
../../modules/services/jellyfin.nix
|
||||
];
|
||||
|
||||
shb.certs = {
|
||||
cas.selfsigned.myca = {
|
||||
name = "My CA";
|
||||
};
|
||||
certs.selfsigned = {
|
||||
n = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
domain = "*.example.com";
|
||||
group = "nginx";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.nginx.after = [ config.shb.certs.certs.selfsigned.n.systemdService ];
|
||||
systemd.services.nginx.requires = [ config.shb.certs.certs.selfsigned.n.systemdService ];
|
||||
|
||||
shb.jellyfin = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "j";
|
||||
ssl = config.shb.certs.certs.selfsigned.n;
|
||||
};
|
||||
# Nginx port.
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
shb.nginx.accessLog = true;
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
# TODO: Test login
|
||||
testScript = { nodes, ... }: ''
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
def curl(target, format, endpoint):
|
||||
return json.loads(target.succeed(
|
||||
"curl --fail-with-body --silent --show-error --output /dev/null --location"
|
||||
+ " --connect-to j.example.com:443:server:443"
|
||||
+ " --connect-to j.example.com:80:server:80"
|
||||
+ f" --write-out '{format}'"
|
||||
+ " " + endpoint
|
||||
))
|
||||
|
||||
start_all()
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_for_open_port(8096)
|
||||
|
||||
server.copy_from_vm("/etc/ssl/certs/ca-certificates.crt")
|
||||
client.succeed("rm -r /etc/ssl/certs")
|
||||
client.copy_from_host(str(pathlib.Path(os.environ.get("out", os.getcwd())) / "ca-certificates.crt"), "/etc/ssl/certs/ca-certificates.crt")
|
||||
|
||||
response = curl(client, """{"code":%{response_code}}""", "https://j.example.com")
|
||||
|
||||
if response['code'] != 200:
|
||||
raise Exception(f"Code is {response['code']}")
|
||||
'';
|
||||
};
|
||||
|
||||
sso = pkgs.nixosTest {
|
||||
name = "jellyfin_sso";
|
||||
|
||||
nodes.server = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
{
|
||||
options = {
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
../../modules/blocks/authelia.nix
|
||||
../../modules/blocks/ldap.nix
|
||||
../../modules/blocks/postgresql.nix
|
||||
../../modules/blocks/ssl.nix
|
||||
../../modules/services/jellyfin.nix
|
||||
];
|
||||
|
||||
shb.ldap = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "ldap";
|
||||
ldapPort = 3890;
|
||||
webUIListenPort = 17170;
|
||||
dcdomain = "dc=example,dc=com";
|
||||
ldapUserPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
|
||||
};
|
||||
|
||||
shb.certs = {
|
||||
cas.selfsigned.myca = {
|
||||
name = "My CA";
|
||||
};
|
||||
certs.selfsigned = {
|
||||
n = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
domain = "*.example.com";
|
||||
group = "nginx";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.nginx.after = [ config.shb.certs.certs.selfsigned.n.systemdService ];
|
||||
systemd.services.nginx.requires = [ config.shb.certs.certs.selfsigned.n.systemdService ];
|
||||
|
||||
shb.authelia = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "auth";
|
||||
ssl = config.shb.certs.certs.selfsigned.n;
|
||||
|
||||
ldapEndpoint = "ldap://127.0.0.1:${builtins.toString config.shb.ldap.ldapPort}";
|
||||
dcdomain = config.shb.ldap.dcdomain;
|
||||
|
||||
secrets = {
|
||||
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
|
||||
ldapAdminPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
sessionSecretFile = pkgs.writeText "sessionSecret" "sessionSecret";
|
||||
storageEncryptionKeyFile = pkgs.writeText "storageEncryptionKey" "storageEncryptionKey";
|
||||
identityProvidersOIDCHMACSecretFile = pkgs.writeText "identityProvidersOIDCHMACSecret" "identityProvidersOIDCHMACSecret";
|
||||
identityProvidersOIDCIssuerPrivateKeyFile = (pkgs.runCommand "gen-private-key" {} ''
|
||||
mkdir $out
|
||||
${pkgs.openssl}/bin/openssl genrsa -out $out/private.pem 4096
|
||||
'') + "/private.pem";
|
||||
};
|
||||
};
|
||||
|
||||
shb.jellyfin = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "j";
|
||||
ssl = config.shb.certs.certs.selfsigned.n;
|
||||
|
||||
ldap = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
port = config.shb.ldap.ldapPort;
|
||||
dcdomain = config.shb.ldap.dcdomain;
|
||||
passwordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
|
||||
};
|
||||
|
||||
sso = {
|
||||
enable = true;
|
||||
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
|
||||
secretFile = pkgs.writeText "ssoSecretFile" "ssoSecretFile";
|
||||
};
|
||||
};
|
||||
# Nginx port.
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
};
|
||||
|
||||
nodes.client = {};
|
||||
|
||||
# TODO: Test login with ldap user
|
||||
testScript = { nodes, ... }: ''
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
def curl(target, format, endpoint):
|
||||
return json.loads(target.succeed(
|
||||
"curl --fail-with-body --silent --show-error --output /dev/null --location"
|
||||
+ " --connect-to j.example.com:443:server:443"
|
||||
+ " --connect-to j.example.com:80:server:80"
|
||||
+ f" --write-out '{format}'"
|
||||
+ " " + endpoint
|
||||
))
|
||||
|
||||
start_all()
|
||||
server.wait_for_unit("jellyfin.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_for_unit("lldap.service")
|
||||
server.wait_for_unit("authelia-auth.example.com.service")
|
||||
server.wait_for_open_port(8096)
|
||||
|
||||
server.copy_from_vm("/etc/ssl/certs/ca-certificates.crt")
|
||||
client.succeed("rm -r /etc/ssl/certs")
|
||||
client.copy_from_host(str(pathlib.Path(os.environ.get("out", os.getcwd())) / "ca-certificates.crt"), "/etc/ssl/certs/ca-certificates.crt")
|
||||
|
||||
response = curl(client, """{"code":%{response_code}}""", "https://j.example.com")
|
||||
|
||||
if response['code'] != 200:
|
||||
raise Exception(f"Code is {response['code']}")
|
||||
'';
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue