8.7 KiB
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
- Prérequis serveur
- Base de données MySQL
- Base de données MongoDB
- Déploiement de l'API
- Déploiement du frontend
- Configuration Apache
- HTTPS avec Let's Encrypt
- PM2 — démarrage automatique
- Procédure de mise à jour
1. Prérequis serveur
Node.js (via nvm — recommandé)
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)
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.
# 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
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é.
-- 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) créeront le schéma.
3. Base de données MongoDB
# 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 :
# /etc/mongod.conf
security:
authorization: enabled
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
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
cp config/env/.env.example config/env/.env.production
nano config/env/.env.production
Valeurs à renseigner obligatoirement :
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 :
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
cd /var/www/adastra_api
pm2 start app.js --name adastra-api
pm2 save
Vérifier que l'API répond :
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
cd /chemin/local/adastra_app
npm install
npm run build # production build → dist/adastra_angular/browser/
Important : vérifier que
src/environments/environment.tspointe vers l'URL de l'API de production avant de builder.apiBaseUrl: 'https://api.adastra.example.com/api'
Transfert sur le serveur
# Depuis la machine locale
rsync -avz --delete dist/adastra_angular/browser/ \
user@serveur:/var/www/adastra_app/
Ou avec scp :
scp -r dist/adastra_angular/browser/* user@serveur:/var/www/adastra_app/
Permissions
# 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
<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
<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
a2ensite adastra-app.conf
a2ensite adastra-api.conf
apache2ctl configtest # doit afficher "Syntax OK"
systemctl reload apache2
7. HTTPS avec Let's Encrypt
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 :
certbot renew --dry-run
Après activation du HTTPS, penser à mettre à jour dans le .env.production :
ALLOWED_ORIGINS=https://adastra.example.com
Et dans environment.ts avant de rebuilder le frontend :
apiBaseUrl: 'https://api.adastra.example.com/api'
8. PM2 — démarrage automatique
Pour que l'API redémarre automatiquement après un reboot :
pm2 startup # affiche une commande à exécuter en root — la copier/coller
pm2 save
Commandes PM2 utiles :
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
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 :
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.