diff --git a/DEPLOYMENT_SOCKET_IO.md b/DEPLOYMENT_SOCKET_IO.md new file mode 100644 index 0000000..b231412 --- /dev/null +++ b/DEPLOYMENT_SOCKET_IO.md @@ -0,0 +1,83 @@ +# Deployment-Anleitung: Socket.IO mit SSL + +Socket.IO läuft jetzt direkt auf HTTPS-Port 3051 (nicht über Apache-Proxy). + +## Schritte nach dem Deployment + +### 1. Firewall-Port öffnen + +```bash +# UFW (Ubuntu Firewall) +sudo ufw allow 3051/tcp + +# Oder iptables +sudo iptables -A INPUT -p tcp --dport 3051 -j ACCEPT +sudo iptables-save +``` + +### 2. Apache-Konfiguration aktualisieren + +```bash +sudo cp /var/www/tt-tagebuch.de/apache.conf.example /etc/apache2/sites-available/tt-tagebuch.de-le-ssl.conf +sudo systemctl restart apache2 +``` + +### 3. Backend neu starten + +```bash +cd /var/www/tt-tagebuch.de/backend +sudo systemctl restart tt-tagebuch-backend +# Oder falls als PM2-Prozess: +pm2 restart tt-tagebuch-backend +``` + +### 4. Prüfen, ob HTTPS-Server läuft + +```bash +# Prüfe, ob Port 3051 geöffnet ist +sudo netstat -tlnp | grep 3051 + +# Prüfe Backend-Logs +sudo journalctl -u tt-tagebuch-backend -f +# Oder bei PM2: +pm2 logs tt-tagebuch-backend +``` + +Du solltest folgende Meldung sehen: +``` +🚀 HTTPS-Server für Socket.IO läuft auf Port 3051 +``` + +### 5. Testen + +Im Browser sollte Socket.IO jetzt direkt zu `wss://tt-tagebuch.de:3051` verbinden. + +## Troubleshooting + +### Port 3051 ist nicht erreichbar + +1. Prüfe Firewall: + ```bash + sudo ufw status + ``` + +2. Prüfe, ob der Server läuft: + ```bash + sudo netstat -tlnp | grep 3051 + ``` + +3. Prüfe Backend-Logs auf Fehler + +### SSL-Zertifikat-Fehler + +Stelle sicher, dass die Zertifikate existieren: +```bash +ls -la /etc/letsencrypt/live/tt-tagebuch.de/ +``` + +### Frontend verbindet nicht + +1. Prüfe Browser-Konsole auf Fehler +2. Prüfe, ob `import.meta.env.PROD` korrekt gesetzt ist +3. Prüfe, ob die Socket.IO-URL korrekt ist (`https://tt-tagebuch.de:3051`) + diff --git a/apache.conf.example b/apache.conf.example index 6309754..ca4527e 100644 --- a/apache.conf.example +++ b/apache.conf.example @@ -30,45 +30,8 @@ ProxyRequests Off - # WebSocket-Proxy für Socket.IO - # WICHTIG: Diese LocationMatch muss VOR den anderen ProxyPass-Direktiven stehen - # WICHTIG: mod_proxy_wstunnel muss aktiviert sein (sudo a2enmod proxy_wstunnel) - # WICHTIG: mod_rewrite muss aktiviert sein (sudo a2enmod rewrite) - # - # HINWEIS: Seit Apache 2.4.47 kann mod_proxy_http WebSockets direkt verarbeiten. - # Falls die RewriteRule nicht funktioniert, verwende die alternative Konfiguration unten. - - # WebSocket-Upgrade erkennen und weiterleiten (wss:// -> ws://) - # Verwende RewriteRule, um WebSocket-Upgrades zu erkennen und weiterzuleiten - - RewriteEngine on - RewriteCond %{HTTP:Upgrade} websocket [NC] - RewriteCond %{HTTP:Connection} upgrade [NC] - RewriteRule ^/socket\.io/?(.*) ws://localhost:3050/socket.io/$1 [P,L,QSA] - - # Fallback für HTTP-Polling (wird verwendet, wenn RewriteRule nicht greift) - ProxyPass http://localhost:3050/socket.io/ - ProxyPassReverse http://localhost:3050/socket.io/ - - ProxyPreserveHost On - ProxyAddHeaders On - - RequestHeader set X-Forwarded-Proto "https" - RequestHeader set X-Real-IP %{REMOTE_ADDR}s - RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s - - - - # ALTERNATIVE: Direkte ProxyPass-Konfiguration (funktioniert ab Apache 2.4.47) - # Falls die RewriteRule nicht funktioniert, kommentiere die obige LocationMatch aus - # und verwende stattdessen diese Konfiguration: - # ProxyPass /socket.io/ ws://localhost:3050/socket.io/ - # ProxyPassReverse /socket.io/ ws://localhost:3050/socket.io/ - # ProxyPass /socket.io/ http://localhost:3050/socket.io/ - # ProxyPassReverse /socket.io/ http://localhost:3050/socket.io/ - - # Timeout für alle Proxy-Verbindungen (außerhalb von LocationMatch) - ProxyTimeout 3600 + # HINWEIS: Socket.IO läuft jetzt direkt auf HTTPS-Port 3051 (nicht über Apache-Proxy) + # Siehe backend/SOCKET_IO_SSL_SETUP.md für Details # API-Routen ProxyPass /api http://localhost:3050/api diff --git a/backend/server.js b/backend/server.js index 9b5102e..5fbe3fd 100644 --- a/backend/server.js +++ b/backend/server.js @@ -2,6 +2,8 @@ import express from 'express'; import path from 'path'; import { fileURLToPath } from 'url'; import { createServer } from 'http'; +import https from 'https'; +import fs from 'fs'; import sequelize from './database.js'; import cors from 'cors'; import { initializeSocketIO } from './services/socketService.js'; @@ -262,15 +264,34 @@ app.get('*', (req, res) => { // Start scheduler service schedulerService.start(); - // Erstelle HTTP-Server für Socket.IO + // Erstelle HTTP-Server für API const httpServer = createServer(app); - - // Initialisiere Socket.IO - initializeSocketIO(httpServer); - httpServer.listen(port, () => { - console.log(`🚀 Server läuft auf Port ${port}`); + console.log(`🚀 HTTP-Server läuft auf Port ${port}`); }); + + // Erstelle HTTPS-Server für Socket.IO (direkt mit SSL) + const httpsPort = process.env.HTTPS_PORT || 3051; + try { + const httpsOptions = { + key: fs.readFileSync('/etc/letsencrypt/live/tt-tagebuch.de/privkey.pem'), + cert: fs.readFileSync('/etc/letsencrypt/live/tt-tagebuch.de/fullchain.pem') + }; + + const httpsServer = https.createServer(httpsOptions, app); + + // Initialisiere Socket.IO auf HTTPS-Server + initializeSocketIO(httpsServer); + + httpsServer.listen(httpsPort, () => { + console.log(`🚀 HTTPS-Server für Socket.IO läuft auf Port ${httpsPort}`); + }); + } catch (err) { + console.error('⚠️ HTTPS-Server konnte nicht gestartet werden:', err.message); + console.log(' → Socket.IO läuft auf HTTP-Server (nur für Entwicklung)'); + // Fallback: Socket.IO auf HTTP-Server + initializeSocketIO(httpServer); + } } catch (err) { console.error('Unable to synchronize the database:', err); } diff --git a/frontend/src/services/socketService.js b/frontend/src/services/socketService.js index 2a03ab8..e3894e3 100644 --- a/frontend/src/services/socketService.js +++ b/frontend/src/services/socketService.js @@ -11,18 +11,27 @@ export const connectSocket = (clubId) => { } } else { // Neue Verbindung erstellen - // Verwende backendBaseUrl direkt, Socket.IO erkennt automatisch den Port - socket = io(backendBaseUrl, { + // Socket.IO läuft direkt auf HTTPS-Port 3051 (nicht über Apache-Proxy) + let socketUrl; + if (import.meta.env.PROD) { + // Produktion: HTTPS direkt auf Port 3051 + socketUrl = 'https://tt-tagebuch.de:3051'; + } else { + // Entwicklung: Verwende backendBaseUrl + socketUrl = backendBaseUrl; + } + + socket = io(socketUrl, { path: '/socket.io/', - transports: ['polling', 'websocket'], // Polling zuerst, dann Upgrade zu WebSocket + transports: ['websocket', 'polling'], // WebSocket zuerst, dann Fallback zu Polling reconnection: true, reconnectionDelay: 1000, reconnectionAttempts: 5, timeout: 20000, - // Erlaube Upgrade von polling zu websocket upgrade: true, - // Force new connection - forceNew: false + forceNew: false, + secure: true, // Wichtig für HTTPS + rejectUnauthorized: false // Für selbst-signierte Zertifikate (nur Entwicklung) }); socket.on('connect', () => {