diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md
index 7ee6a8ee1f39df388a9f1633a6ba96a36f562e67..c0b0ef870d82859db9e8dd65ca3fe779a2514078 100644
--- a/docs/usage/self-hosted-experimental.md
+++ b/docs/usage/self-hosted-experimental.md
@@ -48,6 +48,8 @@ If set to any string, Renovate will use this as the `user-agent` it sends with H
 
 The order method for autodiscover server side repository search.
 
+> If multiple `autodiscoverTopics` are used resulting order will be per topic not global.
+
 Allowed values:
 
 - `asc`
@@ -63,6 +65,8 @@ Default value: `asc`.
 
 The sort method for autodiscover server side repository search.
 
+> If multiple `autodiscoverTopics` are used resulting order will be per topic not global.
+
 Allowed values:
 
 - `alpha`
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index 6531151a934f8810b210c65d4ac2dd5232e0c0fb..e5896456e70d88d789932c4639e5c4522590a1da 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -862,7 +862,7 @@ const options: RenovateOptions[] = [
     subType: 'string',
     default: null,
     globalOnly: true,
-    supportedPlatforms: ['github', 'gitlab'],
+    supportedPlatforms: ['gitea', 'github', 'gitlab'],
   },
   {
     name: 'prCommitsPerRunLimit',
diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts
index ae9a7a9abbd571442890a7980dad4881e53b5c48..3084f4a3c169b07cf4aa8665f43a29bc922087d1 100644
--- a/lib/modules/platform/gitea/index.spec.ts
+++ b/lib/modules/platform/gitea/index.spec.ts
@@ -70,6 +70,8 @@ describe('modules/platform/gitea/index', () => {
     partial<Repo>({ full_name: 'e/f', mirror: true }),
   ];
 
+  const mockTopicRepos: Repo[] = [partial<Repo>({ full_name: 'a/b' })];
+
   const mockPRs: MockPr[] = [
     partial<MockPr>({
       number: 1,
@@ -351,6 +353,43 @@ describe('modules/platform/gitea/index', () => {
       expect(repos).toEqual(['a/b', 'c/d']);
     });
 
+    it('should return an filtered array of repos', async () => {
+      const scope = httpMock.scope('https://gitea.com/api/v1');
+
+      scope
+        .get('/repos/search')
+        .query({
+          uid: 1,
+          archived: false,
+          q: 'renovate',
+          topic: true,
+        })
+        .reply(200, {
+          ok: true,
+          data: mockTopicRepos,
+        });
+
+      scope
+        .get('/repos/search')
+        .query({
+          uid: 1,
+          archived: false,
+          q: 'renovatebot',
+          topic: true,
+        })
+        .reply(200, {
+          ok: true,
+          data: mockTopicRepos,
+        });
+
+      await initFakePlatform(scope);
+
+      const repos = await gitea.getRepos({
+        topics: ['renovate', 'renovatebot'],
+      });
+      expect(repos).toEqual(['a/b']);
+    });
+
     it('Sorts repos', async () => {
       process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT = 'updated';
       process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER = 'desc';
diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts
index 13a8f50152b020224ea596aca3a73042f43bb879..595c8402221428336bf7de0600f761fd9db71c57 100644
--- a/lib/modules/platform/gitea/index.ts
+++ b/lib/modules/platform/gitea/index.ts
@@ -10,13 +10,16 @@ import {
 } from '../../../constants/error-messages';
 import { logger } from '../../../logger';
 import type { BranchStatus } from '../../../types';
+import { deduplicateArray } from '../../../util/array';
 import { parseJson } from '../../../util/common';
 import * as git from '../../../util/git';
 import { setBaseUrl } from '../../../util/http/gitea';
+import { map } from '../../../util/promises';
 import { sanitize } from '../../../util/sanitize';
 import { ensureTrailingSlash } from '../../../util/url';
 import { getPrBodyStruct, hashBody } from '../pr-body';
 import type {
+  AutodiscoverConfig,
   BranchStatusConfig,
   CreatePRConfig,
   EnsureCommentConfig,
@@ -154,6 +157,24 @@ async function lookupLabelByName(name: string): Promise<number | null> {
   return labelList.find((l) => l.name === name)?.id ?? null;
 }
 
+async function fetchRepositories(topic?: string): Promise<string[]> {
+  const repos = await helper.searchRepos({
+    uid: botUserID,
+    archived: false,
+    ...(topic && {
+      topic: true,
+      q: topic,
+    }),
+    ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT && {
+      sort: process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT as RepoSortMethod,
+    }),
+    ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER && {
+      order: process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER as SortMethod,
+    }),
+  });
+  return repos.filter((r) => !r.mirror).map((r) => r.full_name);
+}
+
 const platform: Platform = {
   async initPlatform({
     endpoint,
@@ -295,20 +316,15 @@ const platform: Platform = {
     };
   },
 
-  async getRepos(): Promise<string[]> {
+  async getRepos(config?: AutodiscoverConfig): Promise<string[]> {
     logger.debug('Auto-discovering Gitea repositories');
     try {
-      const repos = await helper.searchRepos({
-        uid: botUserID,
-        archived: false,
-        ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT && {
-          sort: process.env.RENOVATE_X_AUTODISCOVER_REPO_SORT as RepoSortMethod,
-        }),
-        ...(process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER && {
-          order: process.env.RENOVATE_X_AUTODISCOVER_REPO_ORDER as SortMethod,
-        }),
-      });
-      return repos.filter((r) => !r.mirror).map((r) => r.full_name);
+      if (!config?.topics) {
+        return await fetchRepositories();
+      }
+
+      const repos = await map(config.topics, fetchRepositories);
+      return deduplicateArray(repos.flat());
     } catch (err) {
       logger.error({ err }, 'Gitea getRepos() error');
       throw err;
diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts
index 6d0e9dbbbd122b285aecdb3418d5dfd20adc3c7d..877ea4436d0881bcdbbfbb3934f8acf5408d1d72 100644
--- a/lib/modules/platform/gitea/types.ts
+++ b/lib/modules/platform/gitea/types.ts
@@ -144,6 +144,8 @@ export type SortMethod = 'asc' | 'desc';
 export interface RepoSearchParams {
   uid?: number;
   archived?: boolean;
+  topic?: boolean;
+  q?: string;
 
   /**
    * Repo sort type, defaults to `alpha`.