Files
nixconfig/modules/server/containers/apps/jellyfin.nix
soraefir d86c3b76b5 perms
2026-05-14 01:35:26 +02:00

130 lines
4.2 KiB
Nix

{ 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 = {
User = "1000:1000";
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/";
owner = "1000:1000";
mode = "0755";
}
{
path = "${serverCfg.configPath}/jellyfin/";
owner = "1000:1000";
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
#USE CONFIGURATION ENDPOINT
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
#USE AUTH ENDPOINT
SETUP_USER_PAYLOAD=$(${pkgs.jq}/bin/jq -n \
--arg name "$DEFAULT_ADMIN_USERNAME" \
--arg pass "$DEFAULT_ADMIN_PASSWORD" \
'{"Name": $name, "Password": $pass}')
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!"
'';
};
}