diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md
index a46d563be6d49e69b4a4d82f7e8f8bfff1fea548..e0bdd18a359bfd5f724536bb4529b420a5d2b4c2 100644
--- a/docs/usage/self-hosted-configuration.md
+++ b/docs/usage/self-hosted-configuration.md
@@ -415,9 +415,19 @@ In practice, it is implemented by converting the `force` configuration into a `p
 This is set to `true` by default, meaning that any settings (such as `schedule`) take maximum priority even against custom settings existing inside individual repositories.
 It will also override any settings in `packageRules`.
 
-## forkToken
+## forkOrg
+
+This configuration option lets you choose an organization you want repositories forked into when "fork mode" is enabled.
+It must be set to a GitHub Organization name and not a GitHub user account.
+
+This can be used if you're migrating from user-based forks to organization-based forks.
 
-You probably don't need this option - it is an experimental setting developed for the Forking Renovate hosted GitHub App.
+If you've set a `forkOrg` then Renovate will:
+
+1. Check if a fork exists in the preferred organization before checking it exists in the fork user's account
+1. If no fork exists: it will be created in the `forkOrg`, not the user account
+
+## forkToken
 
 If this value is configured then Renovate:
 
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index ce143bdf4c053d6217ac4e798e5310c06c24dd56..061d43406688649b74607155e0093a7a278267a0 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -444,6 +444,16 @@ const options: RenovateOptions[] = [
     supportedPlatforms: ['github'],
     experimental: true,
   },
+  {
+    name: 'forkOrg',
+    description:
+      'The preferred organization to create or find forked repositories, when in fork mode.',
+    stage: 'repository',
+    type: 'string',
+    globalOnly: true,
+    supportedPlatforms: ['github'],
+    experimental: true,
+  },
   {
     name: 'githubTokenWarn',
     description: 'Display warnings about GitHub token not being set.',
diff --git a/lib/modules/platform/github/__snapshots__/index.spec.ts.snap b/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
index 8dbafeab1175df2142851f1ccc61680de5a478eb..9bbc6ed9a5e14e70751318d56f3b45ad2c4a7b4f 100644
--- a/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
+++ b/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
@@ -111,7 +111,7 @@ exports[`modules/platform/github/index initRepo should squash 1`] = `
 }
 `;
 
-exports[`modules/platform/github/index initRepo should update fork when using forkToken 1`] = `
+exports[`modules/platform/github/index initRepo should update fork when using forkToken and forkOrg 1`] = `
 {
   "defaultBranch": "master",
   "isFork": false,
diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts
index fd917c0a98daa33aa82b8fc8bc9e61c25a2603a1..11cda7e46dc6beb30f8e728b09c414f60caebe02 100644
--- a/lib/modules/platform/github/index.spec.ts
+++ b/lib/modules/platform/github/index.spec.ts
@@ -397,26 +397,24 @@ describe('modules/platform/github/index', () => {
       scope.get('/user').reply(200, {
         login: 'forked',
       });
-      // getBranchCommit
       scope.post(`/repos/${repo}/forks`).reply(500);
       await expect(
         github.initRepo({
           repository: 'some/repo',
           forkToken: 'true',
+          forkOrg: 'forked',
         })
       ).rejects.toThrow(REPOSITORY_CANNOT_FORK);
     });
 
-    it('should update fork when using forkToken', async () => {
+    it('should update fork when using forkToken and forkOrg', async () => {
       const scope = httpMock.scope(githubApiHost);
       forkInitRepoMock(scope, 'some/repo', true);
-      scope.get('/user').reply(200, {
-        login: 'forked',
-      });
       scope.patch('/repos/forked/repo/git/refs/heads/master').reply(200);
       const config = await github.initRepo({
         repository: 'some/repo',
         forkToken: 'true',
+        forkOrg: 'forked',
       });
       expect(config).toMatchSnapshot();
     });
diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts
index d00cc2df6365c34883116a1c4bedd7710f711356..8b477ebbbaebb5417a1a84b14c40180033bc22fa 100644
--- a/lib/modules/platform/github/index.ts
+++ b/lib/modules/platform/github/index.ts
@@ -257,20 +257,6 @@ export async function getJsonFile(
   return JSON5.parse(raw);
 }
 
-export async function getForkOrgs(token: string): Promise<string[]> {
-  // This function will be adapted later to support configured forkOrgs
-  if (!config.renovateForkUser) {
-    try {
-      logger.debug('Determining fork user from API');
-      const userDetails = await getUserDetails(platformConfig.endpoint, token);
-      config.renovateForkUser = userDetails.username;
-    } catch (err) {
-      logger.debug({ err }, 'Error getting username for forkToken');
-    }
-  }
-  return config.renovateForkUser ? [config.renovateForkUser] : [];
-}
-
 export async function listForks(
   token: string,
   repository: string
@@ -299,28 +285,38 @@ export async function listForks(
 
 export async function findFork(
   token: string,
-  repository: string
+  repository: string,
+  forkOrg?: string
 ): Promise<GhRestRepo | null> {
   const forks = await listForks(token, repository);
-  const orgs = await getForkOrgs(token);
-  if (!orgs.length) {
-    throw new Error(REPOSITORY_CANNOT_FORK);
+  if (forkOrg) {
+    logger.debug(`Searching for forked repo in forkOrg (${forkOrg})`);
+    const forkedRepo = forks.find((repo) => repo.owner.login === forkOrg);
+    if (forkedRepo) {
+      logger.debug(`Found repo in forkOrg: ${forkedRepo.full_name}`);
+      return forkedRepo;
+    }
+    logger.debug(`No repo found in forkOrg`);
   }
-  let forkedRepo: GhRestRepo | undefined;
-  for (const forkOrg of orgs) {
-    logger.debug(`Searching for forked repo in ${forkOrg}`);
-    forkedRepo = forks.find((repo) => repo.owner.login === forkOrg);
+  logger.debug(`Searching for forked repo in user account`);
+  try {
+    const { username } = await getUserDetails(platformConfig.endpoint, token);
+    const forkedRepo = forks.find((repo) => repo.owner.login === username);
     if (forkedRepo) {
-      logger.debug(`Found existing forked repo: ${forkedRepo.full_name}`);
-      break;
+      logger.debug(`Found repo in user account: ${forkedRepo.full_name}`);
+      return forkedRepo;
     }
+  } catch (err) {
+    throw new Error(REPOSITORY_CANNOT_FORK);
   }
-  return forkedRepo ?? null;
+  logger.debug(`No repo found in user account`);
+  return null;
 }
 
 export async function createFork(
   token: string,
-  repository: string
+  repository: string,
+  forkOrg?: string
 ): Promise<GhRestRepo> {
   let forkedRepo: GhRestRepo | undefined;
   try {
@@ -328,6 +324,7 @@ export async function createFork(
       await githubApi.postJson<GhRestRepo>(`repos/${repository}/forks`, {
         token,
         body: {
+          organization: forkOrg ? forkOrg : undefined,
           name: config.parentRepo!.replace('/', '-_-'),
           default_branch_only: true, // no baseBranches support yet
         },
@@ -339,7 +336,8 @@ export async function createFork(
   if (!forkedRepo) {
     throw new Error(REPOSITORY_CANNOT_FORK);
   }
-  logger.debug(`Created forked repo ${forkedRepo.full_name}, now sleeping 30s`);
+  logger.info({ forkedRepo: forkedRepo.full_name }, 'Created forked repo');
+  logger.debug(`Sleeping 30s after creating fork`);
   await delay(30000);
   return forkedRepo;
 }
@@ -348,6 +346,7 @@ export async function createFork(
 export async function initRepo({
   endpoint,
   repository,
+  forkOrg,
   forkToken,
   renovateUsername,
   cloneSubmodules,
@@ -489,7 +488,7 @@ export async function initRepo({
     // save parent name then delete
     config.parentRepo = config.repository;
     config.repository = null;
-    let forkedRepo = await findFork(forkToken, repository);
+    let forkedRepo = await findFork(forkToken, repository, forkOrg);
     if (forkedRepo) {
       config.repository = forkedRepo.full_name;
       const forkDefaultBranch = forkedRepo.default_branch;
@@ -567,7 +566,7 @@ export async function initRepo({
       }
     } else {
       logger.debug('Forked repo is not found - attempting to create it');
-      forkedRepo = await createFork(forkToken, repository);
+      forkedRepo = await createFork(forkToken, repository, forkOrg);
       config.repository = forkedRepo.full_name;
     }
   }
diff --git a/lib/modules/platform/github/types.ts b/lib/modules/platform/github/types.ts
index ef01406661370ba3fb352567642a5a84a8b13d08..e285ea5a23b036d879c8399cf4a377486338484d 100644
--- a/lib/modules/platform/github/types.ts
+++ b/lib/modules/platform/github/types.ts
@@ -90,6 +90,7 @@ export interface LocalRepoConfig {
   prReviewsRequired: boolean;
   repoForceRebase?: boolean;
   parentRepo: string | null;
+  forkOrg?: string;
   forkToken?: string;
   prList: GhPr[] | null;
   issueList: any[] | null;
diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts
index 4a0d5a825b9cb28f5c48c8f61b04df79561e2598..d9bc8f84caa40d8e8cebf538972869686e5b3d73 100644
--- a/lib/modules/platform/types.ts
+++ b/lib/modules/platform/types.ts
@@ -37,6 +37,7 @@ export interface RepoParams {
   repository: string;
   endpoint?: string;
   gitUrl?: GitUrlOption;
+  forkOrg?: string;
   forkToken?: string;
   forkProcessing?: 'enabled' | 'disabled';
   renovateUsername?: string;