feat: support HTTPS en mode production
- Ajout support HTTPS au serveur Express avec certificats auto-signés - Variable d'environnement ENABLE_HTTPS pour activer/désactiver HTTPS - start.sh active automatiquement HTTPS en mode production (pas --dev) - Messages d'aide clarifiés avec URLs HTTPS et avertissement certificat - WebSocket Audio Levels supporte wss:// en mode HTTPS Mode dev : HTTPS sur port 5173 (Vite) + HTTP API sur 3000 Mode prod : HTTPS sur port 3000 (Express sert client + API)
This commit is contained in:
+46
-17
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import https from 'https';
|
||||||
|
import http from 'http';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { readFileSync, existsSync } from 'fs';
|
import { readFileSync, existsSync } from 'fs';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
@@ -67,6 +69,7 @@ const LIVEKIT_API_SECRET = process.env.LIVEKIT_API_SECRET || 'secret';
|
|||||||
const USE_LOCAL_LIVEKIT = process.env.USE_LOCAL_LIVEKIT === 'true';
|
const USE_LOCAL_LIVEKIT = process.env.USE_LOCAL_LIVEKIT === 'true';
|
||||||
const SERVER_PORT = parseInt(process.env.PORT || config.server.port, 10);
|
const SERVER_PORT = parseInt(process.env.PORT || config.server.port, 10);
|
||||||
const SERVER_HOST = config.server.host;
|
const SERVER_HOST = config.server.host;
|
||||||
|
const ENABLE_HTTPS = process.env.ENABLE_HTTPS === 'true';
|
||||||
|
|
||||||
// Configuration URL LiveKit
|
// Configuration URL LiveKit
|
||||||
let LIVEKIT_URL = process.env.LIVEKIT_URL || config.server.livekit.url;
|
let LIVEKIT_URL = process.env.LIVEKIT_URL || config.server.livekit.url;
|
||||||
@@ -181,18 +184,13 @@ app.use((req, res, next) => {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Middleware redirection HTTP → HTTPS (développement uniquement)
|
// Middleware redirection HTTP → HTTPS (si activé)
|
||||||
// En développement, redirige vers le serveur Vite HTTPS (5173)
|
|
||||||
// En production réelle, utiliser nginx/caddy pour HTTPS
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
const clientDistPath = join(__dirname, '..', 'client', 'dist');
|
// Si HTTPS activé et requête en HTTP, rediriger
|
||||||
const isProd = existsSync(clientDistPath);
|
if (ENABLE_HTTPS && req.protocol === 'http' && req.hostname !== 'localhost') {
|
||||||
|
const httpsUrl = `https://${req.hostname}:${SERVER_PORT}${req.url}`;
|
||||||
// Mode dev : rediriger HTTP → HTTPS (Vite)
|
log('debug', `↪️ Redirection HTTPS: ${httpsUrl}`);
|
||||||
if (!isProd && req.protocol === 'http' && req.hostname !== 'localhost') {
|
return res.redirect(301, httpsUrl);
|
||||||
const devHttpsUrl = `https://${req.hostname}:5173${req.url}`;
|
|
||||||
log('debug', `↪️ Redirection dev HTTPS: ${devHttpsUrl}`);
|
|
||||||
return res.redirect(301, devHttpsUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
@@ -409,31 +407,62 @@ async function start() {
|
|||||||
log('warn', '⚠️ Pour utiliser LiveKit local, définir USE_LOCAL_LIVEKIT=true dans .env');
|
log('warn', '⚠️ Pour utiliser LiveKit local, définir USE_LOCAL_LIVEKIT=true dans .env');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Démarrer API REST
|
// 2. Démarrer API REST (HTTP ou HTTPS selon config)
|
||||||
const server = app.listen(SERVER_PORT, SERVER_HOST, () => {
|
let server;
|
||||||
|
|
||||||
|
if (ENABLE_HTTPS) {
|
||||||
|
// Charger certificats SSL (mêmes que Vite)
|
||||||
|
const certPath = join(__dirname, '..', 'client');
|
||||||
|
const httpsOptions = {
|
||||||
|
key: readFileSync(join(certPath, 'localhost+3-key.pem')),
|
||||||
|
cert: readFileSync(join(certPath, 'localhost+3.pem'))
|
||||||
|
};
|
||||||
|
|
||||||
|
server = https.createServer(httpsOptions, app);
|
||||||
|
server.listen(SERVER_PORT, SERVER_HOST, () => {
|
||||||
|
log('info', `✓ API REST démarrée sur https://${SERVER_HOST}:${SERVER_PORT}`);
|
||||||
|
log('info', '');
|
||||||
|
log('info', 'Serveur prêt !');
|
||||||
|
log('info', `Groupes configurés: ${config.groups.map(g => g.name).join(', ')}`);
|
||||||
|
log('info', '');
|
||||||
|
|
||||||
|
// Afficher URLs d'accès
|
||||||
|
if (networkIP && networkIP !== 'localhost') {
|
||||||
|
const prodUrl = `https://${networkIP}:${SERVER_PORT}`;
|
||||||
|
log('info', '📱 Accès réseau WiFi :');
|
||||||
|
log('info', '');
|
||||||
|
log('info', ` Prod : ${prodUrl}`);
|
||||||
|
log('info', '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
server = http.createServer(app);
|
||||||
|
server.listen(SERVER_PORT, SERVER_HOST, () => {
|
||||||
log('info', `✓ API REST démarrée sur http://${SERVER_HOST}:${SERVER_PORT}`);
|
log('info', `✓ API REST démarrée sur http://${SERVER_HOST}:${SERVER_PORT}`);
|
||||||
log('info', '');
|
log('info', '');
|
||||||
log('info', 'Serveur prêt !');
|
log('info', 'Serveur prêt !');
|
||||||
log('info', `Groupes configurés: ${config.groups.map(g => g.name).join(', ')}`);
|
log('info', `Groupes configurés: ${config.groups.map(g => g.name).join(', ')}`);
|
||||||
log('info', '');
|
log('info', '');
|
||||||
|
|
||||||
// Afficher URLs d'accès avec QR code
|
// Afficher URLs d'accès
|
||||||
if (networkIP && networkIP !== 'localhost') {
|
if (networkIP && networkIP !== 'localhost') {
|
||||||
const clientUrl = `https://${networkIP}:5173`; // Dev mode
|
const clientUrl = `https://${networkIP}:5173`; // Dev mode
|
||||||
const prodUrl = `http://${networkIP}:${SERVER_PORT}`; // Prod mode (redirigera vers HTTPS)
|
const prodUrl = `http://${networkIP}:${SERVER_PORT}`; // Prod mode HTTP
|
||||||
|
|
||||||
log('info', '📱 Accès réseau WiFi :');
|
log('info', '📱 Accès réseau WiFi :');
|
||||||
log('info', '');
|
log('info', '');
|
||||||
log('info', ` Dev : ${clientUrl}`);
|
log('info', ` Dev : ${clientUrl}`);
|
||||||
log('info', ` Prod : ${prodUrl} (redirige → HTTPS)`);
|
log('info', ` Prod : ${prodUrl}`);
|
||||||
log('info', '');
|
log('info', '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 2.5 Démarrer WebSocket Audio Levels (même port que l'API)
|
// 2.5 Démarrer WebSocket Audio Levels (même port que l'API)
|
||||||
const audioLevelsServer = new AudioLevelsServer({ server });
|
const audioLevelsServer = new AudioLevelsServer({ server });
|
||||||
audioLevelsServer.start();
|
audioLevelsServer.start();
|
||||||
log('info', `✓ WebSocket Audio Levels démarré sur ws://${SERVER_HOST}:${SERVER_PORT}`);
|
const wsProtocol = ENABLE_HTTPS ? 'wss' : 'ws';
|
||||||
|
log('info', `✓ WebSocket Audio Levels démarré sur ${wsProtocol}://${SERVER_HOST}:${SERVER_PORT}`);
|
||||||
|
|
||||||
// 3. Démarrer Audio Bridge Manager (Phase 2.5)
|
// 3. Démarrer Audio Bridge Manager (Phase 2.5)
|
||||||
log('info', '');
|
log('info', '');
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ echo ""
|
|||||||
|
|
||||||
cd server
|
cd server
|
||||||
|
|
||||||
|
# En mode production (pas --dev), activer HTTPS
|
||||||
|
if [ "$1" != "--dev" ]; then
|
||||||
|
export ENABLE_HTTPS=true
|
||||||
|
fi
|
||||||
|
|
||||||
# Lancer le serveur en background silencieux
|
# Lancer le serveur en background silencieux
|
||||||
npm start > ../server.log 2>&1 &
|
npm start > ../server.log 2>&1 &
|
||||||
SERVER_PID=$!
|
SERVER_PID=$!
|
||||||
@@ -134,12 +139,15 @@ if [ "$1" == "--dev" ]; then
|
|||||||
echo "✅ PTT Live démarré (mode dev)"
|
echo "✅ PTT Live démarré (mode dev)"
|
||||||
echo "==================================${NC}"
|
echo "==================================${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🌐 Accès client :"
|
echo -e "${BLUE}🌐 ACCÈS CLIENT (HTTPS) :${NC}"
|
||||||
echo " • Local : https://localhost:5173"
|
echo -e "${GREEN} 👉 Local : https://localhost:5173${NC}"
|
||||||
echo " • Réseau : https://${NETWORK_IP}:5173"
|
echo -e "${GREEN} 👉 Réseau : https://${NETWORK_IP}:5173${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📊 API serveur : http://${NETWORK_IP}:3000 (→ redirige vers HTTPS)"
|
echo -e "${YELLOW}⚠️ Acceptez le certificat auto-signé dans votre navigateur${NC}"
|
||||||
echo "🎛️ Interface admin : https://${NETWORK_IP}:5173/admin"
|
echo -e "${YELLOW} (Cliquez sur 'Avancé' puis 'Continuer')${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "📊 API serveur (HTTP uniquement) : http://localhost:3000"
|
||||||
|
echo "🎛️ Interface admin : https://localhost:5173/admin"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📝 Logs serveur : tail -f server.log"
|
echo "📝 Logs serveur : tail -f server.log"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -168,11 +176,14 @@ else
|
|||||||
echo "✅ PTT Live démarré (production)"
|
echo "✅ PTT Live démarré (production)"
|
||||||
echo "==================================${NC}"
|
echo "==================================${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🌐 Accès :"
|
echo -e "${BLUE}🌐 ACCÈS CLIENT (HTTPS) :${NC}"
|
||||||
echo " • Local : http://localhost:3000"
|
echo -e "${GREEN} 👉 Local : https://localhost:3000${NC}"
|
||||||
echo " • Réseau : http://${NETWORK_IP}:3000"
|
echo -e "${GREEN} 👉 Réseau : https://${NETWORK_IP}:3000${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🎛️ Interface admin : http://${NETWORK_IP}:3000/admin"
|
echo -e "${YELLOW}⚠️ Acceptez le certificat auto-signé dans votre navigateur${NC}"
|
||||||
|
echo -e "${YELLOW} (Cliquez sur 'Avancé' puis 'Continuer')${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "🎛️ Interface admin : https://localhost:3000/admin"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📝 Logs serveur : tail -f server.log"
|
echo "📝 Logs serveur : tail -f server.log"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user