# Gigafibre — Infrastructure & Services > Document de référence pour l'infrastructure complète. Sert de guide de transfert pour toute personne reprenant l'environnement. ## Vue d'ensemble ``` Internet │ ▼ 96.125.196.67 (Proxmox VM, Ubuntu 24.04) │ ├─ Traefik v2.11 (ports 80/443) │ ├─ Let's Encrypt TLS auto-renew │ ├─ ForwardAuth middleware → Authentik │ └─ Routes → Docker containers │ ├─ Authentik SSO (auth.targo.ca) │ └─ ForwardAuth pour toutes les apps protégées │ ├─ ERPNext v16.10.1 (erp.gigafibre.ca) │ ├─ 9 containers (frontend, backend, worker, scheduler, redis, postgres) │ └─ Custom doctypes: Dispatch + FSM │ ├─ Dispatch PWA (dispatch.gigafibre.ca) │ ├─ nginx servant les fichiers statiques Vue/Quasar │ └─ Proxy /api/ → ERPNext, /traccar/ → Traccar │ ├─ n8n (n8n.gigafibre.ca) │ ├─ Auto-login proxy (lit X-authentik-email de forwardAuth) │ └─ Workflows: SMS routing, sharing, automation │ ├─ Gitea (git.gigafibre.ca / git.targo.ca) │ ├─ www.gigafibre.ca │ ├─ React/Vite site vitrine │ └─ API Node.js (recherche adresses, contact, SMS) │ ├─ Oktopus CE (oss.gigafibre.ca) — TR-069 CPE management │ └─ Hub (hub.gigafibre.ca) — Dashboard interne ``` ## DNS (Cloudflare) Domaine `gigafibre.ca` géré sur Cloudflare en mode **DNS-only** (pas de proxy CF, Traefik gère le TLS). | Record | Type | Valeur | Notes | |--------|------|--------|-------| | `@` | A | 96.125.196.67 | | | `*.gigafibre.ca` | A | 96.125.196.67 | Wildcard | | `@` | MX | aspmx.l.google.com (10) | Google Workspace | | `@` | MX | alt1-4.aspmx.l.google.com | | | `@` | TXT | v=spf1 include:spf.mailjet.com include:_spf.google.com ~all | | | `mailjet._748826c7` | TXT | 748826c702abf9015ac2e8a202336527 | DKIM Mailjet | Domaine `targo.ca` encore sur OpenSRS (migration Cloudflare planifiée). ## Reverse Proxy (Traefik) **Emplacement serveur:** `/opt/traefik/` - Version: v2.11 (ne pas upgrader à v3 — incompatible Docker 29, API v1.24 vs v1.40) - TLS: Let's Encrypt HTTP-01 challenge - Réseau Docker: `proxy` (tous les containers exposés doivent y être) ### Middleware Authentik ```yaml # /opt/traefik/dynamic/routes.yml http: middlewares: authentik: forwardAuth: address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik trustForwardHeader: true authResponseHeaders: - X-authentik-username - X-authentik-email - X-authentik-name ``` **Gotcha:** Le redirect HTTP→HTTPS ne doit pas intercepter `/.well-known/acme-challenge/` sinon Let's Encrypt échoue. ## Authentik SSO **URL:** https://auth.targo.ca ### Flux d'authentification ``` Utilisateur → app.gigafibre.ca → Traefik vérifie session via forwardAuth → Pas de session? → Redirect auth.targo.ca/flows/authorize/ → Login (username/password ou SSO) → Callback → Cookie session set → App charge ``` ### Applications configurées | App | Type | Status | |-----|------|--------| | dispatch.gigafibre.ca | ForwardAuth (Traefik) | Actif | | n8n.gigafibre.ca | ForwardAuth + auto-login proxy | Actif | | hub.gigafibre.ca | ForwardAuth (Traefik) | Actif | | erp.gigafibre.ca | OAuth2/OIDC (Provider) | En place | ### n8n auto-login (workaround) n8n Community Edition ne supporte pas OIDC. Solution : - Proxy Node.js (`/opt/n8n-proxy/server.js`) devant n8n - Lit le header `X-authentik-email` injecté par forwardAuth - Crée une session n8n via `POST /api/v1/login` avec owner credentials - Forward le cookie de session au navigateur ## ERPNext **URL:** https://erp.gigafibre.ca **Compose:** `/opt/erpnext/` **DB:** PostgreSQL, base `_eb65bdc0c4b1b2d6` ### Token API (service token) ``` b273a666c86d2d0:613842e506d13b8 ``` Utilisé par le Dispatch PWA pour les appels API côté serveur (pas de session utilisateur — Authentik gère l'auth frontend, le token fixe gère l'auth API). **Gotcha:** Ne jamais appeler `generate_keys` sur l'utilisateur Administrator — ça invalide le token existant. ### Doctypes personnalisés (module: Dispatch) **Core:** - `Dispatch Job` — Ordres de travail (SUP-#####) - `Dispatch Technician` — Profils techniciens + GPS - `Dispatch Tag` — Catégorisation **FSM (extension):** - `Service Location` (LOC-#####) — Locaux client - `Service Equipment` (EQP-#####) — ONT, routeur, etc. - `Service Subscription` (SUB-#####) — Forfaits actifs - `Checklist Template` — Templates réutilisables **Tables enfants:** Equipment Move Log, Job Equipment Item, Job Material Used, Job Checklist Item, Job Photo, Checklist Template Item, Dispatch Job Assistant, Dispatch Tag Link ### Patch appliqué `number_card.py` — ERPNext v16 PostgreSQL: `ORDER BY creation` sur queries agrégées cause erreur. Corrigé avec `order_by=""`. ## Dispatch PWA **URL:** https://dispatch.gigafibre.ca **Repo:** `git.targo.ca/louis/OSS-BSS-Field-Dispatch` **Stack:** Vue 3 / Quasar / Pinia / Mapbox GL JS ### Architecture du code ``` src/ App.vue — Router view + auth check au mount api/ auth.js — Service token, détection expiry Authentik dispatch.js — CRUD ERPNext (authFetch) traccar.js — GPS REST + WebSocket stores/ dispatch.js — Store principal: jobs, techs, GPS auth.js — Session check (simplifié, Authentik gère) pages/ DispatchV2Page.vue — Page principale (~1500 lignes) composables/ useMap.js — Carte Mapbox, marqueurs SVG progress ring useScheduler.js — Algorithme timeline useDragDrop.js — Drag & drop avec batch useSelection.js — Lasso, multi-select useAutoDispatch.js — Auto-distribute + route optimize useBottomPanel.js — Panel jobs non-assignés useUndo.js — Undo stack groupé config/ erpnext.js — BASE_URL (vide en prod = same-origin) ``` ### GPS Tracking - **Traccar** sur `tracker.targointernet.com:8082` - Proxy nginx: `dispatch.gigafibre.ca/traccar/api/*` → Traccar - **Hybride REST + WebSocket:** REST initial → WebSocket real-time → fallback polling 30s - Guards module-level (`__gpsStarted`, `__gpsPolling`) pour survivre au remount Vue ### Build & Deploy ```bash cd dispatch-app DEPLOY_BASE=/ npx quasar build -m pwa tar czf /tmp/dispatch-pwa.tar.gz -C dist/pwa . cat /tmp/dispatch-pwa.tar.gz | ssh -i ~/.ssh/proxmox_vm root@96.125.196.67 \ 'rm -rf /opt/dispatch-app/*.js /opt/dispatch-app/*.html /opt/dispatch-app/*.json /opt/dispatch-app/assets /opt/dispatch-app/icons; cat > /tmp/d.tar.gz && cd /opt/dispatch-app && tar xzf /tmp/d.tar.gz && rm /tmp/d.tar.gz' ``` ### nginx config `/opt/dispatch-app/nginx.conf`: - SPA fallback: `try_files $uri /index.html` - Proxy `/api/` → `erpnext-frontend-1:8080` (Docker DNS) - Proxy `/traccar/` → `tracker.targointernet.com:8082` - No-cache sur `index.html` et `sw.js` (éviter caching stale) - Réseau partagé: container dans `erpnext_erpnext` network + `resolver 127.0.0.11` ## Site web (www.gigafibre.ca) **Repo:** `git.targo.ca/louis/site-web-targo` **Stack:** React / Vite / Tailwind / shadcn-ui **Origine:** lovable.dev (modifié) ### API backend `/opt/www-api/server.js` — Node.js Express: | Endpoint | Fonction | |----------|----------| | `POST /rpc/search_addresses` | Recherche fuzzy 5.2M adresses québécoises | | `POST /rpc/contact` | Formulaire contact → email Mailjet | | `POST /rpc/lead` | Qualification adresse → email Mailjet | | `POST /rpc/sms` | Envoi SMS Twilio | | `POST /rpc/sms-incoming` | Webhook Twilio entrant → email Mailjet | ### Base de données adresses (RQA) - Table `rqa_addresses`: 5.2M lignes (Répertoire Québécois des Adresses) - Table `fiber_availability`: 21,623 entrées (matching numero + code_postal) - Recherche 3 phases: exact → fuzzy pg_trgm → J0S/J0L priority - PostgreSQL dans le compose ERPNext (même instance DB) ## Email (Mailjet) **Expéditeur:** `noreply@targo.ca` (Name: Gigafibre) ### Flux ``` Contact form (www) → /rpc/contact → Mailjet API → support@targo.ca Lead capture (www) → /rpc/lead → Mailjet API → louis@targo.ca SMS entrant (Twilio) → webhook → Mailjet API → louis@targo.ca ``` ### DNS requis (targo.ca) - SPF: `v=spf1 include:spf.mailjet.com include:_spf.google.com ~all` - DKIM: `mailjet._748826c7.targo.ca` → valeur Mailjet - **Status:** SPF/DKIM pour targo.ca en erreur côté Mailjet (à corriger) ## SMS (Twilio) **Numéro:** +1 (438) 231-3838 **SID:** ACddff61c2e272ddc4a94586fa7b68e90e **Status:** Compte trial (SMS limité aux numéros vérifiés) ### Flux ``` Envoi: App → /rpc/sms → Twilio API → Destinataire Réception: Twilio → webhook POST → n8n.gigafibre.ca/webhook/sms-incoming → Forward vers www.gigafibre.ca/rpc/sms-incoming → Email Mailjet ``` **À faire:** - Upgrader vers compte Twilio production - Configurer 10DLC ou acheter numéro Toll-Free - Changer webhook vers n8n directement une fois workflow activé ## n8n Workflows **URL:** https://n8n.gigafibre.ca **Compose:** Dans `/opt/erpnext/` (override n8n) ### Workflows créés | Nom | ID | Fonction | Status | |-----|-----|----------|--------| | [System] Share all workflows | MC5CxJ6QD2s8OCrr | Partage workflows/credentials entre projets (SQLite) | À activer via UI | | SMS Incoming → Email + Router | j8lC0f6aHrV9L5Ud | Webhook Twilio → forward API | À activer via UI | **Gotcha:** L'activation via API (`POST /activate`) ne registre pas les webhooks dans n8n 2.x — toujours activer via le toggle UI. **Gotcha:** Le node `executeCommand` n'existe pas dans n8n 2.x — utiliser `n8n-nodes-base.code` avec `require('child_process')`. ## Repos Git (git.targo.ca) | Repo | Contenu | |------|---------| | `louis/OSS-BSS-Field-Dispatch` | Dispatch PWA (Vue/Quasar) | | `louis/site-web-targo` | www.gigafibre.ca (React/Vite) | | `louis/gigafibre-fsm` | Docs architecture, scripts setup FSM | | `louis/gigafibre-infra` | Configs serveur (traefik, docker-compose) | ## Docker — Réseaux et Compose ### Fichiers compose sur le serveur | Emplacement | Services | |-------------|----------| | `/opt/traefik/docker-compose.yml` | Traefik | | `/opt/erpnext/compose.yaml` | ERPNext (9 containers) | | `/opt/erpnext/overrides/compose.n8n.yaml` | n8n + auto-login proxy | | `/opt/apps/docker-compose.yml` | Gitea + dispatch-frontend + targo-db | | `/opt/oktopus/docker-compose.yml` | Oktopus CE (8 containers) | | `/opt/www-api/docker-compose.yml` | API www.gigafibre.ca | ### Réseaux Docker | Réseau | Usage | |--------|-------| | `proxy` | Traefik ↔ tous les containers exposés | | `erpnext_erpnext` | ERPNext interne + dispatch nginx (pour proxy /api/) | **Gotcha:** Containers multi-réseaux → label `traefik.docker.network=proxy` obligatoire. ## Gotchas & Pièges 1. **Traefik v3 incompatible** avec Docker 29 (API v1.24 vs v1.40) — rester sur v2.11 2. **HTTP→HTTPS redirect** ne doit pas intercepter ACME challenge 3. **MongoDB 5+** nécessite AVX — CPU Proxmox doit être type "host" 4. **netplan** override systemd-networkd — supprimer `netplan.io` 5. **DEPLOY_BASE=/** requis pour `quasar build` en déploiement root domain 6. **nginx SPA** fallback: `try_files $uri /index.html` 7. **ERPNext generate_keys** invalide le token existant — ne jamais appeler 8. **Mixed content HTTPS→HTTP** — toujours utiliser proxy pour Traccar 9. **Service Worker cache** — headers no-cache sur index.html et sw.js 10. **Traccar API** ne supporte qu'un seul `deviceId` par requête — parallel calls ## Accès serveur ```bash # SSH ssh -i ~/.ssh/proxmox_vm root@96.125.196.67 # Logs Traefik docker logs -f traefik # Logs ERPNext cd /opt/erpnext && docker compose logs -f backend # Logs n8n cd /opt/erpnext && docker compose -f compose.yaml -f overrides/compose.n8n.yaml logs -f n8n # Restart dispatch nginx docker restart dispatch-frontend # Rebuild dispatch # (voir section Build & Deploy ci-haut) ``` ## Tâches en cours - [ ] Activer les 2 workflows n8n via UI toggle - [ ] Twilio: upgrade production + 10DLC - [ ] Corriger SPF/DKIM targo.ca dans Mailjet - [ ] Google Workspace: ajouter gigafibre.ca comme domaine alias - [ ] FSM Phase 2: customer/location picker, equipment scan, checklist UI - [ ] Portail client self-service sur www.gigafibre.ca - [ ] Pousser frappe_docker mods sur gitea