# Guide de Deploiement - Wordly.art (Homelab) > NPM + IONOS + Docker + Stripe + API Keys + NAS Backup + Monitoring --- ## Architecture ``` Internet | | DNS IONOS: wordly.art -> IP fixe | [Routeur/Box] (port forwarding 80+443 -> machine NPM) | +-- Machine 1: Nginx Proxy Manager (NPM) | - SSL Let's Encrypt auto | - Reverse proxy | +-- Machine 2/3: Docker (192.168.1.151) | +-- wordly-backend (FastAPI :8000) +-- wordly-frontend (Next.js :3000) +-- wordly-postgres (PostgreSQL :5432) +-- wordly-redis (Redis :6379) +-- wordly-prometheus (:9090 interne) +-- wordly-grafana (:3001) +-- wordly-node-exporter + cadvisor | +-- Backup quotidien -> NAS ``` --- ## Etape 1 : DNS IONOS 1. Se connecter sur **ionos.fr** > **Domaines & SSL** > **wordly.art** > **DNS** 2. Modifier les enregistrements **A** existants : | Type | Nom (hote) | Valeur | Attention | |------|-----------|--------|-----------| | **A** | *(vide ou @)* | Ton IP fixe | Pas dans "Sous-domaines", dans DNS principal | | **A** | `www` | Ton IP fixe | Dans Sous-domaines, taper juste `www` | | **A** | `monitoring` | Ton IP fixe | Dans Sous-domaines, taper juste `monitoring` | > Ton IP fixe : ouvre https://api.ipify.org depuis ton reseau Ne **pas** toucher aux lignes Mail (MX, SPF, DKIM, autodiscover). Verifier apres 10 min : ```bash nslookup wordly.art ``` --- ## Etape 2 : Port forwarding + NPM ### 2.1 Routeur : ouvrir les ports Sur ton routeur/box (souvent `192.168.1.1`) : | Port externe | Port interne | IP destination | |-------------|-------------|---------------| | **80** | 80 | IP de la machine NPM | | **443** | 443 | IP de la machine NPM | ### 2.2 NPM : creer les Proxy Hosts Interface NPM : **http://IP_NPM:81** #### Proxy Host 1 : wordly.art **Details :** - Domain Names : `wordly.art` - Scheme : `http` - Forward Hostname/IP : `192.168.1.151` (IP du serveur Wordly) - Forward Port : `3000` - Cocher Block Common Exploits + Websockets **SSL :** - Request a new SSL Certificate - Cocher Force SSL + HTTP/2 + HSTS - Email : `admin@wordly.art` **Advanced** - coller cette config nginx : ```nginx location /api/ { proxy_pass http://192.168.1.151:8000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Connection ""; proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; add_header Access-Control-Allow-Origin https://wordly.art always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With, X-API-Key" always; add_header Access-Control-Allow-Credentials "true" always; if ($request_method = 'OPTIONS') { return 204; } } location /translate { proxy_pass http://192.168.1.151:8000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_send_timeout 600s; proxy_read_timeout 600s; client_max_body_size 100M; } location /health { proxy_pass http://192.168.1.151:8000; proxy_http_version 1.1; proxy_set_header Connection ""; } location /docs { proxy_pass http://192.168.1.151:8000; proxy_set_header Host $host; } location /redoc { proxy_pass http://192.168.1.151:8000; proxy_set_header Host $host; } location /openapi.json { proxy_pass http://192.168.1.151:8000; proxy_set_header Host $host; } location /admin { proxy_pass http://192.168.1.151:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /_next/static/ { proxy_pass http://192.168.1.151:3000; add_header Cache-Control "public, max-age=31536000, immutable"; } ``` > Si NPM et Wordly sont sur la meme machine Docker, remplace `192.168.1.151:8000` par `wordly-backend:8000` etc. #### Proxy Host 2 : www.wordly.art Meme config, meme certificat SSL. Dans Advanced, ajoute : ```nginx return 301 https://wordly.art$request_uri; ``` #### Proxy Host 3 : monitoring.wordly.art - Forward : `192.168.1.151:3001` - SSL Let's Encrypt --- ## Etape 3 : Serveur Docker (192.168.1.151) ### 3.1 Installer Docker ```bash curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER newgrp docker ``` ### 3.2 Cloner le projet ```bash git clone -b production-deployment https://gitea.parsanet.org/sepehr/office_translator.git /opt/wordly cd /opt/wordly ``` ### 3.3 Configurer le .env avec le wizard ```bash bash scripts/setup-env.sh ``` Le wizard demande le domaine, le mot de passe admin, le service de traduction, et genere tous les secrets automatiquement. Ou configurer manuellement : ```bash cp .env.production .env nano .env ``` ### 3.4 Lancer l'application ```bash docker compose up -d --build docker compose ps # Verifier que tout est "Up (healthy)" curl http://localhost:8000/health ``` --- ## Etape 4 : Cles API - Services de traduction L'application supporte **7 providers de traduction**. Tu n'es pas oblige de tous les configurer - commence avec 1 ou 2. ### Gerer les cles ```bash cd /opt/wordly bash scripts/manage-keys.sh ``` Menu interactif pour ajouter/modifier/supprimer des cles API. ### Ou trouver les cles | Provider | URL d'inscription | Cle a recuperer | Cout | |----------|-------------------|-----------------|------| | **Google** | Aucune inscription | Aucune cle (gratuit via deep_translator) | Gratuit | | **DeepL** | https://www.deepl.com/pro-api | Clé API DeepL (format: `xxx-xxx-...`) | Gratuit 500k car/mois, puis 5.49EUR/mois | | **OpenAI** | https://platform.openai.com/api-keys | `sk-...` | ~0.15$/1000 traductions | | **DeepSeek** | https://platform.deepseek.com/api_keys | `sk-...` | ~0.14$/M tokens (tres bon rapport Q/P) | | **Minimax** | https://platform.minimaxi.com/ | Cle API | Variable | | **OpenRouter** | https://openrouter.ai/keys | `sk-or-...` | Multi-modeles, pay-per-use | ### Activer un provider dans le .env Exemple pour DeepSeek : ```bash # Dans le .env DEEPSEEK_ENABLED=true DEEPSEEK_API_KEY=sk-votre-cle-ici DEEPSEEK_MODEL=deepseek-chat DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 ``` Puis `docker compose restart backend`. ### Recommandation pour demarrer 1. **Google** (active par defaut, gratuit, aucune cle) 2. **DeepSeek** (ajouter quand tu veux meilleure qualite, tres peu cher) --- ## Etape 5 : Stripe - Systeme de paiement Stripe gere les abonnements (Starter, Pro, Business). Si tu ne configures pas Stripe, l'app fonctionne en mode gratuit sans limitation d'abonnement. ### 5.1 Creer un compte Stripe 1. Aller sur **https://dashboard.stripe.com/register** 2. Creer un compte avec ton email 3. Activer le compte (verifie identite + banque pour recevoir les paiements) ### 5.2 Recuperer les cles Stripe Dans le dashboard Stripe : **Developers** > **API keys** | Cle | Nom dans .env | Description | |-----|---------------|-------------| | `sk_test_...` ou `sk_live_...` | `STRIPE_SECRET_KEY` | Cle secrete (attention: NE PAS utiliser la cle publique `pk_...`) | | `whsec_...` | `STRIPE_WEBHOOK_SECRET` | Cle du webhook (voir section 5.4) | > **Test vs Live** : commence en mode test (`sk_test_...`), passe en live quand tout fonctionne. ### 5.3 Creer les produits et forfaits Dans Stripe : **Products** > **Add product** Cree 3 produits : **Produit 1 : Starter** - Name : `Starter` - Price : `9.00 EUR` / Monthly (recurring) - Une fois cree, clique sur le prix et copie le **Price ID** (`price_...`) **Produit 2 : Pro** - Name : `Pro` - Price : `19.00 EUR` / Monthly **Produit 3 : Business** - Name : `Business` - Price : `49.00 EUR` / Monthly Copie les 3 Price IDs. ### 5.4 Configurer le Webhook Stripe Le webhook permet a Stripe de notifier ton app quand un paiement reussit, un abonnement est annule, etc. Dans Stripe : **Developers** > **Webhooks** > **Add endpoint** - **Endpoint URL** : `https://wordly.art/api/v1/stripe/webhook` - **Events a ecouter** (cliquer "Select events") : - `checkout.session.completed` - `customer.subscription.updated` - `customer.subscription.deleted` - `invoice.payment_succeeded` - `invoice.payment_failed` Une fois le webhook cree, clique dessus et copie le **Signing secret** (`whsec_...`). ### 5.5 Ajouter les cles Stripe dans le .env ```bash cd /opt/wordly bash scripts/manage-keys.sh # Choisir option 4 (Stripe) ``` Ou manuellement dans `.env` : ```bash STRIPE_SECRET_KEY=sk_live_votre_cle_secrete STRIPE_WEBHOOK_SECRET=whsec_votre_signing_secret STRIPE_STARTER_PRICE_ID=price_votre_price_id_starter STRIPE_PRO_PRICE_ID=price_votre_price_id_pro STRIPE_BUSINESS_PRICE_ID=price_votre_price_id_business ``` Puis `docker compose restart backend`. ### 5.6 Tester Stripe en mode test 1. Utilise `sk_test_...` comme STRIPE_SECRET_KEY 2. Cree des produits en mode test (meme process) 3. Pour tester un paiement, Stripe fournit des cartes test : - **Succes** : `4242 4242 4242 4242` - **Echec** : `4000 0000 0000 0002` - Exp : n'importe quelle date future - CVC : n'importe quel nombre 4. Verifie dans Stripe Dashboard > Payments que les paiements apparaissent ### 5.7 Passer en production Quand tout fonctionne en test : 1. Dans Stripe Dashboard, clique **"Activate your account"** en haut a gauche 2. Remplie les infos business (identite, banque) 3. Change dans le .env : `sk_test_...` -> `sk_live_...` 4. Refais les webhooks et produits en mode live 5. `docker compose restart backend` ### 5.8 Checklist Stripe - [ ] Compte Stripe cree et verifie - [ ] 3 produits crees (Starter 9EUR, Pro 19EUR, Business 49EUR) - [ ] 3 Price IDs copies - [ ] STRIPE_SECRET_KEY configure - [ ] Webhook configure avec les 5 events - [ ] STRIPE_WEBHOOK_SECRET configure - [ ] 3 STRIPE_*_PRICE_ID configures - [ ] Backend redemarre - [ ] Test avec carte 4242 reussi --- ## Etape 6 : Backup automatique vers NAS ### 6.1 Monter le NAS ```bash sudo apt install cifs-utils sudo mkdir -p /mnt/nas-backups/wordly sudo tee /etc/nas-credentials <> /var/log/wordly-backup.log 2>&1 ``` --- ## Etape 7 : Monitoring (Prometheus + Grafana) ### 7.1 Lancer ```bash cd /opt/wordly docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d ``` ### 7.2 Acceder - **URL** : `https://monitoring.wordly.art` - **Login** : `admin` / mot de passe defini dans le .env ### 7.3 Dashboards | Dashboard | Contenu | |-----------|---------| | Wordly - Application | Traductions, latence, providers, taux d'erreur | | Wordly - Infrastructure | CPU, RAM, disque, reseau, status containers | Alertes pre-configures : backend down, erreur > 10%, RAM > 90%, disque < 15%. --- ## Etape 8 : Gitea Actions - Deploiement automatique ### 8.1 Installer le runner sur 192.168.1.151 ```bash mkdir -p /opt/gitea-runner && cd /opt/gitea-runner wget https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-amd64 chmod +x act_runner-linux-amd64 && mv act_runner-linux-amd64 act_runner ./act_runner generate-config > config.yaml ``` ### 8.2 Enregistrer le runner 1. Gitea > office_translator > Settings > Actions > Runners > Create new Runner 2. Copier le token ```bash cd /opt/gitea-runner ./act_runner register \ --instance https://gitea.parsanet.org \ --token LE_TOKEN \ --name homelab-runner \ --labels self-hosted ``` ### 8.3 Service systemd ```bash sudo tee /etc/systemd/system/gitea-runner.service < option 5 | | Espace disque | `df -h && docker system df` | | SSL | NPM gere le renouvellement auto | --- ## Checklist complete ### DNS IONOS - [ ] A record `@` -> IP fixe - [ ] A record `www` -> IP fixe - [ ] A record `monitoring` -> IP fixe - [ ] Propagation verifiee ### Routeur + NPM - [ ] Ports 80+443 ouverts vers machine NPM - [ ] Proxy Host wordly.art avec custom config - [ ] SSL Let's Encrypt obtenu - [ ] Proxy Host monitoring.wordly.art ### Serveur Docker - [ ] Docker installe - [ ] Code clone dans /opt/wordly - [ ] `bash scripts/setup-env.sh` executed - [ ] `docker compose up -d --build` reussi - [ ] Tous les containers healthy ### Cles API (minimum 1 provider) - [ ] Provider de traduction configure et teste - [ ] `bash scripts/manage-keys.sh` pour verifier ### Stripe (optionnel) - [ ] Compte Stripe cree et active - [ ] 3 produits + Price IDs crees - [ ] Webhook configure (5 events) - [ ] Cles Stripe dans le .env - [ ] Test avec carte 4242 reussi ### Backup NAS - [ ] NAS monte sur /mnt/nas-backups/wordly - [ ] Backup manuel OK - [ ] Cron programme a 3h ### Monitoring - [ ] `docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d` - [ ] Grafana accessible sur monitoring.wordly.art ### CI/CD - [ ] Gitea runner installe et enregistre - [ ] Service systemd active ### Verification finale - [ ] https://wordly.art accessible depuis Internet - [ ] HTTPS OK (cadenas vert) - [ ] Inscription utilisateur OK - [ ] Upload + traduction OK - [ ] Page admin /admin OK - [ ] Monitoring OK