# Guide de mise en production — Adastra Serveur cible : VPS Debian 11, Apache, MySQL déjà installés. Stack : Node.js/Express (API) + Angular 18 (frontend). --- ## Table des matières 1. [Prérequis serveur](#1-prérequis-serveur) 2. [Base de données MySQL](#2-base-de-données-mysql) 3. [Base de données MongoDB](#3-base-de-données-mongodb) 4. [Déploiement de l'API](#4-déploiement-de-lapi) 5. [Déploiement du frontend](#5-déploiement-du-frontend) 6. [Configuration Apache](#6-configuration-apache) 7. [HTTPS avec Let's Encrypt](#7-https-avec-lets-encrypt) 8. [PM2 — démarrage automatique](#8-pm2--démarrage-automatique) 9. [Procédure de mise à jour](#9-procédure-de-mise-à-jour) --- ## 1. Prérequis serveur ### Node.js (via nvm — recommandé) ```bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash source ~/.bashrc nvm install 20 nvm use 20 nvm alias default 20 node -v # doit afficher v20.x.x ``` ### PM2 (gestionnaire de process Node) ```bash npm install -g pm2 ``` ### MongoDB L'API utilise à la fois MySQL et MongoDB. MongoDB n'est pas fourni par les dépôts Debian 11 par défaut. ```bash # Clé GPG et dépôt MongoDB 7 curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \ gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/debian bullseye/mongodb-org/7.0 main" \ | tee /etc/apt/sources.list.d/mongodb-org-7.0.list apt update && apt install -y mongodb-org systemctl enable --now mongod mongod --version ``` ### Modules Apache nécessaires ```bash a2enmod proxy proxy_http rewrite headers ssl systemctl restart apache2 ``` --- ## 2. Base de données MySQL MySQL est déjà installé. Créer la base et l'utilisateur dédié. ```sql -- En tant que root MySQL CREATE DATABASE adastra_prod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'adastra'@'localhost' IDENTIFIED BY 'MOT_DE_PASSE_FORT'; GRANT ALL PRIVILEGES ON adastra_prod.* TO 'adastra'@'localhost'; FLUSH PRIVILEGES; ``` Les migrations Sequelize (voir [section 4](#4-déploiement-de-lapi)) créeront le schéma. --- ## 3. Base de données MongoDB ```bash # Créer la base et l'utilisateur applicatif mongosh <<'EOF' use adastradb db.createUser({ user: "adastra", pwd: "MOT_DE_PASSE_FORT", roles: [{ role: "readWrite", db: "adastradb" }] }) EOF ``` Activer l'authentification MongoDB si elle n'est pas encore activée : ```bash # /etc/mongod.conf security: authorization: enabled ``` ```bash systemctl restart mongod ``` La `MONGODB_URI` dans le `.env` devient alors : ``` MONGODB_URI=mongodb://adastra:MOT_DE_PASSE_FORT@localhost:27017/adastradb ``` --- ## 4. Déploiement de l'API ### Récupérer le code ```bash mkdir -p /var/www cd /var/www git clone adastra_api cd adastra_api git checkout master # ou la branche de production npm install --omit=dev ``` ### Fichier d'environnement ```bash cp config/env/.env.example config/env/.env.production nano config/env/.env.production ``` Valeurs à renseigner obligatoirement : ```dotenv APP_ENV=production NODE_ENV=production SERVER_PORT=3200 # Secrets — générer avec : # node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" SECRET=<64-octets-hex> SESSION_SECRET=<64-octets-hex> # MySQL MYSQL_DBNAME=adastra_prod MYSQL_DBUSER=adastra MYSQL_DBPASS=MOT_DE_PASSE_FORT MYSQL_DBHOST=localhost MYSQL_DBPORT=3306 MYSQL_DBTYPE=mysql # MongoDB MONGODB_URI=mongodb://adastra:MOT_DE_PASSE_FORT@localhost:27017/adastradb # CORS — domaine exact du frontend (sans slash final) ALLOWED_ORIGINS=https://adastra.example.com # Proxy Apache → Node = 1 saut TRUST_PROXY=1 # Sendgrid (si les emails sont utilisés) SENDGRID_API_KEY= SENDGRID_FROM_MAIL= SENDGRID_TO_MAIL= ``` ### Migrations et seeds initiaux À exécuter **une seule fois** lors du premier déploiement : ```bash cd /var/www/adastra_api APP_ENV=production npx sequelize-cli db:migrate APP_ENV=production npx sequelize-cli db:seed --seed 20251126-add-roles.js APP_ENV=production npm run create:user # crée le premier compte admin APP_ENV=production npx sequelize-cli db:seed --seed 20251127-add-articles.js ``` ### Démarrer avec PM2 ```bash cd /var/www/adastra_api pm2 start app.js --name adastra-api pm2 save ``` Vérifier que l'API répond : ```bash curl http://localhost:3200/api/health # ou tout endpoint public ``` --- ## 5. Déploiement du frontend Le build se fait **en local** (ou sur un serveur de CI), puis le répertoire `dist/` est transféré sur le serveur. ### Build en local ```bash cd /chemin/local/adastra_app npm install npm run build # production build → dist/adastra_angular/browser/ ``` > **Important :** vérifier que `src/environments/environment.ts` pointe vers l'URL de l'API de production avant de builder. > ```typescript > apiBaseUrl: 'https://api.adastra.example.com/api' > ``` ### Transfert sur le serveur ```bash # Depuis la machine locale rsync -avz --delete dist/adastra_angular/browser/ \ user@serveur:/var/www/adastra_app/ ``` Ou avec scp : ```bash scp -r dist/adastra_angular/browser/* user@serveur:/var/www/adastra_app/ ``` ### Permissions ```bash # Sur le serveur chown -R www-data:www-data /var/www/adastra_app chmod -R 755 /var/www/adastra_app ``` --- ## 6. Configuration Apache Architecture recommandée : deux sous-domaines séparés. | Sous-domaine | Rôle | |---|---| | `adastra.example.com` | Frontend Angular (fichiers statiques) | | `api.adastra.example.com` | API Node.js (reverse proxy) | ### VirtualHost frontend — `/etc/apache2/sites-available/adastra-app.conf` ```apache ServerName adastra.example.com DocumentRoot /var/www/adastra_app Options -Indexes AllowOverride None Require all granted # Angular HTML5 routing — renvoie tout vers index.html FallbackResource /index.html # Compression et cache navigateur AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json Header set Cache-Control "max-age=31536000, public, immutable" Header set Cache-Control "no-cache, no-store, must-revalidate" ErrorLog ${APACHE_LOG_DIR}/adastra-app-error.log CustomLog ${APACHE_LOG_DIR}/adastra-app-access.log combined ``` ### VirtualHost API — `/etc/apache2/sites-available/adastra-api.conf` ```apache ServerName api.adastra.example.com ProxyPreserveHost On ProxyPass / http://127.0.0.1:3200/ ProxyPassReverse / http://127.0.0.1:3200/ # Transmet l'IP réelle du client à Node (requis pour TRUST_PROXY=1) RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s" RequestHeader set X-Forwarded-Proto "http" ErrorLog ${APACHE_LOG_DIR}/adastra-api-error.log CustomLog ${APACHE_LOG_DIR}/adastra-api-access.log combined ``` ### Activer les vhosts ```bash a2ensite adastra-app.conf a2ensite adastra-api.conf apache2ctl configtest # doit afficher "Syntax OK" systemctl reload apache2 ``` --- ## 7. HTTPS avec Let's Encrypt ```bash apt install -y certbot python3-certbot-apache certbot --apache -d adastra.example.com -d api.adastra.example.com ``` Certbot modifie automatiquement les vhosts pour le HTTPS et programme le renouvellement. Vérifier le renouvellement automatique : ```bash certbot renew --dry-run ``` Après activation du HTTPS, penser à mettre à jour dans le `.env.production` : ```dotenv ALLOWED_ORIGINS=https://adastra.example.com ``` Et dans `environment.ts` avant de rebuilder le frontend : ```typescript apiBaseUrl: 'https://api.adastra.example.com/api' ``` --- ## 8. PM2 — démarrage automatique Pour que l'API redémarre automatiquement après un reboot : ```bash pm2 startup # affiche une commande à exécuter en root — la copier/coller pm2 save ``` Commandes PM2 utiles : ```bash pm2 list # état des process pm2 logs adastra-api # logs en temps réel pm2 restart adastra-api # redémarrage manuel pm2 stop adastra-api # arrêt ``` --- ## 9. Procédure de mise à jour ### Mettre à jour l'API ```bash cd /var/www/adastra_api git pull origin master npm install --omit=dev # Si des migrations ont été ajoutées APP_ENV=production npx sequelize-cli db:migrate pm2 restart adastra-api ``` ### Mettre à jour le frontend En local : ```bash cd /chemin/local/adastra_app git pull origin master npm install npm run build rsync -avz --delete dist/adastra_angular/browser/ user@serveur:/var/www/adastra_app/ ``` Aucun redémarrage Apache nécessaire — les fichiers statiques sont servis directement.