From 8b2e56c73ca7aaca52785fe228ca3b4401db3d82 Mon Sep 17 00:00:00 2001 From: ertopogo Date: Sat, 21 Feb 2026 03:50:58 +0100 Subject: feat: attributs bougies (metadata) + Caddy/DNS docs --- DOC_IMPORT_PRODUITS.md | 169 ++++++++++++++++++++++++++++++++++--- DOC_TECHNIQUE.md | 168 ++++++++++++++++++++---------------- INSTALLATION.md | 144 ++++++++++++++++++------------- app-management.md | 83 +++++++++++++----- backend/data/products-import.csv | 13 ++- backend/scripts/import-products.js | 10 +++ env-example | 16 ++-- helper-cmd.md | 62 ++++++-------- storefront/pages/index.js | 26 ++++++ 9 files changed, 485 insertions(+), 206 deletions(-) diff --git a/DOC_IMPORT_PRODUITS.md b/DOC_IMPORT_PRODUITS.md index b41cba8..784e83b 100644 --- a/DOC_IMPORT_PRODUITS.md +++ b/DOC_IMPORT_PRODUITS.md @@ -37,10 +37,20 @@ Colonnes minimales: - `inventory_quantity` (optionnel, defaut: 0) - `manage_inventory` (optionnel, true/false) +Colonnes attributs (optionnelles, stockees dans `product.metadata`): +- `volume` (ex: 200ml, 500ml) +- `type_meche` (ex: bois, coton) +- `parfum` (ex: lavande, vanille) +- `couleur` (ex: blanche, bleue) +- `type_cire` (ex: soja, colza, abeille) + +Ces attributs sont descriptifs (pas de variantes). Ils sont affiches sur la +fiche produit du storefront. Si une colonne est vide, l'attribut n'est pas affiche. + Exemple: ``` -external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory -prod-001,Savon Lavande,savon-lavande,"Savon artisanal a la lavande.",https://via.placeholder.com/600x600.png?text=Savon+Lavande,Taille,100g,100g,SKU-SAV-100,650,eur,100,true +external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory,volume,type_meche,parfum,couleur,type_cire +prod-001,Bougie Lavande,bougie-lavande,"Bougie artisanale a la lavande.",,Taille,200ml,200ml,SKU-BOU-LAV-200,1200,eur,50,true,200ml,coton,lavande,blanche,soja ``` ## FR - Comportement @@ -53,18 +63,82 @@ prod-001,Savon Lavande,savon-lavande,"Savon artisanal a la lavande.",https://via ## FR - Git flow (branche + push) Nom de branche suggere: `feature/import-csv-produits` -Commandes type: +### Creer et developper la feature ``` git flow feature start import-csv-produits git status -git add backend/scripts/import-products.js backend/data/products-import.csv backend/package.json DOC_IMPORT_PRODUITS.md helper-cmd.md DOC_TECHNIQUE.md -git commit -m "Add product CSV import script and docs" +git add -A +git commit -m "feat: attributs bougies (metadata) + import CSV" git push -u chillka feature/import-csv-produits ``` -Selon votre process: +### Tester sur huitral (avant de finir la feature) ``` +# Sur huitral +cd /var/www/lucien-sens-bon +git fetch origin +git checkout feature/import-csv-produits +git reset --hard origin/feature/import-csv-produits + +# Dry-run (test sans ecriture en base) +docker compose run --rm backend npm run import:products -- --dry-run + +# Import reel +docker compose run --rm backend npm run import:products + +# Rebuild storefront (pour afficher les attributs metadata) +docker compose up -d --build storefront + +# Verifier +curl -s http://localhost:9000/store/products | python3 -m json.tool | head -30 +``` + +### Finir la feature et merger dans develop +``` +# Sur le poste de dev git flow feature finish import-csv-produits +git push chillka develop +git push chillka --delete feature/import-csv-produits +``` + +### Deployer develop sur huitral +``` +# Sur huitral +cd /var/www/lucien-sens-bon +git fetch origin +git checkout develop +git reset --hard origin/develop +docker compose up -d --build storefront +``` + +## FR - Alternative : remettre la branche feature dans main (sans git-flow) +Si tu veux ramener le contenu de la feature vers `main` directement : +``` +git checkout main +git merge feature/import-csv-produits +git push origin main +``` + +Si tu veux utiliser la branche distante directement : +``` +git checkout main +git merge origin/feature/import-csv-produits +git push origin main +``` + +## FR - Cas courant: commit fait sur main avant la feature +Si un commit a ete fait sur `main` avant la creation de la feature, il faut le recuperer: +``` +git log --oneline main -n 5 +git cherry-pick +``` +Alternative si plusieurs commits: +``` +git cherry-pick +``` +Ou merger `main` (si votre process l'autorise): +``` +git merge main ``` ## FR - Troubleshoot git-flow @@ -134,10 +208,20 @@ Pflichtspalten: - `inventory_quantity` (optional, Default: 0) - `manage_inventory` (optional, true/false) +Attribut-Spalten (optional, in `product.metadata` gespeichert): +- `volume` (z.B. 200ml, 500ml) +- `type_meche` (z.B. bois, coton) +- `parfum` (z.B. lavande, vanille) +- `couleur` (z.B. blanche, bleue) +- `type_cire` (z.B. soja, colza, abeille) + +Diese Attribute sind beschreibend (keine Varianten). Sie werden auf der +Produktseite im Storefront angezeigt. Leere Spalten werden nicht angezeigt. + Beispiel: ``` -external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory -prod-001,Savon Lavande,savon-lavande,"Savon artisanal a la lavande.",https://via.placeholder.com/600x600.png?text=Savon+Lavande,Taille,100g,100g,SKU-SAV-100,650,eur,100,true +external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory,volume,type_meche,parfum,couleur,type_cire +prod-001,Bougie Lavande,bougie-lavande,"Bougie artisanale a la lavande.",,Taille,200ml,200ml,SKU-BOU-LAV-200,1200,eur,50,true,200ml,coton,lavande,blanche,soja ``` ## DE - Verhalten @@ -150,18 +234,79 @@ prod-001,Savon Lavande,savon-lavande,"Savon artisanal a la lavande.",https://via ## DE - Git flow (Branch + Push) Branch Vorschlag: `feature/import-csv-produits` -Typische Befehle: +### Feature erstellen und entwickeln ``` git flow feature start import-csv-produits git status -git add backend/scripts/import-products.js backend/data/products-import.csv backend/package.json DOC_IMPORT_PRODUITS.md helper-cmd.md DOC_TECHNIQUE.md -git commit -m "Add product CSV import script and docs" +git add -A +git commit -m "feat: Kerzen-Attribute (metadata) + CSV Import" git push -u chillka feature/import-csv-produits ``` -Optional nach Prozess: +### Auf huitral testen (vor Feature-Abschluss) +``` +# Auf huitral +cd /var/www/lucien-sens-bon +git fetch origin +git checkout feature/import-csv-produits +git reset --hard origin/feature/import-csv-produits + +# Dry-run (Test ohne DB-Schreibvorgang) +docker compose run --rm backend npm run import:products -- --dry-run + +# Echter Import +docker compose run --rm backend npm run import:products + +# Storefront neu bauen (fuer Metadata-Attribute) +docker compose up -d --build storefront ``` + +### Feature abschliessen und in develop mergen +``` +# Auf dem Entwicklungsrechner git flow feature finish import-csv-produits +git push chillka develop +git push chillka --delete feature/import-csv-produits +``` + +### Develop auf huitral deployen +``` +# Auf huitral +cd /var/www/lucien-sens-bon +git fetch origin +git checkout develop +git reset --hard origin/develop +docker compose up -d --build storefront +``` + +## DE - Alternative: Feature-Branch direkt in main (ohne git-flow) +Wenn du den Feature-Branch direkt nach `main` holen willst: +``` +git checkout main +git merge feature/import-csv-produits +git push origin main +``` + +Wenn du direkt den Remote-Branch verwenden willst: +``` +git checkout main +git merge origin/feature/import-csv-produits +git push origin main +``` + +## DE - Typisch: Commit auf main vor der Feature +Wenn ein Commit bereits auf `main` erstellt wurde, muss er in die Feature: +``` +git log --oneline main -n 5 +git cherry-pick +``` +Alternative fuer mehrere Commits: +``` +git cherry-pick +``` +Oder `main` mergen (falls erlaubt): +``` +git merge main ``` ## DE - Troubleshooting git-flow diff --git a/DOC_TECHNIQUE.md b/DOC_TECHNIQUE.md index 0c4b2f9..b5576a6 100644 --- a/DOC_TECHNIQUE.md +++ b/DOC_TECHNIQUE.md @@ -12,7 +12,7 @@ Le projet est compose de : - **PostgreSQL** : base de donnees principale (clients, commandes, produits). - **Redis** : cache et event bus. - **Docker Compose** : orchestration des services. -- **Apache** (optionnel) : reverse proxy pour publier en 80/443. +- **Caddy** (sur araucaria) : reverse proxy + HTTPS automatique. Ports principaux : - `8000` : storefront (site public) @@ -47,7 +47,7 @@ Ou le voir : - [Docker Compose](https://docs.docker.com/compose/) - [PostgreSQL](https://www.postgresql.org/docs/) - [Redis](https://redis.io/docs/latest/) -- [Apache reverse proxy](https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html) +- [Caddy reverse proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) ## 3. Fichiers importants @@ -97,26 +97,38 @@ Briques logicielles principales : ### 3.4 Schema technique (ASCII) ``` - +----------------------+ - | Storefront | - | Next.js (Node) | - | :8000 | - +----------+-----------+ - | - | HTTP (API) - v - +----------------------+ - | MedusaJS | - | Node + Express | - | :9000 (API/Admin) | - +-----+----------+-----+ - | | - SQL | | Cache/Event bus - v v - +---------------+ +----------------+ - | PostgreSQL | | Redis | - | :5432 | | :6379 | - +---------------+ +----------------+ + Internet / LAN + | + v + +---------------------------+ + | araucaria (Caddy) | + | HTTPS / reverse proxy | + | lsb.arauco.online | + | api-lsb.arauco.online | + +------------+--------------+ + | + v + +---------------------------+ huitral + | | + | +--------------------+ | + | | Storefront | | + | | Next.js :8000 | | + | +--------+-----------+ | + | | | + | | HTTP (API) | + | v | + | +--------------------+ | + | | MedusaJS | | + | | :9000 (API) | | + | +-----+--------+----+ | + | | | | + | SQL | | Cache | + | v v | + | +----------+ +-------+ | + | |PostgreSQL| | Redis | | + | | :5432 | | :6379 | | + | +----------+ +-------+ | + +---------------------------+ ``` ## 4. Installation rapide (serveur Linux) @@ -143,16 +155,16 @@ docker compose up -d --build ### 4.1 Exemple reel (ce que nous avons fait) -Contexte : backend sur `192.168.99.22:9000`, storefront sur `192.168.99.22:8000`. +Contexte : backend sur huitral:9000, storefront sur huitral:8000, Caddy sur araucaria. -1) Variables d'environnement (exemple utilise) : +1) Variables d'environnement (production) : ``` DATABASE_URL=postgres://luciensbdb:********@192.168.99.35:5432/sens_bon_db JWT_SECRET=supersecret COOKIE_SECRET=supersecret -ADMIN_CORS=http://192.168.99.22:9000 -STORE_CORS=http://192.168.99.22:8000 -NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://192.168.99.22:9000 +NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api-lsb.arauco.online +ADMIN_CORS=https://api-lsb.arauco.online,https://lsb.arauco.online,http://api-lsb.huitral.ruka.lan,http://lsb.huitral.ruka.lan +STORE_CORS=https://lsb.arauco.online,http://lsb.huitral.ruka.lan NODE_ENV=development ``` @@ -205,7 +217,7 @@ docker compose logs -f storefront ### 5.1 Logs systeme avec journalctl (systemd) -Utiliser `journalctl` pour diagnostiquer les services systeme (Apache, dnsmasq, Docker). +Utiliser `journalctl` pour diagnostiquer les services systeme (Caddy, dnsmasq, Docker). Ou sont stockes les logs systeme : - **Persistant** : `/var/log/journal/` (apres reboot) @@ -251,10 +263,11 @@ sudo journalctl -u dnsmasq -S "10 min ago" --no-pager ### 5.2 Tests CORS (exemple utilise) ``` -curl -i -H "Origin: http://192.168.99.22:8000" http://192.168.99.22:9000/store/products +curl -i -H "Origin: https://lsb.arauco.online" https://api-lsb.arauco.online/store/products ``` - Confirme que `Access-Control-Allow-Origin` autorise le storefront. +- Pour le LAN : remplacer par `http://lsb.huitral.ruka.lan` et `http://api-lsb.huitral.ruka.lan`. ## 6. Ou se trouve la base de donnees ? @@ -282,17 +295,36 @@ docker exec -it medusa-backend npm run seed ``` ### 7.2 Storefront affiche "Chargement des produits..." -Le storefront attend l'API backend. Verifier : -- `NEXT_PUBLIC_MEDUSA_BACKEND_URL` dans `.env` -- le backend repond sur `:9000` +Le storefront attend l'API backend. Verifier dans l'ordre : -Si le backend repond, mais que rien ne s'affiche : -- verifier que le storefront a ete **rebuild** apres changement de `.env` : +1) `NEXT_PUBLIC_MEDUSA_BACKEND_URL` dans `.env` doit pointer vers l'API + via Caddy (`https://api-lsb.arauco.online`), pas `localhost`. + +2) Le backend repond sur `:9000` : +``` +curl http://localhost:9000/store/products +``` + +3) Le storefront a ete **rebuild** apres changement de `.env` + (`NEXT_PUBLIC_*` est injecte au build, pas au runtime) : ``` sudo docker compose up -d --build storefront ``` -- verifier que `storefront/pages/_app.js` utilise -`process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL` (pas `localhost` en dur). + +4) Les CORS sont corrects — `STORE_CORS` doit lister l'origine du storefront. + Apres modification, recreer le conteneur (pas juste restart) : +``` +sudo docker compose up -d backend +``` + +5) Le DNS LAN pointe vers **araucaria** (Caddy), pas vers huitral : +``` +dig +short lsb.arauco.online +dig +short api-lsb.arauco.online +``` + Les deux doivent retourner l'IP d'araucaria. Si ca retourne l'IP de + huitral, les navigateurs LAN contournent Caddy → `CONNECTION_REFUSED` + sur le port 443. Corriger dans `/etc/dnsmasq.d/lsb.conf` sur araucaria. ### 7.3 Admin Medusa (login qui boucle) @@ -313,8 +345,9 @@ Objectif : autoriser le navigateur a appeler l'API depuis le storefront et l'adm 1) Verifier `.env` : ``` -ADMIN_CORS=http://:9000 -STORE_CORS=http://:8000 +NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api-lsb.arauco.online +ADMIN_CORS=https://api-lsb.arauco.online,https://lsb.arauco.online,http://api-lsb.huitral.ruka.lan,http://lsb.huitral.ruka.lan +STORE_CORS=https://lsb.arauco.online,http://lsb.huitral.ruka.lan ``` 2) Rebuild backend pour appliquer les variables : @@ -324,7 +357,7 @@ sudo docker compose up -d --build backend 3) Test CORS (storefront) : ``` -curl -i -H "Origin: http://:8000" http://:9000/store/products +curl -i -H "Origin: https://lsb.arauco.online" https://api-lsb.arauco.online/store/products ``` ### 7.5 Admin en HTTP (procedure NODE_ENV) @@ -373,11 +406,16 @@ sudo docker compose build --no-cache backend sudo docker compose up -d backend ``` -## 8. Mise en production (reverse proxy, serveur Linux) +## 8. Mise en production (reverse proxy via Caddy sur araucaria) + +Le reverse proxy est gere par **Caddy** sur `araucaria` (pas sur huitral). +Caddy gere automatiquement les certificats HTTPS via Let's Encrypt. + +Configuration dans `/etc/caddy/Caddyfile` sur araucaria : +- `lsb.arauco.online` → huitral:8000 (storefront) +- `api-lsb.arauco.online` → huitral:9000 (backend) -Pour exposer en HTTP/HTTPS, utiliser Apache ou Nginx. Exemple Apache : -- `apache-vhost.conf` dans le repo -- activer `proxy` et `proxy_http` +Voir `INSTALLATION.md` section 5 pour le detail. ## 9. Sauvegarde et restauration (serveur Linux) @@ -818,50 +856,38 @@ Alternatives : - `curl -v ...` - DevTools navigateur (onglet Network). -#### 12.1.5 Apache / Reverse proxy +#### 12.1.5 Caddy / Reverse proxy (sur araucaria) -**Statut Apache** +**Statut Caddy** ``` -sudo systemctl status apache2 +sudo systemctl status caddy ``` -Alternatives : -- `sudo service apache2 status` -**Logs Apache** +**Logs Caddy** ``` -sudo journalctl -u apache2 -f -sudo tail -f /var/log/apache2/error.log -sudo tail -f /var/log/apache2/access.log +sudo journalctl -u caddy -f +sudo journalctl -u caddy -n 200 --no-pager ``` - `-f` : suivi temps reel. -Alternatives : -- `journalctl -u apache2 -n 200 --no-pager` -**Modules proxy** +**Editer le Caddyfile** ``` -sudo a2enmod proxy -sudo a2enmod proxy_http +sudo nano /etc/caddy/Caddyfile ``` -- active les modules de reverse proxy. -Alternatives : -- `a2enmod headers` -- `a2enmod rewrite` -**Reload Apache** +**Valider la config** ``` -sudo systemctl reload apache2 +caddy validate --config /etc/caddy/Caddyfile ``` -- recharge la config sans couper les connexions actives. -Alternatives : -- `sudo service apache2 restart` -**Activer un vhost** +**Reload Caddy** ``` -sudo a2ensite lucien.conf -sudo apache2ctl configtest -sudo service apache2 restart +sudo systemctl reload caddy ``` -- `configtest` : verifie la syntaxe avant redemarrage. +- recharge la config sans couper les connexions actives. +Alternatives : +- `sudo systemctl restart caddy` +- `caddy reload --config /etc/caddy/Caddyfile` #### 12.1.6 Systemd / Logs systeme (journalctl) diff --git a/INSTALLATION.md b/INSTALLATION.md index 53c8215..a0ac486 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -1,13 +1,13 @@ # Guide d'Installation Complet - Lucien-sens-bon -Ce guide détaille comment installer votre boutique MedusaJS (Backend) + Next.js (Frontend) sur votre serveur "huitral" avec Docker et Apache. +Ce guide détaille comment installer votre boutique MedusaJS (Backend) + Next.js (Frontend) sur votre serveur "huitral" avec Docker, et l'exposer via Caddy (reverse proxy sur araucaria). ## 1. Pré-requis Assurez-vous d'avoir : -- **Docker** et **Docker Compose** installés. +- **Docker** et **Docker Compose** installés sur `huitral`. - Une base de données **PostgreSQL** accessible (version 12+ recommandée). -- **Apache** installé sur la machine hôte. +- **Caddy** installé sur `araucaria` (reverse proxy + HTTPS automatique). ## 1.1 Nomenclature DNS (ruka.lan) @@ -42,16 +42,20 @@ IP_DE_HUITRAL www.lsb.huitral.ruka.lan IP_DE_HUITRAL api.lsb.huitral.ruka.lan ``` -**Cas 3 — DNS public** -Créez des enregistrements A (et AAAA si IPv6) vers l'IP publique : -- `www.lucien-sens-bon.com` → `IP_PUBLIQUE` -- `api.lucien-sens-bon.com` → `IP_PUBLIQUE` +**Cas 3 — DNS public (arauco.online)** +Le DynDNS sync `*`, `@` et `git` pour `arauco.online`. Le wildcard `*` couvre tous +les sous-domaines, donc `lsb.arauco.online` et `api-lsb.arauco.online` résolvent +automatiquement vers l'IP publique. Pas besoin d'ajouter d'enregistrements. + +URLs publiques utilisées : +- `https://lsb.arauco.online` → storefront +- `https://api-lsb.arauco.online` → API Medusa **Bonnes pratiques** -- Utilisez les mêmes noms partout (DNS, Apache, variables d'environnement). -- Évitez les ports dans les URLs publiques (Apache s'en charge). +- Utilisez les mêmes noms partout (DNS, Caddy, variables d'environnement). +- Évitez les ports dans les URLs publiques (Caddy s'en charge). - Quand vous basculez en DNS public, mettez à jour `NEXT_PUBLIC_MEDUSA_BACKEND_URL`, - `ADMIN_CORS` et `STORE_CORS` dans `.env`, puis redémarrez les conteneurs. + `ADMIN_CORS` et `STORE_CORS` dans `.env`, puis rebuild le storefront. ### 1.3 DNS interne avec dnsmasq (araucaria) @@ -62,12 +66,26 @@ sudo nano /etc/dnsmasq.d/lsb.conf Contenu recommandé : ``` -# Lucien Sens Bon - ruka.lan -address=/www.lsb.huitral.ruka.lan/IP_DE_HUITRAL -address=/api.lsb.huitral.ruka.lan/IP_DE_HUITRAL -address=/admin.lsb.huitral.ruka.lan/IP_DE_HUITRAL +# Lucien Sens Bon - domaines publics +# Doivent pointer vers araucaria (Caddy) et non vers huitral directement, +# sinon les clients LAN contournent Caddy et tombent sur un port sans HTTPS. +address=/lsb.arauco.online/IP_DE_ARAUCARIA +address=/api-lsb.arauco.online/IP_DE_ARAUCARIA + +# Lucien Sens Bon - domaines internes ruka.lan +# Pointent aussi vers araucaria (Caddy gere le proxy HTTP pour ces domaines). +address=/lsb.huitral.ruka.lan/IP_DE_ARAUCARIA +address=/api-lsb.huitral.ruka.lan/IP_DE_ARAUCARIA ``` +Remplacez `IP_DE_ARAUCARIA` par l'IP LAN d'araucaria (ex: `192.168.99.50`). + +> **Important** : ne pas pointer les domaines `arauco.online` vers huitral +> directement. Depuis l'extérieur, le DynDNS résout vers l'IP publique qui +> arrive sur araucaria (Caddy). Depuis le LAN, dnsmasq doit aussi envoyer +> vers araucaria, sinon les navigateurs se connectent à huitral:443 où rien +> n'écoute → `CONNECTION_REFUSED`. + Rechargez dnsmasq : ```bash sudo systemctl restart dnsmasq @@ -76,8 +94,10 @@ sudo systemctl status dnsmasq --no-pager Tests rapides depuis un client : ```bash -dig +short www.lsb.huitral.ruka.lan -dig +short api.lsb.huitral.ruka.lan +dig +short lsb.arauco.online # doit retourner IP_DE_ARAUCARIA +dig +short api-lsb.arauco.online # doit retourner IP_DE_ARAUCARIA +dig +short lsb.huitral.ruka.lan # doit retourner IP_DE_ARAUCARIA +dig +short api-lsb.huitral.ruka.lan # doit retourner IP_DE_ARAUCARIA ``` ### 1.4 Procédure complète DNS (Windows + WSL) @@ -148,9 +168,9 @@ dig +short www.lsb.huitral.ruka.lan Exemple de valeurs utilisées dans ce projet (PostgreSQL sur `npagnun`) : ```ini DATABASE_URL=postgres://luciensbdb:VOTRE_MOT_DE_PASSE_DB@192.168.99.35:5432/sens_bon_db - NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://api.lucien-sens-bon.com - ADMIN_CORS=http://api.lucien-sens-bon.com - STORE_CORS=http://lucien-sens-bon.com + NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api-lsb.arauco.online + ADMIN_CORS=https://api-lsb.arauco.online,https://lsb.arauco.online,http://api-lsb.huitral.ruka.lan,http://lsb.huitral.ruka.lan + STORE_CORS=https://lsb.arauco.online,http://lsb.huitral.ruka.lan ``` Édition avec `vim` : @@ -244,59 +264,69 @@ Une fois les conteneurs démarrés, vous devez initialiser la base de données M ``` *(Remplacez l'email et le mot de passe par les vôtres).* -## 5. Configuration Apache (Reverse Proxy) +## 5. Configuration Caddy (Reverse Proxy sur araucaria) -Objectif : exposer proprement le site et l'API en HTTP/HTTPS via Apache, sans exposer les ports 8000/9000 aux utilisateurs. +Objectif : exposer proprement le site et l'API en HTTPS via Caddy sur `araucaria`, +sans exposer les ports 8000/9000 aux utilisateurs. -### 5.1 Créer le vhost Apache -1. **Copiez la configuration fournie** : - ```bash - sudo cp apache-vhost.conf /etc/apache2/sites-available/lucien.conf - ``` - *Le fichier définit 2 vhosts :* - - `www.lsb.huitral.ruka.lan` → storefront (port 8000) - - `api.lsb.huitral.ruka.lan` → backend Medusa (port 9000) +Architecture : +``` +Internet → araucaria (Caddy, HTTPS) → huitral (Docker containers) +LAN → araucaria (Caddy, HTTP) → huitral (Docker containers) +``` -2. **Vérifiez/ajustez les ServerName** selon vos DNS internes/publics. - Si vous n'avez pas encore de DNS, ajoutez temporairement dans `/etc/hosts` : - ``` - 127.0.0.1 www.lsb.huitral.ruka.lan - 127.0.0.1 api.lsb.huitral.ruka.lan - ``` +### 5.1 Éditer le Caddyfile sur araucaria -### 5.2 Activer les modules nécessaires -```bash -sudo a2enmod proxy -sudo a2enmod proxy_http -``` -*(optionnel mais recommandé si vous ajoutez du HTTPS plus tard : `headers`, `rewrite`)* -```bash -sudo a2enmod headers -sudo a2enmod rewrite +Sur `araucaria`, éditez `/etc/caddy/Caddyfile` et ajoutez : + +```caddyfile +# Lucien-sens-bon — acces public (HTTPS automatique) +lsb.arauco.online { + reverse_proxy IP_DE_HUITRAL:8000 +} + +api-lsb.arauco.online { + reverse_proxy IP_DE_HUITRAL:9000 +} + +# Lucien-sens-bon — acces LAN (HTTP, pas de certificat) +http://lsb.huitral.ruka.lan { + reverse_proxy IP_DE_HUITRAL:8000 +} + +http://api-lsb.huitral.ruka.lan { + reverse_proxy IP_DE_HUITRAL:9000 +} ``` -### 5.3 Activer le site et redémarrer Apache +Remplacez `IP_DE_HUITRAL` par l'IP LAN de huitral (ex: `192.168.99.22`). + +### 5.2 Recharger Caddy + ```bash -sudo a2ensite lucien.conf -sudo apache2ctl configtest -sudo service apache2 restart +sudo systemctl reload caddy +sudo systemctl status caddy ``` -### 5.4 Bénéfices de ce reverse proxy -- **URL propres** : accès en `http://www...` et `http://api...` sans ports. -- **Centralisation HTTPS** : un seul endroit pour gérer les certificats (Certbot). -- **Sécurité** : vous pouvez restreindre l'accès direct aux ports 8000/9000. -- **Logs clairs** : logs séparés pour storefront et API. +### 5.3 Bénéfices de ce reverse proxy +- **HTTPS automatique** : Caddy obtient et renouvelle les certificats Let's Encrypt. +- **URL propres** : accès en `https://lsb...` et `https://api-lsb...` sans ports. +- **Double accès** : public via `arauco.online`, local via `ruka.lan`. +- **Sécurité** : les ports 8000/9000 ne sont pas exposés directement. + +### 5.4 Vérification Caddy -### 5.5 Option HTTPS (recommandé en production) ```bash -sudo certbot --apache -d www.lsb.huitral.ruka.lan -d api.lsb.huitral.ruka.lan +# Sur araucaria +sudo systemctl status caddy +curl -I https://lsb.arauco.online +curl -I https://api-lsb.arauco.online/store/products ``` ## 6. Vérification -- **Storefront** : Accédez à `http://lucien-sens-bon.com` (ou votre domaine). Vous devriez voir la page d'accueil. -- **Admin** : Accédez à `http://api.lucien-sens-bon.com/app` (le dashboard admin est servi par le backend). Connectez-vous avec l'utilisateur créé à l'étape 4. +- **Storefront** : Accédez à `https://lsb.arauco.online` (ou `http://lsb.huitral.ruka.lan` en local). Vous devriez voir la page d'accueil. +- **Admin** : Accédez à `https://api-lsb.arauco.online/app` (le dashboard admin est servi par le backend). Connectez-vous avec l'utilisateur créé à l'étape 4. ## 7. Dépôt Git (Chillka) et déploiement sur Huitral diff --git a/app-management.md b/app-management.md index 8fcb3db..26ca251 100644 --- a/app-management.md +++ b/app-management.md @@ -1,7 +1,7 @@ # App management - Lucien-sens-bon Ce document explique comment diagnostiquer les conteneurs, la base de donnees -et le reverse proxy (Apache). +et le reverse proxy (Caddy sur araucaria). ## 1) Diagnostic Docker @@ -115,19 +115,29 @@ curl -v http://localhost:9000/store/products ### C.1) Test CORS (depuis le serveur) +Via le domaine public : +``` +curl -i -H "Origin: https://lsb.arauco.online" https://api-lsb.arauco.online/store/products +``` + +Via le LAN : +``` +curl -i -H "Origin: http://lsb.huitral.ruka.lan" http://api-lsb.huitral.ruka.lan/store/products +``` + +Via IP directe (sans reverse proxy) : ``` curl -i -H "Origin: http://192.168.99.22:8000" http://192.168.99.22:9000/store/products ``` - `-i` : affiche les en-tetes HTTP de la reponse (utile pour CORS). - `-H "Origin: ..."` : simule l'origine du navigateur (storefront). -- `http://192.168.99.22:9000/store/products` : endpoint backend teste. -- Attendu : `Access-Control-Allow-Origin: http://192.168.99.22:8000`. +- Attendu : `Access-Control-Allow-Origin` avec l'origine envoyee. Retour attendu (exemple) : ``` HTTP/1.1 200 OK -Access-Control-Allow-Origin: http://192.168.99.22:8000 +Access-Control-Allow-Origin: https://lsb.arauco.online Vary: Origin Access-Control-Allow-Credentials: true Content-Type: application/json; charset=utf-8 @@ -326,7 +336,7 @@ curl -v http://localhost:9000/store/products Verifier `NEXT_PUBLIC_MEDUSA_BACKEND_URL` dans `.env` : ``` -NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://api.lsb.huitral.ruka.lan +NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api-lsb.arauco.online ``` Puis reconstruire le storefront : @@ -334,56 +344,83 @@ Puis reconstruire le storefront : sudo docker compose up -d --build storefront ``` -Si on travaille en local (pas via Apache), utiliser l'URL directe : +Si on travaille en local (pas via Caddy), utiliser l'URL directe : ``` NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://:9000 ``` -## 4) Apache / Reverse proxy +## 4) Caddy / Reverse proxy (sur araucaria) + +Le reverse proxy est gere par Caddy sur `araucaria`, pas sur `huitral`. -Verifier les services Apache : +Verifier le service Caddy (sur araucaria) : ``` -sudo systemctl status apache2 +sudo systemctl status caddy ``` -Logs Apache : +Logs Caddy : ``` -sudo journalctl -u apache2 -f -sudo tail -f /var/log/apache2/error.log -sudo tail -f /var/log/apache2/access.log +sudo journalctl -u caddy -f +sudo journalctl -u caddy -n 200 --no-pager ``` -Modules proxy : +Editer le Caddyfile : ``` -sudo a2enmod proxy -sudo a2enmod proxy_http +sudo nano /etc/caddy/Caddyfile ``` -Reload Apache : +Valider et recharger : ``` -sudo systemctl reload apache2 +caddy validate --config /etc/caddy/Caddyfile +sudo systemctl reload caddy ``` -Documentation Apache reverse proxy : -https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html +Documentation Caddy : +https://caddyserver.com/docs/caddyfile/directives/reverse_proxy ## 5) Ports a verifier -- `8000` : storefront -- `9000` : backend +- `8000` : storefront (huitral) +- `9000` : backend (huitral) - `5432` : PostgreSQL - `6379` : Redis +- `80/443` : Caddy (araucaria) -Verifier l'ouverture locale : +Verifier l'ouverture sur huitral : ``` ss -lntp | egrep '8000|9000|5432|6379' ``` +Verifier Caddy sur araucaria : +``` +ss -lntp | grep caddy +``` + Verifier le firewall (UFW) : ``` sudo ufw status ``` +## 5.1) DNS LAN (piege courant) + +Si le site est accessible depuis l'exterieur mais pas depuis le LAN, +verifier la resolution DNS : +``` +dig +short lsb.arauco.online +dig +short api-lsb.arauco.online +``` + +Les deux doivent retourner l'IP d'**araucaria** (ex: `192.168.99.50`), +pas celle de huitral. Si dnsmasq renvoie l'IP de huitral, les navigateurs +se connectent directement a huitral:443 ou rien n'ecoute → `CONNECTION_REFUSED`. + +Corriger dans `/etc/dnsmasq.d/lsb.conf` sur araucaria : +``` +address=/lsb.arauco.online/192.168.99.50 +address=/api-lsb.arauco.online/192.168.99.50 +``` +Puis `sudo systemctl restart dnsmasq`. + ## 6) Git - Remise en ordre apres modifications locales Cette section documente les commandes utilisees pour remettre la branche locale diff --git a/backend/data/products-import.csv b/backend/data/products-import.csv index 29c61c8..5321a92 100644 --- a/backend/data/products-import.csv +++ b/backend/data/products-import.csv @@ -1,2 +1,11 @@ -external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory -prod-001,Savon Lavande,savon-lavande,"Savon artisanal a la lavande.",https://via.placeholder.com/600x600.png?text=Savon+Lavande,Taille,100g,100g,SKU-SAV-100,650,eur,100,true +external_id,title,handle,description,thumbnail,option_title,option_value,variant_title,variant_sku,price_amount,currency_code,inventory_quantity,manage_inventory,volume,type_meche,parfum,couleur,type_cire +prod-001,Bougie Lavande Classique,bougie-lavande-classique,"Bougie artisanale a la lavande, cire de soja naturelle.",,Taille,200ml,200ml,SKU-BOU-LAV-200,1200,eur,50,true,200ml,coton,lavande,blanche,soja +prod-002,Bougie Vanille Boisee,bougie-vanille-boisee,"Notes chaudes de vanille et bois de santal.",,Taille,150ml,150ml,SKU-BOU-VAN-150,950,eur,40,true,150ml,bois,vanille,creme,soja +prod-003,Bougie Fleur d'Oranger,bougie-fleur-oranger,"Parfum delicat de fleur d'oranger mediterraneenne.",,Taille,300ml,300ml,SKU-BOU-FLO-300,1800,eur,30,true,300ml,coton,fleur d'oranger,orange,colza +prod-004,Bougie Cedre & Mousse,bougie-cedre-mousse,"Ambiance forestiere avec des notes de cedre et de mousse.",,Taille,200ml,200ml,SKU-BOU-CED-200,1400,eur,25,true,200ml,bois,cedre et mousse,verte,soja +prod-005,Bougie Cannelle Epices,bougie-cannelle-epices,"Melange epice de cannelle, girofle et muscade.",,Taille,150ml,150ml,SKU-BOU-CAN-150,1050,eur,35,true,150ml,coton,cannelle epices,rouge,abeille +prod-006,Bougie Rose Ancienne,bougie-rose-ancienne,"Senteur classique de rose de Grasse.",,Taille,200ml,200ml,SKU-BOU-ROS-200,1500,eur,20,true,200ml,coton,rose,rose,soja +prod-007,Bougie Ambre Oriental,bougie-ambre-oriental,"Notes profondes d'ambre, oud et resine.",,Taille,500ml,500ml,SKU-BOU-AMB-500,2800,eur,15,true,500ml,bois,ambre oriental,doree,colza +prod-008,Bougie Citron Basilic,bougie-citron-basilic,"Fraicheur mediterraneenne, citron et basilic.",,Taille,150ml,150ml,SKU-BOU-CIT-150,900,eur,45,true,150ml,coton,citron basilic,jaune,soja +prod-009,Bougie Figue Sauvage,bougie-figue-sauvage,"Douceur sucree de la figue de Provence.",,Taille,300ml,300ml,SKU-BOU-FIG-300,1700,eur,20,true,300ml,bois,figue sauvage,violette,colza +prod-010,Bougie Bois de Oud,bougie-bois-de-oud,"Oud rare et precieux, intensite boisee.",,Taille,200ml,200ml,SKU-BOU-OUD-200,2200,eur,10,true,200ml,bois,oud,noire,abeille diff --git a/backend/scripts/import-products.js b/backend/scripts/import-products.js index 04b24aa..bd0db24 100644 --- a/backend/scripts/import-products.js +++ b/backend/scripts/import-products.js @@ -75,6 +75,14 @@ class CsvProductImporter { return ["true", "1", "yes", "y"].includes(normalized); }; + const metadata = {}; + const metadataFields = ["volume", "type_meche", "parfum", "couleur", "type_cire"]; + for (const field of metadataFields) { + if (row[field] && row[field].trim()) { + metadata[field] = row[field].trim(); + } + } + return { external_id: row.external_id || "", title: row.title || "", @@ -89,6 +97,7 @@ class CsvProductImporter { currency_code: row.currency_code || this.defaultCurrency, inventory_quantity: Number.parseInt(row.inventory_quantity, 10) || 0, manage_inventory: toBool(row.manage_inventory, true), + metadata, }; } @@ -129,6 +138,7 @@ class CsvProductImporter { handle: row.handle, description: row.description, thumbnail: row.thumbnail || undefined, + metadata: Object.keys(row.metadata).length > 0 ? row.metadata : undefined, options: [{ title: row.option_title }], variants: [variant], }); diff --git a/env-example b/env-example index c8e63b7..64d329a 100644 --- a/env-example +++ b/env-example @@ -14,18 +14,22 @@ COOKIE_SECRET=supersecret # -------------------------------------------------------- # CONFIGURATION DES URLS -# Pour la production, mettez vos vrais domaines (ex: https://api.monsite.com) +# Production : domaines publics via Caddy (araucaria) +# Local : domaines internes ruka.lan # -------------------------------------------------------- -# URL du Backend (API) accessible par le navigateur -NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://api.lsb.huitral.ruka.lan +# URL du Backend (API) accessible par le navigateur (une seule URL, injectée au build) +# Production : +NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api-lsb.arauco.online +# Local uniquement : +# NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://api-lsb.huitral.ruka.lan # CORS Admin : Quels domaines peuvent accéder à l'admin ? -ADMIN_CORS=http://api.lsb.huitral.ruka.lan +# Lister toutes les origines (public + local) +ADMIN_CORS=https://api-lsb.arauco.online,https://lsb.arauco.online,http://api-lsb.huitral.ruka.lan,http://lsb.huitral.ruka.lan # CORS Store : Quels domaines (le frontend) peuvent accéder à l'API ? -# En production, ce sera https://monsite.com -STORE_CORS=http://www.lsb.huitral.ruka.lan +STORE_CORS=https://lsb.arauco.online,http://lsb.huitral.ruka.lan # -------------------------------------------------------- # PAIEMENTS (Optionnel) diff --git a/helper-cmd.md b/helper-cmd.md index 7edef87..9b87ea2 100644 --- a/helper-cmd.md +++ b/helper-cmd.md @@ -282,9 +282,13 @@ curl http://localhost:8000 - `curl -I http://localhost:8000` ### 4.3 Test CORS -**Commande** +**Commande (public)** +``` +curl -i -H "Origin: https://lsb.arauco.online" https://api-lsb.arauco.online/store/products +``` +**Commande (LAN)** ``` -curl -i -H "Origin: http://:8000" http://:9000/store/products +curl -i -H "Origin: http://lsb.huitral.ruka.lan" http://api-lsb.huitral.ruka.lan/store/products ``` **Paramètres** - `-i` : inclut les en-têtes. @@ -294,62 +298,50 @@ curl -i -H "Origin: http://:8000" http://:9000/store/products - `curl -v ...` - DevTools navigateur (onglet Network). -## 5. Apache / Reverse proxy +## 5. Caddy / Reverse proxy (sur araucaria) -### 5.1 Statut Apache +Le reverse proxy est géré par Caddy sur `araucaria`, pas sur `huitral`. + +### 5.1 Statut Caddy **Commande** ``` -sudo systemctl status apache2 +sudo systemctl status caddy ``` -**Alternatives** -- `sudo service apache2 status` -### 5.2 Logs Apache +### 5.2 Logs Caddy **Commandes** ``` -sudo journalctl -u apache2 -f -sudo tail -f /var/log/apache2/error.log -sudo tail -f /var/log/apache2/access.log +sudo journalctl -u caddy -f +sudo journalctl -u caddy -n 200 --no-pager ``` **Paramètres** - `-f` : suivi temps réel. -**Alternatives** -- `journalctl -u apache2 -n 200 --no-pager` +### 5.3 Éditer le Caddyfile +**Commande** +``` +sudo nano /etc/caddy/Caddyfile +``` -### 5.3 Modules proxy -**Commandes** +### 5.4 Valider la config +**Commande** ``` -sudo a2enmod proxy -sudo a2enmod proxy_http +caddy validate --config /etc/caddy/Caddyfile ``` **Explication** -- active les modules de reverse proxy. +- vérifie la syntaxe avant rechargement. -**Alternatives** -- `a2enmod headers` -- `a2enmod rewrite` - -### 5.4 Reload Apache +### 5.5 Reload Caddy **Commande** ``` -sudo systemctl reload apache2 +sudo systemctl reload caddy ``` **Explication** - recharge la config sans couper les connexions actives. **Alternatives** -- `sudo service apache2 restart` - -### 5.5 Activer un vhost -**Commandes** -``` -sudo a2ensite lucien.conf -sudo apache2ctl configtest -sudo service apache2 restart -``` -**Paramètres** -- `configtest` : vérifie la syntaxe avant redémarrage. +- `sudo systemctl restart caddy` +- `caddy reload --config /etc/caddy/Caddyfile` ## 6. DNS / Résolution (Windows + Linux) diff --git a/storefront/pages/index.js b/storefront/pages/index.js index dda2a6d..43ebeb7 100644 --- a/storefront/pages/index.js +++ b/storefront/pages/index.js @@ -4,6 +4,31 @@ import { medusaClient } from "../lib/medusa-client" import { ensureCart } from "../lib/storefront" import { formatAmount } from "../lib/format" +const METADATA_LABELS = { + volume: "Volume", + type_meche: "Mèche", + parfum: "Parfum", + couleur: "Couleur", + type_cire: "Cire", +} + +function ProductAttributes({ metadata }) { + if (!metadata) return null + const entries = Object.entries(METADATA_LABELS) + .filter(([key]) => metadata[key]) + .map(([key, label]) => ({ label, value: metadata[key] })) + if (entries.length === 0) return null + return ( +
    + {entries.map(({ label, value }) => ( +
  • + {label}: {value} +
  • + ))} +
+ ) +} + export default function Home() { const { products, isLoading } = useProducts() const [status, setStatus] = useState("") @@ -44,6 +69,7 @@ export default function Home() {

{product.title}

{product.description}

+

{formatAmount( product?.variants?.[0]?.prices?.[0]?.amount, -- cgit v1.2.3