diff --git a/README.md b/README.md
index a4d5949..42c7ffa 100644
--- a/README.md
+++ b/README.md
@@ -37,5 +37,5 @@ services. Also, the design will be extendable to allow users to add services not
- [X] Jellyfin
- [ ] Export metrics to Prometheus.
- [X] LDAP auth through `jellyfin_user` and `jellyfin_admin` LDAP groups.
- - [ ] SSO auth.
+ - [X] SSO auth.
- [X] Backup support.
diff --git a/modules/jellyfin.nix b/modules/jellyfin.nix
index 66f1823..7df1929 100644
--- a/modules/jellyfin.nix
+++ b/modules/jellyfin.nix
@@ -47,10 +47,40 @@ in
dcdomain = lib.mkOption {
type = lib.types.str;
- description = "dc domain for ldap.";
+ description = "dc domain for ldap";
example = "dc=mydomain,dc=com";
};
+ oidcProvider = lib.mkOption {
+ type = lib.types.str;
+ description = "OIDC provider name";
+ default = "Authelia";
+ };
+
+ oidcEndpoint = lib.mkOption {
+ type = lib.types.str;
+ description = "OIDC endpoint for SSO";
+ example = "https://authelia.example.com";
+ };
+
+ oidcClientID = lib.mkOption {
+ type = lib.types.str;
+ description = "Client ID for the OIDC endpoint";
+ default = "jellyfin";
+ };
+
+ oidcAdminUserGroup = lib.mkOption {
+ type = lib.types.str;
+ description = "OIDC admin group";
+ default = "jellyfin_admin";
+ };
+
+ oidcUserGroup = lib.mkOption {
+ type = lib.types.str;
+ description = "OIDC user group";
+ default = "jellyfin_user";
+ };
+
sopsFile = lib.mkOption {
type = lib.types.path;
description = "Sops file location";
@@ -190,6 +220,13 @@ in
group = "jellyfin";
restartUnits = [ "jellyfin.service" ];
};
+ sops.secrets."jellyfin/sso_secret" = {
+ inherit (cfg) sopsFile;
+ mode = "0440";
+ owner = "jellyfin";
+ group = "jellyfin";
+ restartUnits = [ "jellyfin.service" ];
+ };
shb.backup.instances.jellyfin = {
sourceDirectories = [
@@ -238,10 +275,109 @@ in
'';
+
+ ssoConfig = pkgs.writeText "SSO-Auth.xml" ''
+
+
+
+
+ -
+
+ ${cfg.oidcProvider}
+
+
+
+ ${cfg.oidcEndpoint}
+ ${cfg.oidcClientID}
+ %SSO_SECRET%
+ true
+ true
+ true
+
+
+ ${cfg.oidcAdminUserGroup}
+
+
+ ${cfg.oidcUserGroup}
+
+ false
+
+ groups
+
+ groups
+
+
+
+
+
+
+
+ '';
+
+ brandingConfig = pkgs.writeText "branding.xml" ''
+
+
+ <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}
+ <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
+ </a>
+ <a href="${cfg.oidcEndpoint}" class="raised cancel block emby-button authentik-sso">
+ ${cfg.oidcProvider} config
+ </a>
+
+
+ /* Hide this in lieu of authentik link */
+ .emby-button.block.btnForgotPassword {
+ display: none;
+ }
+
+ /* Make links look like buttons */
+ a.raised.emby-button {
+ padding: 0.9em 1em;
+ color: inherit !important;
+ }
+
+ /* Let disclaimer take full width */
+ .disclaimerContainer {
+ display: block;
+ }
+
+ /* Optionally, apply some styling to the `.authentik-sso` class, probably let users configure this */
+ .authentik-sso {
+ /* idk set a background image or something lol */
+ }
+
+ .oauth-login-image {
+ height: 24px;
+ position: absolute;
+ top: 12px;
+ }
+
+ true
+
+ '';
in
template ldapConfig "/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml" {
"%LDAP_PASSWORD%" = "$(cat /run/secrets/jellyfin/ldap_password)";
- };
+ }
+ + template ssoConfig "/var/lib/jellyfin/plugins/configurations/SSO-Auth.xml" {
+ "%SSO_SECRET%" = "$(cat /run/secrets/jellyfin/sso_secret)";
+ }
+ + template brandingConfig "/var/lib/jellyfin/config/branding.xml" {"%a%" = "%a%";};
+
+ shb.authelia.oidcClients = [
+ {
+ id = cfg.oidcClientID;
+ description = "Jellyfin";
+ secret = "jbmVCAZluESWbOvbKQtHhjwcuaNjlMVaidMbJGKaHXHPOmwilCWYBFAQtrnohJzIhbuhWTBwhbDKLmdtyrLXeankWgXNspWCmJxzayHiHRvOPDbcsnquYReI";
+ public = "false";
+ authorization_policy = "one_factor";
+ redirect_uris = [ "https://${cfg.subdomain}.${cfg.domain}/sso/OID/r/${cfg.oidcProvider}" ];
+ }
+ ];
# For backup