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:
2026-05-27 15:36:52 +02:00
parent 244aadcf8b
commit 6b13981dad
2 changed files with 77 additions and 37 deletions
+46 -17
View File
@@ -2,6 +2,8 @@
import 'dotenv/config';
import express from 'express';
import https from 'https';
import http from 'http';
import { spawn } from 'child_process';
import { readFileSync, existsSync } from 'fs';
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 SERVER_PORT = parseInt(process.env.PORT || config.server.port, 10);
const SERVER_HOST = config.server.host;
const ENABLE_HTTPS = process.env.ENABLE_HTTPS === 'true';
// Configuration URL LiveKit
let LIVEKIT_URL = process.env.LIVEKIT_URL || config.server.livekit.url;
@@ -181,18 +184,13 @@ app.use((req, res, next) => {
next();
});
// Middleware redirection HTTP → HTTPS (développement uniquement)
// En développement, redirige vers le serveur Vite HTTPS (5173)
// En production réelle, utiliser nginx/caddy pour HTTPS
// Middleware redirection HTTP → HTTPS (si activé)
app.use((req, res, next) => {
const clientDistPath = join(__dirname, '..', 'client', 'dist');
const isProd = existsSync(clientDistPath);
// Mode dev : rediriger HTTP → HTTPS (Vite)
if (!isProd && req.protocol === 'http' && req.hostname !== 'localhost') {
const devHttpsUrl = `https://${req.hostname}:5173${req.url}`;
log('debug', `↪️ Redirection dev HTTPS: ${devHttpsUrl}`);
return res.redirect(301, devHttpsUrl);
// Si HTTPS activé et requête en HTTP, rediriger
if (ENABLE_HTTPS && req.protocol === 'http' && req.hostname !== 'localhost') {
const httpsUrl = `https://${req.hostname}:${SERVER_PORT}${req.url}`;
log('debug', `↪️ Redirection HTTPS: ${httpsUrl}`);
return res.redirect(301, httpsUrl);
}
next();
@@ -409,31 +407,62 @@ async function start() {
log('warn', '⚠️ Pour utiliser LiveKit local, définir USE_LOCAL_LIVEKIT=true dans .env');
}
// 2. Démarrer API REST
const server = app.listen(SERVER_PORT, SERVER_HOST, () => {
// 2. Démarrer API REST (HTTP ou HTTPS selon config)
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', '');
log('info', 'Serveur prêt !');
log('info', `Groupes configurés: ${config.groups.map(g => g.name).join(', ')}`);
log('info', '');
// Afficher URLs d'accès avec QR code
// Afficher URLs d'accès
if (networkIP && networkIP !== 'localhost') {
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', '');
log('info', ` Dev : ${clientUrl}`);
log('info', ` Prod : ${prodUrl} (redirige → HTTPS)`);
log('info', ` Prod : ${prodUrl}`);
log('info', '');
}
});
}
// 2.5 Démarrer WebSocket Audio Levels (même port que l'API)
const audioLevelsServer = new AudioLevelsServer({ server });
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)
log('info', '');
+20 -9
View File
@@ -84,6 +84,11 @@ echo ""
cd server
# En mode production (pas --dev), activer HTTPS
if [ "$1" != "--dev" ]; then
export ENABLE_HTTPS=true
fi
# Lancer le serveur en background silencieux
npm start > ../server.log 2>&1 &
SERVER_PID=$!
@@ -134,12 +139,15 @@ if [ "$1" == "--dev" ]; then
echo "✅ PTT Live démarré (mode dev)"
echo "==================================${NC}"
echo ""
echo "🌐 Accès client :"
echo " Local : https://localhost:5173"
echo " Réseau : https://${NETWORK_IP}:5173"
echo -e "${BLUE}🌐 ACCÈS CLIENT (HTTPS) :${NC}"
echo -e "${GREEN} 👉 Local : https://localhost:5173${NC}"
echo -e "${GREEN} 👉 Réseau : https://${NETWORK_IP}:5173${NC}"
echo ""
echo "📊 API serveur : http://${NETWORK_IP}:3000 (→ redirige vers HTTPS)"
echo "🎛️ Interface admin : https://${NETWORK_IP}:5173/admin"
echo -e "${YELLOW}⚠️ Acceptez le certificat auto-signé dans votre navigateur${NC}"
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 "📝 Logs serveur : tail -f server.log"
echo ""
@@ -168,11 +176,14 @@ else
echo "✅ PTT Live démarré (production)"
echo "==================================${NC}"
echo ""
echo "🌐 Accès :"
echo " Local : http://localhost:3000"
echo " Réseau : http://${NETWORK_IP}:3000"
echo -e "${BLUE}🌐 ACCÈS CLIENT (HTTPS) :${NC}"
echo -e "${GREEN} 👉 Local : https://localhost:3000${NC}"
echo -e "${GREEN} 👉 Réseau : https://${NETWORK_IP}:3000${NC}"
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 "📝 Logs serveur : tail -f server.log"
echo ""