Files
office_translator/DEPLOYMENT_HOMELAB.md
sepehr 034d6bfce8
Some checks failed
Deploy to Homelab / Deploy Wordly to 192.168.1.151 (push) Has been cancelled
Deploy to Homelab / Deploy Monitoring (if configured) (push) Has been cancelled
docs: rewrite deployment guide with Stripe and API keys management
Complete rewrite of DEPLOYMENT_HOMELAB.md covering:
- IONOS DNS setup (with @ record workaround)
- NPM proxy host config with exact nginx custom config
- Docker server setup with setup-env.sh wizard
- All 7 translation providers (Google, DeepL, OpenAI, DeepSeek, Minimax, OpenRouter, Ollama)
- Full Stripe integration guide (account, products, webhooks, test cards, live mode)
- NAS backup setup
- Prometheus + Grafana monitoring
- Gitea Actions CI/CD runner setup
- Complete checklist

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:36:47 +02:00

15 KiB

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 :

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 :

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 :

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

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker

3.2 Cloner le projet

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 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 :

cp .env.production .env
nano .env

3.4 Lancer l'application

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

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 :

# 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

cd /opt/wordly
bash scripts/manage-keys.sh
# Choisir option 4 (Stripe)

Ou manuellement dans .env :

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

sudo apt install cifs-utils
sudo mkdir -p /mnt/nas-backups/wordly

sudo tee /etc/nas-credentials <<EOF
username=wordly-backup
password=MOT_DE_PASSE_NAS
domain=WORKGROUP
EOF
sudo chmod 600 /etc/nas-credentials

echo "//IP_DU_NAS/wordly-backups /mnt/nas-backups/wordly cifs credentials=/etc/nas-credentials,uid=$(id -u),gid=$(id -g),iocharset=utf8,vers=3.0,noperm 0 0" | sudo tee -a /etc/fstab
sudo mount /mnt/nas-backups/wordly

6.2 Tester et programmer

cd /opt/wordly
bash scripts/backup-to-nas.sh --full
ls -lh /mnt/nas-backups/wordly/daily/

# Programmer le cron quotidien a 3h
crontab -e
# Ajouter :
0 3 * * * /opt/wordly/scripts/backup-to-nas.sh >> /var/log/wordly-backup.log 2>&1

Etape 7 : Monitoring (Prometheus + Grafana)

7.1 Lancer

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

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
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

sudo tee /etc/systemd/system/gitea-runner.service <<EOF
[Unit]
Description=Gitea Act Runner
After=docker.service
Requires=docker.service

[Service]
Type=simple
User=root
WorkingDirectory=/opt/gitea-runner
ExecStart=/opt/gitea-runner/act_runner daemon --config config.yaml
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner
sudo systemctl status gitea-runner

Desormais, chaque git push sur production-deployment deploye automatiquement.


Etape 9 : Operations courantes

Action Commande
Voir les logs docker compose logs -f --tail=100
Redemarrer backend docker compose restart backend
Mettre a jour cd /opt/wordly && git pull && docker compose up -d --build
Restaurer backup bash scripts/backup-to-nas.sh --restore
Gerer les cles API bash scripts/manage-keys.sh
Changer mot de passe admin bash scripts/manage-keys.sh > 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