388 lines
8.7 KiB
Markdown
388 lines
8.7 KiB
Markdown
# 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 <url-du-repo> 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
|
|
<VirtualHost *:80>
|
|
ServerName adastra.example.com
|
|
|
|
DocumentRoot /var/www/adastra_app
|
|
|
|
<Directory /var/www/adastra_app>
|
|
Options -Indexes
|
|
AllowOverride None
|
|
Require all granted
|
|
|
|
# Angular HTML5 routing — renvoie tout vers index.html
|
|
FallbackResource /index.html
|
|
</Directory>
|
|
|
|
# Compression et cache navigateur
|
|
<IfModule mod_deflate.c>
|
|
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
|
|
</IfModule>
|
|
|
|
<FilesMatch "\.(js|css|woff2|png|jpg|svg)$">
|
|
Header set Cache-Control "max-age=31536000, public, immutable"
|
|
</FilesMatch>
|
|
<FilesMatch "index\.html$">
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
|
</FilesMatch>
|
|
|
|
ErrorLog ${APACHE_LOG_DIR}/adastra-app-error.log
|
|
CustomLog ${APACHE_LOG_DIR}/adastra-app-access.log combined
|
|
</VirtualHost>
|
|
```
|
|
|
|
### VirtualHost API — `/etc/apache2/sites-available/adastra-api.conf`
|
|
|
|
```apache
|
|
<VirtualHost *:80>
|
|
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
|
|
</VirtualHost>
|
|
```
|
|
|
|
### 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.
|