From 10feaa37ce1a3ecd28246db9b2f1b0414d0a75e6 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Fri, 29 Aug 2025 19:58:01 +0200 Subject: [PATCH] feat(env): improve support for instances without internet connection (#3915) --- packages/common/env.ts | 4 +++- packages/cron-jobs/src/jobs/analytics.ts | 2 ++ packages/cron-jobs/src/jobs/icons-updater.ts | 3 +++ packages/request-handler/src/update-checker.ts | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/common/env.ts b/packages/common/env.ts index 2a7cd43d5..cbccc8b70 100644 --- a/packages/common/env.ts +++ b/packages/common/env.ts @@ -1,7 +1,7 @@ import { randomBytes } from "crypto"; import { z } from "zod/v4"; -import { createEnv } from "@homarr/core/infrastructure/env"; +import { createBooleanSchema, createEnv } from "@homarr/core/infrastructure/env"; const errorSuffix = `, please generate a 64 character secret in hex format or use the following: "${randomBytes(32).toString("hex")}"`; @@ -23,9 +23,11 @@ export const env = createEnv({ .regex(/^[0-9a-fA-F]{64}$/, { message: `SECRET_ENCRYPTION_KEY must only contain hex characters${errorSuffix}`, }), + NO_EXTERNAL_CONNECTION: createBooleanSchema(false), }, runtimeEnv: { SECRET_ENCRYPTION_KEY: process.env.SECRET_ENCRYPTION_KEY, NODE_ENV: process.env.NODE_ENV, + NO_EXTERNAL_CONNECTION: process.env.NO_EXTERNAL_CONNECTION, }, }); diff --git a/packages/cron-jobs/src/jobs/analytics.ts b/packages/cron-jobs/src/jobs/analytics.ts index 100ba79d4..128c4bc89 100644 --- a/packages/cron-jobs/src/jobs/analytics.ts +++ b/packages/cron-jobs/src/jobs/analytics.ts @@ -1,4 +1,5 @@ import { sendServerAnalyticsAsync } from "@homarr/analytics"; +import { env } from "@homarr/common/env"; import { EVERY_WEEK } from "@homarr/cron-jobs-core/expressions"; import { db } from "@homarr/db"; import { getServerSettingByKeyAsync } from "@homarr/db/queries"; @@ -9,6 +10,7 @@ export const analyticsJob = createCronJob("analytics", EVERY_WEEK, { runOnStart: true, preventManualExecution: true, }).withCallback(async () => { + if (env.NO_EXTERNAL_CONNECTION) return; const analyticSetting = await getServerSettingByKeyAsync(db, "analytics"); if (!analyticSetting.enableGeneral) { diff --git a/packages/cron-jobs/src/jobs/icons-updater.ts b/packages/cron-jobs/src/jobs/icons-updater.ts index 8308661ef..64332de51 100644 --- a/packages/cron-jobs/src/jobs/icons-updater.ts +++ b/packages/cron-jobs/src/jobs/icons-updater.ts @@ -1,4 +1,5 @@ import { createId, splitToNChunks, Stopwatch } from "@homarr/common"; +import { env } from "@homarr/common/env"; import { EVERY_WEEK } from "@homarr/cron-jobs-core/expressions"; import type { InferInsertModel } from "@homarr/db"; import { db, handleTransactionsAsync, inArray, sql } from "@homarr/db"; @@ -12,6 +13,8 @@ export const iconsUpdaterJob = createCronJob("iconsUpdater", EVERY_WEEK, { runOnStart: true, expectedMaximumDurationInMillis: 10 * 1000, }).withCallback(async () => { + if (env.NO_EXTERNAL_CONNECTION) return; + logger.info("Updating icon repository cache..."); const stopWatch = new Stopwatch(); const repositoryIconGroups = await fetchIconsAsync(); diff --git a/packages/request-handler/src/update-checker.ts b/packages/request-handler/src/update-checker.ts index bd9a52361..a12e63564 100644 --- a/packages/request-handler/src/update-checker.ts +++ b/packages/request-handler/src/update-checker.ts @@ -3,6 +3,7 @@ import { Octokit } from "octokit"; import { compareSemVer, isValidSemVer } from "semver-parser"; import { fetchWithTimeout } from "@homarr/common"; +import { env } from "@homarr/common/env"; import { logger } from "@homarr/log"; import { createChannelWithLatestAndEvents } from "@homarr/redis"; import { createCachedRequestHandler } from "@homarr/request-handler/lib/cached-request-handler"; @@ -13,6 +14,11 @@ export const updateCheckerRequestHandler = createCachedRequestHandler({ queryKey: "homarr-update-checker", cacheDuration: dayjs.duration(1, "hour"), async requestAsync(_) { + if (env.NO_EXTERNAL_CONNECTION) + return { + availableUpdates: [], + }; + const octokit = new Octokit({ request: { fetch: fetchWithTimeout,