ProtoFlix

Documentation

Pour qui installe et administre un serveur ProtoFlix. Ces pages viennent du dépôt du projet, telles quelles.

Installer et configurer

Installer

Essayé sur des systèmes vierges avec un vrai systemd : Debian 13 et Ubuntu 24.04 (deploy/package/test/run.sh). La lecture y est faite par le processeur : aucune accélération matérielle n'y est validée.

Le paquet, l'archive et l'image apportent le FFmpeg de ProtoFlix (ADR 0041) : rien à installer à part. Ils demandent une distribution récente (glibc 2.36) : Debian 12 et 13, Ubuntu 24.04 et plus récents. Sur Ubuntu 22.04, passez par l'image Docker.

Un FFmpeg du système reste accepté à partir de la 5.1, celle de Debian 12, avec PROTOFLIX_FFMPEG_PATH et PROTOFLIX_FFPROBE_PATH. Avec un FFmpeg trop ancien, le serveur démarre, l'écrit dans son journal et n'analyse ni ne convertit rien, sans toucher à ce qu'il connaît déjà.

Avec un FFmpeg du système antérieur à la 6.1, deux différences :

  • Le fichier est rouvert. Avant FFmpeg 6.0, le moteur ne sait pas lire le fichier que le serveur lui a ouvert : il le rouvre par /dev/fd/3, et seuls les formats de fichiers multimédias lui sont permis. Sous le compte séparé du service média (ADR 0028), ce compte doit pouvoir lire la bibliothèque.
  • Le démarrage est un peu plus lent. La conversion ne prend pas d'avance au démarrage : elle travaille aussi vite qu'elle peut, mise en pause quand elle a trop d'avance sur le lecteur.

Les tests du moteur passent sous FFmpeg 5.1, Debian 12, VAAPI compris. Le paquet lui-même n'a pas encore été installé sur un Debian 12 vierge.

Debian, Ubuntu

bash
sudo apt install ./protoflix_<version>_amd64.deb

Le paquet apporte son FFmpeg, crée l'utilisateur protoflix (dans les groupes video et render), démarre le service et donne l'adresse à ouvrir pour créer le compte administrateur.

  • Premier compte : sa création demande un code que le serveur écrit dans son journal, nouveau à chaque démarrage (journalctl -u protoflix), et n'est possible que depuis le réseau local. PROTOFLIX_SETUP_TOKEN le fixe d'avance.
  • Vos films doivent être lisibles par l'utilisateur protoflix, et hors de /var/lib.
  • Réglages : /etc/protoflix/protoflix.env, gardés lors des mises à jour.
  • Mise à jour : la même commande avec le nouveau paquet. La base est migrée au démarrage, après une sauvegarde vérifiée.
  • Retrait : sudo apt remove protoflix garde la base. sudo apt purge protoflix efface aussi la base et les réglages. Vos films ne sont jamais touchés.
  • Journal : journalctl -u protoflix.

Autres systèmes avec systemd

bash
tar xzf protoflix-<version>-linux-amd64.tar.gz
cd protoflix-<version>-linux-amd64
sudo sh install.sh

Il faut systemd. L'archive apporte son FFmpeg ; s'il ne démarre pas, il manque libva2 et libva-drm2. sudo sh install.sh --remove retire le service et garde la base.

Docker

bash
docker compose -f deploy/docker/compose.yaml up -d --build

Indiquez d'abord vos dossiers dans compose.yaml. Dans l'interface, ajoutez la bibliothèque sous son chemin dans le conteneur (/media/films). L'image contient le FFmpeg de ProtoFlix (ADR 0041) : avant de la diffuser hors de votre serveur, voir risks.md.

  • Mise à jour : comme pour le paquet, en un clic ou automatiquement, depuis Administration › Mises à jour. Le conteneur updater installe la version signée dans le volume protoflix-app, relance le serveur dessus, et revient en arrière s'il ne répond pas (ADR 0027, « Sous Docker »). Aucun des deux conteneurs n'a accès au socket Docker. Tirer ou reconstruire une image plus récente met aussi à jour : la plus récente des deux versions démarre.
  • Sans mises à jour intégrées : retirez le service updater et PROTOFLIX_SELF_UPDATE ; l'image se met alors à jour seulement en la remplaçant.

Carte graphique

Le serveur essaie au démarrage ce que la machine sait faire, et n'utilise que ce qui a fonctionné. Si ça échoue en cours de route, le processeur prend le relais.

  • Nvidia : installez le pilote de la carte, avec la bibliothèque libnvidia-encode. En Docker, décommentez gpus dans compose.yaml. Mesuré sur une GTX 1080 par le pilote Windows dans Docker ; pas encore essayé sur un vrai Linux, le service systemd avec ses protections compris. Voir docs/testing/benchmarks/nvidia-gtx1080.md.
  • Intel et AMD (VAAPI) : la partie graphique intégrée décode le H.264 et le HEVC (10 bits compris), réduit l'image et l'encode en H.264. Il faut le pilote VAAPI de la carte : intel-media-va-driver-non-free pour Intel, mesa-va-drivers pour AMD ; le paquet met déjà l'utilisateur du service dans le groupe render. Mesuré sur un Intel UHD 750 : six conversions 4K vers 1080p tiennent ensemble le temps réel, la limite est fixée à quatre (docs/testing/benchmarks/vaapi-intel-uhd750.md), et les tons HDR se calculent sur la carte. Les Radeon n'ont pas encore été essayées sur du vrai matériel.

Port

Le paquet et l'image écoutent sur le port 8097, car 8096 est celui de Jellyfin et les deux peuvent tourner côte à côte. Le binaire lancé seul reste sur 127.0.0.1:8096.

Construire les paquets

bash
sh deploy/package/build.sh <version>
sh deploy/package/test/run.sh <version>

Ils sortent dans dist/, depuis le dernier commit. Il faut seulement git et Docker.

1. Plateformes

PlateformeStatut
Linux x86_64Cible prioritaire. Installation essayée sur Debian 13 et Ubuntu 24.04
Linux ARM64Paquet construit, pas essayé tel quel. Le serveur tourne sur un Pixel 6, installé à la main, avec sa chaîne matérielle
Windows, macOSNon supportés comme serveur en V1 (le développement local fonctionne)

Dépendances d'exécution :

  • aucune base de données à installer : la base est un fichier SQLite embarqué dans le binaire (ADR 0019), protoflix.db dans PROTOFLIX_DATA_DIR. DATA_DIR doit être sur un disque local : le serveur refuse de démarrer si la base est sur un montage SMB ou NFS, car le verrouillage de SQLite n'y est pas fiable ;
  • FFmpeg et ffprobe, version 5.1 ou plus, vérifiée au démarrage ;
  • pour l'accélération matérielle : pilotes et périphériques exposés (/dev/dri pour VA-API/QSV, runtime NVIDIA pour NVENC/NVDEC). Aucune combinaison n'est déclarée supportée avant test (docs/media/).

Pas de serveur de base de données, pas de Redis, pas de broker, pas de moteur de recherche externe (ADR 0013, 0019).

2. Configuration

Configuration validée au démarrage : une combinaison invalide arrête le processus avec un message explicite. Valeurs par défaut sûres.

VariableDéfautRôle
PROTOFLIX_HTTP_ADDR127.0.0.1:8096Adresse HTTP. Loopback par défaut : l'exposition passe par un reverse proxy
PROTOFLIX_DATA_DIR/var/lib/protoflixDonnées persistantes : base SQLite protoflix.db (avec -wal et -shm), clé de chiffrement des secrets, artwork, sauvegardes. Disque local obligatoire
PROTOFLIX_AUTO_MIGRATEfalse (true dans l'image Docker)Migre une base existante au démarrage, après une sauvegarde vérifiée. Sinon, le serveur refuse de démarrer et indique protoflix migrate up. Une base neuve est toujours initialisée
PROTOFLIX_CACHE_DIRDATA_DIR/cacheCaches régénérables : images des fournisseurs (artwork/), plus tard miniatures. Peut être supprimé sans perte (tout est retéléchargé), ou placé sur un autre disque
PROTOFLIX_TRANSCODE_DIRCACHE_DIR/transcodeSegments temporaires des conversions. Vidé à chaque démarrage : ne jamais le faire pointer vers un dossier contenant autre chose. Une conversion peut occuper autant que le fichier source (40 Gio au plus)
PROTOFLIX_DISCOVERYactivéoff : le serveur ne s'annonce plus sur le réseau local (mDNS, réseaux privés seulement). Les clients saisissent alors son adresse
PROTOFLIX_FFMPEG_PATHffmpeg trouvé dans le PATHChemin absolu de FFmpeg, utilisé par les conversions de lecture et la TV en direct (ADR 0021). Introuvable : seuls les fichiers lisibles tels quels sont lus, la TV répond tv_unavailable, le reste du serveur fonctionne. Version 5.1 au moins ; la TV en direct profite de la 7.0 (-readrate_initial_burst)
PROTOFLIX_FFPROBE_PATHffprobe à côté de PROTOFLIX_FFMPEG_PATH, sinon celui du PATHChemin absolu de ffprobe, utilisé pour analyser les fichiers (pistes, HDR, chapitres). Introuvable : les fichiers sont indexés mais pas analysés, un avertissement est journalisé au démarrage. L'image Docker contient le FFmpeg de ProtoFlix, choisi par défaut
PROTOFLIX_PLAYBACK_EXPERIMENTALtrueLaisse les règles de compatibilité non encore mesurées par le banc décider de la lecture directe (compatibility-matrix.md). À false, seules les règles validées servent ; il n'y en a aucune tant que le banc n'existe pas
PROTOFLIX_READAHEAD_MIB256Mémoire de fichiers que la lecture anticipée peut remplir devant toutes les lectures en cours ensemble, sur les disques lents seulement : mécaniques, USB, partages réseau (ADR 0029). Entre 32 et 4096, ou 0 pour l'arrêter
PROTOFLIX_LOG_LEVELinfodebug, info, warn, error
PROTOFLIX_LOG_FORMATjsonjson ou text (développement)
PROTOFLIX_ROLESapi,worker,scannerRôles actifs dans ce processus (ADR 0002)
PROTOFLIX_TRUSTED_PROXIESvideCIDR des reverse proxies dont les en-têtes X-Forwarded-* sont crus. Vide = aucun
PROTOFLIX_PUBLIC_URL—URL publique (vérification Origin, liens d'invitation)
PROTOFLIX_ADMIN_ADDRvide (désactivé)Écoute d'administration sans authentification (/metrics, /debug/pprof/), ex. 127.0.0.1:9096. Jamais derrière le proxy public
PROTOFLIX_OTLP_ENDPOINTvide (désactivé)Export des traces en OTLP/HTTP vers un collecteur choisi par l'administrateur, ex. http://127.0.0.1:4318
PROTOFLIX_INTERNAL_ADDRvide (désactivé)API interne coordinateur ↔ workers distants (ADR 0020). Jamais derrière le proxy public ; TLS obligatoire hors localhost
PROTOFLIX_MEDIA_SERVICE—Socket du service média (ADR 0028), pour les noyaux sans Landlock : voir deploy/systemd/protoflix-media.service
PROTOFLIX_ISOLATE_MEDIAtrueConfine FFmpeg et ffprobe (ADR 0028). À ne couper qu'en dernier recours
PROTOFLIX_PRIVATE_MAX_GIB0Plafond de tous les espaces privés ensemble, 0 pour aucun
PROTOFLIX_GUARDIAN_RATE_MIB25Débit de lecture du gardien de la bibliothèque, en Mio/s (ADR 0032). 0 arrête les sommes de contrôle
PROTOFLIX_GUARDIAN_VERIFY_DAYS90Chaque fichier est relu et vérifié après ce nombre de jours
PROTOFLIX_SMART_DIR/var/lib/protoflix/smartRapports SMART déposés par le minuteur root optionnel de deploy/smart ; le serveur ne lance jamais smartctl
PROTOFLIX_PUSH_RELAYvide (désactivé)Relais de notifications du projet (ADR 0034), https://push.protoflix.club pour le relais officiel. Vide : rien ne part vers le projet, les applications vérifient le serveur toutes les 15 minutes. Voir push-relay.md
PROTOFLIX_PRIVATE_DIR/var/lib/protoflix/privateBibliothèques privées des comptes (quota par compte fixé dans l'admin)
PROTOFLIX_DOWNLOADS_DIR/var/lib/protoflix/downloadsQuarantaine du module Téléchargements (désactivé par défaut)
PROTOFLIX_ALLOWED_ORIGINSvideOrigines navigateur supplémentaires autorisées à appeler l'API avec cookies, ex. http://localhost:5173 pour le serveur de développement web. L'origine du serveur est toujours autorisée
PROTOFLIX_LOCAL_NETWORKSplages privées RFC 1918, ULA IPv6, loopbackPlages considérées comme « local » pour l'accès distant et le code rapide
PROTOFLIX_TRANSCODE_QUOTA20GiBPlafond du répertoire de transcodage
PROTOFLIX_CACHE_QUOTA10GiBPlafond du cache

Les noms définitifs seront figés avec l'implémentation de internal/platform/config ; ce tableau est la référence de départ.

3. Répertoires

RépertoireContenuSauvegardeQuota
DATA_DIRbase SQLite (protoflix.db, -wal, -shm), clé de secrets, artwork d'origine téléchargé ou importé, configuration locale, backups/Oui, via protoflix backup create (jamais une copie à chaud de protoflix.db seul, voir backup-restore-upgrade.md)Surveillé ; écritures refusées proprement sous un seuil d'espace libre
CACHE_DIRdérivés régénérablesNonOui, éviction LRU
TRANSCODE_DIRsegments temporaires par jobNonOui, nettoyage au démarrage et par TTL ; nouvelles sessions refusées si saturé
PRIVATE_DIRfichiers des bibliothèques privées, un sous-répertoire opaque par compteOption (voir sauvegarde)Quota par compte + plafond global
DOWNLOADS_DIRquarantaine des téléchargements avant importNonOui ; refus de nouveaux téléchargements sous un seuil d'espace libre
Journauxstdout/stderr → journald ou DockerSelon politiqueRotation par journald / pilote Docker
Bibliothèquesmédias originauxHors périmètre ProtoFlix— (lecture seule)

Recommandation : TRANSCODE_DIR sur un disque rapide distinct ou un tmpfs de taille bornée, jamais sur le même système de fichiers que DATA_DIR sans quota : une saturation du disque bloquerait les écritures de la base.

4. Service systemd natif

Utilisateur dédié sans shell ni répertoire personnel :

bash
sudo useradd --system --no-create-home --shell /usr/sbin/nologin protoflix

Unité proposée (deploy/systemd/protoflix.service, à créer et tester) :

ini
[Unit]
Description=ProtoFlix media server
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=protoflix
Group=protoflix
# Accès GPU uniquement si l'accélération est activée :
# SupplementaryGroups=render video
EnvironmentFile=/etc/protoflix/protoflix.env
ExecStart=/usr/bin/protoflix serve
Restart=on-failure
TimeoutStopSec=30

StateDirectory=protoflix
CacheDirectory=protoflix
# Bibliothèques en lecture seule :
ReadOnlyPaths=/srv/media

NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
LockPersonality=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
# À tester avec l'accélération matérielle avant activation :
# PrivateDevices=yes   (incompatible avec /dev/dri sans DeviceAllow=)
# SystemCallFilter=@system-service
MemoryMax=8G
TasksMax=512
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Type=notify suppose que le binaire signale sa disponibilité (sd_notify) une fois la base ouverte et les migrations appliquées ; sinon Type=exec (choix actuel de deploy/systemd/protoflix.service). À trancher à l'implémentation.

Le fichier protoflix.db est créé avec les permissions 0600, propriétaire protoflix (StateDirectoryMode=0750, UMask=0027). Il n'existe pas de mot de passe de base : la protection de la base repose sur les permissions du fichier et du répertoire.

5. Docker Compose

Docker est une option, pas une obligation (accès GPU et montages parfois plus simples en natif).

Le fichier de référence est deploy/docker/compose.yaml : un conteneur server sans privilèges ni capacités, un conteneur updater pour les mises à jour (ADR 0027), et les volumes protoflix-data (base, images, sauvegardes) et protoflix-app (versions installées). Pour une carte Intel ou AMD, décommentez devices et group_add, avec le GID du groupe render de l'hôte. Pour Nvidia, décommentez gpus.

Points à vérifier : volume protoflix-data sur un disque local de l'hôte (pas un montage réseau), GID render différent selon l'hôte, montages SMB/NFS des bibliothèques déjà montés sur l'hôte puis exposés en :ro. Un seul coordinateur doit ouvrir le volume de données : ne jamais lancer deux conteneurs protoflix coordinateurs sur le même protoflix.db.

6. Reverse proxy

Le serveur n'assure pas TLS lui-même en V1 : il écoute en HTTP sur loopback (ou un réseau Docker privé) derrière un reverse proxy.

Exigences :

  • TLS terminé au proxy ; HSTS côté proxy une fois la configuration stable.
  • PROTOFLIX_TRUSTED_PROXIES restreint à l'adresse du proxy ; sinon X-Forwarded-For est ignoré.
  • Pas de mise en mémoire tampon des réponses de streaming et de SSE.
  • Délais longs pour SSE ; requêtes Range transmises telles quelles.
  • Taille maximale de corps modeste, sauf sur les routes d'envoi de « Ma bibliothèque » (envoi reprenable par morceaux, ADR 0018) : la taille de morceau est à fixer, et le proxy doit l'accepter.

Caddy

caddyfile
media.example.org {
    reverse_proxy 127.0.0.1:8096 {
        flush_interval -1          # SSE et streaming sans tampon
        transport http {
            read_timeout 0         # flux longs
        }
    }
    request_body {
        max_size 10MB
    }
}

nginx

nginx
server {
    listen 443 ssl;
    http2 on;
    server_name media.example.org;
    # ssl_certificate ... ; ssl_certificate_key ... ;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:8096;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;           # streaming
        proxy_request_buffering off;
        proxy_read_timeout 1h;         # SSE, lectures longues
    }

    location /api/v1/events {
        proxy_pass http://127.0.0.1:8096;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 24h;
    }
}

Le chemin SSE exact sera fixé par la spécification OpenAPI (api/openapi.yaml).

7. Exposition à distance

  • Ne jamais exposer directement le port 8096 sur Internet.
  • Les endpoints d'administration restent accessibles via le même domaine mais exigent le rôle admin ; une option pour restreindre /api/v1/admin/* aux réseaux locaux est planifiée.
  • /metrics n'est jamais exposé par le proxy (écoute séparée, voir observability.md).
  • Le caractère local ou distant d'une connexion (droit « accès distant », code rapide) est déduit de l'IP client vue à travers PROTOFLIX_TRUSTED_PROXIES et de PROTOFLIX_LOCAL_NETWORKS. Un proxy mal déclaré fait apparaître tout le monde comme local : protoflix doctor doit le signaler.

8. Workers distants (planifié, ADR 0020)

Par défaut, tous les rôles tournent dans un seul processus, le coordinateur, qui est le seul à ouvrir protoflix.db. Un worker distant (autre processus ou autre machine) n'accède jamais à la base : il parle au coordinateur par l'API interne.

  • Coordinateur : PROTOFLIX_INTERNAL_ADDR (désactivé par défaut), par exemple 10.0.0.5:8097 sur le réseau local, ou 127.0.0.1:8097 pour un worker sur la même machine. Cette adresse n'est jamais publiée par le reverse proxy public. TLS obligatoire hors localhost (certificat fourni par l'administrateur ; mTLS à évaluer en phase 6).
  • Enrôlement : protoflix worker enroll --name gpu-1, lancé sur le coordinateur, produit un jeton de worker (stocké haché, révocable dans l'administration). Le jeton est transmis au worker par fichier (PROTOFLIX_WORKER_TOKEN_FILE), jamais en ligne de commande.
  • Correspondance des sources : chaque worker déclare source_id → racine locale pour les sources qu'il voit (le même NAS peut être monté à un autre chemin). Un worker ne réclame que les jobs des sources qu'il peut lire.
  • Panne : un worker perdu laisse expirer son lease. Le job repart vers un autre worker, et une lecture transcodée par ce worker est renégociée par le client.

Exemple de worker GPU (cible, non testé) :

ini
# /etc/protoflix/worker.env sur la machine GPU
PROTOFLIX_ROLES=worker
PROTOFLIX_COORDINATOR_URL=https://10.0.0.5:8097
PROTOFLIX_WORKER_TOKEN_FILE=/etc/protoflix/secrets/worker-token
PROTOFLIX_SOURCE_MAP=src_01JD…=/mnt/nas/films,src_01JE…=/mnt/nas/series
PROTOFLIX_TRANSCODE_DIR=/var/cache/protoflix/transcode

Le service systemd du worker reprend l'unité du serveur, avec SupplementaryGroups=render video et DeviceAllow=/dev/dri/renderD128 rw pour l'accès au GPU. Un worker n'a pas besoin de DATA_DIR contenant une base. Les noms des variables du worker seront figés à l'implémentation.

9. Module Téléchargements BitTorrent (si activé)

Le client BitTorrent n'est pas embarqué dans le binaire : il tourne comme démon externe isolé (ADR 0017), sous un compte dédié, avec écriture limitée à DOWNLOADS_DIR, sans accès aux bibliothèques ni à la base. Port entrant fermé par défaut ; seed désactivé par défaut. Choix du démon et exemple de déploiement à fixer avec l'ADR.

  • Alternatives à un port ouvert (VPN maillé, tunnel) : documentées comme choix de l'administrateur, non intégrées au produit.

10. Vérification après installation (planifiée)

Commande protoflix doctor : base ouverte en lecture et en écriture, DATA_DIR sur un système de fichiers local (refus des montages SMB/NFS), mode WAL actif, PRAGMA quick_check, migrations à jour, permissions de protoflix.db (0600), FFmpeg trouvé et version, permissions des répertoires, espace disque, accès en lecture aux bibliothèques, présence d'en-têtes proxy attendus, avertissements de configuration (écoute non loopback sans proxy de confiance, fichiers de secrets trop permissifs, PROTOFLIX_INTERNAL_ADDR joignable depuis Internet ou sans TLS hors localhost).

Source : docs/operations/deployment.md, dans le dépôt de ProtoFlix.