This page was machine-translated. Spotted a mistake?Help improve it.
Skip to content

Déploiement

SnapOtter se déploie sous la forme d'une pile Docker Compose à 3 conteneurs : l'image applicative SnapOtter, PostgreSQL 17 et Redis 8. L'image applicative prend en charge linux/amd64 (avec NVIDIA CUDA pour l'accélération de l'IA) et linux/arm64 (CPU), elle s'exécute donc nativement sur les serveurs Intel/AMD, les Mac Apple Silicon et les appareils ARM comme le Raspberry Pi 4/5. L'accélération par iGPU Intel/AMD via VA-API, Quick Sync ou OpenCL n'est pas prise en charge pour l'inférence IA aujourd'hui.

Consultez Image Docker pour la configuration GPU, les exemples Docker Compose et l'épinglage de version.

Démarrage rapide (CPU)

yaml
# docker-compose.yml - Copy this file and run: docker compose up -d
services:
  SnapOtter:
    image: snapotter/snapotter:latest    # or ghcr.io/snapotter-hq/snapotter:latest
    container_name: SnapOtter
    ports:
      - "1349:1349"                # Web UI + API
    volumes:
      - SnapOtter-data:/data           # AI models, user files (PERSISTENT)
      - SnapOtter-workspace:/tmp/workspace  # Temp processing files (can be tmpfs)
    environment:
      # --- Authentication ---
      - AUTH_ENABLED=true          # Set to false to disable login entirely
      - DEFAULT_USERNAME=admin     # First-run admin username
      - DEFAULT_PASSWORD=admin     # First-run admin password (you'll be forced to change it)

      # --- Database + Queue ---
      - DATABASE_URL=postgres://snapotter:snapotter@postgres:5432/snapotter
      - REDIS_URL=redis://redis:6379

      # --- Limits (set 0 for unlimited) ---
      # - MAX_UPLOAD_SIZE_MB=100   # Per-file upload limit in MB
      # - MAX_BATCH_SIZE=100       # Max files per batch request
      # - RATE_LIMIT_PER_MIN=1000  # API rate limit per IP, default shown (0 = disabled)
      # - MAX_USERS=0              # Max user accounts

      # --- Networking ---
      # - TRUST_PROXY=true         # Trust X-Forwarded-For headers (set false if not behind a proxy)

      # --- Bind mount permissions ---
      # - PUID=1000                # Match your host user's UID (run: id -u)
      # - PGID=1000                # Match your host user's GID (run: id -g)
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:1349/api/v1/health"]
      interval: 30s
      timeout: 5s
      start_period: 60s
      retries: 3
    shm_size: "2gb"            # Needed for Python ML shared memory
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  postgres:
    image: postgres:17-alpine
    container_name: SnapOtter-postgres
    environment:
      POSTGRES_USER: snapotter
      POSTGRES_PASSWORD: snapotter     # Change this for non-local deployments
      POSTGRES_DB: snapotter
    volumes:
      - SnapOtter-pgdata:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U snapotter"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 15s

  redis:
    image: redis:8-alpine
    container_name: SnapOtter-redis
    command: ["redis-server", "--maxmemory-policy", "noeviction", "--appendonly", "yes"]
    volumes:
      - SnapOtter-redisdata:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 10s

volumes:
  SnapOtter-data:       # Named volume - Docker manages permissions automatically
  SnapOtter-workspace:
  SnapOtter-pgdata:
  SnapOtter-redisdata:
bash
docker compose up -d

L'application est ensuite disponible sur http://localhost:1349.

Limites de débit Docker Hub ? Remplacez snapotter/snapotter:latest par ghcr.io/snapotter-hq/snapotter:latest pour récupérer l'image depuis GitHub Container Registry à la place. Les deux registres reçoivent la même image à chaque publication.

Démarrage rapide (NVIDIA CUDA)

Pour l'accélération NVIDIA CUDA sur les outils IA (suppression d'arrière-plan, agrandissement, amélioration des visages, OCR) :

yaml
# docker-compose-gpu.yml - Requires: NVIDIA GPU + nvidia-container-toolkit
# Install toolkit: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
services:
  SnapOtter:
    image: snapotter/snapotter:latest
    container_name: SnapOtter
    ports:
      - "1349:1349"
    volumes:
      - SnapOtter-data:/data
      - SnapOtter-workspace:/tmp/workspace
    environment:
      - AUTH_ENABLED=true
      - DEFAULT_USERNAME=admin
      - DEFAULT_PASSWORD=admin
      - DATABASE_URL=postgres://snapotter:snapotter@postgres:5432/snapotter
      - REDIS_URL=redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:1349/api/v1/health"]
      interval: 30s
      timeout: 5s
      start_period: 60s
      retries: 3
    shm_size: "2gb"                # Required for PyTorch CUDA shared memory
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all           # Or set to 1 for a specific GPU
              capabilities: [gpu]
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  postgres:
    image: postgres:17-alpine
    container_name: SnapOtter-postgres
    environment:
      POSTGRES_USER: snapotter
      POSTGRES_PASSWORD: snapotter
      POSTGRES_DB: snapotter
    volumes:
      - SnapOtter-pgdata:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U snapotter"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 15s

  redis:
    image: redis:8-alpine
    container_name: SnapOtter-redis
    command: ["redis-server", "--maxmemory-policy", "noeviction", "--appendonly", "yes"]
    volumes:
      - SnapOtter-redisdata:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 10s

volumes:
  SnapOtter-data:
  SnapOtter-workspace:
  SnapOtter-pgdata:
  SnapOtter-redisdata:
bash
docker compose -f docker-compose-gpu.yml up -d

Vérifiez la détection de CUDA dans les journaux :

bash
docker logs SnapOtter 2>&1 | head -20
# Look for: [gpu] CUDA available via torch

Exigences matérielles

Ces chiffres proviennent de tests de performance sur toute une gamme de systèmes, d'un poste de travail amd64 moderne équipé d'une NVIDIA RTX 4070 jusqu'à un Raspberry Pi, en exécutant l'intégralité du catalogue d'outils sur chacun et en balayant les limites de ressources Docker pour trouver le plancher réel.

Référence rapide

NiveauCas d'usageCPURAMGPUStockage
MinimumOutils image, fichiers et PDF légers ; utilisateur unique ; petits lots2 cœurs2 GoAucun~7 Go
RecommandéLes cinq modalités, y compris vidéo, PDF et IA sur CPU ; lots ; quelques utilisateurs4 cœurs4 GoAucun~25 Go
CompletTout à pleine vitesse, y compris IA sur GPU ; grands lots ; nombreux utilisateurs6-8 cœurs8 GoNVIDIA 8 Go+ de VRAM (12 Go confortable)~35 Go

Architecture : 64 bits uniquement (linux/amd64 ou linux/arm64). SnapOtter s'exécute nativement sur les serveurs Intel/AMD, les Mac Apple Silicon et les cartes ARM 64 bits, y compris le Raspberry Pi 4 et 5 (4-8 Go). Il ne fonctionne pas sur ARM 32 bits (armv7/armhf), aucune image n'étant construite pour cette cible, ni sur les cartes de la classe 512 Mo comme le Pi Zero, qui sont sous le plancher mémoire (voir ci-dessous).

Minimum (outils image, fichiers et PDF légers ; sans IA)

RessourceExigence
CPU2 cœurs
RAM2 Go
Disque~5,5 Go (image) + volume de données
GPUNon requis

Les 222 outils non-IA du catalogue - image (redimensionner, rogner, convertir, compresser, ajuster, filigraner), vidéo (couper, rendre muet, remultiplexer), audio (convertir, normaliser, couper), PDF (fusionner, diviser, compresser, pivoter, protéger), conversions de fichiers et préréglages de conversion dédiés - s'exécutent sur du matériel modeste. La plupart des opérations se terminent en bien moins d'une seconde, même sur un gros fichier : une image de 2,7 Mo est redimensionnée en ~0,05 s et réencodée en WebP en ~2 s.

Le plancher mémoire est réel, d'après un balayage des limites de ressources Docker : 512 Mo ne peuvent pas démarrer la pile (même un simple redimensionnement d'image est tué), 1 Go gère les opérations sur un seul fichier mais un lot multi-fichiers manque de mémoire, et 2 Go / 2 cœurs est la plus petite configuration qui gère les lots confortablement.

yaml
deploy:
  resources:
    limits:
      cpus: '2'
      memory: 2G

La seule exception gourmande en CPU est le réencodage vidéo. Les opérations de copie de flux (couper, rendre muet, remultiplexage de conteneur) sont instantanées, mais le transcodage vers un codec différent est limité par le CPU. Un clip 1080p / 45 secondes réencodé en VP9 (WebM) prend environ ~40 s sur un CPU moderne rapide, ~45 s sur Apple Silicon, ~80 s sur un ancien 4 cœurs mobile et ~130 s sur un ancien serveur 4 cœurs. Si votre charge de travail est axée sur la vidéo, privilégiez les cœurs CPU et la fréquence d'horloge, ou augmentez la limite cpus: du conteneur : le compose fourni plafonne l'application à 4 cœurs par défaut (8 sur le compose GPU).

RessourceExigence
CPU4 cœurs
RAM4 Go
Disque3 Go (image) + 24 Go (modèles IA) + espace de travail
GPUNon requis (repli sur CPU)

C'est l'installation des bundles IA qui pousse la RAM à 4 Go. Sans IA installée, l'application est au repos autour de 360 Mo ; avec les sept bundles installés, elle maintient ~2,6 Go résidents, car le sidecar IA Python précharge ses modèles (suppression d'arrière-plan, agrandissement, OCR, transcription, détection de visages, restauration) au démarrage. Les installations non-IA restent légères ; les installations IA nécessitent ≥4 Go.

La plupart des outils IA sont parfaitement utilisables sur CPU ; deux ou trois veulent vraiment un GPU. Mesuré sur un CPU 4 cœurs moderne :

Outil IATemps CPUUtilisable sur CPU ?
Détection de visages (flouter les visages, recadrage intelligent, yeux rouges), suppression du bruitmoins de 1 sOui
OCR, transcription, sous-titres1-3 sOui
Coloriser, amélioration des visages~10 sOui
Suppression / remplacement / floutage d'arrière-plan~29 sOui (il faudra patienter)
Agrandissement IA (RealESRGAN)~33 s sur petit format ; plusieurs minutes sur les grandes imagesLimite - GPU fortement recommandé
Restauration de photo (pipeline complet)plusieurs minutesNon - nécessite un GPU ou un CPU rapide à nombreux cœurs

SnapOtter n'intègre volontairement pas ces téléchargements de modèles dans l'image Docker. Les bundles IA ne sont récupérés que lorsqu'un administrateur active l'outil concerné, stockés dans le volume persistant /data/ai et partagés par chaque outil qui dépend de la même pile de modèles. Cela maintient l'image finale du conteneur petite tout en permettant à une installation IA complète d'atteindre les chiffres de stockage plus élevés ci-dessous.

Certains outils dépendent de plus d'un bundle partagé. Par exemple, Photo d'identité a besoin à la fois de background-removal et de face-detection ; si background-removal est déjà installé, activer Photo d'identité ne télécharge que le bundle face-detection manquant. La même réutilisation s'applique à tous les outils IA.

Tailles de téléchargement des modèles IA :

BundleTaille disque
Suppression d'arrière-plan4-5 Go
Agrandissement + Amélioration des visages + Suppression du bruit5-6 Go
Détection de visages200-300 Mo
Gomme d'objets + Coloriser1-2 Go
OCR5-6 Go
Restauration de photo4-5 Go
Tous les bundles~24 Go
yaml
deploy:
  resources:
    limits:
      cpus: '4'
      memory: 4G

Complet (outils IA sur NVIDIA CUDA)

RessourceExigence
CPU6-8 cœurs (la préparation vidéo + la concurrence s'exécutent sur CPU même avec l'IA sur GPU)
RAM8 Go
GPUNVIDIA avec 8+ Go de VRAM (12 Go recommandé)
Disque~35 Go au total

Un GPU NVIDIA (CUDA) accélère considérablement les modèles IA lourds. Mesuré sur une RTX 4070 par rapport à un CPU moderne :

Outil IAAccélération avec GPUNotes
Agrandissement IA (RealESRGAN 2×)~47×Le plus gros gain - moins d'une seconde contre ~33 s (plusieurs minutes sur les grandes images)
Amélioration des visages (CodeFormer)~12×~0,9 s contre ~11 s
Transcription (Whisper)~4,5×
Suppression / remplacement / floutage d'arrière-plan~4×~7 s sur GPU contre ~29 s sur CPU
Coloriser~1,8×
OCR, détection de visages, yeux rouges, suppression du bruit~1×Déjà rapide sur CPU - un GPU n'apporte rien
Restauration de photoaucuneLimité par le CPU même sur un GPU (0 % d'utilisation du GPU) ; un CPU rapide compte plus qu'un GPU ici

Les outils qui valent un GPU sont l'agrandissement, l'amélioration des visages, la transcription et la suppression d'arrière-plan. La détection de visages, l'OCR et les yeux rouges sont limités par le CPU et déjà rapides, un GPU n'apporte donc rien.

L'utilisation de VRAM en pic atteint 7,5 Go pendant un agrandissement avec amélioration des visages. Un GPU NVIDIA de 6 Go convient pour la plupart des outils IA pris individuellement, mais échouera sur l'agrandissement. 8-12 Go de VRAM gèrent tout.

L'accélération par iGPU Intel/AMD via VA-API, Quick Sync ou OpenCL n'est pas prise en charge pour l'inférence IA aujourd'hui. Mapper /dev/dri dans le conteneur n'active pas l'accélération GPU de l'IA ; SnapOtter exécutera les outils IA sur CPU sauf si NVIDIA CUDA est disponible.

yaml
deploy:
  resources:
    limits:
      cpus: '4'
      memory: 8G
    reservations:
      devices:
        - driver: nvidia
          count: all
          capabilities: [gpu]

Utilisateurs simultanés

Requêtes de redimensionnement d'image parallèles sur le conteneur applicatif plafonné à 4 cœurs par défaut :

Requêtes simultanéesTemps de réponse moyenErreurs
10,4 s0
51,2 s0
102,1 s0

Le temps de réponse se dégrade de manière sous-linéaire sans erreur à mesure que le pool de workers sature. Augmenter la limite cpus: du conteneur applicatif (ou utiliser un hôte avec plus de cœurs) relève le plafond. Notez que les tâches lourdes (transcodage vidéo, IA sur CPU) mobilisent un worker pendant toute leur durée, dimensionnez donc le CPU selon votre nombre attendu de tâches lourdes simultanées, et pas seulement selon le nombre de requêtes.

Formats d'image pris en charge

SnapOtter prend en charge 55+ formats d'entrée et 14 formats de sortie, dont les fichiers RAW de 20+ marques d'appareils photo, les formats professionnels (PSD, EPS, OpenEXR, HDR), les codecs modernes (JPEG XL, AVIF, HEIC, QOI) et les formats scientifiques/de jeu (FITS, DDS).

Consultez la liste complète des formats pour les détails sur chaque format pris en charge, le décodeur utilisé et les contrôles de qualité disponibles.

Limitations connues

  • Le redimensionnement sensible au contenu plante sur les grandes images (>5 MP) en raison d'une limitation du binaire caire. Fonctionne bien avec des images plus petites.
  • Le décodage HEIF prend 13-23 secondes. HEIC (la variante d'Apple) est bien plus rapide, à 0,3-0,9 seconde.
  • L'OCR japonais échoue sur CPU à cause d'un bug MKLDNN de PaddlePaddle. Fonctionne sur GPU.
  • L'agrandissement expire sur CPU pour tout ce qui dépasse les petites images. GPU requis pour un usage pratique.
  • L'amélioration des visages CodeFormer est nettement plus lente que GFPGAN (53 s contre 2 s sur GPU). GFPGAN est recommandé pour la plupart des cas d'usage.

Volumes

Montage / VolumeRôleRequis ?
/data (app)Modèles IA, venv Python, fichiers utilisateurOui - perte de fichiers sans lui
/tmp/workspace (app)Fichiers de traitement temporaires (nettoyés automatiquement)Recommandé
SnapOtter-pgdata (postgres)Répertoire de données PostgreSQL (utilisateurs, paramètres, pipelines, tâches)Oui - perte de données sans lui
SnapOtter-redisdata (redis)Fichier append-only Redis pour des files de tâches durablesRecommandé

Montages liés (bind mounts) vs volumes nommés

Volumes nommés (recommandés) - Docker gère les permissions automatiquement :

yaml
volumes:
  - SnapOtter-data:/data

Montages liés - Vous gérez les permissions. Réglez PUID/PGID pour correspondre à votre utilisateur hôte :

yaml
volumes:
  - ./SnapOtter-data:/data
environment:
  - PUID=1000    # Your host UID (run: id -u)
  - PGID=1000    # Your host GID (run: id -g)

Permissions de stockage

SnapOtter écrit à deux emplacements à l'exécution : /data (fichiers utilisateur, journaux, modèles IA et le venv Python) et /tmp/workspace (espace de travail temporaire de traitement). Les deux doivent être accessibles en écriture par l'utilisateur sous lequel le conteneur s'exécute. Si l'un ne l'est pas, le conteneur échoue rapidement au démarrage avec un message nommant le répertoire, l'UID/GID en cours d'exécution et comment corriger, au lieu de démarrer « en bonne santé » puis d'échouer au premier téléversement avec une erreur cryptique.

La façon dont les permissions sont gérées dépend de la manière dont le conteneur est lancé :

Par défaut (démarre en root, redescend vers snapotter) - le point d'entrée démarre en root, corrige la propriété des volumes montés, puis redescend vers l'utilisateur non privilégié snapotter via gosu. Les volumes nommés fonctionnent sans aucune configuration. Pour les montages liés, réglez PUID/PGID sur votre utilisateur hôte (ci-dessus) afin que les fichiers qu'il écrit vous appartiennent.

Kubernetes / OpenShift (non-root via runAsUser) - lancé directement en tant qu'utilisateur non-root, le conteneur ne peut pas chown les volumes lui-même, l'orchestrateur doit donc les rendre accessibles en écriture. Réglez fsGroup :

yaml
securityContext:
  runAsUser: 999
  runAsGroup: 999
  fsGroup: 999        # makes mounted volumes writable by the pod

Les répertoires accessibles en écriture de l'image appartiennent au groupe GID 0 et sont accessibles en écriture par le groupe, de sorte qu'un pod s'exécutant avec un UID arbitraire plus le groupe supplémentaire root (le défaut OpenShift) peut écrire sans chown.

TrueNAS Scale (et autres configurations à « UID étranger ») - TrueNAS exécute les applications sous un utilisateur non-root (souvent 568:568) et monte des jeux de données hôtes appartenant à un autre utilisateur, de sorte que ni le point d'entrée ni fsGroup ne les rendent accessibles en écriture par lui-même. Choisissez l'une des options :

  • Exécuter l'application en root (recommandé) - laissez l'utilisateur de l'application non défini ou réglez-le sur 0, et laissez le point d'entrée par défaut corriger les permissions et redescendre vers snapotter.

  • Exécuter en tant qu'UID 999 - réglez l'utilisateur/groupe de l'application sur 999:999 (l'utilisateur intégré snapotter de SnapOtter) pour qu'il corresponde à la propriété de l'image.

  • chown le jeu de données hôte vers l'UID sous lequel le conteneur s'exécute, depuis le shell TrueNAS :

    bash
    # Utilisez l'UID de l'erreur de démarrage (ou exécutez `id` dans le conteneur)
    chown -R 568:568 /mnt/<pool>/<dataset>

L'erreur de démarrage nomme l'UID exact à utiliser, le chemin le plus rapide est donc de démarrer l'application une fois, de lire le message, puis d'exécuter chown (ou d'ajuster l'utilisateur) en conséquence.

Variables d'environnement

VariableDéfautDescription
AUTH_ENABLEDtrueActiver/désactiver l'exigence de connexion
DEFAULT_USERNAMEadminNom d'utilisateur admin initial
DEFAULT_PASSWORDadminMot de passe admin initial (changement forcé à la première connexion)
MAX_UPLOAD_SIZE_MB100Limite de téléversement par fichier
MAX_BATCH_SIZE100Nombre max de fichiers par requête de lot
RATE_LIMIT_PER_MIN1000Requêtes API par minute et par IP (mettez 0 pour désactiver)
MAX_USERS0 (illimité)Nombre maximal de comptes utilisateur
TRUST_PROXYtrueFaire confiance aux en-têtes X-Forwarded-For du reverse proxy
PUID999Exécuter sous cet UID (pour les permissions de montage lié)
PGID999Exécuter sous ce GID (pour les permissions de montage lié)
LOG_LEVELinfoVerbosité des journaux : fatal, error, warn, info, debug, trace
CONCURRENT_JOBS0 (auto)Nombre max de tâches de traitement IA en parallèle
SESSION_DURATION_HOURS168Durée de vie de la session de connexion (7 jours)
CORS_ORIGIN(vide)Origines autorisées séparées par des virgules, ou vide pour même origine

Vérification d'état (health check)

Le conteneur inclut une vérification d'état intégrée :

bash
# Check container health status
docker inspect --format='{{.State.Health.Status}}' SnapOtter

# Manual health check
curl http://localhost:1349/api/v1/health
# {"status":"healthy","version":"x.y.z"}

Reverse proxy

SnapOtter définit TRUST_PROXY=true par défaut afin que la limitation de débit et la journalisation utilisent l'IP client réelle issue des en-têtes X-Forwarded-For.

Nginx

nginx
server {
    listen 80;
    server_name images.example.com;

    # Match MAX_UPLOAD_SIZE_MB (0 = nginx default 1M, so set high for unlimited)
    client_max_body_size 500M;

    location / {
        proxy_pass http://localhost:1349;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # SSE support (batch progress, feature install progress)
        proxy_buffering off;
        proxy_read_timeout 300s;
    }
}

Nginx Proxy Manager

  1. Ajoutez un nouveau Proxy Host
  2. Réglez Domain Name sur votre domaine
  3. Réglez Scheme sur http, Forward Hostname sur SnapOtter (ou l'IP de votre conteneur), Forward Port sur 1349
  4. Activez la prise en charge WebSocket
  5. Sous Advanced, ajoutez : client_max_body_size 500M; et proxy_buffering off;

Traefik

yaml
# Add these labels to the SnapOtter service in docker-compose.yml
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.snapotter.rule=Host(`images.example.com`)"
  - "traefik.http.routers.snapotter.entrypoints=websecure"
  - "traefik.http.routers.snapotter.tls.certresolver=letsencrypt"
  - "traefik.http.services.snapotter.loadbalancer.server.port=1349"
  # Increase upload limit (default 2MB is too low)
  - "traefik.http.middlewares.snapotter-body.buffering.maxRequestBodyBytes=524288000"
  - "traefik.http.routers.snapotter.middlewares=snapotter-body"

Caddy

txt
images.example.com {
    reverse_proxy localhost:1349 {
        flush_interval -1
        transport http {
            read_timeout 300s
            write_timeout 300s
        }
    }
}

flush_interval -1 désactive la mise en tampon des réponses, ce qui est requis pour les événements de progression SSE (traitement par lots, outils IA, installations de fonctionnalités). Les délais d'expiration étendus permettent aux gros téléversements de fichiers de se terminer sans que Caddy ne ferme la connexion trop tôt.

Cloudflare Tunnels

bash
cloudflared tunnel --url http://localhost:1349

Remarque : Cloudflare impose une limite de téléversement de 100 Mo sur les offres gratuites. Réglez MAX_UPLOAD_SIZE_MB=100 en conséquence.

CI/CD

Le dépôt GitHub comporte trois workflows :

  • ci.yml - S'exécute automatiquement à chaque push et PR. Effectue le lint, la vérification de types, les tests, la construction et la validation de l'image Docker (sans push).
  • release.yml - Déclenché manuellement via workflow_dispatch. Exécute semantic-release pour créer un tag de version et une release GitHub, puis construit une image Docker multi-architecture (amd64 + arm64) et la pousse vers Docker Hub (snapotter/snapotter) et GitHub Container Registry (ghcr.io/snapotter-hq/snapotter).
  • deploy-docs.yml - Construit ce site de documentation et le déploie sur Cloudflare Pages lors d'un push vers main.

Pour créer une release, allez dans Actions > Release > Run workflow dans l'interface GitHub, ou exécutez :

bash
gh workflow run release.yml

Semantic-release détermine la version à partir de l'historique des commits. Le tag Docker latest pointe toujours vers la release la plus récente.

Analytique

SnapOtter inclut une analytique produit anonyme (schémas d'utilisation des outils, rapports d'erreurs) pour aider à détecter les bugs et améliorer les fonctionnalités. Elle est activée par défaut. Vos fichiers, leurs noms et vos données personnelles n'en font jamais partie. SnapOtter fonctionne normalement avec l'analytique désactivée.

Désactiver l'analytique

Le retrait à l'exécution est un basculement admin en un clic. Ouvrez Settings > System > Privacy et désactivez Anonymous Product Analytics. Cela s'arrête immédiatement pour toute l'instance, sans reconstruction requise.

Pour une image qui ne peut jamais émettre d'analytique, définissez l'arrêt matériel au moment de la construction en clonant le dépôt et en le reconstruisant :

bash
git clone https://github.com/snapotter-hq/SnapOtter.git
cd SnapOtter
docker compose -f docker/docker-compose.yml build --build-arg SNAPOTTER_ANALYTICS=off
docker compose -f docker/docker-compose.yml up -d

Ou ajoutez l'argument de construction à votre docker-compose.yml existant :

yaml
services:
  snapotter:
    build:
      context: .
      dockerfile: docker/Dockerfile
      args:
        SNAPOTTER_ANALYTICS: "off"