mostly because code is being autogenerated by all the AI stuff using this prefix. it's also used in the stack trace.
104 lines
3.5 KiB
JavaScript
Executable File
104 lines
3.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
'use strict';
|
|
|
|
const constants = require('./src/constants.js'),
|
|
fs = require('node:fs'),
|
|
ldapServer = require('./src/ldapserver.js'),
|
|
net = require('node:net'),
|
|
oidcServer = require('./src/oidcserver.js'),
|
|
paths = require('./src/paths.js'),
|
|
proxyAuth = require('./src/proxyauth.js'),
|
|
safe = require('safetydance'),
|
|
server = require('./src/server.js'),
|
|
directoryServer = require('./src/directoryserver.js');
|
|
|
|
let logFd;
|
|
|
|
async function setupLogging() {
|
|
if (constants.TEST) return;
|
|
|
|
logFd = fs.openSync(paths.BOX_LOG_FILE, 'a');
|
|
// we used to write using a stream before but it caches internally and there is no way to flush it when things crash
|
|
process.stdout.write = process.stderr.write = function (...args) {
|
|
const callback = typeof args[args.length-1] === 'function' ? args.pop() : function () {}; // callback is required for fs.write
|
|
fs.write.apply(fs, [logFd, ...args, callback]);
|
|
};
|
|
}
|
|
|
|
// happy eyeballs workaround. when there is no ipv6, nodejs timesout prematurely since the default for ipv4 is just 250ms
|
|
// https://github.com/nodejs/node/issues/54359
|
|
async function setupNetworking() {
|
|
net.setDefaultAutoSelectFamilyAttemptTimeout(2500);
|
|
}
|
|
|
|
// this is also used as the 'uncaughtException' handler which can only have synchronous functions
|
|
function exitSync(status) {
|
|
const ts = new Date().toISOString();
|
|
if (status.message) fs.write(logFd, `${ts} ${status.message}\n`, function () {});
|
|
const msg = status.error.stack.replace(/\n/g, `\n${ts} `); // prefix each line with ts
|
|
if (status.error) fs.write(logFd, `${ts} ${msg}\n`, function () {});
|
|
fs.fsyncSync(logFd);
|
|
fs.closeSync(logFd);
|
|
process.exit(status.code);
|
|
}
|
|
|
|
async function startServers() {
|
|
await setupLogging();
|
|
await setupNetworking();
|
|
await server.start(); // do this first since it also inits the database
|
|
await proxyAuth.start();
|
|
await ldapServer.start();
|
|
|
|
const conf = await directoryServer.getConfig();
|
|
if (conf.enabled) await directoryServer.start();
|
|
}
|
|
|
|
async function main() {
|
|
const [error] = await safe(startServers());
|
|
if (error) return exitSync({ error, code: 1, message: 'Error starting servers' });
|
|
|
|
// require this here so that logging handler is already setup
|
|
const debug = require('debug')('box:box');
|
|
|
|
process.on('SIGHUP', async function () {
|
|
debug('Received SIGHUP. Re-reading configs.');
|
|
const conf = await directoryServer.getConfig();
|
|
if (conf.enabled) await directoryServer.checkCertificate();
|
|
});
|
|
|
|
process.on('SIGINT', async function () {
|
|
debug('Received SIGINT. Shutting down.');
|
|
|
|
await proxyAuth.stop();
|
|
await server.stop();
|
|
await directoryServer.stop();
|
|
await ldapServer.stop();
|
|
await oidcServer.stop();
|
|
|
|
setTimeout(() => {
|
|
debug('Shutdown complete');
|
|
process.exit();
|
|
}, 2000); // need to wait for the task processes to die
|
|
});
|
|
|
|
process.on('SIGTERM', async function () {
|
|
debug('Received SIGTERM. Shutting down.');
|
|
|
|
await proxyAuth.stop();
|
|
await server.stop();
|
|
await directoryServer.stop();
|
|
await ldapServer.stop();
|
|
await oidcServer.stop();
|
|
|
|
setTimeout(() => {
|
|
debug('Shutdown complete');
|
|
process.exit();
|
|
}, 2000); // need to wait for the task processes to die
|
|
});
|
|
|
|
process.on('uncaughtException', (error) => exitSync({ error, code: 1, message: 'From uncaughtException handler.' }));
|
|
}
|
|
|
|
main();
|