diff --git a/lib/modules/manager/git-submodules/extract.spec.ts b/lib/modules/manager/git-submodules/extract.spec.ts
index 6850f30f1930f47bd3cc04f231f349b0b3e67d1b..c6e53cc5ea7f5c024542eb89622f414a8bcf67c0 100644
--- a/lib/modules/manager/git-submodules/extract.spec.ts
+++ b/lib/modules/manager/git-submodules/extract.spec.ts
@@ -57,6 +57,29 @@ describe('modules/manager/git-submodules/extract', () => {
       expect(res?.deps[0].currentValue).toBe('main');
     });
 
+    it('default branch is detected with using git environment variables when no branch is specified', async () => {
+      gitMock.listRemote.mockResolvedValueOnce(
+        'ref: refs/heads/main  HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964        HEAD'
+      );
+      hostRules.add({
+        hostType: 'github',
+        matchHost: 'github.com',
+        token: 'abc123',
+      });
+      const res = await extractPackageFile('', '.gitmodules.2', {});
+      expect(res?.deps).toHaveLength(1);
+      expect(res?.deps[0].currentValue).toBe('main');
+      expect(gitMock.env).toHaveBeenCalledWith({
+        GIT_CONFIG_COUNT: '3',
+        GIT_CONFIG_KEY_0: 'url.https://ssh:abc123@github.com/.insteadOf',
+        GIT_CONFIG_KEY_1: 'url.https://git:abc123@github.com/.insteadOf',
+        GIT_CONFIG_KEY_2: 'url.https://abc123@github.com/.insteadOf',
+        GIT_CONFIG_VALUE_0: 'ssh://git@github.com/',
+        GIT_CONFIG_VALUE_1: 'git@github.com:',
+        GIT_CONFIG_VALUE_2: 'https://github.com/',
+      });
+    });
+
     it('default to master if no branch can be detected', async () => {
       const res = await extractPackageFile('', '.gitmodules.2', {});
       expect(res?.deps).toHaveLength(1);
diff --git a/lib/modules/manager/git-submodules/extract.ts b/lib/modules/manager/git-submodules/extract.ts
index 468a89a747ee1f61db2459cdb14cda0467894d24..b38aef1677d7a0b133d4e1e081ed1c3fdfbd1316 100644
--- a/lib/modules/manager/git-submodules/extract.ts
+++ b/lib/modules/manager/git-submodules/extract.ts
@@ -4,6 +4,7 @@ import upath from 'upath';
 import { GlobalConfig } from '../../../config/global';
 import { logger } from '../../../logger';
 import { detectPlatform } from '../../../util/common';
+import { getGitEnvironmentVariables } from '../../../util/git/auth';
 import { simpleGitConfig } from '../../../util/git/config';
 import { getHttpUrl, getRemoteUrlWithToken } from '../../../util/git/url';
 import { regEx } from '../../../util/regex';
@@ -37,11 +38,16 @@ async function getUrl(
 const headRefRe = regEx(/ref: refs\/heads\/(?<branch>\w+)\s/);
 
 async function getDefaultBranch(subModuleUrl: string): Promise<string> {
-  const val = await Git(simpleGitConfig()).listRemote([
-    '--symref',
-    subModuleUrl,
-    'HEAD',
-  ]);
+  const gitSubmoduleAuthEnvironmentVariables = getGitEnvironmentVariables();
+  const gitEnv = {
+    // pass all existing env variables
+    ...process.env,
+    // add all known git Variables
+    ...gitSubmoduleAuthEnvironmentVariables,
+  };
+  const val = await Git(simpleGitConfig())
+    .env(gitEnv)
+    .listRemote(['--symref', subModuleUrl, 'HEAD']);
   return headRefRe.exec(val)?.groups?.branch ?? 'master';
 }
 
diff --git a/lib/modules/manager/git-submodules/readme.md b/lib/modules/manager/git-submodules/readme.md
index 680c780f157855f00652859ca3ab01cb1dfe247b..a6194f456ca6dd87a058e44118b0c01d01449700 100644
--- a/lib/modules/manager/git-submodules/readme.md
+++ b/lib/modules/manager/git-submodules/readme.md
@@ -1,7 +1,4 @@
-Keeps publicly accessible Git submodules updated within a repository.
-
-Renovate does not support updating Git submodules that are hosted on a private repository.
-Subscribe to [issue #10149 on GitHub](https://github.com/renovatebot/renovate/issues/10149) to keep track of our progress towards supporting private Git submodules.
+Keeps Git submodules updated within a repository.
 
 You can customize the per-submodule checks of the git-submodules manager like this:
 
@@ -13,3 +10,19 @@ You can customize the per-submodule checks of the git-submodules manager like th
   }
 }
 ```
+
+### Private Modules Authentication
+
+Before running the `git` commands to update the submodules, Renovate exports `git` [`insteadOf`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf) directives in environment variables.
+
+The following logic is executed prior to "submodules" updating:
+
+The token from the `hostRules` entry matching `hostType=github` and `matchHost=api.github.com` is added as the default authentication for `github.com`.
+For those running against `github.com`, this token will be the default platform token.
+
+Next, all `hostRules` with both a token and `matchHost` will be fetched, except for any github.com one from above.
+
+Rules from this list are converted to environment variable directives if they match _any_ of the following characteristics:
+
+- No `hostType` is defined, or
+- `hostType` is a platform (`github`, `gitlab`, `azure`, etc.)
diff --git a/lib/modules/manager/git-submodules/update.spec.ts b/lib/modules/manager/git-submodules/update.spec.ts
index 6b5111ed5cea27cb4a6e099e1c989dbad7430fd2..2b77fd380385f4ae985bf744fbfcd45644f1d007 100644
--- a/lib/modules/manager/git-submodules/update.spec.ts
+++ b/lib/modules/manager/git-submodules/update.spec.ts
@@ -62,5 +62,30 @@ describe('modules/manager/git-submodules/update', () => {
       });
       expect(update).toBe('');
     });
+
+    it('returns content on update and uses git environment variables', async () => {
+      gitMock.submoduleUpdate.mockResolvedValue('');
+      gitMock.checkout.mockResolvedValue('');
+      hostRules.add({
+        hostType: 'github',
+        matchHost: 'github.com',
+        token: 'abc123',
+      });
+
+      const update = await updateDependency({
+        fileContent: '',
+        upgrade,
+      });
+      expect(update).toBe('');
+      expect(gitMock.env).toHaveBeenCalledWith({
+        GIT_CONFIG_COUNT: '3',
+        GIT_CONFIG_KEY_0: 'url.https://ssh:abc123@github.com/.insteadOf',
+        GIT_CONFIG_KEY_1: 'url.https://git:abc123@github.com/.insteadOf',
+        GIT_CONFIG_KEY_2: 'url.https://abc123@github.com/.insteadOf',
+        GIT_CONFIG_VALUE_0: 'ssh://git@github.com/',
+        GIT_CONFIG_VALUE_1: 'git@github.com:',
+        GIT_CONFIG_VALUE_2: 'https://github.com/',
+      });
+    });
   });
 });
diff --git a/lib/modules/manager/git-submodules/update.ts b/lib/modules/manager/git-submodules/update.ts
index 54df033376cba57c611fa2914e4284977d74126a..75eae26982f35436393490af2cdb8dd7e2c91591 100644
--- a/lib/modules/manager/git-submodules/update.ts
+++ b/lib/modules/manager/git-submodules/update.ts
@@ -2,6 +2,7 @@ import Git from 'simple-git';
 import upath from 'upath';
 import { GlobalConfig } from '../../../config/global';
 import { logger } from '../../../logger';
+import { getGitEnvironmentVariables } from '../../../util/git/auth';
 import type { UpdateDependencyConfig } from '../types';
 
 export default async function updateDependency({
@@ -9,7 +10,14 @@ export default async function updateDependency({
   upgrade,
 }: UpdateDependencyConfig): Promise<string | null> {
   const localDir = GlobalConfig.get('localDir');
-  const git = Git(localDir);
+  const gitSubmoduleAuthEnvironmentVariables = getGitEnvironmentVariables();
+  const gitEnv = {
+    // pass all existing env variables
+    ...process.env,
+    // add all known git Variables
+    ...gitSubmoduleAuthEnvironmentVariables,
+  };
+  const git = Git(localDir).env(gitEnv);
   const submoduleGit = Git(upath.join(localDir, upgrade.depName));
 
   try {