Synology [Tuto] BentoPDF (Traitement fichier PDF)

  • Vague de SPAM

    Suite à une vague de spam sur le forum, les inscriptions sont temporairement limitées.

    Après votre inscription, un membre de l'équipe devra valider votre compte avant qu'il ne soit activé. Nous sommes désolés pour la gêne occasionnée et vous remercions de votre patience.

Titux

Apprenti
Membre Confirmé
1 Novembre 2023
49
37
33
Aujourd'hui parlons de PDF, je vous propose un petit tuto pour installer BentoPDF.

J'utilisais Stirling-PDF depuis longtemps, mais depuis la version 2.0, l'application a introduit des changements importants qui ne me conviennent plus :
Ce qui a changé dans Stirling-PDF v2 :
  1. Authentification obligatoire par défaut - Nécessité de créer un compte utilisateur et de se connecter
  2. Limitation compte gratuit - Limite de 5 comptes puis payant (cher pour du Homelab)
  3. Stockage de documents - Les fichiers peuvent être stockés sur le serveur entre les sessions
Et pourquoi je préfère BentoPDF en ce moment :
  • 100% client-side - Tout se passe dans le navigateur, rien n'est envoyé au serveur
  • Aucun stockage - Les fichiers ne sont jamais sauvegardés sur le serveur
  • Respect de la vie privée - Vos documents restent sur votre machine
  • Simple - Vous lancez, vous utilisez, c'est tout
  • Léger - Pas de base de données, pas de gestion d'utilisateurs
  • Pas de compte utilisateur- Accès direct, aucune authentification requise
    • Un avantage ou inconvénient, car si vous ouvrez votre instance sur le WAN, n'import qui peut exploiter le logiciel. Et prendre de la ressource de votre serveur. Il est possible de bloquer l'accès avec un nom d'utilisateur ou mots de passe avec un logiciel d'authentification. Je n'en parle pas dans ce tuto.

Source​

Prérequis​

  • Synology DSM 7.x
  • Container Manager installé (via Package Center)
  • Connaissances de base Docker
  • Un navigateur web

nstallation étape par étape​


Étape 1 : Créer les dossiers (via File Station)

  1. Ouvrez File Station sur votre Synology
  2. Naviguez vers docker (si le dossier n'existe pas, créez-le dans /volume1/)
  3. Dans le dossier docker, créez un nouveau dossier nommé bentopdf
Ce qui donne /volume1/docker/bentopdf

Note : BentoPDF ne stocke aucune donnée, donc aucun sous-dossier n'est nécessaire !

Étape 2 : Créer le réseau

  1. Dans Container Manager partie réseau
  2. Ajouter un réseau nommer bentopdf

Étape 3 : Créer le stack bentopdf

  1. Ouvrez Container Manager
  2. Allez dans l'onglet Projet
  3. Cliquez sur Créer
  4. Configurez le projet :
    • Nom du projet : bentopdf
    • Chemin : Cliquez sur Sélectionner et naviguez vers /volume1/docker/bentopdf
    • Source : Sélectionnez Créer docker-compose.yml
  5. Entrer le docker-compose du dessous
  6. Cliquez sur Suivant
  7. Vérifiez la configuration affichée
  8. Cliquez sur Terminé
YAML:
version: '3.8'

services:
  bentopdf:
    image: ghcr.io/alam00000/bentopdf-simple:latest
    container_name: bentopdf
    restart: unless-stopped
    ports:
      - "44080:8080"
    environment:
      - DISABLE_IPV6=true # For IPv4-only environments
    healthcheck:
      test: ["CMD-SHELL", "nc -z 127.0.0.1 8080 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 120s
      
networks:
  bentopdf:
    external: true

Étape 4 : Accéder à BentoPDF

  1. Ouvrez votre navigateur et allez sur :http://IP_DE_VOTRE_NAS:44080
    Vous devriez voir l'interface de BentoPDF avec tous les outils disponibles !

Étape 5 : Reverse Proxy pour BentoPDF

Une image est plus parlante :
2026-02-13 13_53_30-Parc informatique.xlsx - Excel.png

Amusez-vous bien, vous pouvez passer l'appli en français. Voir tout en bas à droite de la page :
2026-02-13 13_56_57-Parc informatique.xlsx - Excel.png
2026-02-13 13_56_39-Parc informatique.xlsx - Excel.png
 

Pièces jointes

  • 2026-02-13 09_35_44-Greenshot.png
    2026-02-13 09_35_44-Greenshot.png
    30.7 KB · Affichages: 0
  • J'aime
Réactions: morgyann
Pourquoi ? Pour avoir deux Reverse Proxy.
NPM qui expose les services et me génère le certificat WildCart. J'aime beaucoup son bouton en plus qui rend actif ou pas un service.
Ce Certificat, je l'importe dans le Synology. Oui une action de temps en temps, mais vu le temps que je passe devant mon ordi, cela n'est pas dérangeant.
Les services que je ne veux pas exposer au WAN mais où je veux du HTTPS en local, passe par le reverse proxy du Synology.

Ma prochaine étape serait d'augmenter la protection en remplacement NPM par BunkerWeb. Mais là, on passe un cap niveau technique.
 
  • J'aime
Réactions: morgyann
Ma prochaine étape serait d'augmenter la protection en remplacement NPM par BunkerWeb. Mais là, on passe un cap niveau technique.
(Apparté hors sujet du tuto) Vu le poste et ta réponse ce matin sur CACHEM, donc je suis aller creuser sur le web (je ne connaissais pas), ça a l'air vraiment pas mal.
Cependant, pour avoir une interface graphique (quand même + sympa pour la lecture), il faut se connecter (avec un compte) en ligne (si j'ai bien compris).
Bref, si tu creuses le sujet, n'hésite pas à ouvrir un poste dédié sur le Forum. ;)
 
  • J'aime
Réactions: Titux
Non pas besoin de compte.

J'ai un docker-compose qui me lance bunkerweb via container manager.
Par contre, je n'ai toujours pas eu le temps de faire les tests.
J'ai des doutes sur la configuration pour qu'il puisse lire les logs des autres instances docker et donc faire le bon taff.

Voici le docker-compose
YAML:
# =============================================================================
# FICHIER 1/2 : docker-compose.yml
# =============================================================================
# Configuration BunkerWeb pour Synology avec fichier .env séparé
# Documentation: https://docs.bunkerweb.io/latest/web-ui/
# =============================================================================

version: "3.9"

# Variables communes pour éviter les répétitions
x-bw-env: &bw-env
  TZ: ${TZ:-Europe/Paris}
  API_WHITELIST_IP: ${API_WHITELIST_IP}
  DATABASE_URI: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@bw-db:5432/${POSTGRES_DB}

# Configuration des logs (rotation automatique)
x-logging: &default-logging
  driver: json-file
  options:
    max-size: ${LOG_MAX_SIZE:-10m}
    max-file: ${LOG_MAX_FILE:-10}

services:
  # ---------------------------------------------------------------------------
  # BUNKERWEB - Reverse Proxy WAF Principal
  # ---------------------------------------------------------------------------
  bunkerweb:
    container_name: bunkerweb
    image: bunkerity/bunkerweb:1.6.8
    restart: unless-stopped
    networks:
      - bw-universe
      - bw-services
    ports:
      - "${BW_HTTP_PORT}:8080/tcp"
      - "${BW_HTTPS_PORT}:8443/tcp"
      - "${BW_HTTPS_PORT}:8443/udp"
    environment:
      <<: *bw-env
      # Désactive le serveur par défaut pour éviter les conflits
      DISABLE_DEFAULT_SERVER: ${DISABLE_DEFAULT_SERVER:-yes}
      # Autorise les connexions HTTP sans nom de domaine
      SERVER_NAME: ""
      # Sécurité
      USE_MODSECURITY: ${USE_MODSECURITY:-yes}
      USE_MODSECURITY_CRS: ${USE_MODSECURITY_CRS:-yes}
      USE_ANTIBOT: ${USE_ANTIBOT:-cookie}
      USE_CROWDSEC: ${USE_CROWDSEC:-yes}
      CROWDSEC_API: ${CROWDSEC_API}
      USE_DNSBL: ${USE_DNSBL:-yes}
      USE_COUNTRY: ${USE_COUNTRY:-yes}
      WHITELIST_COUNTRY: ${WHITELIST_COUNTRY:-FR}
      USE_LIMIT_REQ: ${USE_LIMIT_REQ:-yes}
      LIMIT_REQ_RATE: ${LIMIT_REQ_RATE:-20r/s}
    volumes:
      - ${BW_DATA_PATH}:/data
      - ${BW_CACHE_PATH}:/cache
      - ${BW_LOGS_PATH}:/var/log/bunkerweb
    logging: *default-logging
    depends_on:
      bw-db:
        condition: service_healthy

  # ---------------------------------------------------------------------------
  # SCHEDULER - Gestion de la configuration
  # ---------------------------------------------------------------------------
  bw-scheduler:
    container_name: bw-scheduler
    image: bunkerity/bunkerweb-scheduler:1.6.8
    restart: unless-stopped
    networks:
      - bw-universe
      - bw-db-net
    environment:
      <<: *bw-env
      BUNKERWEB_INSTANCES: ${BUNKERWEB_INSTANCES}
      MULTISITE: ${MULTISITE:-yes}
       # SERVER_NAME vide = accès par IP
      SERVER_NAME: ""
      UI_HOST: ${UI_HOST}
      SERVE_FILES: ${SERVE_FILES:-no}
      DISABLE_DEFAULT_SERVER: ${DISABLE_DEFAULT_SERVER:-yes}
      USE_CLIENT_CACHE: ${USE_CLIENT_CACHE:-yes}
      USE_GZIP: ${USE_GZIP:-yes}
       # Autorise l'accès sans nom de domaine
      USE_CUSTOM_HTTPS: "yes"
      CUSTOM_HTTPS_CERT: ""
      CUSTOM_HTTPS_KEY: ""
    volumes:
      - ${BW_DATA_PATH}:/data
      - ${BW_CACHE_PATH}:/cache
    logging: *default-logging
    depends_on:
      - bunkerweb
      - bw-db

  # ---------------------------------------------------------------------------
  # WEB UI - Interface d'administration
  # ---------------------------------------------------------------------------
  bw-ui:
    container_name: bw-ui
    image: bunkerity/bunkerweb-ui:1.6.8
    restart: unless-stopped
    networks:
      - bw-universe
      - bw-db-net
    ports:
      - "${UI_PORT}:7000"
    environment:
      <<: *bw-env
      ADMIN_USERNAME: ${ADMIN_USERNAME}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      #TOTP_ENCRYPTION_KEYS: ${TOTP_ENCRYPTION_KEYS}
    volumes:
      - ${BW_DATA_PATH}:/data
      - ${BW_LOGS_PATH}:/var/log/bunkerweb:ro
    logging: *default-logging
    depends_on:
      - bw-db

  # ---------------------------------------------------------------------------
  # POSTGRESQL - Base de données
  # ---------------------------------------------------------------------------
  bw-db:
    container_name: bw-db
    image: postgres:17
    restart: unless-stopped
    networks:
      - bw-db-net
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATA: /var/lib/postgresql/data/pgdata
      # Locale compatible avec toutes les images PostgreSQL
      LANG: C.UTF-8
      LC_ALL: C.UTF-8
    volumes:
      - ${BW_DB_PATH}:/var/lib/postgresql/data
    logging: *default-logging
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 30s
      timeout: 10s
      retries: 3
    command:
      - postgres
      - -c
      - max_connections=50
      - -c
      - shared_buffers=128MB
      - -c
      - effective_cache_size=512MB

  # ---------------------------------------------------------------------------
  # CROWDSEC - Protection collaborative
  # ---------------------------------------------------------------------------
  crowdsec:
    container_name: crowdsec
    image: crowdsecurity/crowdsec:latest
    restart: unless-stopped
    networks:
      - bw-universe
    environment:
      TZ: ${TZ:-Europe/Paris}
      COLLECTIONS: ${CROWDSEC_COLLECTIONS}
      LEVEL_INFO: ${CROWDSEC_LOG_LEVEL:-info}
    volumes:
      - ${CROWDSEC_CONFIG_PATH}:/etc/crowdsec
      - ${CROWDSEC_DATA_PATH}:/var/lib/crowdsec/data
      - ${BW_LOGS_PATH}:/var/log/bunkerweb:ro
    logging: *default-logging

# =============================================================================
# RÉSEAUX - Architecture 3 niveaux
# =============================================================================
networks:
  bw-universe:
    driver: bridge
    enable_ipv6: false
    ipam:
      config:
        - subnet: ${BW_UNIVERSE_SUBNET}
    driver_opts:
      com.docker.network.bridge.name: br-bw-universe
      com.docker.network.bridge.enable_ip_masquerade: "true"

  bw-services:
    driver: bridge
    enable_ipv6: false
    ipam:
      config:
        - subnet: ${BW_SERVICES_SUBNET}
    driver_opts:
      com.docker.network.bridge.name: br-bw-services

  bw-db-net:
    driver: bridge
    enable_ipv6: false
    ipam:
      config:
        - subnet: ${BW_DB_SUBNET}
    driver_opts:
      com.docker.network.bridge.name: br-bw-db

Et le fichier ;env
Markdown (GitHub flavored):
# =============================================================================
# FICHIER 2/2 : .env
# =============================================================================
# Créez ce fichier dans le même répertoire que docker-compose.yml
# Documentation: https://docs.docker.com/compose/environment-variables/
# =============================================================================
# ATTENTION : Ne JAMAIS commiter ce fichier dans Git !
# Ajoutez ".env" dans votre .gitignore
# =============================================================================

# -----------------------------------------------------------------------------
# PORTS SYNOLOGY (80 et 443 sont réservés par DSM)
# -----------------------------------------------------------------------------
BW_HTTP_PORT=          # HTTP - Configurer NAT: 80 externe → 9880 NAS
BW_HTTPS_PORT=         # HTTPS/QUIC - Configurer NAT: 443 externe → 9443 NAS
UI_PORT=7000               # Interface Web UI (accès interne uniquement)

# -----------------------------------------------------------------------------
# CHEMINS DE VOLUMES SYNOLOGY
# -----------------------------------------------------------------------------
BW_DATA_PATH=/volume2/docker/bunkerweb/data
BW_CACHE_PATH=/volume2/docker/bunkerweb/cache
BW_LOGS_PATH=/volume2/docker/bunkerweb/logs
BW_DB_PATH=/volume2/docker/bunkerweb/db
CROWDSEC_CONFIG_PATH=/volume2/docker/bunkerweb/crowdsec/config
CROWDSEC_DATA_PATH=/volume2/docker/bunkerweb/crowdsec/data

# -----------------------------------------------------------------------------
# CONFIGURATION RÉSEAU
# -----------------------------------------------------------------------------
# Subnets pour les 3 réseaux Docker isolés
BW_UNIVERSE_SUBNET=10.20.30.0/24      # Gestion BunkerWeb
BW_SERVICES_SUBNET=10.20.31.0/24      # Applications web
BW_DB_SUBNET=10.20.32.0/24            # Base de données

# API Whitelist - CRITIQUE : doit inclure le réseau bw-universe
#API_WHITELIST_IP=API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24

# -----------------------------------------------------------------------------
# POSTGRESQL - BASE DE DONNÉES
# -----------------------------------------------------------------------------
#  CHANGEZ CES VALEURS AVANT LE DÉPLOIEMENT !
POSTGRES_DB=db
POSTGRES_USER=bunkerweb
POSTGRES_PASSWORD=

# -----------------------------------------------------------------------------
# WEB UI - INTERFACE D'ADMINISTRATION
# -----------------------------------------------------------------------------
#  CHANGEZ CES VALEURS AVANT LE DÉPLOIEMENT !
# Le mot de passe doit contenir au moins 8 caractères avec :
# - 1 minuscule, 1 majuscule, 1 chiffre, 1 caractère spécial
ADMIN_USERNAME=
ADMIN_PASSWORD=

# Clé de chiffrement pour 2FA (TOTP)
# Générer avec : python3 -c "from passlib import totp; print(totp.generate_secret())"
#  GÉNÉREZ UNE NOUVELLE CLÉ AVANT LE DÉPLOIEMENT !
#TOTP_ENCRYPTION_KEYS=CHANGEME_GENERATE_WITH_PASSLIB

# -----------------------------------------------------------------------------
# BUNKERWEB - CONFIGURATION
# -----------------------------------------------------------------------------
BUNKERWEB_INSTANCES=bunkerweb
MULTISITE=yes
SERVER_NAME=                           # Défini via l'UI
UI_HOST=http://192.168.*.***:7000
SERVE_FILES=no
DISABLE_DEFAULT_SERVER=yes
USE_CLIENT_CACHE=yes
USE_GZIP=yes

# -----------------------------------------------------------------------------
# SÉCURITÉ - MODSECURITY
# -----------------------------------------------------------------------------
USE_MODSECURITY=yes
USE_MODSECURITY_CRS=yes
USE_ANTIBOT=cookie

# -----------------------------------------------------------------------------
# SÉCURITÉ - CROWDSEC
# -----------------------------------------------------------------------------
USE_CROWDSEC=yes
CROWDSEC_API=http://crowdsec:8080
CROWDSEC_COLLECTIONS=crowdsecurity/nginx crowdsecurity/http-cve bunkerity/bunkerweb Dominic-Wagner/vaultwarden crowdsecurity/base-http-scenarios
CROWDSEC_LOG_LEVEL=info

# -----------------------------------------------------------------------------
# SÉCURITÉ - FILTRES GÉOGRAPHIQUES ET RATE LIMITING
# -----------------------------------------------------------------------------
USE_DNSBL=yes
USE_COUNTRY=yes
WHITELIST_COUNTRY=FR                   # Code ISO pays autorisés (séparés par espaces)
USE_LIMIT_REQ=yes
LIMIT_REQ_RATE=20r/s                   # Taux de requêtes maximum

# -----------------------------------------------------------------------------
# LOGS - ROTATION
# -----------------------------------------------------------------------------
LOG_MAX_SIZE=10m                       # Taille max par fichier de log
LOG_MAX_FILE=10                        # Nombre de fichiers conservés

# -----------------------------------------------------------------------------
# FUSEAU HORAIRE
# -----------------------------------------------------------------------------
TZ=Europe/Paris

Mais on est bien hors sujet. Je suis partant pour créer un sujet reverse proxy.
D'autre ici utilise NPMPlus + Crowdsec + Fail2ban + geoipupdate. Je serais curieux de voir comment ils ont fait sur un Synology.
Pok @EVO @PackTu @MilesTEG (et autre) partant pour discuter du sujet ? On le fait dans quelle rubrique ?
 
Dernière édition:
  • J'aime
Réactions: morgyann