Aller au contenu

Déploiement instance unique

Configuration pour un déploiement mono-instance, sans PgBouncer. Le Compose utilise le réseau Docker externe traefik_proxy pour raccorder Stream Fusion Reborn au reverse proxy. Cette configuration est adaptée à un usage personnel ou à un petit groupe.

Pour commencer

C’est la configuration recommandée pour un premier déploiement. Passez à la configuration scalable uniquement si vous avez besoin de haute disponibilité.


Lancement

# 1. Créer le répertoire
mkdir stream-fusion && cd stream-fusion

# 2. Créer le .env (voir la page Environnement pour le template complet)
nano .env

# 3. (Optionnel) Créer user.env pour le mode unique_account (debrid/indexeurs partagés)
# nano user.env

# 4. Créer le docker-compose.yml (copier le contenu ci-dessous)
nano docker-compose.yml

# 5. Lancer
docker compose up -d

# 6. Suivre les logs
docker compose logs -f stream-fusion

Accès aux services

Service URL
Application Via le domaine configuré sur votre reverse proxy
Admin https://votre-domaine/admin/
PostgreSQL localhost:5432 (non exposé par défaut)
Redis localhost:6379 (non exposé par défaut)

Exposition réseau

Le Compose ne publie pas directement le port 8080 sur l’hôte. Le service stream-fusion est accessible via le réseau Docker externe traefik_proxy. PostgreSQL, Redis et Meilisearch ne doivent pas être exposés publiquement.


Préparer le fichier .env

Avant de démarrer la stack, créez un fichier .env à côté du docker-compose.yml.

Les valeurs utilisateur sont :

  • ADMIN_SECRET_KEY : clé d’accès à l’interface d’administration ;
  • TMDB_API_KEY : clé API TMDB.

Les autres valeurs sont des secrets internes et doivent être générées indépendamment.

Secrets PostgreSQL

POSTGRES_PASSWORD, PG_PASS et PG_MIGRATION_PASS doivent être trois secrets différents, composés chacun de 64 caractères hexadécimaux.

Générer un secret

La commande suivante génère une valeur hexadécimale aléatoire de 64 caractères :

openssl rand -hex 32

Générer tous les secrets internes

Vous pouvez générer toutes les valeurs nécessaires en une seule fois :

for name in \
  SECRET_API_KEY \
  CONFIG_SECRET_KEY \
  SESSION_KEY \
  PEER_MASTER_KEY \
  POSTGRES_PASSWORD \
  PG_PASS \
  PG_MIGRATION_PASS
do
  printf '%s=' "$name"
  openssl rand -hex 32
done

Ne réutilisez pas la même valeur

Chaque secret doit recevoir sa propre valeur aléatoire. En particulier, POSTGRES_PASSWORD, PG_PASS et PG_MIGRATION_PASS doivent obligatoirement être différents.

Exemple complet de .env

Créez le fichier :

nano .env

Puis utilisez le modèle suivant en remplaçant les valeurs d’exemple :

# =============================================================================
# Stream Fusion Reborn — Environment Configuration
# =============================================================================
#
# ADMIN_SECRET_KEY = clé choisie par l'utilisateur pour l'interface admin.
# Les autres secrets internes doivent être générés séparément.
#
# Génération d'un secret interne :
#   openssl rand -hex 32
#
# IMPORTANT :
# POSTGRES_PASSWORD, PG_PASS et PG_MIGRATION_PASS doivent être des valeurs
# hexadécimales de 64 caractères et toutes différentes.
# =============================================================================

# ── Valeurs utilisateur ────────────────────────────────────────────────────────

ADMIN_SECRET_KEY=replace-with-your-admin-key-at-least-32-characters
TMDB_API_KEY=replace-with-your-tmdb-api-key


# ── Secrets internes ──────────────────────────────────────────────────────────

SECRET_API_KEY=RANDOM_64_HEX
CONFIG_SECRET_KEY=RANDOM_64_HEX
SESSION_KEY=RANDOM_64_HEX
PEER_MASTER_KEY=RANDOM_64_HEX


# ── PostgreSQL ────────────────────────────────────────────────────────────────

POSTGRES_PASSWORD=RANDOM_64_HEX
PG_PASS=RANDOM_64_HEX
PG_MIGRATION_PASS=RANDOM_64_HEX


# ── Déploiement ───────────────────────────────────────────────────────────────

TZ=Europe/Paris
USE_HTTPS=true
PROXY_URL=http://warp:1080
STREMTHRU_URL=

PG_RESTORE_PASS

Aucun PG_RESTORE_PASS n’est à définir dans .env.

Le Compose génère automatiquement un quatrième secret PostgreSQL, dédié à la restauration, dans le volume Docker pg-restore-secret.

Ce secret est ensuite utilisé par le rôle streamfusion_restore.


Docker Compose complet

Le fichier ci-dessous correspond au fichier deploy/docker-compose.yml utilisé actuellement par Stream Fusion Reborn.

Source de référence

Lors des futures mises à jour de Stream Fusion Reborn, le fichier deploy/docker-compose.yml présent dans le dépôt reste la source de référence.

Réseau Docker requis

Le Compose utilise un réseau Docker externe nommé traefik_proxy.

Vérifiez d’abord s’il existe :

docker network inspect traefik_proxy

S’il n’existe pas encore, créez-le :

docker network create traefik_proxy

Reverse proxy

Le service stream-fusion utilise expose: 8080 et non un mapping ports: vers l’hôte.

Le reverse proxy doit donc être connecté au réseau Docker traefik_proxy pour joindre l’application.

docker-compose.yml

Copiez le contenu suivant dans votre fichier docker-compose.yml :

---
networks:
  proxy_network:
    external: true

services:

  # ===========================================================================
  # SECRET POSTGRESQL RESTORE
  # ===========================================================================

  pg-restore-secret-init:
    image: postgres:17-alpine
    command:
      - /bin/sh
      - -ec
      - |
        umask 077

        secret=/run/pg-restore-secret/pg_restore_pass
        tmp="$${secret}.tmp"

        if [ ! -s "$$secret" ]; then
          rm -f "$$tmp"

          od -An -N32 -tx1 /dev/urandom \
            | tr -d ' \n' \
            > "$$tmp"

          test "$$(wc -c < "$$tmp")" -eq 64

          chmod 0444 "$$tmp"
          mv "$$tmp" "$$secret"
        fi

        test "$$(wc -c < "$$secret")" -eq 64
        chmod 0444 "$$secret"

    volumes:
      - pg-restore-secret:/run/pg-restore-secret

    network_mode: none

    cap_drop:
      - ALL

    security_opt:
      - no-new-privileges:true

    read_only: true
    restart: "no"


  # ===========================================================================
  # POSTGRESQL
  #
  # PostgreSQL démarre d'abord avec son compte bootstrap "streamfusion".
  # Les rôles applicatifs sont créés ensuite par postgres-security-init.
  # ===========================================================================

  stremio-postgres:
    image: postgres:17-alpine
    container_name: stremio-postgres
    restart: unless-stopped

    environment:
      PGDATA: /var/lib/postgresql/data/pgdata

      POSTGRES_USER: streamfusion
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
      POSTGRES_DB: streamfusion

    expose:
      - 5432

    volumes:
      - stremio-postgres:/var/lib/postgresql/data/pgdata

    healthcheck:
      test:
        - CMD-SHELL
        - >-
          PGPASSWORD="$$POSTGRES_PASSWORD"
          psql
          -h 127.0.0.1
          -U "$$POSTGRES_USER"
          -d "$$POSTGRES_DB"
          -X
          -qAt
          -v ON_ERROR_STOP=1
          -c "SELECT 1"
          | grep -qx 1

      interval: 5s
      timeout: 5s
      retries: 20
      start_period: 5s

    networks:
      - proxy_network


  # ===========================================================================
  # SECURISATION POSTGRESQL
  #
  # Création et validation :
  #
  # - streamfusion_owner
  # - streamfusion_runtime
  # - streamfusion_migration
  # - streamfusion_restore
  #
  # Fonctionne aussi avec un volume PostgreSQL déjà existant.
  # ===========================================================================

  postgres-security-init:
    image: postgres:17-alpine
    restart: "no"

    environment:
      POSTGRES_USER: streamfusion
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
      POSTGRES_DB: streamfusion

      PG_PASS: ${PG_PASS:?PG_PASS is required}
      PG_MIGRATION_PASS: ${PG_MIGRATION_PASS:?PG_MIGRATION_PASS is required}

      PG_RESTORE_PASS_FILE: /run/pg-restore-secret/pg_restore_pass

    volumes:
      - pg-restore-secret:/run/pg-restore-secret:ro

    depends_on:
      pg-restore-secret-init:
        condition: service_completed_successfully

      stremio-postgres:
        condition: service_healthy

    command:
      - /bin/sh
      - -ec
      - |
        set -eu

        echo "[postgres-security] Configuration des rôles Stream Fusion"

        : "$${POSTGRES_USER:?POSTGRES_USER manquant}"
        : "$${POSTGRES_DB:?POSTGRES_DB manquant}"
        : "$${POSTGRES_PASSWORD:?POSTGRES_PASSWORD manquant}"
        : "$${PG_PASS:?PG_PASS manquant}"
        : "$${PG_MIGRATION_PASS:?PG_MIGRATION_PASS manquant}"

        RESTORE_PASS_FILE="$${PG_RESTORE_PASS_FILE:-/run/pg-restore-secret/pg_restore_pass}"

        validate_hex64() {
          name="$$1"
          value="$$2"

          if [ "$${#value}" -ne 64 ]; then
            echo "[postgres-security] ERREUR : $$name doit contenir exactement 64 caractères hexadécimaux"
            exit 1
          fi

          case "$$value" in
            *[!0-9a-f]*)
              echo "[postgres-security] ERREUR : $$name doit être hexadécimal en minuscules"
              exit 1
              ;;
          esac
        }

        validate_hex64 "POSTGRES_PASSWORD" "$$POSTGRES_PASSWORD"
        validate_hex64 "PG_PASS" "$$PG_PASS"
        validate_hex64 "PG_MIGRATION_PASS" "$$PG_MIGRATION_PASS"

        if [ ! -s "$$RESTORE_PASS_FILE" ]; then
          echo "[postgres-security] ERREUR : secret restore absent : $$RESTORE_PASS_FILE"
          exit 1
        fi

        RESTORE_PASS="$$(cat "$$RESTORE_PASS_FILE")"

        validate_hex64 "PG_RESTORE_PASS" "$$RESTORE_PASS"

        if [ "$$POSTGRES_PASSWORD" = "$$PG_PASS" ] || \
           [ "$$POSTGRES_PASSWORD" = "$$PG_MIGRATION_PASS" ] || \
           [ "$$POSTGRES_PASSWORD" = "$$RESTORE_PASS" ] || \
           [ "$$PG_PASS" = "$$PG_MIGRATION_PASS" ] || \
           [ "$$PG_PASS" = "$$RESTORE_PASS" ] || \
           [ "$$PG_MIGRATION_PASS" = "$$RESTORE_PASS" ]; then

          echo "[postgres-security] ERREUR : les quatre secrets PostgreSQL doivent être distincts"
          exit 1
        fi

        export PGPASSWORD="$$POSTGRES_PASSWORD"

        psql \
          --host=stremio-postgres \
          --username="$$POSTGRES_USER" \
          --dbname="$$POSTGRES_DB" \
          --no-psqlrc \
          --set=ON_ERROR_STOP=1 \
          --set=runtime_password="$$PG_PASS" \
          --set=migration_password="$$PG_MIGRATION_PASS" \
          --set=restore_password="$$RESTORE_PASS" <<'SQL'

        DO $$$$
        BEGIN

          IF NOT EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_owner'
          ) THEN
            CREATE ROLE streamfusion_owner;
          END IF;

          IF NOT EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_runtime'
          ) THEN
            CREATE ROLE streamfusion_runtime LOGIN;
          END IF;

          IF NOT EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_migration'
          ) THEN
            CREATE ROLE streamfusion_migration LOGIN;
          END IF;

          IF NOT EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_restore'
          ) THEN
            CREATE ROLE streamfusion_restore LOGIN;
          END IF;

        END
        $$$$;


        ALTER ROLE streamfusion_owner
          WITH
          NOLOGIN
          NOSUPERUSER
          CREATEDB
          NOCREATEROLE
          NOINHERIT
          NOREPLICATION
          NOBYPASSRLS;


        ALTER ROLE streamfusion_runtime
          WITH
          LOGIN
          NOSUPERUSER
          NOCREATEDB
          NOCREATEROLE
          NOINHERIT
          NOREPLICATION
          NOBYPASSRLS
          PASSWORD :'runtime_password';


        ALTER ROLE streamfusion_migration
          WITH
          LOGIN
          NOSUPERUSER
          NOCREATEDB
          NOCREATEROLE
          NOINHERIT
          NOREPLICATION
          NOBYPASSRLS
          PASSWORD :'migration_password';


        ALTER ROLE streamfusion_restore
          WITH
          LOGIN
          NOSUPERUSER
          CREATEDB
          NOCREATEROLE
          NOINHERIT
          NOREPLICATION
          NOBYPASSRLS
          PASSWORD :'restore_password';


        GRANT streamfusion_owner
          TO streamfusion_migration
          WITH INHERIT FALSE, SET TRUE;


        GRANT streamfusion_owner
          TO streamfusion_restore
          WITH INHERIT FALSE, SET TRUE;


        GRANT pg_signal_backend
          TO streamfusion_restore
          WITH INHERIT TRUE, SET TRUE;


        -- Le runtime ne doit jamais devenir propriétaire.
        DO $$$$
        BEGIN

          IF EXISTS (
            SELECT 1
            FROM pg_auth_members m
            JOIN pg_roles parent
              ON parent.oid = m.roleid
            JOIN pg_roles member
              ON member.oid = m.member
            WHERE parent.rolname = 'streamfusion_owner'
              AND member.rolname = 'streamfusion_runtime'
          ) THEN

            EXECUTE
              'REVOKE streamfusion_owner FROM streamfusion_runtime';

          END IF;

        END
        $$$$;


        ALTER DATABASE streamfusion
          OWNER TO streamfusion_owner;


        ALTER SCHEMA public
          OWNER TO streamfusion_owner;


        -- Conversion ciblée d'une ancienne installation.
        -- On transfère uniquement les objets applicatifs du schema public.
        DO $$$$
        DECLARE

          obj record;
          ddl text;

        BEGIN

          FOR obj IN

            SELECT
              n.nspname,
              c.relname,
              c.relkind

            FROM pg_class c

            JOIN pg_namespace n
              ON n.oid = c.relnamespace

            WHERE n.nspname = 'public'

              AND pg_get_userbyid(c.relowner) = 'streamfusion'

              AND c.relkind IN (
                'r',
                'p',
                'S',
                'v',
                'm',
                'f'
              )

              AND NOT EXISTS (

                SELECT 1

                FROM pg_depend d

                WHERE d.classid = 'pg_class'::regclass
                  AND d.objid = c.oid
                  AND d.deptype = 'e'

              )

            ORDER BY

              CASE c.relkind
                WHEN 'S' THEN 2
                ELSE 1
              END,

              c.relname

          LOOP

            ddl := CASE obj.relkind

              WHEN 'S' THEN
                format(
                  'ALTER SEQUENCE %I.%I OWNER TO streamfusion_owner',
                  obj.nspname,
                  obj.relname
                )

              WHEN 'v' THEN
                format(
                  'ALTER VIEW %I.%I OWNER TO streamfusion_owner',
                  obj.nspname,
                  obj.relname
                )

              WHEN 'm' THEN
                format(
                  'ALTER MATERIALIZED VIEW %I.%I OWNER TO streamfusion_owner',
                  obj.nspname,
                  obj.relname
                )

              WHEN 'f' THEN
                format(
                  'ALTER FOREIGN TABLE %I.%I OWNER TO streamfusion_owner',
                  obj.nspname,
                  obj.relname
                )

              ELSE
                format(
                  'ALTER TABLE %I.%I OWNER TO streamfusion_owner',
                  obj.nspname,
                  obj.relname
                )

            END;

            EXECUTE ddl;

          END LOOP;

        END
        $$$$;


        REVOKE ALL
          ON DATABASE streamfusion
          FROM PUBLIC;


        GRANT CONNECT
          ON DATABASE streamfusion
          TO
            streamfusion_runtime,
            streamfusion_migration,
            streamfusion_restore;


        REVOKE CREATE
          ON SCHEMA public
          FROM PUBLIC;


        REVOKE CREATE
          ON SCHEMA public
          FROM streamfusion_runtime;


        GRANT USAGE
          ON SCHEMA public
          TO streamfusion_runtime;


        GRANT
          SELECT,
          INSERT,
          UPDATE,
          DELETE
        ON ALL TABLES
        IN SCHEMA public
        TO streamfusion_runtime;


        GRANT
          USAGE,
          SELECT,
          UPDATE
        ON ALL SEQUENCES
        IN SCHEMA public
        TO streamfusion_runtime;


        ALTER DEFAULT PRIVILEGES
          FOR ROLE streamfusion_owner
          IN SCHEMA public
          GRANT
            SELECT,
            INSERT,
            UPDATE,
            DELETE
          ON TABLES
          TO streamfusion_runtime;


        ALTER DEFAULT PRIVILEGES
          FOR ROLE streamfusion_owner
          IN SCHEMA public
          GRANT
            USAGE,
            SELECT,
            UPDATE
          ON SEQUENCES
          TO streamfusion_runtime;

        SQL


        echo "[postgres-security] Validation"


        result="$$(

          psql \
            --host=stremio-postgres \
            --username="$$POSTGRES_USER" \
            --dbname="$$POSTGRES_DB" \
            --no-psqlrc \
            --tuples-only \
            --no-align \
            --set=ON_ERROR_STOP=1 <<'SQL'

        SELECT CASE

        WHEN

          EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_owner'
              AND NOT rolcanlogin
              AND NOT rolsuper
              AND rolcreatedb
              AND NOT rolcreaterole
              AND NOT rolinherit
              AND NOT rolreplication
              AND NOT rolbypassrls
          )

          AND EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_runtime'
              AND rolcanlogin
              AND NOT rolsuper
              AND NOT rolcreatedb
              AND NOT rolcreaterole
              AND NOT rolinherit
              AND NOT rolreplication
              AND NOT rolbypassrls
          )

          AND EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_migration'
              AND rolcanlogin
              AND NOT rolsuper
              AND NOT rolcreatedb
              AND NOT rolcreaterole
              AND NOT rolinherit
              AND NOT rolreplication
              AND NOT rolbypassrls
          )

          AND EXISTS (
            SELECT 1
            FROM pg_roles
            WHERE rolname = 'streamfusion_restore'
              AND rolcanlogin
              AND NOT rolsuper
              AND rolcreatedb
              AND NOT rolcreaterole
              AND NOT rolinherit
              AND NOT rolreplication
              AND NOT rolbypassrls
          )

          AND EXISTS (
            SELECT 1
            FROM pg_auth_members m

            JOIN pg_roles parent
              ON parent.oid = m.roleid

            JOIN pg_roles member
              ON member.oid = m.member

            WHERE parent.rolname = 'streamfusion_owner'
              AND member.rolname = 'streamfusion_migration'
              AND NOT m.inherit_option
              AND m.set_option
          )

          AND EXISTS (
            SELECT 1
            FROM pg_auth_members m

            JOIN pg_roles parent
              ON parent.oid = m.roleid

            JOIN pg_roles member
              ON member.oid = m.member

            WHERE parent.rolname = 'streamfusion_owner'
              AND member.rolname = 'streamfusion_restore'
              AND NOT m.inherit_option
              AND m.set_option
          )

          AND pg_has_role(
            'streamfusion_restore',
            'pg_signal_backend',
            'MEMBER'
          )

          AND pg_has_role(
            'streamfusion_restore',
            'pg_signal_backend',
            'USAGE'
          )

          AND (
            SELECT pg_get_userbyid(datdba)
            FROM pg_database
            WHERE datname = 'streamfusion'
          ) = 'streamfusion_owner'

          AND (
            SELECT pg_get_userbyid(nspowner)
            FROM pg_namespace
            WHERE nspname = 'public'
          ) = 'streamfusion_owner'

          AND NOT EXISTS (

            SELECT 1

            FROM pg_class c

            JOIN pg_namespace n
              ON n.oid = c.relnamespace

            WHERE n.nspname = 'public'

              AND pg_get_userbyid(c.relowner) = 'streamfusion'

              AND c.relkind IN (
                'r',
                'p',
                'S',
                'v',
                'm',
                'f'
              )

              AND NOT EXISTS (

                SELECT 1

                FROM pg_depend d

                WHERE d.classid = 'pg_class'::regclass
                  AND d.objid = c.oid
                  AND d.deptype = 'e'

              )

          )

        THEN 'OK'

        ELSE 'ERROR'

        END;

        SQL

        )"

        test "$$result" = "OK"

        echo "[postgres-security] Configuration validée"

    cap_drop:
      - ALL

    security_opt:
      - no-new-privileges:true

    read_only: true

    tmpfs:
      - /tmp:mode=1777

    networks:
      - proxy_network


  # ===========================================================================
  # REDIS
  # ===========================================================================

  stremio-redis:
    image: redis:7-alpine
    container_name: stremio-redis

    expose:
      - 6379

    volumes:
      - stremio-redis:/data

    command:
      - redis-server
      - --appendonly
      - "yes"

    restart: unless-stopped

    networks:
      - proxy_network


  # ===========================================================================
  # WARP
  # ===========================================================================

  warp:
    image: caomingjun/warp:latest
    container_name: warp
    restart: always

    expose:
      - 1080

    environment:
      - WARP_SLEEP=2

    cap_add:
      - NET_ADMIN

    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
      - net.ipv4.conf.all.src_valid_mark=1

    volumes:
      - warp-data:/var/lib/cloudflare-warp

    networks:
      - proxy_network


  # ===========================================================================
  # TASKIQ WORKER
  # ===========================================================================

  taskiq-worker:
    image: laster13/stream-fusion-reborn:latest
    container_name: taskiq-worker

    command:
      python -m taskiq worker stream_fusion.worker:broker

    # env_file: user.env
    # Décommenter uniquement pour unique_account / debrid / indexers.

    environment:
      SECRET_API_KEY: ${SECRET_API_KEY:?Provide SECRET_API_KEY}
      CONFIG_SECRET_KEY: ${CONFIG_SECRET_KEY:?Provide CONFIG_SECRET_KEY}
      PEER_MASTER_KEY: ${PEER_MASTER_KEY:-}
      TMDB_API_KEY: ${TMDB_API_KEY:?Provide TMDB_API_KEY}

      PG_USER: streamfusion_runtime
      PG_PASS: ${PG_PASS:?PG_PASS is required}
      PG_BASE: streamfusion

      PG_RESTORE_USER: streamfusion_restore
      PG_RESTORE_PASS_FILE: /run/pg-restore-secret/pg_restore_pass
      PG_OWNER_ROLE: streamfusion_owner

      TZ: ${TZ}
      PROXY_URL: ${PROXY_URL}
      STREMTHRU_URL: ${STREMTHRU_URL:-}
      REDIS_HOST: stremio-redis
      PG_HOST: stremio-postgres
      TASKIQ_REDIS_DB: "6"

    cap_drop:
      - ALL

    security_opt:
      - no-new-privileges:true

    read_only: true

    tmpfs:
      - /tmp:mode=1777,size=4g
      - /home/appuser:uid=1000,gid=1000,mode=0700

    volumes:
      - dmm-hashlists:/data/dmm_hashlists
      - imdb-db:/data/imdb_db
      - sfr-db-backups:/data/backups
      - pg-restore-secret:/run/pg-restore-secret:ro
      - taskiq-logs:/app/config/logs

    depends_on:
      pg-restore-secret-init:
        condition: service_completed_successfully

      postgres-security-init:
        condition: service_completed_successfully

      stremio-redis:
        condition: service_started

    restart: unless-stopped

    networks:
      - proxy_network


  # ===========================================================================
  # TASKIQ SCHEDULER
  # ===========================================================================

  taskiq-scheduler:
    image: laster13/stream-fusion-reborn:latest
    container_name: taskiq-scheduler

    command:
      python -m taskiq scheduler stream_fusion.tkq:scheduler

    environment:
      PG_USER: streamfusion_runtime
      PG_PASS: ${PG_PASS:?PG_PASS is required}
      PG_BASE: streamfusion

      TZ: ${TZ}

      REDIS_HOST: stremio-redis
      PG_HOST: stremio-postgres
      TASKIQ_REDIS_DB: "6"

    cap_drop:
      - ALL

    security_opt:
      - no-new-privileges:true

    read_only: true

    tmpfs:
      - /tmp:mode=1777
      - /home/appuser:uid=1000,gid=1000,mode=0700

    volumes:
      - taskiq-logs:/app/config/logs

    depends_on:
      postgres-security-init:
        condition: service_completed_successfully

      stremio-redis:
        condition: service_started

    restart: unless-stopped

    networks:
      - proxy_network

    # IMPORTANT : replicas doit toujours rester à 1.


  # ===========================================================================
  # STREAM FUSION
  # ===========================================================================

  stream-fusion:
    image: laster13/stream-fusion-reborn:latest
    container_name: stream-fusion

    # env_file: user.env
    # Décommenter uniquement pour unique_account / debrid / indexers.

    environment:
      RUN_MIGRATIONS: "true"

      SECRET_API_KEY: ${SECRET_API_KEY:?Provide SECRET_API_KEY}
      ADMIN_SECRET_KEY: ${ADMIN_SECRET_KEY:?Provide ADMIN_SECRET_KEY}
      CONFIG_SECRET_KEY: ${CONFIG_SECRET_KEY:?Provide CONFIG_SECRET_KEY}
      PEER_MASTER_KEY: ${PEER_MASTER_KEY:-}
      TMDB_API_KEY: ${TMDB_API_KEY:?Provide TMDB_API_KEY}

      PG_USER: streamfusion_runtime
      PG_PASS: ${PG_PASS:?PG_PASS is required}
      PG_BASE: streamfusion

      PG_MIGRATION_USER: streamfusion_migration
      PG_MIGRATION_PASS: ${PG_MIGRATION_PASS:?PG_MIGRATION_PASS is required}

      PG_OWNER_ROLE: streamfusion_owner

      TZ: ${TZ}
      USE_HTTPS: ${USE_HTTPS}
      PROXY_URL: ${PROXY_URL}
      STREMTHRU_URL: ${STREMTHRU_URL:-}
      REDIS_HOST: stremio-redis
      PG_HOST: stremio-postgres
      TASKIQ_REDIS_DB: "6"

    cap_drop:
      - ALL

    security_opt:
      - no-new-privileges:true

    read_only: true

    tmpfs:
      - /tmp:mode=1777
      - /home/appuser:uid=1000,gid=1000,mode=0700

    expose:
      - 8080
    ports:
      - 8080:8080

    volumes:
      - stream-fusion:/app/config
      - taskiq-logs:/app/config/logs
      - torrent-cache:/var/cache/torrents
      - imdb-db:/data/imdb_db
      - sfr-db-backups:/data/backups

    depends_on:
      postgres-security-init:
        condition: service_completed_successfully

      stremio-redis:
        condition: service_started

    restart: unless-stopped

    networks:
      - proxy_network


# =============================================================================
# VOLUMES
# =============================================================================

volumes:
  stremio-postgres:
  stremio-redis:
  stream-fusion:
  warp-data:
  dmm-hashlists:
  sfr-db-backups:
  imdb-db:
  torrent-cache:
  taskiq-logs:
  pg-restore-secret:

Mise à jour

docker compose pull
docker compose up -d