diff --git a/lib/modules/datasource/api.ts b/lib/modules/datasource/api.ts
index ff31d16c158362b528f1b9e6306cbe2407cb241e..eff7da102edd8136fcde6580fc36a0637c1e9ebd 100644
--- a/lib/modules/datasource/api.ts
+++ b/lib/modules/datasource/api.ts
@@ -32,6 +32,7 @@ import { GithubTagsDatasource } from './github-tags';
 import { GitlabPackagesDatasource } from './gitlab-packages';
 import { GitlabReleasesDatasource } from './gitlab-releases';
 import { GitlabTagsDatasource } from './gitlab-tags';
+import { GlasskubePackagesDatasource } from './glasskube-packages';
 import { GoDatasource } from './go';
 import { GolangVersionDatasource } from './golang-version';
 import { GradleVersionDatasource } from './gradle-version';
@@ -102,6 +103,7 @@ api.set(GithubTagsDatasource.id, new GithubTagsDatasource());
 api.set(GitlabPackagesDatasource.id, new GitlabPackagesDatasource());
 api.set(GitlabReleasesDatasource.id, new GitlabReleasesDatasource());
 api.set(GitlabTagsDatasource.id, new GitlabTagsDatasource());
+api.set(GlasskubePackagesDatasource.id, new GlasskubePackagesDatasource());
 api.set(GoDatasource.id, new GoDatasource());
 api.set(GolangVersionDatasource.id, new GolangVersionDatasource());
 api.set(GradleVersionDatasource.id, new GradleVersionDatasource());
diff --git a/lib/modules/datasource/glasskube-packages/__fixtures__/package.yaml b/lib/modules/datasource/glasskube-packages/__fixtures__/package.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f3a2c5e887dd4ecc0eaf4ae4244bc5f7062484bd
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/__fixtures__/package.yaml
@@ -0,0 +1,18 @@
+# yaml-language-server: $schema=https://glasskube.dev/schemas/v1/package-manifest.json
+name: cloudnative-pg
+iconUrl: https://github.com/glasskube/glasskube/assets/16959694/99f3192a-587f-4eb9-884d-62800c022992
+shortDescription: A comprehensive platform designed to seamlessly manage PostgreSQL databases
+longDescription: |
+  **CloudNativePG** is an open source operator designed to manage PostgreSQL workloads on any supported Kubernetes
+  cluster running in private, public, hybrid, or multi-cloud environments. CloudNativePG adheres to DevOps principles
+  and concepts such as declarative configuration and immutable infrastructure.
+references:
+  - label: GitHub
+    url: https://github.com/cloudnative-pg/cloudnative-pg
+  - label: Website
+    url: https://cloudnative-pg.io/
+  - label: Documentation
+    url: https://cloudnative-pg.io/documentation/1.23/
+defaultNamespace: cnpg-system
+manifests:
+  - url: https://github.com/cloudnative-pg/cloudnative-pg/releases/download/v1.23.1/cnpg-1.23.1.yaml
diff --git a/lib/modules/datasource/glasskube-packages/__fixtures__/package_no_references.yaml b/lib/modules/datasource/glasskube-packages/__fixtures__/package_no_references.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6ca871e6c6eb535b7e43992f02ed5e9f205c95d6
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/__fixtures__/package_no_references.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=https://glasskube.dev/schemas/v1/package-manifest.json
+name: cloudnative-pg
+iconUrl: https://github.com/glasskube/glasskube/assets/16959694/99f3192a-587f-4eb9-884d-62800c022992
+shortDescription: A comprehensive platform designed to seamlessly manage PostgreSQL databases
+longDescription: |
+  **CloudNativePG** is an open source operator designed to manage PostgreSQL workloads on any supported Kubernetes
+  cluster running in private, public, hybrid, or multi-cloud environments. CloudNativePG adheres to DevOps principles
+  and concepts such as declarative configuration and immutable infrastructure.
+defaultNamespace: cnpg-system
+manifests:
+  - url: https://github.com/cloudnative-pg/cloudnative-pg/releases/download/v1.23.1/cnpg-1.23.1.yaml
diff --git a/lib/modules/datasource/glasskube-packages/__fixtures__/versions.yaml b/lib/modules/datasource/glasskube-packages/__fixtures__/versions.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..23416688f31514afcbc789f4dac4da61fbea39f8
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/__fixtures__/versions.yaml
@@ -0,0 +1,4 @@
+latestVersion: v1.23.1+1
+versions:
+  - version: v1.22.0+1
+  - version: v1.23.1+1
diff --git a/lib/modules/datasource/glasskube-packages/index.spec.ts b/lib/modules/datasource/glasskube-packages/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a136cd13b4bc66dd768d9ed9fb7afda645d8ed57
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/index.spec.ts
@@ -0,0 +1,153 @@
+import { getPkgReleases } from '..';
+import { Fixtures } from '../../../../test/fixtures';
+import * as httpMock from '../../../../test/http-mock';
+import { GlasskubePackagesDatasource } from '.';
+
+describe('modules/datasource/glasskube-packages/index', () => {
+  const customRegistryUrl = 'https://packages.test.example/packages';
+  const customVersionsUrl = new URL(
+    `${customRegistryUrl}/cloudnative-pg/versions.yaml`,
+  );
+  const defaultVersionUrl = new URL(
+    `${GlasskubePackagesDatasource.defaultRegistryUrl}/cloudnative-pg/versions.yaml`,
+  );
+  const versionsYaml = Fixtures.get('versions.yaml');
+  const customPackageManifestUrl = new URL(
+    `${customRegistryUrl}/cloudnative-pg/v1.23.1+1/package.yaml`,
+  );
+  const defaultPackageManifestUrl = new URL(
+    `${GlasskubePackagesDatasource.defaultRegistryUrl}/cloudnative-pg/v1.23.1+1/package.yaml`,
+  );
+  const packageManifestYaml = Fixtures.get('package.yaml');
+  const packageManifestNoReferencesYaml = Fixtures.get(
+    'package_no_references.yaml',
+  );
+
+  it('should handle error response on versions request', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(500, 'internal server error');
+    await expect(
+      getPkgReleases({
+        datasource: GlasskubePackagesDatasource.id,
+        packageName: 'cloudnative-pg',
+        registryUrls: [customRegistryUrl],
+      }),
+    ).rejects.toThrow();
+  });
+
+  it('should handle empty response on versions request', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(200);
+    const response = await getPkgReleases({
+      datasource: GlasskubePackagesDatasource.id,
+      packageName: 'cloudnative-pg',
+      registryUrls: [customRegistryUrl],
+    });
+    expect(response).toBeNull();
+  });
+
+  it('should handle error response on manifest request', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(200, versionsYaml);
+    httpMock
+      .scope(customPackageManifestUrl.origin)
+      .get(customPackageManifestUrl.pathname)
+      .reply(500, 'internal server error');
+    await expect(
+      getPkgReleases({
+        datasource: GlasskubePackagesDatasource.id,
+        packageName: 'cloudnative-pg',
+        registryUrls: [customRegistryUrl],
+      }),
+    ).rejects.toThrow();
+  });
+
+  it('should handle empty response on manifest request', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(200, versionsYaml);
+    httpMock
+      .scope(customPackageManifestUrl.origin)
+      .get(customPackageManifestUrl.pathname)
+      .reply(200);
+    const response = await getPkgReleases({
+      datasource: GlasskubePackagesDatasource.id,
+      packageName: 'cloudnative-pg',
+      registryUrls: [customRegistryUrl],
+    });
+    expect(response).toBeNull();
+  });
+
+  it('should handle package manifest without references', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(200, versionsYaml);
+    httpMock
+      .scope(customPackageManifestUrl.origin)
+      .get(customPackageManifestUrl.pathname)
+      .reply(200, packageManifestNoReferencesYaml);
+    const response = await getPkgReleases({
+      datasource: GlasskubePackagesDatasource.id,
+      packageName: 'cloudnative-pg',
+      registryUrls: [customRegistryUrl],
+    });
+    expect(response).toEqual({
+      registryUrl: customRegistryUrl,
+      tags: { latest: 'v1.23.1+1' },
+      releases: [{ version: 'v1.22.0+1' }, { version: 'v1.23.1+1' }],
+    });
+  });
+
+  it('should handle package manifest with references and default url', async () => {
+    httpMock
+      .scope(defaultVersionUrl.origin)
+      .get(defaultVersionUrl.pathname)
+      .reply(200, versionsYaml);
+    httpMock
+      .scope(defaultPackageManifestUrl.origin)
+      .get(defaultPackageManifestUrl.pathname)
+      .reply(200, packageManifestYaml);
+    const response = await getPkgReleases({
+      datasource: GlasskubePackagesDatasource.id,
+      packageName: 'cloudnative-pg',
+    });
+    expect(response).toEqual({
+      sourceUrl: 'https://github.com/cloudnative-pg/cloudnative-pg',
+      homepage: 'https://cloudnative-pg.io/',
+      registryUrl: GlasskubePackagesDatasource.defaultRegistryUrl,
+      tags: { latest: 'v1.23.1+1' },
+      releases: [{ version: 'v1.22.0+1' }, { version: 'v1.23.1+1' }],
+    });
+  });
+
+  it('should handle package manifest with references and custom url', async () => {
+    httpMock
+      .scope(customVersionsUrl.origin)
+      .get(customVersionsUrl.pathname)
+      .reply(200, versionsYaml);
+    httpMock
+      .scope(customPackageManifestUrl.origin)
+      .get(customPackageManifestUrl.pathname)
+      .reply(200, packageManifestYaml);
+    const response = await getPkgReleases({
+      datasource: GlasskubePackagesDatasource.id,
+      packageName: 'cloudnative-pg',
+      registryUrls: [customRegistryUrl],
+    });
+    expect(response).toEqual({
+      sourceUrl: 'https://github.com/cloudnative-pg/cloudnative-pg',
+      homepage: 'https://cloudnative-pg.io/',
+      registryUrl: customRegistryUrl,
+      tags: { latest: 'v1.23.1+1' },
+      releases: [{ version: 'v1.22.0+1' }, { version: 'v1.23.1+1' }],
+    });
+  });
+});
diff --git a/lib/modules/datasource/glasskube-packages/index.ts b/lib/modules/datasource/glasskube-packages/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fef07896ed597232db520d6cb1caf1a2adabbbc1
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/index.ts
@@ -0,0 +1,76 @@
+import { cache } from '../../../util/cache/package/decorator';
+import { joinUrlParts } from '../../../util/url';
+import * as glasskubeVersioning from '../../versioning/glasskube';
+import { Datasource } from '../datasource';
+import type { GetReleasesConfig, ReleaseResult } from '../types';
+import {
+  GlasskubePackageManifestYaml,
+  GlasskubePackageVersions,
+  GlasskubePackageVersionsYaml,
+} from './schema';
+
+export class GlasskubePackagesDatasource extends Datasource {
+  static readonly id = 'glasskube-packages';
+  static readonly defaultRegistryUrl =
+    'https://packages.dl.glasskube.dev/packages';
+  override readonly customRegistrySupport = true;
+  override defaultVersioning = glasskubeVersioning.id;
+
+  override defaultRegistryUrls = [
+    GlasskubePackagesDatasource.defaultRegistryUrl,
+  ];
+
+  constructor() {
+    super(GlasskubePackagesDatasource.id);
+  }
+
+  @cache({
+    namespace: `datasource-${GlasskubePackagesDatasource.id}`,
+    key: ({ registryUrl, packageName }: GetReleasesConfig) =>
+      `${registryUrl}:${packageName}`,
+  })
+  override async getReleases({
+    packageName,
+    registryUrl,
+  }: GetReleasesConfig): Promise<ReleaseResult | null> {
+    let versions: GlasskubePackageVersions;
+    const result: ReleaseResult = { releases: [] };
+
+    try {
+      const response = await this.http.get(
+        joinUrlParts(registryUrl!, packageName, 'versions.yaml'),
+      );
+      versions = GlasskubePackageVersionsYaml.parse(response.body);
+    } catch (err) {
+      this.handleGenericErrors(err);
+    }
+
+    result.releases = versions.versions.map((it) => ({
+      version: it.version,
+    }));
+    result.tags = { latest: versions.latestVersion };
+
+    try {
+      const response = await this.http.get(
+        joinUrlParts(
+          registryUrl!,
+          packageName,
+          versions.latestVersion,
+          'package.yaml',
+        ),
+      );
+      const latestManifest = GlasskubePackageManifestYaml.parse(response.body);
+      for (const ref of latestManifest?.references ?? []) {
+        if (ref.label.toLowerCase() === 'github') {
+          result.sourceUrl = ref.url;
+        } else if (ref.label.toLowerCase() === 'website') {
+          result.homepage = ref.url;
+        }
+      }
+    } catch (err) {
+      this.handleGenericErrors(err);
+    }
+
+    return result;
+  }
+}
diff --git a/lib/modules/datasource/glasskube-packages/schema.ts b/lib/modules/datasource/glasskube-packages/schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5e299304b4104fe203540b04c2117d61af03e119
--- /dev/null
+++ b/lib/modules/datasource/glasskube-packages/schema.ts
@@ -0,0 +1,23 @@
+import { z } from 'zod';
+import { Yaml } from '../../../util/schema-utils';
+
+const GlasskubePackageVersions = z.object({
+  latestVersion: z.string(),
+  versions: z.array(z.object({ version: z.string() })),
+});
+
+const GlasskubePackageManifest = z.object({
+  references: z.optional(
+    z.array(
+      z.object({
+        label: z.string(),
+        url: z.string(),
+      }),
+    ),
+  ),
+});
+
+export const GlasskubePackageVersionsYaml = Yaml.pipe(GlasskubePackageVersions);
+export const GlasskubePackageManifestYaml = Yaml.pipe(GlasskubePackageManifest);
+
+export type GlasskubePackageVersions = z.infer<typeof GlasskubePackageVersions>;
diff --git a/lib/util/cache/package/types.ts b/lib/util/cache/package/types.ts
index e301414c99be6e7633e1667ef7c545f6bfdf54b2..e8a479bd1dce51682516a06a593847701f40d2f8 100644
--- a/lib/util/cache/package/types.ts
+++ b/lib/util/cache/package/types.ts
@@ -67,6 +67,7 @@ export type PackageCacheNamespace =
   | 'datasource-gitlab-releases'
   | 'datasource-gitlab-tags-commit'
   | 'datasource-gitlab-tags'
+  | 'datasource-glasskube-packages'
   | 'datasource-go-direct'
   | 'datasource-go-proxy'
   | 'datasource-go'