# Guide d'installation from scratch — JH Photomaton **Raspberry Pi 4 (2 Go) · Pi Camera Module V3 · Pi OS Lite 64-bit + cage (kiosk Wayland)** *Les Sapins Du Web — juillet 2026* --- ## Vue d'ensemble du stack ``` Internet / réseau local │ [Zoraxy] :443 / :80 — reverse proxy HTTPS │ [RaspAP] — point d'accès WiFi "Photomaton" │ ┌──────┴──────────────────────┐ │ photobooth-app :8000 │ — kiosque, caméra, frames │ JH Photomaton :8090 │ — admin, LEDs, bouton, imprimantes │ CUPS :631 │ — Canon Selphy CP1300 x2 └─────────────────────────────┘ ``` **Matériel :** - Raspberry Pi 4 (2 Go RAM), carte SD 32 Go+ - Pi Camera Module V3 (Sony IMX708, 12 MP) - Anneau LED WS2812b — 35 LEDs — GPIO 18 - Bouton arcade — GPIO 23 / Relay — GPIO 12 - 2× Canon Selphy CP1300 --- ## Étape 1 — Flasher la carte SD Utiliser **Raspberry Pi Imager** sur ton PC : - OS : **Raspberry Pi OS Lite (64-bit)** — sans bureau *(choisir "Raspberry Pi OS (other)" → "Lite")* - Activer SSH, définir utilisateur `pi` et mot de passe dans les options avancées - Hostname : `photomaton` - WiFi : **ne pas configurer** (RaspAP va le prendre en charge) > **Pourquoi Lite ?** > Le bureau complet (PIXEL) consomme ~450–600 Mo RAM à l'idle. > Lite + cage + Chromium consomme ~150–250 Mo — soit ~300 Mo libérés pour picamera2 > et le reste du stack. > **Bookworm vs Trixie :** Bookworm est plus stable pour picamera2 et rpi-ws281x. > Si l'ancienne carte tournait sur Trixie sans problème, reste sur Trixie. Flasher, insérer dans le Pi, brancher en Ethernet, démarrer. --- ## Étape 2 — Premier démarrage et préparation système ```bash # Trouver l'IP du Pi sur ton réseau local (depuis ton PC) # Puis se connecter ssh pi@ # Mise à jour complète sudo apt update && sudo apt full-upgrade -y sudo apt autoremove -y # Outils essentiels sudo apt install -y git curl wget vim rsync python3-pip python3-venv \ python3-dev build-essential gcc make # Redémarrer pour appliquer les mises à jour du noyau sudo reboot ``` --- ## Étape 3 — Désactiver l'audio (requis pour les LEDs WS2812b) Les LEDs WS2812b utilisent le PWM sur GPIO 18, qui entre en conflit avec la carte son intégrée. ```bash sudo nano /boot/firmware/config.txt ``` Trouver la ligne `dtparam=audio=on` et la remplacer par : ``` dtparam=audio=off ``` Ajouter aussi en bas du fichier (si pas déjà présent) : ``` # Désactive le Bluetooth pour libérer l'UART si besoin dtoverlay=disable-bt ``` Sauvegarder et redémarrer : ```bash sudo reboot ``` --- ## Étape 4 — Installer l'environnement kiosk (cage + Chromium) Sur Pi OS Lite, il n'y a pas de bureau. On installe uniquement ce qu'il faut pour afficher Chromium en mode kiosque via le compositeur Wayland minimal **cage**. ```bash sudo apt install -y \ cage \ chromium-browser \ xdg-utils \ fonts-liberation \ fonts-noto \ dbus-user-session \ libcap2-bin ``` ### Auto-login console ```bash sudo raspi-config # → System Options → Boot / Auto Login → Console Autologin ``` ### Service kiosk systemd Ce service démarre cage + Chromium automatiquement au boot, après que photobooth-app soit prêt. ```bash sudo nano /etc/systemd/system/photobooth-kiosk.service ``` ```ini [Unit] Description=Photobooth Kiosk (cage + Chromium) After=photobooth-app.service network.target Wants=photobooth-app.service [Service] Type=simple User=pi PAMName=login TTYPath=/dev/tty1 StandardInput=tty Environment=XDG_RUNTIME_DIR=/run/user/1000 Environment=WAYLAND_DISPLAY=wayland-1 # Attendre que photobooth-app soit prêt ExecStartPre=/bin/sleep 8 ExecStart=/usr/bin/cage -- /usr/bin/chromium-browser \ --kiosk \ --noerrdialogs \ --disable-infobars \ --disable-session-crashed-bubble \ --disable-features=TranslateUI \ --no-first-run \ --disable-restore-session-state \ --autoplay-policy=no-user-gesture-required \ http://localhost:8000 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable photobooth-kiosk ``` > **Note :** cage est un compositeur Wayland "single-app" — il lance Chromium et rien d'autre. > Pas de gestionnaire de fenêtres, pas de barre des tâches, pas de bureau. > C'est exactement ce qu'on veut pour un kiosque. --- ## Étape 5 — Activer la caméra ```bash # Installer picamera2 et les outils libcamera (paquets système) sudo apt install -y python3-picamera2 libcamera-apps # Vérifier que la caméra est détectée libcamera-hello --list-cameras # Doit afficher : "Available cameras" avec le Sony IMX708 ``` --- ## Étape 6 — Installer photobooth-app photobooth-app est l'application kiosque qui gère la caméra, le décompte et les frames. ```bash # Créer le dossier de données mkdir -p /home/pi/photobooth-data/{media/processed_full,userdata,script} # Installer dans un venv avec accès aux paquets système (nécessaire pour picamera2) sudo apt install -y python3-venv python3 -m venv /home/pi/photobooth-venv --system-site-packages /home/pi/photobooth-venv/bin/pip install photobooth-app ``` ### Créer le service systemd pour photobooth-app ```bash sudo nano /etc/systemd/system/photobooth-app.service ``` ```ini [Unit] Description=Photobooth App After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi ExecStart=/home/pi/photobooth-venv/bin/photobooth Restart=always RestartSec=5 Environment=HOME=/home/pi [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable photobooth-app sudo systemctl start photobooth-app # Attendre ~10s puis vérifier sudo systemctl status photobooth-app ``` photobooth-app est accessible sur `http://localhost:8000`. ### Configurer photobooth-app Accéder à l'interface d'administration : `http://:8000/admin` **Réglages à faire impérativement :** #### a) Backend caméra `Settings → Backends → Add / Edit` : - Backend type : **Picamera2** - Camera num : **0** - Capture resolution : **4608 × 2592** *(mode natif IMX708 — 14 fps)* - Preview resolution : **2304 × 1296** *(mode natif — 56 fps, champ complet)* - Liveview resolution : **960 × 540** *(min. height=500 imposé par photobooth-app, 16:9)* - Framerate still mode : **14** *(max en full res)* #### b) Désactiver les GPIO internes de photobooth-app `Settings → Hardware → GPIO` → **désactiver** (JH Photomaton gère ses propres GPIO) ``` gpio_enabled: false ``` #### c) Plugin commander — connecter à JH Photomaton Copier la config depuis le dépôt après l'avoir cloné (étape 7) : ```bash # Après avoir cloné le dépôt JH Photomaton : cp /home/pi/jh-photomaton/photobooth-app/config/plugin_commander_jh.json \ ~/.config/photobooth-app/plugin_commander.json sudo systemctl restart photobooth-app ``` #### d) Bouton "Demande d'impression" Dans photobooth-app `Settings → Share → Actions` : Remplacer la share_command : ``` curl http://127.0.0.1:8090/api/print/request?filename={filename} ``` > ⚠️ L'ancienne valeur pointait vers Node-RED (`:1880`). Bien remplacer par `:8090`. --- ## Étape 7 — Cloner et installer JH Photomaton ```bash # Cloner depuis Gitea cd /home/pi git clone https://gitea.lespatas.ovh/admin/photoBooth.git jh-photomaton cd jh-photomaton # Lancer l'installation (crée le venv, installe les dépendances, active le service) sudo bash scripts/install.sh ``` Le script `install.sh` fait automatiquement : - `apt install` des dépendances système - Création du venv Python avec `--system-site-packages` - `pip install -r requirements.txt` - `pip install rpi-ws281x` (LEDs) - Copie du service systemd + `systemctl enable` ### Vérifier l'installation ```bash sudo systemctl status jh-photomaton sudo journalctl -u jh-photomaton -f ``` Interface admin : `http://:8090/admin` Mot de passe : **PhotoBooth2026!** --- ## Étape 8 — Configurer settings.yaml ```bash nano /home/pi/jh-photomaton/config/settings.yaml ``` Points à vérifier / adapter : ```yaml app: port: 8090 admin_password: "PhotoBooth2026!" # changer si voulu photobooth: base_url: "http://localhost:8000" data_dir: "/home/pi/photobooth-data" media_dir: "/home/pi/photobooth-data/media/processed_full" event: name: "Evenement" # sera modifié depuis l'admin slug: "evenement" leds: pin: 18 count: 35 # nombre de LEDs dans l'anneau brightness: 180 # 0-255, luminosité normale effects: capture: color: [255, 200, 80] # blanc chaud (évite la dominante bleue WS2812b) flashes: 2 flash_duration: 0.30 button: pin: 23 # GPIO du bouton arcade relay_pin: 12 # GPIO du relay print_enabled: true print: mode: "validation" printers: - name: "Selphy_Blanche_WiFi" label: "Selphy Blanche (WiFi)" - name: "Selphy_Noire_WiFi" label: "Selphy Noire (WiFi)" ``` Après modification : ```bash sudo systemctl restart jh-photomaton ``` --- ## Étape 9 — Installer CUPS et les imprimantes Selphy ```bash # Installer CUPS + pilotes Gutenprint sudo apt install -y cups printer-driver-gutenprint # Ajouter l'utilisateur pi au groupe lpadmin sudo usermod -aG lpadmin pi # Démarrer CUPS sudo systemctl enable cups sudo systemctl start cups # Autoriser l'accès distant à l'interface CUPS sudo cupsctl --remote-admin sudo systemctl restart cups ``` Accéder à CUPS : `http://:631` ### Ajouter les imprimantes `Administration → Add Printer` pour chaque Selphy : | Champ | Valeur | |-------|--------| | Connection | `socket://192.168.X.X:9100` (IP de la Selphy sur le WiFi) ou USB | | Name | `Selphy_Blanche_WiFi` *(exactement ce nom — utilisé par le script)* | | Driver | Canon SELPHY CP1300 — Gutenprint | | Media | Postcard 100×148mm | Répéter pour `Selphy_Noire_WiFi`. ### Script d'impression Vérifier que le script est exécutable et pointe vers les bons noms d'imprimantes : ```bash ls -la /home/pi/photobooth-data/script/script_print.sh chmod +x /home/pi/photobooth-data/script/script_print.sh # Test manuel /home/pi/photobooth-data/script/script_print.sh \ "/home/pi/photobooth-data/media/processed_full/test.jpg" \ "image" "test" "1" # Doit retourner : PRINTED:Selphy_Blanche_WiFi:1 ``` --- ## Étape 10 — Point d'accès WiFi (hostapd + dnsmasq) > **Pourquoi pas RaspAP ?** > RaspAP installe lighttpd + PHP + une interface web — ~40 Mo de RAM pour une UI qu'on n'utilise pas. > On configure directement hostapd et dnsmasq, ce qu'il y a en dessous. ```bash sudo apt install -y hostapd dnsmasq sudo systemctl unmask hostapd ``` ### IP statique sur wlan0 Ajouter dans `/etc/dhcpcd.conf` : ```ini interface wlan0 static ip_address=192.168.4.1/24 nohook wpa_supplicant ``` ### hostapd — point d'accès WiFi ouvert ```bash sudo nano /etc/hostapd/hostapd.conf ``` ```ini interface=wlan0 driver=nl80211 ssid=Photomaton-LSDW hw_mode=g channel=6 wmm_enabled=0 macaddr_acl=0 # WiFi ouvert — pas de mot de passe auth_algs=1 ignore_broadcast_ssid=0 ``` Déclarer le fichier de config dans `/etc/default/hostapd` : ```ini DAEMON_CONF="/etc/hostapd/hostapd.conf" ``` ### dnsmasq — DHCP + redirection DNS (portail captif) Ajouter à la fin de `/etc/dnsmasq.conf` : ```ini interface=wlan0 bind-interfaces # DHCP : distribue des IPs aux clients WiFi dhcp-range=192.168.4.2,192.168.4.100,255.255.255.0,24h # Annonce le Pi comme serveur DNS aux clients dhcp-option=6,192.168.4.1 # ── Portail captif ────────────────────────────────────────────── # Tout le trafic DNS → Pi (192.168.4.1) # google.com, instagram.com, lessapinsduweb.com... tout arrive ici. # Zoraxy fait le tri par HTTP Host header : # - *.lessapinsduweb.com → apps configurées dans Zoraxy # - tout le reste → redirect vers photomaton.lessapinsduweb.com address=/#/192.168.4.1 # Sondes de détection portail captif — iOS et Android ouvrent # automatiquement le navigateur sur la galerie address=/captive.apple.com/192.168.4.1 address=/connectivitycheck.gstatic.com/192.168.4.1 address=/detectportal.firefox.com/192.168.4.1 address=/www.msftconnecttest.com/192.168.4.1 ``` > **Note :** `address=/#/192.168.4.1` s'applique uniquement aux clients WiFi > (DHCP sur wlan0). Le Pi lui-même utilise le DNS de son routeur via eth0. ### Activer les services ```bash sudo systemctl enable --now hostapd sudo systemctl enable --now dnsmasq ``` --- ## Étape 11 — Installer Zoraxy (reverse proxy HTTPS + catch-all) Zoraxy sert deux rôles ici : reverse proxy HTTPS pour les apps, et redirection captive portal pour tout le trafic inconnu des clients WiFi. ```bash # Télécharger le binaire ARM64 mkdir ~/zoraxy && cd ~/zoraxy wget https://github.com/tobychui/zoraxy/releases/download/v3.3.2/zoraxy_linux_arm64 -O zoraxy chmod +x zoraxy # Service systemd sudo nano /etc/systemd/system/zoraxy.service ``` ```ini [Unit] Description=Zoraxy Reverse Proxy After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi/zoraxy ExecStart=/home/pi/zoraxy/zoraxy -port=8888 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable zoraxy sudo systemctl start zoraxy ``` ### Configurer les routes dans Zoraxy | Hostname | Destination | Notes | |----------|-------------|-------| | `photomaton.lessapinsduweb.com` | `127.0.0.1:8000` | Galerie publique / kiosque | | `admin.lessapinsduweb.com` | `127.0.0.1:8090` | Interface admin JH Photomaton | | `cups.lessapinsduweb.com` | `127.0.0.1:631` | Optionnel | | **`*` (catch-all)** | **Redirect → `http://photomaton.lessapinsduweb.com`** | **Portail captif** | La règle catch-all est la clé : quand un client WiFi tape `google.com`, DNS résout vers `192.168.4.1`, Zoraxy reçoit la requête, ne reconnaît pas l'hôte, et redirige vers la galerie photo. > **Limite HTTPS :** si un client tape `https://google.com`, le navigateur voit > un certificat invalide et bloque avant la redirection. C'est inhérent à tout > portail DNS captif. En pratique : QR code sur les tables + iOS/Android qui > détectent le portail automatiquement via les sondes dnsmasq ci-dessus. --- ## Étape 12 — Copier les données de l'ancienne carte SD Depuis ton PC, copier les fichiers importants de l'ancienne carte : ```bash # Monter l'ancienne carte SD sur le PC (remplacer /dev/sdX) # ou utiliser un lecteur de carte # Cadres (frames) photobooth rsync -av /mnt/old-sd/home/pi/photobooth-data/userdata/ \ pi@:/home/pi/photobooth-data/userdata/ # Script d'impression rsync -av /mnt/old-sd/home/pi/photobooth-data/script/ \ pi@:/home/pi/photobooth-data/script/ # Config photobooth-app (actions, frames configurées) rsync -av /mnt/old-sd/home/pi/.config/photobooth-app/ \ pi@:/home/pi/.config/photobooth-app/ # ⚠️ Après cette copie, vérifier que plugin_commander.json pointe bien vers :8090 (pas :1880) # Config JH Photomaton (settings.yaml + base SQLite) rsync -av /mnt/old-sd/home/pi/jh-photomaton/config/settings.yaml \ pi@:/home/pi/jh-photomaton/config/ rsync -av /mnt/old-sd/home/pi/jh-photomaton/data/ \ pi@:/home/pi/jh-photomaton/data/ ``` --- ## Étape 13 — Vérification finale ```bash # Tous les services actifs ? sudo systemctl status photobooth-app jh-photomaton cups # Logs JH Photomaton sudo journalctl -u jh-photomaton -f # Tests API rapides curl http://localhost:8090/api/event # événement en cours curl http://localhost:8090/api/system/stats # CPU/RAM/temp # Test LED curl -X POST "http://localhost:8090/api/leds/play?effect=capture" # Test webhook photobooth (simule une photo prise) curl "http://localhost:8090/api/webhook/photobooth?event_key=capture" curl "http://localhost:8090/api/webhook/photobooth?event_key=finished" # Imprimantes disponibles lpstat -p ``` Interface admin : `http://:8090/admin` --- ## Résumé des ports | Service | Port | Accès | |---------|------|-------| | JH Photomaton (admin) | 8090 | `http://admin.lessapinsduweb.com` ou `http://:8090/admin` | | photobooth-app (kiosque) | 8000 | `http://photomaton.lessapinsduweb.com` | | CUPS (imprimantes) | 631 | `http://:631` (réseau local uniquement) | | Zoraxy (proxy admin) | 8888 | `http://192.168.4.1:8888` | | WiFi hotspot | — | SSID `Photomaton-LSDW` — IP Pi : `192.168.4.1` | --- ## Points d'attention post-installation 1. **plugin_commander.json** — vérifier que la URL pointe vers `:8090` (pas l'ancien Node-RED `:1880`) 2. **share_command dans photobooth-app** — même chose, changer `:1880` → `:8090/api/print/request` 3. **Nom des imprimantes CUPS** — doit correspondre exactement à ce qui est dans `settings.yaml` 4. **GPIO18 / audio** — `dtparam=audio=off` dans `/boot/firmware/config.txt` est obligatoire pour les LEDs 5. **Couleur du flash** — le réglage warm white `[255, 200, 80]` est dans `settings.yaml` → ajustable depuis l'admin dans Réglages → Flash photo 6. **Zoraxy catch-all** — ne pas oublier la règle `*` → redirect `photomaton.lessapinsduweb.com`, c'est elle qui fait le portail captif 7. **DAEMON_CONF hostapd** — sans cette ligne dans `/etc/default/hostapd`, hostapd démarre mais ignore la config (SSID invisible) --- ## CI/CD (déploiement automatique depuis Gitea) Voir `docs/CI-CD-SETUP.md` pour la configuration complète du pipeline Gitea Actions. En résumé : ```bash # Sur le Pi — générer la clé SSH pour le CI ssh-keygen -t ed25519 -C "gitea-cicd" -f ~/.ssh/gitea_deploy -N "" cat ~/.ssh/gitea_deploy.pub >> ~/.ssh/authorized_keys # Installer la règle sudoers sudo cp /home/pi/jh-photomaton/scripts/sudoers-jh-photomaton /etc/sudoers.d/jh-photomaton sudo chmod 440 /etc/sudoers.d/jh-photomaton ``` Puis dans Gitea → Settings → Secrets : ajouter `PI_SSH_HOST`, `PI_SSH_USER`, `PI_SSH_KEY`.