diff --git a/packages/lib/ntp.ts b/packages/lib/ntp.ts index db138696f..972d32911 100644 --- a/packages/lib/ntp.ts +++ b/packages/lib/ntp.ts @@ -2,19 +2,29 @@ import shim from './shim'; import time from './time'; const ntpClient_ = require('./vendor/ntp-client'); -const server = { - domain: 'pool.ntp.org', - port: 123, -}; +interface NtpServer { + domain: string; + port: number; +} function ntpClient() { ntpClient_.dgram = shim.dgram(); return ntpClient_; } -export async function getNetworkTime(): Promise { +const parseNtpServer = (ntpServer: string): NtpServer => { + const s = ntpServer.split(':'); + if (s.length !== 2) throw new Error('NTP server URL must be in format `domain:port`'); + return { + domain: s[0], + port: Number(s[1]), + }; +}; + +export async function getNetworkTime(ntpServer: string): Promise { return new Promise((resolve: Function, reject: Function) => { - ntpClient().getNetworkTime(server.domain, server.port, (error: any, date: Date) => { + const s = parseNtpServer(ntpServer); + ntpClient().getNetworkTime(s.domain, s.port, (error: any, date: Date) => { if (error) { reject(error); return; @@ -25,7 +35,7 @@ export async function getNetworkTime(): Promise { }); } -export async function getDeviceTimeDrift(): Promise { +export async function getDeviceTimeDrift(ntpServer: string): Promise { const maxTries = 3; let tryCount = 0; @@ -34,12 +44,12 @@ export async function getDeviceTimeDrift(): Promise { while (true) { tryCount++; try { - ntpTime = await getNetworkTime(); + ntpTime = await getNetworkTime(ntpServer); break; } catch (error) { if (tryCount >= maxTries) { const newError = typeof error === 'string' ? new Error(error) : error; - newError.message = `Cannot retrieve the network time from ${server.domain}:${server.port}: ${newError.message}`; + newError.message = `Cannot retrieve the network time from ${ntpServer}: ${newError.message}`; throw newError; } else { await time.msleep(tryCount * 1000); diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index 3c11621b3..edcbaad15 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -255,7 +255,8 @@ async function main() { appLogger().info(`Starting server v${config().appVersion} (${env}) on port ${config().port} and PID ${process.pid}...`); if (config().maxTimeDrift) { - const timeDrift = await getDeviceTimeDrift(); + appLogger().info(`Checking for time drift using NTP server: ${config().NTP_SERVER}`); + const timeDrift = await getDeviceTimeDrift(config().NTP_SERVER); if (Math.abs(timeDrift) > config().maxTimeDrift) { throw new Error(`The device time drift is ${timeDrift}ms (Max allowed: ${config().maxTimeDrift}ms) - cannot continue as it could cause data loss and conflicts on the sync clients. You may increase env var MAX_TIME_DRIFT to pass the check, or set to 0 to disabled the check.`); } diff --git a/packages/server/src/env.ts b/packages/server/src/env.ts index 1e6668887..634f0dccb 100644 --- a/packages/server/src/env.ts +++ b/packages/server/src/env.ts @@ -31,6 +31,7 @@ const defaultEnvValues: EnvVariables = { // check. https://github.com/laurent22/joplin/issues/5738 MAX_TIME_DRIFT: 2000, + NTP_SERVER: 'pool.ntp.org:123', // ================================================== // URL config @@ -109,6 +110,7 @@ export interface EnvVariables { COOKIES_SECURE: boolean; RUNNING_IN_DOCKER: boolean; MAX_TIME_DRIFT: number; + NTP_SERVER: string; APP_BASE_URL: string; USER_CONTENT_BASE_URL: string;