diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md
index f80219fd96fde904cc2ab13ef6ee78f0c5a72535..78ea76a020dba67cab909db0aff22e090fff1d86 100644
--- a/docs/usage/self-hosted-experimental.md
+++ b/docs/usage/self-hosted-experimental.md
@@ -23,6 +23,13 @@ For more information see [the OpenTelemetry docs](opentelemetry.md).
 
 If set to any value, Renovate will always paginate requests to GitHub fully, instead of stopping after 10 pages.
 
+## `RENOVATE_STATIC_REPO_CONFIG`
+
+If set to a _valid_ `JSON` string containing a _valid_ Renovate configuration, it will be applied to the repository config before resolving the actual configuration file within the repository.
+
+> [!warning]
+> An invalid value will result in the scan being aborted.
+
 ## `RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP`
 
 If set to any value, Renovate will skip attempting to get release labels (e.g. gitRef, sourceUrl) from manifest annotations for `https://index.docker.io`.
diff --git a/lib/workers/global/config/parse/env.ts b/lib/workers/global/config/parse/env.ts
index a5543bb1983549ff19146c0f29d4765c97af9b26..79ed110d6b5be095a6332d3b96ddaf8736d30a7a 100644
--- a/lib/workers/global/config/parse/env.ts
+++ b/lib/workers/global/config/parse/env.ts
@@ -121,16 +121,10 @@ export async function getConfig(
   inputEnv: NodeJS.ProcessEnv,
   configEnvKey = 'RENOVATE_CONFIG',
 ): Promise<AllConfig> {
-  let env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
-  env = massageConvertedExperimentalVars(env);
-  env = renameEnvKeys(env);
-  // massage the values of migrated configuration keys
-  env = massageEnvKeyValues(env);
-
-  const options = getOptions();
-
+  const env = prepareEnv(inputEnv);
   const config = await parseAndValidateOrExit(env, configEnvKey);
 
+  const options = getOptions();
   config.hostRules ??= [];
 
   for (const option of options) {
@@ -235,7 +229,15 @@ export async function getConfig(
   return config;
 }
 
-async function parseAndValidateOrExit(
+export function prepareEnv(inputEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
+  let env = normalizePrefixes(inputEnv, inputEnv.ENV_PREFIX);
+  env = massageConvertedExperimentalVars(env);
+  env = renameEnvKeys(env);
+  // massage the values of migrated configuration keys
+  return massageEnvKeyValues(env);
+}
+
+export async function parseAndValidateOrExit(
   env: NodeJS.ProcessEnv,
   configEnvKey: string,
 ): Promise<AllConfig> {
diff --git a/lib/workers/repository/init/config.spec.ts b/lib/workers/repository/init/config.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..33cedcd071fd81f820a74f1ae1e1921b8fa0b585
--- /dev/null
+++ b/lib/workers/repository/init/config.spec.ts
@@ -0,0 +1,46 @@
+import type { AllConfig } from '../../../config/types';
+import { mergeStaticRepoEnvConfig } from './config';
+
+describe('workers/repository/init/config', () => {
+  describe('mergeRepoEnvConfig()', () => {
+    type MergeRepoEnvTestCase = {
+      name: string;
+      env: NodeJS.ProcessEnv;
+      currentConfig: AllConfig;
+      wantConfig: AllConfig;
+    };
+
+    const testCases: MergeRepoEnvTestCase[] = [
+      {
+        name: 'it does nothing',
+        env: {},
+        currentConfig: { repositories: ['some/repo'] },
+        wantConfig: { repositories: ['some/repo'] },
+      },
+      {
+        name: 'it merges env with the current config',
+        env: { RENOVATE_STATIC_REPO_CONFIG: '{"dependencyDashboard":true}' },
+        currentConfig: { repositories: ['some/repo'] },
+        wantConfig: {
+          dependencyDashboard: true,
+          repositories: ['some/repo'],
+        },
+      },
+      {
+        name: 'it ignores env with other renovate specific configuration options',
+        env: { RENOVATE_CONFIG: '{"dependencyDashboard":true}' },
+        currentConfig: { repositories: ['some/repo'] },
+        wantConfig: { repositories: ['some/repo'] },
+      },
+    ];
+
+    it.each(testCases)(
+      '$name',
+      async ({ env, currentConfig, wantConfig }: MergeRepoEnvTestCase) => {
+        const got = await mergeStaticRepoEnvConfig(currentConfig, env);
+
+        expect(got).toEqual(wantConfig);
+      },
+    );
+  });
+});
diff --git a/lib/workers/repository/init/config.ts b/lib/workers/repository/init/config.ts
index a8f9a14c6dfeceb8b5b3293cdccd72dce10ab32b..fe3122896b32aee3f819b32092c118f644e0800a 100644
--- a/lib/workers/repository/init/config.ts
+++ b/lib/workers/repository/init/config.ts
@@ -1,4 +1,7 @@
-import type { RenovateConfig } from '../../../config/types';
+import is from '@sindresorhus/is';
+import { mergeChildConfig } from '../../../config';
+import type { AllConfig, RenovateConfig } from '../../../config/types';
+import { parseAndValidateOrExit } from '../../global/config/parse/env';
 import { checkOnboardingBranch } from '../onboarding/branch';
 import { mergeInheritedConfig } from './inherited';
 import { mergeRenovateConfig } from './merge';
@@ -10,7 +13,24 @@ export async function getRepoConfig(
   let config = { ...config_ };
   config.baseBranch = config.defaultBranch;
   config = await mergeInheritedConfig(config);
+  config = await mergeStaticRepoEnvConfig(config, process.env);
   config = await checkOnboardingBranch(config);
   config = await mergeRenovateConfig(config);
   return config;
 }
+
+export async function mergeStaticRepoEnvConfig(
+  config: AllConfig,
+  env: NodeJS.ProcessEnv,
+): Promise<AllConfig> {
+  const repoEnvConfig = await parseAndValidateOrExit(
+    env,
+    'RENOVATE_STATIC_REPO_CONFIG',
+  );
+
+  if (!is.nonEmptyObject(repoEnvConfig)) {
+    return config;
+  }
+
+  return mergeChildConfig(config, repoEnvConfig);
+}