Compare commits
No commits in common. "cecde3e1977d8e595b21798914643ce6bc3c738d" and "ebebd19a13b030f1351fc5e825eb26dea184de51" have entirely different histories.
cecde3e197
...
ebebd19a13
@ -21,31 +21,6 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: jellyfin
|
app: jellyfin
|
||||||
spec:
|
spec:
|
||||||
# Clean up any lingering OIDC artifacts and strip the injected script tag
|
|
||||||
initContainers:
|
|
||||||
- name: strip-oidc
|
|
||||||
image: docker.io/jellyfin/jellyfin:10.11.5
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
runAsGroup: 0
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
set -euxo pipefail
|
|
||||||
cp -a /jellyfin/jellyfin-web/. /web-root
|
|
||||||
# remove injected OIDC script tags everywhere just in case
|
|
||||||
for f in $(find /web-root -type f -name 'index.html'); do
|
|
||||||
sed -i '/oidc\/inject/d' "$f"
|
|
||||||
printf '%s\n' "$f"
|
|
||||||
done
|
|
||||||
# clean any lingering OIDC plugin artifacts on the config volume
|
|
||||||
rm -rf "/config/plugins/OIDC Authentication_"* /config/plugins/configurations/JellyfinOIDCPlugin.v2.xml || true
|
|
||||||
volumeMounts:
|
|
||||||
- name: web-root
|
|
||||||
mountPath: /web-root
|
|
||||||
- name: config
|
|
||||||
mountPath: /config
|
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
jellyfin: "true"
|
jellyfin: "true"
|
||||||
securityContext:
|
securityContext:
|
||||||
@ -53,6 +28,142 @@ spec:
|
|||||||
fsGroup: 65532
|
fsGroup: 65532
|
||||||
fsGroupChangePolicy: OnRootMismatch
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
runAsGroup: 65532
|
runAsGroup: 65532
|
||||||
|
initContainers:
|
||||||
|
- name: fetch-oidc-plugin
|
||||||
|
image: alpine:3.20
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
env:
|
||||||
|
- name: OIDC_PLUGIN_REPO
|
||||||
|
value: "registry.bstein.dev/streaming/oidc-plugin"
|
||||||
|
- name: OIDC_PLUGIN_TAG
|
||||||
|
value: "10.11.5"
|
||||||
|
- name: ORAS_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: harbor-robot
|
||||||
|
key: username
|
||||||
|
optional: true
|
||||||
|
- name: ORAS_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: harbor-robot
|
||||||
|
key: password
|
||||||
|
optional: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: oidc-plugin
|
||||||
|
mountPath: /plugin-src
|
||||||
|
command: ["/bin/sh", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
set -euo pipefail
|
||||||
|
apk add --no-cache curl tar
|
||||||
|
ORAS_VERSION=1.2.0
|
||||||
|
curl -sSL "https://github.com/oras-project/oras/releases/download/v${ORAS_VERSION}/oras_${ORAS_VERSION}_linux_amd64.tar.gz" | tar -xz -C /usr/local/bin oras
|
||||||
|
ref="${OIDC_PLUGIN_REPO}:${OIDC_PLUGIN_TAG}"
|
||||||
|
cd /plugin-src
|
||||||
|
if [ -n "${ORAS_USERNAME:-}" ] && [ -n "${ORAS_PASSWORD:-}" ]; then
|
||||||
|
oras login "$(echo "${OIDC_PLUGIN_REPO}" | cut -d/ -f1)" -u "${ORAS_USERNAME}" -p "${ORAS_PASSWORD}"
|
||||||
|
fi
|
||||||
|
oras pull --allow-path-traversal "${ref}"
|
||||||
|
ls -lh /plugin-src
|
||||||
|
- name: install-oidc-plugin
|
||||||
|
image: alpine:3.20
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
env:
|
||||||
|
- name: OIDC_PLUGIN_VERSION
|
||||||
|
value: "1.0.2.0"
|
||||||
|
- name: OIDC_ISSUER
|
||||||
|
value: "https://sso.bstein.dev/realms/atlas"
|
||||||
|
- name: OIDC_REDIRECT_URI
|
||||||
|
value: "https://stream.bstein.dev/api/oidc/callback"
|
||||||
|
- name: OIDC_LOGOUT_URI
|
||||||
|
value: "https://sso.bstein.dev/realms/atlas/protocol/openid-connect/logout?redirect_uri=https://stream.bstein.dev/"
|
||||||
|
- name: OIDC_SCOPES
|
||||||
|
value: "openid,profile,email"
|
||||||
|
- name: OIDC_ROLE_CLAIM
|
||||||
|
value: "groups"
|
||||||
|
- name: OIDC_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: jellyfin-oidc
|
||||||
|
key: client-id
|
||||||
|
- name: OIDC_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: jellyfin-oidc
|
||||||
|
key: client-secret
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: oidc-plugin
|
||||||
|
mountPath: /plugin-src
|
||||||
|
command: ["/bin/sh", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -z "${OIDC_CLIENT_ID:-}" ] || [ -z "${OIDC_CLIENT_SECRET:-}" ]; then
|
||||||
|
echo "OIDC_CLIENT_ID or OIDC_CLIENT_SECRET missing; create secret jellyfin-oidc" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm -rf "/config/plugins/LDAP Authentication_20.0.0.0"
|
||||||
|
apk add --no-cache unzip
|
||||||
|
plugin_dir="/config/plugins/OIDC Authentication_${OIDC_PLUGIN_VERSION}"
|
||||||
|
config_dir="/config/plugins/configurations"
|
||||||
|
plugin_zip="/plugin-src/OIDC_Authentication_${OIDC_PLUGIN_VERSION}-net9.zip"
|
||||||
|
if [ ! -s "${plugin_zip}" ]; then
|
||||||
|
echo "Plugin zip missing at ${plugin_zip}" >&2
|
||||||
|
echo "Contents of /plugin-src:" >&2
|
||||||
|
ls -lah /plugin-src >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm -rf "${plugin_dir}"
|
||||||
|
mkdir -p "${plugin_dir}" "${config_dir}"
|
||||||
|
unzip -o "${plugin_zip}" -d "${plugin_dir}"
|
||||||
|
rm -f "${plugin_dir}"/Microsoft.Extensions.*.dll
|
||||||
|
cat >"${plugin_dir}/meta.json" <<'EOF'
|
||||||
|
{
|
||||||
|
"category": "Authentication",
|
||||||
|
"changelog": "OIDC SSO authentication plugin; auto user creation and role mapping",
|
||||||
|
"description": "OpenID Connect (OIDC) authentication provider for Jellyfin with SSO support.",
|
||||||
|
"guid": "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6",
|
||||||
|
"name": "OIDC Authentication",
|
||||||
|
"overview": "Enable Single Sign-On (SSO) for Jellyfin using an OpenID Connect provider.",
|
||||||
|
"owner": "lolerskatez",
|
||||||
|
"targetAbi": "10.11.5.0",
|
||||||
|
"timestamp": "2025-12-17T04:00:00Z",
|
||||||
|
"version": "1.0.2.0",
|
||||||
|
"status": "Active",
|
||||||
|
"autoUpdate": false,
|
||||||
|
"imagePath": "",
|
||||||
|
"assemblies": []
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
scope_lines=""
|
||||||
|
for s in $(echo "${OIDC_SCOPES}" | tr ',' ' '); do
|
||||||
|
trimmed="$(echo "${s}" | xargs)"
|
||||||
|
[ -z "${trimmed}" ] && continue
|
||||||
|
scope_lines="${scope_lines} <string>${trimmed}</string>\n"
|
||||||
|
done
|
||||||
|
config_file="${config_dir}/JellyfinOIDCPlugin.v2.xml"
|
||||||
|
cat >"${config_file}" <<EOF
|
||||||
|
<?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">
|
||||||
|
<OidEndpoint>${OIDC_ISSUER}</OidEndpoint>
|
||||||
|
<OidClientId>${OIDC_CLIENT_ID}</OidClientId>
|
||||||
|
<OidSecret>${OIDC_CLIENT_SECRET}</OidSecret>
|
||||||
|
<OidScopes>
|
||||||
|
$(printf "%b" "${scope_lines}") </OidScopes>
|
||||||
|
<RoleClaim>${OIDC_ROLE_CLAIM}</RoleClaim>
|
||||||
|
<RedirectUri>${OIDC_REDIRECT_URI}</RedirectUri>
|
||||||
|
<LogoutUri>${OIDC_LOGOUT_URI}</LogoutUri>
|
||||||
|
<CertificatePath />
|
||||||
|
<AutoCreateUser>true</AutoCreateUser>
|
||||||
|
<AllowRememberMe>false</AllowRememberMe>
|
||||||
|
</PluginConfiguration>
|
||||||
|
EOF
|
||||||
|
chown -R 1000:65532 "${plugin_dir}" "${config_file}"
|
||||||
runtimeClassName: nvidia
|
runtimeClassName: nvidia
|
||||||
containers:
|
containers:
|
||||||
- name: jellyfin
|
- name: jellyfin
|
||||||
@ -72,6 +183,22 @@ spec:
|
|||||||
value: "65532"
|
value: "65532"
|
||||||
- name: UMASK
|
- name: UMASK
|
||||||
value: "002"
|
value: "002"
|
||||||
|
lifecycle:
|
||||||
|
postStart:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
target="/jellyfin/jellyfin-web/index.html"
|
||||||
|
marker='api/oidc/inject'
|
||||||
|
if grep -q "${marker}" "${target}"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
awk -v marker="${marker}" 'BEGIN{inserted=0} /<\/head>/ && !inserted {print " <script src=\"/api/oidc/inject\"></script>"; inserted=1} {print}' "${target}" > "${tmp}"
|
||||||
|
cp "${tmp}" "${target}"
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
nvidia.com/gpu: 1
|
nvidia.com/gpu: 1
|
||||||
@ -84,35 +211,16 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: config
|
- name: config
|
||||||
mountPath: /config
|
mountPath: /config
|
||||||
# Override LDAP plugin configuration from a secret to avoid embedding credentials in the PVC.
|
|
||||||
- name: ldap-config
|
|
||||||
mountPath: /config/plugins/configurations/LDAP-Auth.xml
|
|
||||||
subPath: ldap-config.xml
|
|
||||||
- name: cache
|
- name: cache
|
||||||
mountPath: /cache
|
mountPath: /cache
|
||||||
- name: media
|
- name: media
|
||||||
mountPath: /media
|
mountPath: /media
|
||||||
- name: web-root
|
|
||||||
mountPath: /jellyfin/jellyfin-web
|
|
||||||
lifecycle:
|
|
||||||
postStart:
|
|
||||||
exec:
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
set -eux
|
|
||||||
for f in $(find /jellyfin/jellyfin-web -type f -name 'index.html'); do
|
|
||||||
sed -i '/oidc\/inject/d' "$f" || true
|
|
||||||
done
|
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 0
|
runAsUser: 0
|
||||||
runAsGroup: 0
|
runAsGroup: 0
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
volumes:
|
volumes:
|
||||||
- name: web-root
|
|
||||||
emptyDir: {}
|
|
||||||
- name: config
|
- name: config
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: jellyfin-config-astreae
|
claimName: jellyfin-config-astreae
|
||||||
@ -122,9 +230,5 @@ spec:
|
|||||||
- name: media
|
- name: media
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: jellyfin-media-asteria-new
|
claimName: jellyfin-media-asteria-new
|
||||||
- name: ldap-config
|
- name: oidc-plugin
|
||||||
secret:
|
emptyDir: {}
|
||||||
secretName: jellyfin-ldap-config
|
|
||||||
items:
|
|
||||||
- key: ldap-config.xml
|
|
||||||
path: ldap-config.xml
|
|
||||||
|
|||||||
@ -145,7 +145,6 @@ spec:
|
|||||||
value: "-Dorg.ice4j.ice.harvest.DISABLE_TCP_HARVESTER=false -Dorg.jitsi.videobridge.TCP_HARVESTER_PORT=4443 -Dorg.jitsi.videobridge.TCP_HARVESTER_MAPPED_PORT=4443"
|
value: "-Dorg.ice4j.ice.harvest.DISABLE_TCP_HARVESTER=false -Dorg.jitsi.videobridge.TCP_HARVESTER_PORT=4443 -Dorg.jitsi.videobridge.TCP_HARVESTER_MAPPED_PORT=4443"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- { name: cfg, mountPath: /config }
|
- { name: cfg, mountPath: /config }
|
||||||
- { name: jvb-custom, mountPath: /config/custom-jvb.conf, subPath: custom-jvb.conf }
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: cfg
|
- name: cfg
|
||||||
persistentVolumeClaim: { claimName: jitsi-jvb-config }
|
persistentVolumeClaim: { claimName: jitsi-jvb-config }
|
||||||
|
|||||||
@ -15,3 +15,7 @@ data:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sip-communicator.properties: |
|
||||||
|
org.ice4j.ice.harvest.DISABLE_TCP_HARVESTER=false
|
||||||
|
org.jitsi.videobridge.TCP_HARVESTER_PORT=4443
|
||||||
|
org.jitsi.videobridge.TCP_HARVESTER_MAPPED_PORT=4443
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user