diff --git a/nix/modules/nixos/containers/authelia/default.nix b/nix/modules/nixos/containers/authelia/default.nix index 3830f13..9efd16b 100644 --- a/nix/modules/nixos/containers/authelia/default.nix +++ b/nix/modules/nixos/containers/authelia/default.nix @@ -176,16 +176,18 @@ in { identity_providers = { oidc = { clients = [ - # { - # client_id = "jellyfin"; - # client_name = "Jellyfin"; - # client_secret = "$pbkdf2-sha512$310000$w8/7AXV6ljEACFLwkc.neQ$bMnyFnhUjuFjhKGw.awXKfK1EK6n9XS5P6RcywAbBxLhI6hcJqJ8jDCt3oOBp9YpaPCbNh3Sm23NCwJaUIci5w"; - # require_pkce = true; - # pkce_challenge_method = "S256"; - # authorization_policy = "one_factor"; - # redirect_uris = [ "https://jellyfin.${config.domain.base}/sso/OID/redirect/authelia" ]; - # token_endpoint_auth_method = "client_secret_post"; - # } + { + authorization_policy = "one_factor"; + client_id = "jellyfin"; + client_name = "Jellyfin"; + client_secret = "$pbkdf2-sha512$310000$zsC4o9RfhpGEdyk6zlKtvw$ERgl4RYHk2IfILuFRfsOCcK.R1MYiyvUrU2XBgmYLSH5.DALMqw.5ZdRdIKAKAJakYHt/HkkB/lVf96uw6kGNg"; + consent_mode = "implicit"; + pkce_challenge_method = "S256"; + public = "false"; + redirect_uris = ["https://jellyfin2.${cfg.domain}/sso/OID/redirect/authelia"]; + require_pkce = true; + token_endpoint_auth_method = "client_secret_post"; + } { authorization_policy = "one_factor"; client_id = "nextcloud"; diff --git a/nix/modules/nixos/containers/jellyfin/default.nix b/nix/modules/nixos/containers/jellyfin/default.nix index 9319014..d4735d4 100644 --- a/nix/modules/nixos/containers/jellyfin/default.nix +++ b/nix/modules/nixos/containers/jellyfin/default.nix @@ -2,6 +2,7 @@ config, lib, namespace, + pkgs, ... }: with lib; @@ -14,6 +15,7 @@ in { dataPath = mkOpt str "/tank/jellyfin" "Jellyfin data path on host machine"; hostAddress = mkOpt str "172.16.64.10" "With private network, which address to use on Host"; localAddress = mkOpt str "172.16.64.107" "With privateNetwork, which address to use in container"; + secret_file = mkOpt str "secrets/serverz/default.yaml" "SOPS secret to get creds from"; }; imports = [ (import ../shared/shared-traefik-route.nix @@ -22,7 +24,6 @@ in { host = "${cfg.host}"; url = "http://${cfg.localAddress}:8096"; route_enabled = cfg.enable; - # middleware = "secure-headers"; }) (import ../shared/shared-adguard-dns-rewrite.nix { @@ -32,6 +33,12 @@ in { ]; config = mkIf cfg.enable { + sops.secrets = { + "jellyfin/oidc_client_secret" = { + sopsFile = lib.snowfall.fs.get-file "${cfg.secret_file}"; + uid = 999; + }; + }; networking.nat = { enable = true; internalInterfaces = ["ve-jellyfin"]; @@ -47,6 +54,9 @@ in { localAddress = "${cfg.localAddress}"; bindMounts = { + "${config.sops.secrets."jellyfin/oidc_client_secret".path}" = { + isReadOnly = true; + }; "/var/lib/jellyfin/config/" = { hostPath = "${cfg.dataPath}/config/"; isReadOnly = false; @@ -61,13 +71,119 @@ in { }; }; - config = {...}: { + config = {pkgs, ...}: { systemd.tmpfiles.rules = [ "d /var/lib/jellyfin 700 jellyfin jellyfin -" ]; services.jellyfin = { enable = true; }; + systemd.services.jellyfin.preStart = let + ssoConfig = pkgs.writeTextFile { + name = "SSO-Auth.xml"; + text = '' + + + + + + + authelia + + + + https://${config.${namespace}.containers.authelia.host} + jellyfin + CLIENT_SECRET_REPLACE + true + true + true + + + admins + + + users + + false + false + false + false + + + + groups + + groups + + + false + false + false + + + + + + ''; + executable = false; + }; + + brandingConfig = pkgs.writeTextFile { + name = "brandingConfig.xml"; + text = '' + + + <a href="https://${cfg.host}/SSO/OID/p/authelia" class="raised cancel block emby-button authentik-sso"> + Sign in with Authelia&nbsp; + <img alt="OpenID Connect (authelia)" title="OpenID Connect (authelia)" class="oauth-login-image" src="https://raw.githubusercontent.com/goauthentik/authentik/master/web/icons/icon.png"> + </a> + <a href="https://${cfg.host}/SSOViews/linking" class="raised cancel block emby-button authentik-sso"> + Link Authentik config&nbsp; + </a> + <a href="https://${config.${namespace}.containers.authelia.host}" class="raised cancel block emby-button authentik-sso"> + Authelia config&nbsp; + </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 + + ''; + executable = false; + }; + in '' + mkdir -p /var/lib/jellyfin/plugins + CLIENT_SECRET="$(cat ${config.sops.secrets."jellyfin/oidc_client_secret".path})" + sed "s/CLIENT_SECRET_REPLACE/$CLIENT_SECRET/" ${ssoConfig} > /var/lib/jellyfin/plugins/configurations/SSO-Auth.xml + cat ${brandingConfig} > /var/lib/jellyfin/plugins/configurations/brandingConfig.xml + ''; networking = { firewall = { diff --git a/nix/secrets/serverz/default.yaml b/nix/secrets/serverz/default.yaml index 2c3d79f..c4ae601 100644 --- a/nix/secrets/serverz/default.yaml +++ b/nix/secrets/serverz/default.yaml @@ -6,6 +6,8 @@ authelia-storage-encryption-key: ENC[AES256_GCM,data:ub+rSg3lNyxVJapVhMJBu+9kfG6 authelia-jwt-rsa-key: ENC[AES256_GCM,data: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,iv:1Mdm76uIxkYvK4NO0HlvO5azAx5npHCHrHs74i1qzCA=,tag:M2o2mTE0jAtQLmpzy4tsoQ==,type:str] nextcloud-admin-pass: ENC[AES256_GCM,data:yJFfJ7K/gyM71omo//qURGs=,iv:5JmRGdHHtJtiZeuF4kjok2nUrWQArRRTr5XbwJtDXxI=,tag:SY9Lz7QMCNoixUesA3Q9WQ==,type:str] nextcloud-secretFile: ENC[AES256_GCM,data:gb4HBa9cNpvColxyWKEFwPkYPh7iGOXQgI1uEaz61gotnoK3sOcDnt7N+1fBi9yAJeQopxWunq9TN9TvNMycMcWqXjtKD9WFtPXL/Yb9zTokfw8VO8uzcvbUkKsWTxiO2o8wC1u5Rrw=,iv:ojbPycEo9I3G79uqOi24QC0UAwjp4umxpoH/DkSvvAQ=,tag:S/e1Rh7ny1bnV4YAdid6Ig==,type:str] +jellyfin: + oidc_client_secret: ENC[AES256_GCM,data:ujmIM11wTQGgsQXvCKZxH9XJkyZBLrqs8LFUuystJtJ3BPD0X86Vjw+5fzZEExrOiKkhRg==,iv:q3LSlyeARA44F4IiZ4PeawqKQOylTJ4mXO8ZVN4y5tU=,tag:LPMj4u+xSIVvQMK/6vT4DQ==,type:str] sops: kms: [] gcp_kms: [] @@ -30,8 +32,8 @@ sops: SVdkN2htWTBaLy9jdGJ6S0RocE9JMFUK8yejh6yKp+OLsNFXWHUJzvHnwaGI1yXA Y4F7JY6bhXcu8KJGvjgy08ox+n82V6xY9ov1hwhUlfyIZf4H0/bjuA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-11-18T13:43:04Z" - mac: ENC[AES256_GCM,data:tZPqK/opHF8NjJbjBfEzRV4CjNIpBV/S5h6QG1O8s9JhfreZ1WarQisaIfRpHhjGwseWDRD9wKf/Q5DctiTEUPPQl161BCaqtJ2AHXEhVEZ+fx6/FxtxCMI3KyYOIRP8AiT0X13aOM6Ux0SM9Rf2iYH2JGLANTLBRLRcEskcnI0=,iv:BA4NK5ingfMTZPpJ8WQbzNLPZ+gnlRq/umZiTjbyGSg=,tag:tPKrB45DzM0aAMVPK59QIw==,type:str] + lastmodified: "2024-11-22T13:21:33Z" + mac: ENC[AES256_GCM,data:feUoc4LQVbl/sAXxcu/JtNOf/7tdr2wafOXNEKTvR/p3oC7KXV2ozoo90/4hOD1gMqjzI/NrUeaXVPVgaC/EMw9RegTUpPWc8bNqjsgR378tyaZWXihQ/WfFJe3UhGU7oev8JsKOsN+ICccHGd9q4GVT/uA3O2CcPAaWrY0LD2o=,iv:qOgTjMww4dCHVIw5TjM1GIAJThDCaNtrZgGUNcOoINg=,tag:9RuvY1ytLD8fb6Lgi9kyGg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.1