import * as toml from 'toml'; import IConfig from './IConfig.js'; import * as fs from 'fs'; import CollabVMServer from './CollabVMServer.js'; import { QemuVmDefinition } from '@computernewb/superqemu'; import AuthManager from './AuthManager.js'; import WSServer from './WebSocket/WSServer.js'; import { User } from './User.js'; import TCPServer from './TCP/TCPServer.js'; import VM from './vm/interface.js'; import VNCVM from './vm/vnc/VNCVM.js'; import GeoIPDownloader from './GeoIPDownloader.js'; import pino from 'pino'; import { Database } from './Database.js'; import { BanManager } from './BanManager.js'; import { QemuVMShim } from './vm/qemu.js'; let logger = pino(); logger.info('CollabVM Server starting up'); // Parse the config file let Config: IConfig; if (!fs.existsSync('config.toml')) { logger.error('Fatal error: Config.toml not found. Please copy config.example.toml and fill out fields'); process.exit(1); } try { var configRaw = fs.readFileSync('config.toml').toString(); Config = toml.parse(configRaw); } catch (e) { logger.error({err: e}, 'Fatal error: Failed to read or parse the config file'); process.exit(1); } let exiting = false; let VM: VM; async function stop() { if (exiting) return; exiting = true; await VM.Stop(); process.exit(0); } async function start() { let geoipReader = null; if (Config.geoip.enabled) { let downloader = new GeoIPDownloader(Config.geoip.directory, Config.geoip.accountID, Config.geoip.licenseKey); geoipReader = await downloader.getGeoIPReader(); } // Init the auth manager if enabled let auth = Config.auth.enabled ? new AuthManager(Config.auth.apiEndpoint, Config.auth.secretKey) : null; // Database and ban manager if (Config.bans.cvmban && !Config.mysql.enabled) { logger.error('MySQL must be configured to use cvmban.'); process.exit(1); } if (!Config.bans.cvmban && !Config.bans.bancmd) { logger.warn('Neither cvmban nor ban command are configured. Bans will not function.'); } let db = undefined; if (Config.mysql.enabled) { db = new Database(Config.mysql); await db.init(); } let banmgr = new BanManager(Config.bans, db); switch (Config.vm.type) { case 'qemu': { // Fire up the VM let def: QemuVmDefinition = { id: Config.collabvm.node, command: Config.qemu.qemuArgs, snapshot: Config.qemu.snapshots, forceTcp: false, vncHost: '127.0.0.1', vncPort: Config.qemu.vncPort, }; VM = new QemuVMShim(def, Config.qemu.resourceLimits); break; } case 'vncvm': { VM = new VNCVM(Config.vncvm); break; } default: { logger.error(`Invalid VM type in config: ${Config.vm.type}`); process.exit(1); return; } } process.on('SIGINT', async () => await stop()); process.on('SIGTERM', async () => await stop()); await VM.Start(); // Start up the server var CVM = new CollabVMServer(Config, VM, banmgr, auth, geoipReader); var WS = new WSServer(Config, banmgr); WS.on('connect', (client: User) => CVM.addUser(client)); WS.start(); if (Config.tcp.enabled) { var TCP = new TCPServer(Config, banmgr); TCP.on('connect', (client: User) => CVM.addUser(client)); TCP.start(); } } start();