![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.quebec/public_html/ |
// Fixed Production HTTPS server for lavocat.quebec
// Compatible with Next.js 15 - handles missing manifest files gracefully
require('dotenv').config({ path: '.env.production' });
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const WebSocket = require('ws');
const os = require('os');
const fs = require('fs');
const path = require('path');
const dev = false; // Production mode
const hostname = process.env.HOSTNAME || '0.0.0.0';
const port = process.env.PORT || 3443;
// Check if we have the required build files
const checkBuildFiles = () => {
const requiredFiles = [
'.next/BUILD_ID',
'.next/build-manifest.json',
'.next/routes-manifest.json'
];
const missingFiles = requiredFiles.filter(file => !fs.existsSync(file));
if (missingFiles.length > 0) {
console.warn(`⚠️ Missing build files: ${missingFiles.join(', ')}`);
console.warn('💡 Run "npm run build:production" to rebuild the application');
return false;
}
return true;
};
// Production Next.js app with error handling
let app, handle;
try {
app = next({
dev,
hostname,
port,
conf: require('./next.config.production.js')
});
handle = app.getRequestHandler();
console.log('✅ Next.js app initialized successfully');
} catch (error) {
console.error('❌ Failed to initialize Next.js app:', error.message);
process.exit(1);
}
// Global variables for WebSocket management
global.wsClients = new Map();
global.wsRoomSubscriptions = new Map();
global.wsUserPresence = new Map();
// Helper function to get network IP
const getNetworkIP = () => {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
if (iface.family === 'IPv4' && !iface.internal) {
return iface.address;
}
}
}
return 'localhost';
};
function initializeWebSocketServer(server) {
if (global.wsServer) {
console.log('WebSocket server is already running.');
return;
}
const wss = new WebSocket.Server({
server,
path: '/_ws',
clientTracking: true,
maxPayload: 1024 * 1024 // 1MB max payload
});
global.wsServer = wss;
console.log('🚀 WebSocket server initialized for production');
// WebSocket connection handling
wss.on('connection', (ws, req) => {
console.log('✅ WebSocket connection established');
// Message handling
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
console.log('📨 WebSocket message received:', message.type);
// Handle different message types
switch (message.type) {
case 'JOIN_ROOM': {
const { chatRoomId } = message.data;
if (chatRoomId) {
if (!global.wsRoomSubscriptions.has(chatRoomId)) {
global.wsRoomSubscriptions.set(chatRoomId, new Set());
}
global.wsRoomSubscriptions.get(chatRoomId).add(ws);
console.log(`User joined room ${chatRoomId}`);
}
break;
}
case 'LEAVE_ROOM': {
const { chatRoomId } = message.data;
if (chatRoomId && global.wsRoomSubscriptions.has(chatRoomId)) {
global.wsRoomSubscriptions.get(chatRoomId).delete(ws);
console.log(`User left room ${chatRoomId}`);
}
break;
}
case 'CHAT_MESSAGE': {
const { chatRoomId } = message.data;
if (chatRoomId && global.wsRoomSubscriptions.has(chatRoomId)) {
const outboundMessage = JSON.stringify(message);
global.wsRoomSubscriptions.get(chatRoomId).forEach(clientWs => {
if (clientWs.readyState === WebSocket.OPEN) {
clientWs.send(outboundMessage);
}
});
}
break;
}
case 'ping': {
ws.send(JSON.stringify({ type: 'pong' }));
break;
}
}
} catch (error) {
console.error('WebSocket message error:', error);
}
});
// Connection close handling
ws.on('close', (code, reason) => {
console.log(`🔌 WebSocket connection closed - Code: ${code}, Reason: ${reason}`);
});
// Error handling
ws.on('error', (error) => {
console.error('❌ WebSocket error:', error);
});
});
// Heartbeat interval
const interval = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, 30000);
wss.on('close', () => {
clearInterval(interval);
});
}
// Start the application with enhanced error handling
const startServer = async () => {
try {
// Check build files first
if (!checkBuildFiles()) {
console.log('🔄 Attempting to start server anyway...');
}
// Prepare the Next.js app
console.log('🔄 Preparing Next.js application...');
await app.prepare();
console.log('✅ Next.js app prepared successfully');
// HTTP Server (DirectAdmin handles HTTPS)
const httpServer = createServer((req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
});
initializeWebSocketServer(httpServer);
httpServer.listen(port, hostname, (err) => {
if (err) throw err;
console.log(`🚀 Production HTTP server running on http://${hostname}:${port}`);
console.log(`🌐 Domain: lavocat.quebec (HTTPS handled by DirectAdmin)`);
console.log(`📊 Environment: Production`);
console.log(`🔌 WebSocket endpoint: ws://${hostname}:${port}/_ws`);
console.log(`📁 Build files: ${checkBuildFiles() ? '✅ Complete' : '⚠️ Incomplete'}`);
});
} catch (error) {
console.error('❌ Error starting production server:', error.message);
// Provide helpful error information
if (error.code === 'ENOENT') {
console.error('💡 This usually means the build is incomplete or corrupted.');
console.error('💡 Try running: npm run build:production');
}
if (error.message.includes('prerender-manifest')) {
console.error('💡 Next.js 15 compatibility issue detected.');
console.error('💡 The build should work without this file.');
}
process.exit(1);
}
};
// Start the server
startServer();