From 052583a8fb790c1916100403275c3755c04adf4d Mon Sep 17 00:00:00 2001 From: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com> Date: Sun, 11 Oct 2026 08:02:44 -0700 Subject: [PATCH] Server: Allow syncing with a web app instance hosted on a custom domain (#16760) --- packages/server/src/app.ts | 32 ++++++++++++++++++-------------- packages/server/src/env.ts | 6 ++++++ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index 5d6ce22293..62e4868187 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -94,6 +94,23 @@ async function getEnvFilePath(env: Env, argv: { envFile?: string }): Promise { + const corsAllowedDomains = envVariables.CORS_ALLOWED_DOMAINS + .split(',') + .map(domain => domain.trim()) + .filter(domain => !!domain); + + if (env === Env.Dev) { + // Stripe (dev) + corsAllowedDomains.push('http://localhost:8077'); + + // Web client (dev) + corsAllowedDomains.push('http://localhost:8088'); + } + + return corsAllowedDomains; +}; + async function main() { const { selectedCommand, argv: yargsArgv } = await setupCommands(); @@ -126,21 +143,8 @@ async function main() { // loads the user, which is then used by notificationHandler. And finally // routeHandler uses data from both previous middlewares. It would be good to // layout these dependencies in code but not clear how to do this. - const corsAllowedDomains = [ - 'https://joplinapp.org', - - // Allows sync with the web version of Joplin - 'https://app.joplincloud.com', - ]; - - if (env === Env.Dev) { - // Stripe (dev) - corsAllowedDomains.push('http://localhost:8077'); - - // Web client (dev) - corsAllowedDomains.push('http://localhost:8088'); - } + const corsAllowedDomains = getCorsAllowedDomains(envVariables, env); function acceptOrigin(origin: string): boolean { // Origin can be string "null" if (origin === 'null') return false; diff --git a/packages/server/src/env.ts b/packages/server/src/env.ts index 151f1fedfa..24156e34f3 100644 --- a/packages/server/src/env.ts +++ b/packages/server/src/env.ts @@ -59,6 +59,11 @@ const defaultEnvValues: EnvVariables = { TERMS_URL: '', PRIVACY_URL: '', + // Comma-separated list of trusted domains that can access server API. + // Use this to grant the Joplin web app access to Joplin Server. + // Entries must be in :// form (no trailing slash). + CORS_ALLOWED_DOMAINS: 'https://joplinapp.org,https://app.joplincloud.com', + // ================================================== // Database config // ================================================== @@ -215,6 +220,7 @@ export interface EnvVariables { JOPLINAPP_BASE_URL: string; TERMS_URL: string; PRIVACY_URL: string; + CORS_ALLOWED_DOMAINS: string; DEFAULT_ADMIN_PASSWORD: string;