diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md
index b1b8a67bd311bca185b299442897f74276e9f72e..04eb5a9ac6f5121f22d0a1c672e8663b4f4f939b 100644
--- a/docs/usage/self-hosted-configuration.md
+++ b/docs/usage/self-hosted-configuration.md
@@ -79,9 +79,9 @@ If you want Renovate to run on only a subset of those, use the `autodiscoverFilt
 ## autodiscoverFilter
 
 You can use this option to filter the list of repositories that the Renovate bot account can access through `autodiscover`.
-It takes a [minimatch](https://www.npmjs.com/package/minimatch) glob-style pattern.
+It takes a [minimatch](https://www.npmjs.com/package/minimatch) glob-style or regex pattern.
 
-e.g.
+**Minimatch**:
 
 ```json
 {
@@ -89,6 +89,24 @@ e.g.
 }
 ```
 
+**Regex**:
+
+All text inside the start and end `/` will be treated as a regular expression.
+
+```json
+{
+  "autodiscoverFilter": "/project/.*/"
+}
+```
+
+You can negate the regex by putting a `!` in front:
+
+```json
+{
+  "autodiscoverFilter": "!/project/.*/"
+}
+```
+
 ## baseDir
 
 By default Renovate uses a temporary directory like `/tmp/renovate` to store its data.
diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts
index 076d179cc3fa9c0975c37f99154ec7f23d6931e2..deaf9af9f8068263715b2eb203d9f87019a3d2a9 100644
--- a/lib/workers/global/autodiscover.spec.ts
+++ b/lib/workers/global/autodiscover.spec.ts
@@ -72,4 +72,42 @@ describe('workers/global/autodiscover', () => {
     const res = await autodiscoverRepositories(config);
     expect(res).toEqual(config);
   });
+  it('filters autodiscovered github repos with regex', async () => {
+    config.autodiscover = true;
+    config.autodiscoverFilter = '/project/re*./';
+    config.platform = PlatformId.Github;
+    hostRules.find = jest.fn(() => ({
+      token: 'abc',
+    }));
+    ghApi.getRepos = jest.fn(() =>
+      Promise.resolve(['project/repo', 'project/another-repo'])
+    );
+    const res = await autodiscoverRepositories(config);
+    expect(res.repositories).toEqual(['project/repo']);
+  });
+  it('filters autodiscovered github repos with regex negation', async () => {
+    config.autodiscover = true;
+    config.autodiscoverFilter = '!/project/re*./';
+    config.platform = PlatformId.Github;
+    hostRules.find = jest.fn(() => ({
+      token: 'abc',
+    }));
+    ghApi.getRepos = jest.fn(() =>
+      Promise.resolve(['project/repo', 'project/another-repo'])
+    );
+    const res = await autodiscoverRepositories(config);
+    expect(res.repositories).toEqual(['project/another-repo']);
+  });
+  it('fail if regex pattern is not valid', async () => {
+    config.autodiscover = true;
+    config.autodiscoverFilter = '/project/re**./';
+    config.platform = PlatformId.Github;
+    hostRules.find = jest.fn(() => ({
+      token: 'abc',
+    }));
+    ghApi.getRepos = jest.fn(() =>
+      Promise.resolve(['project/repo', 'project/another-repo'])
+    );
+    await expect(autodiscoverRepositories(config)).rejects.toThrow();
+  });
 });
diff --git a/lib/workers/global/autodiscover.ts b/lib/workers/global/autodiscover.ts
index 03b66b293acdf0c0c79b0b29e98005be2e0e945d..3a4c7747c6d6cfb54a3ee1b51c579ded93617de3 100644
--- a/lib/workers/global/autodiscover.ts
+++ b/lib/workers/global/autodiscover.ts
@@ -3,6 +3,7 @@ import minimatch from 'minimatch';
 import type { AllConfig } from '../../config/types';
 import { logger } from '../../logger';
 import { platform } from '../../platform';
+import { configRegexPredicate, isConfigRegex } from '../../util/regex';
 
 // istanbul ignore next
 function repoName(value: string | { repository: string }): string {
@@ -30,7 +31,19 @@ export async function autodiscoverRepositories(
     return config;
   }
   if (config.autodiscoverFilter) {
-    discovered = discovered.filter(minimatch.filter(config.autodiscoverFilter));
+    if (isConfigRegex(config.autodiscoverFilter)) {
+      const autodiscoveryPred = configRegexPredicate(config.autodiscoverFilter);
+      if (!autodiscoveryPred) {
+        throw new Error(
+          `Failed to parse regex pattern "${config.autodiscoverFilter}"`
+        );
+      }
+      discovered = discovered.filter(autodiscoveryPred);
+    } else {
+      discovered = discovered.filter(
+        minimatch.filter(config.autodiscoverFilter)
+      );
+    }
     if (!discovered.length) {
       // Soft fail (no error thrown) if no accessible repositories match the filter
       logger.debug('None of the discovered repositories matched the filter');