{ config, containerCfg, pkgs, lib, builder, name, ... }: let serverCfg = config.syscfg.server; image = pkgs.dockerTools.streamLayeredImage { # pkgs.dockerTools.buildImage{# name = pkgs.jellyfin.name; tag = pkgs.jellyfin.version; contents = [ pkgs.cacert ]; config = { Entrypoint = [ "${pkgs.jellyfin}/bin/jellyfin" ]; ExposedPorts = { "8096/tcp" = { }; }; Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" "NIX_SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]; }; }; #LDAP_DC_DOMAIN = "dc=ldap,dc=helcel,dc=net" #HOST=... #LDAP_BIND_USER=ldap-sa #LDAP_BIND_PASSWORD=... #LDAP_GROUP=flix #LDAP_ADMIN=admin in { paths = [ { path = "${serverCfg.dataPath}/media/"; mode = "0755"; } { path = "${serverCfg.configPath}/jellyfin/"; mode = "0755"; } ]; containers = { server = builder.mkContainer { subdomain = containerCfg.subdomain; imageStream = image; # imageFile = image; port = 8096; extraEnv = { HOME = "/config/data"; DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = "1"; JELLYFIN_WEB_DIR = "${pkgs.jellyfin-web}/share/jellyfin-web"; JELLYFIN_HttpListenerHost__BindAddress= "0.0.0.0"; #we can use settings.xml override JELLYFIN_ServerName = if containerCfg.extra?name then containerCfg.extra.name else "Flix"; }; extraOptions = [ "--tmpfs=/tmp:rw,noexec,nosuid,size=512m" ]; overrides = { cmd = [ "--datadir" "/config/data" "--cachedir" "/config/cache" "--configdir" "/config/config" "--logdir" "/config/log" ]; volumes = [ "${serverCfg.dataPath}/media:/media:ro" "${serverCfg.configPath}/jellyfin:/config" ]; # If you have an Intel/AMD GPU for transcoding, add the device: devices = lib.optionals (builtins.pathExists "/dev/dri") [ "/dev/dri:/dev/dri" ]; }; }; }; setup = { trigger = "server"; envFile = config.sops.secrets."CUSTOM".path; script = pkgs.writeShellScript "setup" '' JELLYFIN_URL="https://${containerCfg.subdomain}.${serverCfg.hostDomain}" until ${pkgs.curl}/bin/curl -sf "$JELLYFIN_URL/health" > /dev/null 2>&1; do sleep 5 done echo "Jellyfin is up. Sleeping for 20 seconds..." sleep 20 WIZARD_COMPLETE=$(${pkgs.curl}/bin/curl -sSf "$JELLYFIN_URL/System/Info/Public" 2>/dev/null | \ ${pkgs.jq}/bin/jq -r '.StartupWizardCompleted // false') if [ "$WIZARD_COMPLETE" = "true" ]; then echo "Jellyfin wizard already completed. Exiting cleanly." exit 0 fi if ! ${pkgs.curl}/bin/curl -sSf -X POST "$JELLYFIN_URL/Startup/Configuration" \ -H "Content-Type: application/json" \ -d '{"ServerName":"Flix","UICulture":"en-US","MetadataCountryCode":"US","PreferredMetadataLanguage":"en"}'; then echo "ERROR: Failed to set startup configuration." exit 1 fi SETUP_USER_PAYLOAD=$(${pkgs.jq}/bin/jq -n \ --arg name "$DEFAULT_ADMIN_USERNAME" \ --arg pass "$DEFAULT_ADMIN_PASSWORD" \ '{"Name": $name, "Password": $pass}') echo "Payload to be sent to /Startup/User: $SETUP_USER_PAYLOAD" if ! ${pkgs.curl}/bin/curl -sSf -X POST "$JELLYFIN_URL/Startup/User" \ -H 'accept: */*' \ -H "Content-Type: application/json" \ -d "$SETUP_USER_PAYLOAD"; then echo "ERROR: Failed to set admin user." exit 1 fi # Enable remote access, disable UPnP auto-mapping if ! ${pkgs.curl}/bin/curl -sSf -X POST "$JELLYFIN_URL/Startup/RemoteAccess" \ -H "Content-Type: application/json" \ -d '{"EnableRemoteAccess":true,"EnableAutomaticPortMapping":false}'; then echo "ERROR: Failed to configure remote access." exit 1 fi # Complete the wizard if ! ${pkgs.curl}/bin/curl -sSf -X POST "''$JELLYFIN_URL/Startup/Complete"; then echo "ERROR: Failed to complete wizard." exit 1 fi echo "Jellyfin initialization successfully completed!" ''; }; }