Skip to content

Instantly share code, notes, and snippets.

@lpenaud
Last active November 2, 2025 01:16
Show Gist options
  • Select an option

  • Save lpenaud/2bcdca30f4876d37cdf71893110ccf80 to your computer and use it in GitHub Desktop.

Select an option

Save lpenaud/2bcdca30f4876d37cdf71893110ccf80 to your computer and use it in GitHub Desktop.
Jellyfin backup

Sauvegarde de Jellyfin

Maintenant que Jellyfin propose une option de création de sauvegardes, j’ai mis à jour mon processus de sauvegarde de mon instance.

  1. Se rendre dans la section sauvegarde du tableau de bord administrateur.
  2. Création d’une nouvelle sauvegarde avec uniquement les bases de données. Une nouvelle archive ZIP sera générée.
  3. Extraire l’archive ZIP dans un répertoire temporaire.
  4. Ajouter ce répertoire à l’archive tar contenant la sauvegarde du dossier des métadonnées.

Le script utilise la variable d’environnement JELLYFIN_DATA_DIR pour résoudre les différents chemins vers les données à sauvegarder.

Note

Ce script m’a permis d’expérimenter la commande Bash trap pour capturer les signaux et réaliser des actions avant la fin du script même si celui-ci tombe en erreur.

Jellyfin backup

Now Jellyfin has a backup solution, which I use for the databases.

  1. In the admin panel go to the backup section.
  2. Create a new backup of the databases only. The backup is a ZIP file.
  3. Extract the ZIP file into a temporary directory.
  4. Add this new directory to my tarball alongside the metadata backup directory.

I use the JELLYFIN_DATA_DIR environment variable to resolve paths.

#!/bin/bash
# Failed on error pls
set -e
# ...files
function get_nt () {
local nt="${1}"
while shift; do
[ "${1}" -nt "${nt}" ] && nt="${1}"
done
[ -n "${nt}" ] && [ -f "${nt}" ] && realpath "${nt}"
}
# var_name
function error-indir () {
local -n __indir="${1}"
if [ -z "${__indir}" ]; then
echo "ERROR: ${1} is not defined." >&2
return 0
fi
if [ ! -d "${__indir}" ]; then
echo "ERROR: '${__indir}' is not a valid directory." >&2
return 0
fi
return 1
}
function cleanup () {
local -i status=$?
local -a dirs
echo "Exit with code: ${status}" >&2
[[ "${TMPDIR}" =~ jellyfin.backup.[[:alnum:]]+$ ]] && [ -d "${TMPDIR}" ] && dirs+=("${TMPDIR}")
[ "${status}" -ne 0 ] && [ -n "${tar_file}" ] && [ -f "${tar_file}" ] && dirs+=("${tar_file}")
rm -rf "${dirs[@]}"
printf "Removed: %s\n" ${dirs[@]} >&2
}
function interupt () {
local sig="${1}"
echo "Receive signal: ${sig}" >&2
case "${sig}" in
SIGINT)
exit 130
;;
SIGTERM)
exit 143
;;
*)
exit 1
;;
esac
}
declare backup_dir metadata_dir backup unzip_dir tar_file
declare -a zipfiles
error-indir JELLYFIN_DATA_DIR && exit 1
data_dir="${JELLYFIN_DATA_DIR}/data"
metadata_dir="${JELLYFIN_DATA_DIR}/metadata"
backup="$(get_nt "${data_dir}/backups"/*.zip)"
if [ ! -f "${backup}" ]; then
echo "No backup file found" >&2
exit 1
fi
trap cleanup EXIT
trap 'interupt SIGINT' SIGINT
trap 'interupt SIGTERM' SIGTERM
export TMPDIR="$(mktemp -d -t "jellyfin.backup.XXXXXXXXXX")"
unzip_dir="${TMPDIR}/data"
echo "unzip ${backup}" >&2
unzip -q "${backup}" -d "${unzip_dir}"
tar_file="${HOME}/$(date "+%F.%T").jellyfin.tar"
echo "tar ${tar_file}"
tar --create --file="${tar_file}" \
--directory="${unzip_dir}" . \
--directory="${metadata_dir}" .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment