From 74d2711d8053ab7f8ff0799a8000c5cfc2ff289b Mon Sep 17 00:00:00 2001 From: pritchey Date: Thu, 4 Jan 2024 20:22:15 -0500 Subject: [PATCH] 523-Added support for HTTPS to Server. (#524) * Added support for HTTPS to server. * Move boot scripts to helper file catch bad ssl boot config fallback SSL boot to HTTP --------- Co-authored-by: timothycarambat --- docker/.env.example | 11 ++++++- server/.env.example | 9 ++++++ server/index.js | 25 ++++----------- server/utils/boot/index.js | 63 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 20 deletions(-) create mode 100644 server/utils/boot/index.js diff --git a/docker/.env.example b/docker/.env.example index 0db90aa2..1a1511f6 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -100,4 +100,13 @@ GID='1000' # PASSWORDUPPERCASE=1 # PASSWORDNUMERIC=1 # PASSWORDSYMBOL=1 -# PASSWORDREQUIREMENTS=4 \ No newline at end of file +# PASSWORDREQUIREMENTS=4 + +########################################### +######## ENABLE HTTPS SERVER ############## +########################################### +# By enabling this and providing the path/filename for the key and cert, +# the server will use HTTPS instead of HTTP. +#ENABLE_HTTPS="true" +#HTTPS_CERT_PATH="sslcert/cert.pem" +#HTTPS_KEY_PATH="sslcert/key.pem" diff --git a/server/.env.example b/server/.env.example index 07abed62..93a1d766 100644 --- a/server/.env.example +++ b/server/.env.example @@ -99,3 +99,12 @@ VECTOR_DB="lancedb" #PASSWORDNUMERIC=1 #PASSWORDSYMBOL=1 #PASSWORDREQUIREMENTS=4 + +########################################### +######## ENABLE HTTPS SERVER ############## +########################################### +# By enabling this and providing the path/filename for the key and cert, +# the server will use HTTPS instead of HTTP. +#ENABLE_HTTPS="true" +#HTTPS_CERT_PATH="sslcert/cert.pem" +#HTTPS_KEY_PATH="sslcert/key.pem" diff --git a/server/index.js b/server/index.js index 1a106053..d8d3eabb 100644 --- a/server/index.js +++ b/server/index.js @@ -15,10 +15,9 @@ const { getVectorDbClass } = require("./utils/helpers"); const { adminEndpoints } = require("./endpoints/admin"); const { inviteEndpoints } = require("./endpoints/invite"); const { utilEndpoints } = require("./endpoints/utils"); -const { Telemetry } = require("./models/telemetry"); const { developerEndpoints } = require("./endpoints/api"); -const setupTelemetry = require("./utils/telemetry"); const { extensionEndpoints } = require("./endpoints/extensions"); +const { bootHTTP, bootSSL } = require("./utils/boot"); const app = express(); const apiRouter = express.Router(); const FILE_LIMIT = "3GB"; @@ -95,20 +94,8 @@ app.all("*", function (_, response) { response.sendStatus(404); }); -app - .listen(process.env.SERVER_PORT || 3001, async () => { - await setupTelemetry(); - console.log( - `Primary server listening on port ${process.env.SERVER_PORT || 3001}` - ); - }) - .on("error", function (err) { - process.once("SIGUSR2", function () { - Telemetry.flush(); - process.kill(process.pid, "SIGUSR2"); - }); - process.on("SIGINT", function () { - Telemetry.flush(); - process.kill(process.pid, "SIGINT"); - }); - }); +if (!!process.env.ENABLE_HTTPS) { + bootSSL(app, process.env.SERVER_PORT || 3001); +} else { + bootHTTP(app, process.env.SERVER_PORT || 3001); +} diff --git a/server/utils/boot/index.js b/server/utils/boot/index.js new file mode 100644 index 00000000..7134198e --- /dev/null +++ b/server/utils/boot/index.js @@ -0,0 +1,63 @@ +const { Telemetry } = require("../../models/telemetry"); +const setupTelemetry = require("../telemetry"); + +function bootSSL(app, port = 3001) { + try { + console.log( + `\x1b[33m[SSL BOOT ENABLED]\x1b[0m Loading the certificate and key for HTTPS mode...` + ); + const fs = require("fs"); + const https = require("https"); + const privateKey = fs.readFileSync(process.env.HTTPS_KEY_PATH); + const certificate = fs.readFileSync(process.env.HTTPS_CERT_PATH); + const credentials = { key: privateKey, cert: certificate }; + + https + .createServer(credentials, app) + .listen(port, async () => { + await setupTelemetry(); + console.log(`Primary server in HTTPS mode listening on port ${port}`); + }) + .on("error", catchSigTerms); + return app; + } catch (e) { + console.error( + `\x1b[31m[SSL BOOT FAILED]\x1b[0m ${e.message} - falling back to HTTP boot.`, + { + ENABLE_HTTPS: process.env.ENABLE_HTTPS, + HTTPS_KEY_PATH: process.env.HTTPS_KEY_PATH, + HTTPS_CERT_PATH: process.env.HTTPS_CERT_PATH, + stacktrace: e.stack, + } + ); + return bootHTTP(app, port); + } +} + +function bootHTTP(app, port = 3001) { + if (!app) throw new Error('No "app" defined - crashing!'); + + app + .listen(port, async () => { + await setupTelemetry(); + console.log(`Primary server in HTTP mode listening on port ${port}`); + }) + .on("error", catchSigTerms); + return app; +} + +function catchSigTerms() { + process.once("SIGUSR2", function () { + Telemetry.flush(); + process.kill(process.pid, "SIGUSR2"); + }); + process.on("SIGINT", function () { + Telemetry.flush(); + process.kill(process.pid, "SIGINT"); + }); +} + +module.exports = { + bootHTTP, + bootSSL, +};