2017-10-14 23:31:44 -04:00
#!/usr/bin/env node
2023-05-07 15:23:46 +02:00
// setup basic error handling even before requiring dependencies, since those can produce errors as well
2017-10-26 19:16:36 -04:00
process . on ( 'unhandledRejection' , error => {
2017-10-22 22:56:42 -04:00
// this makes sure that stacktrace of failed promise is printed out
2017-10-26 19:16:36 -04:00
console . log ( error ) ;
2017-10-25 22:39:21 -04:00
// but also try to log it into file
2018-01-28 22:18:14 -05:00
require ( './services/log' ) . info ( error ) ;
2017-10-22 22:56:42 -04:00
} ) ;
2017-10-14 23:31:44 -04:00
2021-04-25 11:05:09 +02:00
function exit ( ) {
console . log ( "Caught interrupt/termination signal. Exiting." ) ;
process . exit ( 0 ) ;
}
process . on ( 'SIGINT' , exit ) ;
process . on ( 'SIGTERM' , exit ) ;
2019-05-28 13:33:03 +03:00
2023-05-07 15:23:46 +02:00
const app = require ( './app' ) ;
const sessionParser = require ( './routes/session_parser' ) ;
2017-11-16 23:55:50 -05:00
const fs = require ( 'fs' ) ;
2017-10-25 22:39:21 -04:00
const http = require ( 'http' ) ;
2017-11-16 23:55:50 -05:00
const https = require ( 'https' ) ;
2018-01-28 22:18:14 -05:00
const config = require ( './services/config' ) ;
const log = require ( './services/log' ) ;
2018-04-01 21:27:46 -04:00
const appInfo = require ( './services/app_info' ) ;
2022-01-10 17:09:20 +01:00
const ws = require ( './services/ws' ) ;
2018-01-28 22:18:14 -05:00
const utils = require ( './services/utils' ) ;
2018-07-31 19:50:18 +02:00
const port = require ( './services/port' ) ;
2019-07-09 22:50:20 +02:00
const host = require ( './services/host' ) ;
2019-01-26 19:59:51 +01:00
const semver = require ( 'semver' ) ;
if ( ! semver . satisfies ( process . version , ">=10.5.0" ) ) {
console . error ( "Trilium only supports node.js 10.5 and later" ) ;
process . exit ( 1 ) ;
}
2017-10-14 23:31:44 -04:00
2023-05-07 15:23:46 +02:00
startTrilium ( ) ;
2017-10-14 23:31:44 -04:00
2023-05-07 15:23:46 +02:00
function startTrilium ( ) {
2022-08-02 22:53:06 +02:00
/ * *
* The intended behavior is to detect when a second instance is running , in that case open the old instance
* instead of the new one . This is complicated by the fact that it is possible to run multiple instances of Trilium
2023-06-30 11:18:34 +02:00
* if port and data dir are configured separately . This complication is the source of the following weird usage .
2022-08-02 22:53:06 +02:00
*
* The line below makes sure that the "second-instance" ( process in window . js ) is fired . Normally it returns a boolean
* indicating whether another instance is running or not , but we ignore that and kill the app only based on the port conflict .
*
* A bit weird is that "second-instance" is triggered also on the valid usecases ( different port / data dir ) and
* focuses the existing window . But the new process is start as well and will steal the focus too , it will win , because
2023-05-07 15:23:46 +02:00
* its startup is slower than focusing the existing process / window . So in the end , it works out without having
* to do a complex evaluation .
2022-08-02 22:53:06 +02:00
* /
2022-08-09 21:34:18 +02:00
if ( utils . isElectron ( ) ) {
require ( "electron" ) . app . requestSingleInstanceLock ( ) ;
}
2022-08-02 22:53:06 +02:00
2023-05-07 15:23:46 +02:00
log . info ( JSON . stringify ( appInfo , null , 2 ) ) ;
const cpuInfos = require ( 'os' ) . cpus ( ) ;
log . info ( ` CPU model: ${ cpuInfos [ 0 ] . model } , logical cores: ${ cpuInfos . length } freq: ${ cpuInfos [ 0 ] . speed } Mhz ` ) ; // for perf. issues it's good to know the rough configuration
const httpServer = startHttpServer ( ) ;
ws . init ( httpServer , sessionParser ) ;
if ( utils . isElectron ( ) ) {
const electronRouting = require ( './routes/electron' ) ;
electronRouting ( app ) ;
}
}
function startHttpServer ( ) {
2022-08-03 00:19:29 +02:00
app . set ( 'port' , port ) ;
app . set ( 'host' , host ) ;
2017-11-16 23:06:16 -05:00
2022-08-04 00:19:54 +02:00
// Check from config whether to trust reverse proxies to supply user IPs, hostnames and protocols
if ( config [ 'Network' ] [ 'trustedReverseProxy' ] ) {
if ( config [ 'Network' ] [ 'trustedReverseProxy' ] === true || config [ 'Network' ] [ 'trustedReverseProxy' ] . trim ( ) . length ) {
app . set ( 'trust proxy' , config [ 'Network' ] [ 'trustedReverseProxy' ] )
}
}
2023-05-07 15:23:46 +02:00
2022-12-21 15:19:05 +01:00
log . info ( ` Trusted reverse proxy: ${ app . get ( 'trust proxy' ) } ` )
2022-08-04 00:19:54 +02:00
2023-05-07 15:23:46 +02:00
let httpServer ;
2018-07-31 19:50:18 +02:00
if ( config [ 'Network' ] [ 'https' ] ) {
2019-04-08 20:08:29 +02:00
if ( ! config [ 'Network' ] [ 'keyPath' ] || ! config [ 'Network' ] [ 'keyPath' ] . trim ( ) . length ) {
throw new Error ( "keyPath in config.ini is required when https=true, but it's empty" ) ;
}
if ( ! config [ 'Network' ] [ 'certPath' ] || ! config [ 'Network' ] [ 'certPath' ] . trim ( ) . length ) {
throw new Error ( "certPath in config.ini is required when https=true, but it's empty" ) ;
}
2018-07-31 19:50:18 +02:00
const options = {
key : fs . readFileSync ( config [ 'Network' ] [ 'keyPath' ] ) ,
cert : fs . readFileSync ( config [ 'Network' ] [ 'certPath' ] )
} ;
2017-11-21 00:25:53 -05:00
2018-07-31 19:50:18 +02:00
httpServer = https . createServer ( options , app ) ;
2017-10-14 23:31:44 -04:00
2022-12-21 15:19:05 +01:00
log . info ( ` App HTTPS server starting up at port ${ port } ` ) ;
2023-05-07 15:23:46 +02:00
} else {
2018-07-31 19:50:18 +02:00
httpServer = http . createServer ( app ) ;
2017-11-25 17:43:05 -05:00
2022-12-21 15:19:05 +01:00
log . info ( ` App HTTP server starting up at port ${ port } ` ) ;
2018-07-31 19:50:18 +02:00
}
2017-10-14 23:31:44 -04:00
2018-07-31 19:50:18 +02:00
/ * *
* Listen on provided port , on all network interfaces .
* /
2017-10-14 23:31:44 -04:00
2018-07-31 19:50:18 +02:00
httpServer . keepAliveTimeout = 120000 * 5 ;
2023-03-12 21:37:13 +01:00
const listenOnTcp = port !== 0 ;
2023-05-07 15:23:46 +02:00
2023-03-12 21:37:13 +01:00
if ( listenOnTcp ) {
2023-05-07 15:23:46 +02:00
httpServer . listen ( port , host ) ; // TCP socket.
2023-03-11 20:21:32 +11:00
} else {
2023-05-07 15:23:46 +02:00
httpServer . listen ( host ) ; // Unix socket.
2023-03-11 20:21:32 +11:00
}
2023-05-07 15:23:46 +02:00
2019-12-04 22:59:26 +01:00
httpServer . on ( 'error' , error => {
2023-03-12 21:37:13 +01:00
if ( ! listenOnTcp || error . syscall !== 'listen' ) {
2019-12-04 22:59:26 +01:00
throw error ;
}
// handle specific listen errors with friendly messages
switch ( error . code ) {
case 'EACCES' :
2023-03-08 07:31:10 +01:00
console . error ( ` Port ${ port } requires elevated privileges. It's recommended to use port above 1024. ` ) ;
2019-12-04 22:59:26 +01:00
process . exit ( 1 ) ;
break ;
case 'EADDRINUSE' :
2023-03-08 07:31:10 +01:00
console . error ( ` Port ${ port } is already in use. Most likely, another Trilium process is already running. You might try to find it, kill it, and try again. ` ) ;
2019-12-04 22:59:26 +01:00
process . exit ( 1 ) ;
break ;
default :
throw error ;
}
}
2020-06-20 12:31:38 +02:00
)
2023-03-11 20:57:16 +11:00
httpServer . on ( 'listening' , ( ) => {
2023-03-12 21:37:13 +01:00
if ( listenOnTcp ) {
2023-03-11 20:57:16 +11:00
log . info ( ` Listening on port ${ port } ` )
} else {
log . info ( ` Listening on unix socket ${ host } ` )
}
} ) ;
2017-10-14 23:31:44 -04:00
2023-05-07 15:23:46 +02:00
return httpServer ;
2017-10-14 23:31:44 -04:00
}