Déploiement sur etherbay.tech
La démonstration publique de BlockLucky est hébergée sous le domaine etherbay.tech, sur une machine virtuelle Azure. Cette page décrit ce qui est en place, la procédure prévue pour déployer l'application et ce qui reste à faire.
Important
À la date de rédaction (novembre 2026), la machine virtuelle, le pare-feu et le proxy Caddy sont opérationnels, et la documentation est publiée sur docs.etherbay.tech. L'application elle-même n'est pas encore déployée : etherbay.tech, api.etherbay.tech et tourisme.etherbay.tech renvoient une page « Bientôt en ligne » avec le statut 503. Les étapes marquées « à faire » ci-dessous n'ont pas été exécutées.
Ressources
| Ressource | Valeur |
|---|---|
| Domaine | etherbay.tech, acheté chez get.tech avec le GitHub Student Pack |
| Validité du domaine | jusqu'au 11 novembre 2027, renouvellement automatique désactivé |
| Abonnement | Azure for Students |
| Groupe de ressources | rg-etherbay |
| Machine virtuelle | vm-etherbay, région Denmark East |
| Taille | Standard_B4as_v2 : 4 vCPU, 16 Go de mémoire |
| Système | Ubuntu 24.04 |
| Compte | etherbay, connexion SSH par clé uniquement |
| Fin de vie prévue | suppression de la VM après la soutenance, vers le 18 novembre 2026 |
L'adresse IP publique et la clé SSH ne sont pas consignées dans la documentation. La connexion se fait par le nom de domaine :
ssh etherbay@etherbay.techArchitecture cible
flowchart LR
U["Navigateur ou application mobile"] -->|"HTTPS 443"| C["Caddy, projet edge, network_mode host"]
C -->|"etherbay.tech"| W["web, 127.0.0.1:3000"]
C -->|"api.etherbay.tech"| A["backend, 127.0.0.1:2053"]
C -->|"tourisme.etherbay.tech"| T["tourisme, 127.0.0.1:4000"]
C -->|"docs.etherbay.tech"| D["fichiers statiques /srv/docs"]
A --> PG["postgres"]
A --> R["redis"]
A --> BC["blockchain, nœud Hardhat"]
K["worker"] --> PG
K --> R
K --> BCDeux projets Compose cohabitent sur la VM :
edge, dans/opt/edge: Caddy seul, ennetwork_mode: host, qui écoute sur les ports 80 et 443 de l'hôte et obtient les certificats Let's Encrypt ;blocklucky: la stack du dépôt avec le profilapp, dont les ports applicatifs sont publiés sur127.0.0.1.
Le nœud Hardhat tourne sur la VM, dans le service blockchain de la stack. La démonstration n'utilise pas Sepolia : elle reste indépendante des robinets et du financement d'un abonnement Chainlink.
Ce qui est en place
Préparation de la machine
| Élément | État |
|---|---|
| Docker Engine et le plugin Compose | installés |
Pare-feu ufw |
ouvert sur 22 (SSH), 80 et 443 uniquement |
fail2ban |
installé, protège SSH contre la force brute |
| Swap | 4 Go |
| DNS de la machine | serveurs DNS publics ajoutés, car le résolveur Azure renvoyait SERVFAIL pour archive.ubuntu.com et bloquait apt |
Proxy Caddy
Caddy route chaque nom vers sa cible et gère HTTPS de bout en bout :
| Nom | Comportement actuel | Comportement cible |
|---|---|---|
etherbay.tech |
page « Bientôt en ligne », statut 503 | proxy vers le web, port 3000 |
www.etherbay.tech |
redirection vers etherbay.tech |
inchangé |
api.etherbay.tech |
page « Bientôt en ligne », statut 503 | proxy vers 127.0.0.1:2053 (REST et Socket.IO) |
tourisme.etherbay.tech |
page « Bientôt en ligne », statut 503 | proxy vers le port 4000 |
docs.etherbay.tech |
documentation statique | inchangé, voir Publier la documentation |
Le statut 503 signale aux robots d'indexation une indisponibilité temporaire et non une page définitive.
Le Caddyfile de /opt/edge n'est pas versionné dans le dépôt, à l'exception du bloc de la documentation (documentation-officielle/deploiement/Caddyfile).
Procédure de déploiement prévue
Les commandes s'exécutent sur la VM, sous le compte etherbay, depuis la racine d'un clone du dépôt.
1. Récupérer le code
Cloner le dépôt MarceauTDML/BlockLucky et se placer sur la branche ou le commit à présenter. Noter le SHA du commit déployé : c'est la référence pour un retour arrière.
2. Créer les secrets
Créer un fichier .env à la racine du clone, lisible par le seul compte etherbay :
umask 077
cat > .env <<EOF
JWT_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
RELAYER_PRIVATE_KEY=0x$(openssl rand -hex 32)
WEBHOOK_SECRET=$(openssl rand -hex 24)
METRICS_TOKEN=$(openssl rand -hex 24)
EOFCes cinq variables sont exigées par le schéma de env.config.ts dès que NODE_ENV=production (voir Docker Compose). Une clé RELAYER_PRIVATE_KEY aléatoire convient : le service blockchain habilite et approvisionne automatiquement le compte qui en dérive. Conserver une copie de ENCRYPTION_KEY hors de la VM tant que la démonstration dure : sans elle, les portefeuilles intégrés ne peuvent plus être déchiffrés.
3. Adapter la configuration aux URL publiques (à faire)
Le fichier docker-compose.yml vise localhost. Plusieurs valeurs y sont écrites en dur et doivent être remplacées. La solution prévue est un fichier de surcharge propre à la VM, par exemple docker-compose.etherbay.yml, non commité, chargé après le fichier principal.
| Variable ou réglage | Valeur actuelle | Valeur pour etherbay.tech | Où elle est lue |
|---|---|---|---|
FRONTEND_URL |
http://localhost:3000 |
https://etherbay.tech |
liens des emails RGPD, lien de parrainage, external_url des métadonnées POAP, origine CORS |
CORS_ORIGINS |
http://localhost:3000,http://localhost:8081 |
https://etherbay.tech |
app.ts et socket.handler.ts, via corsOrigins |
TRUST_PROXY |
absente, donc false |
1 |
app.set('trust proxy', …) dans app.ts |
argument NEXT_PUBLIC_API_URL du service web |
http://localhost:2053/api |
https://api.etherbay.tech/api |
figé dans le bundle et dans la CSP au build |
argument NEXT_PUBLIC_WS_URL du service web |
http://localhost:2053 |
https://api.etherbay.tech |
client Socket.IO, figé au build |
POAP_BASE_URI du service blockchain |
http://localhost:2053/api/v1/lottery/poap/ |
https://api.etherbay.tech/api/v1/lottery/poap/ |
tokenURI des badges, fixé au déploiement du contrat |
ports 2053, 3000, 4000 |
toutes les interfaces | 127.0.0.1 seulement |
Docker contourne ufw |
lotteryAppUrl du site de l'Office de Tourisme |
http://localhost:3000 |
https://etherbay.tech |
site.js, copié dans l'image : modifier le fichier avant la construction |
Pourquoi chaque point compte :
TRUST_PROXY. Derrière Caddy, toutes les requêtes arrivent au conteneur depuis la même adresse interne. SansTRUST_PROXY=1, Express ignore l'en-têteX-Forwarded-Forposé par Caddy : tous les visiteurs partagent alors le même compteur du rate limiter global (300 requêtes par 15 minutes) et du limiteur d'authentification (30 tentatives par 10 minutes), et la démonstration se bloque en quelques minutes. La valeur1fait confiance à un seul saut, Caddy. La lecture de la variable est faite danstrustProxydeenv.config.ts, qui convertit un entier en nombre de sauts.NEXT_PUBLIC_*. Ces valeurs sont des arguments de build. Après modification, l'imagewebdoit être reconstruite (--build), sinon le navigateur continue d'appelerlocalhostet la CSP bloque les appels versapi.etherbay.tech.POAP_BASE_URI. Le préfixe est passé au constructeur deBlockLuckyPOAPpardeploy-local.ts. Il ne change qu'au prochain démarrage du serviceblockchain, qui redéploie les contrats, ou par un appel àsetBaseUrisigné par un détenteur deDEFAULT_ADMIN_ROLE(le compte Hardhat n° 0 en local).- Ports. Docker écrit ses propres règles iptables pour les ports publiés, en amont de
ufw. Un port publié sur toutes les interfaces est joignable depuis Internet malgré le pare-feu, sauf si le groupe de sécurité réseau Azure le bloque. Lier les ports à127.0.0.1laisse Caddy seul exposé.
Exemple de fichier de surcharge :
services:
backend:
environment:
FRONTEND_URL: https://etherbay.tech
CORS_ORIGINS: https://etherbay.tech
TRUST_PROXY: "1"
ports: !override
- "127.0.0.1:2053:2053"
worker:
environment:
FRONTEND_URL: https://etherbay.tech
CORS_ORIGINS: https://etherbay.tech
TRUST_PROXY: "1"
web:
build:
args:
NEXT_PUBLIC_API_URL: https://api.etherbay.tech/api
NEXT_PUBLIC_WS_URL: https://api.etherbay.tech
ports: !override
- "127.0.0.1:3000:3000"
tourisme:
ports: !override
- "127.0.0.1:4000:8080"
blockchain:
environment:
POAP_BASE_URI: https://api.etherbay.tech/api/v1/lottery/poap/Les clés environment et build.args se fusionnent clé par clé avec le fichier principal. Les listes ports, elles, s'additionnent : la balise !override de Compose remplace la liste au lieu de la compléter. Avant tout démarrage, contrôler le résultat :
docker compose -f docker-compose.yml -f docker-compose.etherbay.yml --profile app configVérifier dans la sortie que chaque port applicatif commence par 127.0.0.1 et que les URL sont en https://.
4. Construire et démarrer (à faire)
docker compose -f docker-compose.yml -f docker-compose.etherbay.yml --profile app up -d --build --waitL'ordre de démarrage est géré par Compose : PostgreSQL, Redis et la blockchain, puis les migrations, puis l'API et le worker, puis le web (voir Docker Compose). Le premier démarrage de blockchain compile et déploie les contrats, ce qui peut prendre une minute.
5. Basculer Caddy vers l'application (à faire)
Dans le Caddyfile de /opt/edge, remplacer la réponse 503 de chaque nom par un proxy :
etherbay.tech {
reverse_proxy 127.0.0.1:3000
}
api.etherbay.tech {
reverse_proxy 127.0.0.1:2053
}
tourisme.etherbay.tech {
reverse_proxy 127.0.0.1:4000
}reverse_proxy relaie aussi les connexions WebSocket de Socket.IO, sans réglage supplémentaire. Caddy ajoute X-Forwarded-For, X-Forwarded-Proto et X-Forwarded-Host. Le frontend web et le site de l'Office de Tourisme envoient déjà leurs propres en-têtes de sécurité. Recharger Caddy depuis /opt/edge après modification.
Il est recommandé de ne pas exposer /metrics publiquement, même s'il est protégé par METRICS_TOKEN, par exemple avec un bloc respond /metrics 404 dans le site api.etherbay.tech.
6. Décider du contenu de démonstration (à faire)
Le service migrate applique les migrations mais ne lance aucun seed : la base démarre vide, sans compte administrateur, sans partenaire ni récompense. Pour présenter l'espace Mairie et la boutique, il faut charger les données de prisma/seed.ts. L'image runtime ne contient pas tsx ; l'image migrator contient toutes les dépendances de développement et le dossier prisma/. Le chargement depuis cette image, et la façon dont l'administrateur obtient ensuite sa double authentification, restent à valider sur la stack Docker locale avant la VM. Voir Seed et Comptes de démonstration et connexion.
7. Décider de l'envoi des emails (à faire)
En production, la connexion exige un code envoyé par email (LOGIN_EMAIL_CODE_REQUIRED ne peut pas être désactivé quand NODE_ENV=production). Dans la stack, SMTP_HOST vaut mailpit : les codes sont capturés par Mailpit et n'atteignent pas les boîtes des visiteurs. Deux options :
Démonstration encadrée : garder Mailpit et lire les codes dans son interface, liée à
127.0.0.1:8025sur la VM, par un tunnel SSH :Terminalssh -L 8025:127.0.0.1:8025 etherbay@etherbay.techpuis ouvrir
http://localhost:8025sur le poste. Seules les personnes ayant la clé SSH peuvent se connecter.Démonstration ouverte : configurer un vrai relais SMTP.
SMTP_HOSTetSMTP_PORTsont écrits en dur dansx-backend-envetSMTP_USER,SMTP_PASS,SMTP_FROMn'y figurent pas : il faut les ajouter dans la surcharge pourbackendetworker. Le port 465 active TLS (securedansmailer.config.ts). Le domaine d'expédition doit alors être autorisé par le relais (SPF, DKIM).
8. Vérifier
curl -fsS https://api.etherbay.tech/health/readycurl -fsS https://api.etherbay.tech/api/configcurl -fsS -H "Authorization: Bearer $METRICS_TOKEN" https://api.etherbay.tech/health/deepPuis, dans un navigateur : ouverture de https://etherbay.tech, absence d'erreur CSP dans la console, inscription, réception du code, achat d'un ticket et apparition du tirage en direct. Le scénario complet de démonstration est dans Préparer la soutenance. Un test de fumée k6 peut compléter (voir Tests de charge).
9. Application mobile (à faire)
Pour qu'un téléphone utilise la démonstration, construire l'application avec EXPO_PUBLIC_API_URL=https://api.etherbay.tech/api et EXPO_PUBLIC_WS_URL=https://api.etherbay.tech. Ces variables sont lues par api.client.ts et socket.client.ts. Les applications natives n'envoient pas d'en-tête Origin et ne sont donc pas concernées par CORS_ORIGINS.
Exploitation pendant la démonstration
| Sujet | Point d'attention | Référence |
|---|---|---|
Redémarrage de la VM ou du conteneur blockchain |
la chaîne Hardhat repart de zéro, la base garde l'ancien état | Runbooks blockchain |
| Tirage bloqué | l'oracle VRF local est un processus du conteneur blockchain |
Runbooks blockchain |
| Incident applicatif | sondes, journaux, files | Runbooks |
| Sauvegarde avant soutenance | pg_dump de la base |
Sauvegardes et reprise |
| Mise à jour du code | git pull puis la commande de l'étape 4 ; les migrations s'appliquent seules |
Runbooks |
| Swagger | /api/docs annonce http://localhost:2053 comme serveur, le bouton d'essai ne vise pas la démonstration |
Dette technique et limites |
Les journaux se lisent depuis le clone :
docker compose --profile app logs -f --since 10m backend workerFin de vie
Après la soutenance, vers le 18 novembre 2026 :
sauvegarder ce qui doit l'être (aucune donnée réelle n'est traitée, une sauvegarde n'est utile que pour rejouer la démonstration) ;
supprimer le groupe de ressources, ce qui supprime la VM, son disque, son adresse IP et son groupe de sécurité réseau :
Terminalaz group delete --name rg-etherbayretirer ou rediriger les enregistrements DNS chez get.tech, pour qu'aucun sous-domaine ne pointe vers une adresse IP réattribuée à un tiers.
Le domaine reste enregistré jusqu'au 11 novembre 2027 et ne sera pas renouvelé automatiquement.
Récapitulatif de ce qui reste à faire
| Étape | État |
|---|---|
VM, Docker, ufw, fail2ban, swap, DNS de la machine |
fait |
| Caddy et certificats Let's Encrypt pour tous les noms | fait |
Documentation sur docs.etherbay.tech |
fait |
Clone du dépôt et fichier .env |
à faire |
Fichier de surcharge (URL publiques, TRUST_PROXY, ports locaux, POAP_BASE_URI) |
à faire |
Lien lotteryAppUrl du site de l'Office de Tourisme vers https://etherbay.tech |
à faire |
Construction et démarrage de la stack avec le profil app |
à faire |
Bascule des blocs Caddy de 503 vers reverse_proxy |
à faire |
| Données de démonstration (seed) | à décider puis à faire |
| Envoi des emails (Mailpit par tunnel ou relais SMTP) | à décider |
Build mobile pointé vers api.etherbay.tech |
à faire si une démonstration mobile est prévue |
Suppression du groupe rg-etherbay |
après la soutenance |