Garage Opener

Auto-héberger le bridge

Le bridge est un petit service dans un conteneur. Il parle à votre console Protect, tient la machine à états de la porte, sert l’app et exécute les règles d’alerte. Il tourne sur un NAS, un Raspberry Pi ou n’importe quelle machine avec Docker, sur amd64 et arm64.

Vous n’êtes pas obligé de l’utiliser. L’app se connecte directement à votre console Protect et fonctionne sur votre réseau domestique sans rien installer d’autre. Le bridge sert si vous voulez des règles d’alerte permanentes, un journal d’activité exportable, les invitations familiales ou des raccourcis fiables en arrière-plan.

Avant de commencer

  1. Configurez une sortie de relais en Pulse. Dans Protect, ouvrez le relais et configurez en Pulse, type porte de garage, la sortie câblée sur les bornes du bouton-poussoir de votre moteur. Notez de quelle sortie il s’agit : la numérotation commence à 1 dans l’app, mais les identifiants de l’API commencent à 0.
  2. Montez le capteur et réglez son type de montage sur Garage. C’est ce que lit le bridge pour décider si la porte est ouverte. Avec un autre type de montage, l’appairage automatique ne le retiendra pas.
  3. Créez une clé d’API Protect. Console → Réglages → Control Plane → Intégrations → Créer une clé d’API. Copiez-la immédiatement : elle n’est plus affichée ensuite.

    Cette clé peut lire toutes les caméras de votre console. Traitez-la comme un mot de passe donnant accès à votre domicile, parce que c’est fonctionnellement ce qu’elle est.

Le lancer

Créez un dossier, déposez-y un docker-compose.yml et un .env, puis démarrez :

# .env : les cinq valeurs qui comptent
GARAGE_BRIDGE_TAG=latest                # voir « le tenir à jour » plus bas
PROTECT_URL=https://192.168.1.1         # votre console, avec https://
PROTECT_API_KEY=…                       # la clé que vous venez de créer
BRIDGE_TOKENS=$(openssl rand -hex 24)   # jeton admin : générez-le, ne l'inventez pas
WEBHOOK_SECRET=$(openssl rand -hex 24)  # secret de chemin pour le webhook Alarm Manager
TZ=Europe/Zurich
docker compose up -d
curl -s localhost:8787/healthz

Vous devriez obtenir {"ok":true,"ready":true,…}, avec la version réellement en cours d’exécution. Si ready vaut false, le bridge tourne mais n’a pas encore joint la console, et le message indique pourquoi.

À propos des jetons

BRIDGE_TOKENS est l’identifiant qui ouvre votre porte de garage. Le bridge refuse de démarrer sur une valeur de moins de 24 caractères, ou sur quoi que ce soit de devinable. Générez-la. Les téléphones de votre famille n’ont pas besoin d’une entrée ici : ils rejoignent par invitation, plus bas.

Réseau de l’hôte, ou pas

L’app trouve le bridge via Bonjour, et le multicast ne traverse pas le réseau bridge de Docker : le compose de référence utilise donc network_mode: host. Si ce n’est pas possible chez vous, par exemple sur Docker Desktop pour macOS ou Windows, publiez plutôt 8787:8787, mettez BONJOUR=false et saisissez l’adresse dans l’app. Tout est identique, sauf la découverte.

Appairer votre téléphone

Ne copiez pas votre jeton admin dans l’app. Tant qu’aucun téléphone n’a rejoint, le bridge affiche une invitation à usage unique au démarrage :

docker logs garage-bridge | tail -20

Collez le lien garageopener://join…, ou simplement le code, dans la feuille Famille → Rejoindre de l’app. Il est valable quinze minutes ; redémarrez le conteneur pour en obtenir un nouveau. Dès qu’un téléphone a rejoint, l’affichage cesse et les téléphones suivants sont invités depuis l’app elle-même.

Laisser la console informer le bridge

Le bridge interroge la console régulièrement, mais les webhooks le font réagir immédiatement. Dans Protect, créez deux règles Alarm Manager, capteur ouvert et fermé, publiant toutes deux vers :

http://<hôte-du-bridge>:8787/v1/webhooks/alarm-manager/<WEBHOOK_SECRET>

La console doit pouvoir joindre cette adresse ; elle est sur le même réseau que le bridge, donc rien n’est requis depuis Internet. Un secret erroné renvoie un simple 404 : si les règles semblent sans effet, vérifiez d’abord le secret.

Certificats

Votre console présente un certificat auto-signé : la valeur par défaut est donc PROTECT_TLS=insecure, ce qui convient sur un réseau local. Épinglez-le correctement une fois en route :

openssl s_client -connect 192.168.1.1:443 -servername 192.168.1.1 </dev/null 2>/dev/null \
  | openssl x509 -noout -fingerprint -sha256

Placez le résultat dans PROTECT_TLS=fingerprint:<sha256>. Si votre console possède un vrai certificat, utilisez system. Le bridge refuse de démarrer avec insecure si PROTECT_URL n’est pas une adresse locale, car cela exposerait votre clé d’API à quiconque se trouve sur le chemin.

Y accéder depuis l’extérieur

Définissez PUBLIC_URL sur l’adresse que le téléphone utilisera : c’est elle que portent les liens d’invitation. Ensuite, choisissez :

ApprocheRemarques
VPN vers votre domicile (WireGuard sur l’UDM, ou Tailscale)Recommandé. Rien n’est exposé ; le téléphone rejoint simplement votre réseau.
Tunnel CloudflareVrai nom d’hôte, vrai certificat, aucun port entrant. Mettez TRUST_PROXY=true.
Votre propre reverse proxyCaddy, nginx ou Traefik en terminaison TLS. Mettez TRUST_PROXY=true, et désactivez la mise en tampon sur /v1/events, sinon l’état de la porte accusera du retard.
Redirection de portNon. Cela place sur l’internet public un appareil qui ouvre votre garage, derrière un seul jeton, en général sans TLS.

TRUST_PROXY compte davantage qu’il n’y paraît. Sans lui, toutes les requêtes semblent venir du proxy : la limite par adresse sur les invitations devient cinq par minute pour tout votre foyer. Avec lui, alors que rien en amont ne filtre X-Forwarded-For, un appelant peut déclarer l’adresse qu’il veut : ne l’activez donc que si un proxy que vous contrôlez est réellement en place.

Le tenir à jour

latest est la valeur par défaut et convient à la plupart des gens. Docker ne met jamais un conteneur à jour tout seul : latest signifie simplement que vous obtiendrez la version courante au prochain pull que vous déciderez de faire. Vous restez donc sur les correctifs de sécurité sans avoir à suivre les publications.

docker compose pull && docker compose up -d
curl -s localhost:8787/healthz   # vérifiez la version récupérée

Épinglez plutôt une version exacte, GARAGE_BRIDGE_TAG=0.4.1, si vous voulez que les mises à jour soient une décision et non un effet de bord d’un pull, ou si vous utilisez un outil de mise à jour automatique comme Watchtower. Avec latest et une mise à jour automatique combinés, une version exigeant un changement de configuration redémarrerait votre bridge sur un refus de démarrer, sans que vous le voyiez.

Dans tous les cas, lisez le changelog avant un pull. Tout ce qui demande de toucher à la configuration figure sous Action required, et le bridge échoue bruyamment au démarrage plutôt que de tourner dans un état dégradé.

Sources et licence

Le bridge et son contrat OpenAPI sont open source sous licence Apache-2.0. Vous le faites tourner sur votre propre matériel avec un identifiant vers votre console : vous devez pouvoir le lire plutôt que de le croire sur parole, y compris l’audit de sécurité mené avant sa publication.

L’app iOS n’est pas open source, et le service d’alertes cloud non plus. Ce service est quelque chose que nous exploitons, pas que vous faites tourner ; il ne détient aucun identifiant vers votre console et ne peut rien ouvrir ni fermer. Ce qu’il conserve est décrit intégralement sur la page de confidentialité.

Hors périmètre

Une porte par bridge. UniFi Protect uniquement, sans autres relais ni autres hubs. Aucune intégration Home Assistant. Pas d’Android. Une installation sans Docker (Node 22 directement) fonctionnera mais n’est pas prise en charge : Docker est le chemin testé, et le seul que couvrent ces instructions.

Bloqué ? La FAQ couvre les cas courants, et support@garageopener.app vous met en contact avec une personne.

Dernière mise à jour: