diff --git a/lib/modules/datasource/repology/readme.md b/lib/modules/datasource/repology/readme.md
index c6589c338637349be8ccdcbc8151b8f6683d9ddd..001015b3f7cfe5b68379467c1bbf4e4868ec1dae 100644
--- a/lib/modules/datasource/repology/readme.md
+++ b/lib/modules/datasource/repology/readme.md
@@ -49,5 +49,5 @@ When the operating system package for `gcc` of `Alpine Linux 3.12` is updated, R
 
 <!-- prettier-ignore -->
 !!! tip
-    We recommend you try `loose` versioning for distribution packages first.
+    We recommend you try `loose` or `deb` versioning for distribution packages first.
     This is because the version number usually doesn't match Renovate's default `semver` specification.
diff --git a/lib/modules/versioning/api.ts b/lib/modules/versioning/api.ts
index 089d31360de60c8d4b9e0e0178db26197440aa35..3fc867e4472a721a90dcd50b2d5072213e6bcc87 100644
--- a/lib/modules/versioning/api.ts
+++ b/lib/modules/versioning/api.ts
@@ -2,6 +2,7 @@ import * as amazonMachineImage from './aws-machine-image';
 import * as cargo from './cargo';
 import * as composer from './composer';
 import * as conan from './conan';
+import * as deb from './deb';
 import * as debian from './debian';
 import * as docker from './docker';
 import * as git from './git';
@@ -40,6 +41,7 @@ api.set(amazonMachineImage.id, amazonMachineImage.api);
 api.set(cargo.id, cargo.api);
 api.set(composer.id, composer.api);
 api.set(conan.id, conan.api);
+api.set(deb.id, deb.api);
 api.set(debian.id, debian.api);
 api.set(docker.id, docker.api);
 api.set(git.id, git.api);
diff --git a/lib/modules/versioning/deb/index.spec.ts b/lib/modules/versioning/deb/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f571a9674b6f45b5ddeb9b0ea1e2b54b571aca02
--- /dev/null
+++ b/lib/modules/versioning/deb/index.spec.ts
@@ -0,0 +1,174 @@
+import deb from '.';
+
+describe('modules/versioning/deb/index', () => {
+  test.each`
+    version                                        | expected
+    ${'1.1'}                                       | ${true}
+    ${'1.3.RC2'}                                   | ${true}
+    ${'0:1.1-1'}                                   | ${true}
+    ${'a:1.1-1'}                                   | ${false}
+    ${'1.1:1.3-1'}                                 | ${false}
+    ${'1.1a:1.3-1'}                                | ${false}
+    ${'1a:1.3-1'}                                  | ${false}
+    ${'-1:1.3-1'}                                  | ${false}
+    ${'1:1:1:2-1'}                                 | ${true}
+    ${'1:a:b:c:2-1'}                               | ${true}
+    ${'1:3_3.2-1'}                                 | ${false}
+    ${'1:3!3.2-1'}                                 | ${false}
+    ${'1:3/3.2-1'}                                 | ${false}
+    ${'1.0-3_2'}                                   | ${false}
+    ${'1.0-3!3'}                                   | ${false}
+    ${'1.0-3/3'}                                   | ${false}
+    ${'1.0+ä1-1'}                                  | ${false}
+    ${'1,0-1'}                                     | ${false}
+    ${'2:1.1-1'}                                   | ${true}
+    ${'1.1.1-0debian1'}                            | ${true}
+    ${'1.1.1+really1.1.2-0debian1'}                | ${true}
+    ${'2.31-13+deb11u5'}                           | ${true}
+    ${'1:4.14+20190211-1ubuntu1'}                  | ${true}
+    ${'2.7.7+dfsg-12'}                             | ${true}
+    ${'9.5.0-1ubuntu1~22.04'}                      | ${true}
+    ${'5:20.10.17~3-0~ubuntu-focal'}               | ${true}
+    ${'1:6.0.1r16-1.1build1'}                      | ${true}
+    ${'2:102.12+LibO7.3.7-0ubuntu0.22.04.1'}       | ${true}
+    ${'1:2.20.1-1~bpo9+1'}                         | ${true}
+    ${'v1.4'}                                      | ${true}
+    ${'3.5.0'}                                     | ${true}
+    ${'4.2.21.Final'}                              | ${true}
+    ${'0.6.5.1'}                                   | ${true}
+    ${'20100527'}                                  | ${true}
+    ${'2.1.0-M3'}                                  | ${true}
+    ${'4.3.20.RELEASE'}                            | ${true}
+    ${'1.1-groovy-2.4'}                            | ${true}
+    ${'0.8a'}                                      | ${true}
+    ${'3.1.0.GA'}                                  | ${true}
+    ${'3.0.0-beta.3'}                              | ${true}
+    ${'foo'}                                       | ${true}
+    ${'1.2.3.4.5.6.7'}                             | ${true}
+    ${'0a1b2c3'}                                   | ${true}
+    ${'0a1b2c3d'}                                  | ${true}
+    ${'0a1b2c3d4e5f6a7b8c9d0a1b2c3d4e5f6a7b8c9d'}  | ${true}
+    ${'0a1b2c3d4e5f6a7b8c9d0a1b2c3d4e5f6a7b8c9d0'} | ${true}
+    ${'0a1b2C3'}                                   | ${true}
+    ${'0z1b2c3'}                                   | ${true}
+    ${'0A1b2c3d4e5f6a7b8c9d0a1b2c3d4e5f6a7b8c9d'}  | ${true}
+    ${'123098140293'}                              | ${true}
+  `('isValid("$version") === $expected', ({ version, expected }) => {
+    expect(deb.isValid(version)).toBe(expected);
+  });
+
+  test.each`
+    a                         | b                         | expected
+    ${'2.4'}                  | ${'2.4'}                  | ${true}
+    ${'2.4.0'}                | ${'2.4.0'}                | ${true}
+    ${'2.4.0'}                | ${'2.4'}                  | ${false}
+    ${'2.4.1'}                | ${'2.4'}                  | ${false}
+    ${'2.4.2'}                | ${'2.4.1'}                | ${false}
+    ${'0.8a'}                 | ${'0.8a'}                 | ${true}
+    ${'9.5.0-1ubuntu1~22.04'} | ${'9.5.0-1ubuntu1'}       | ${false}
+    ${'9.5.0-1ubuntu1~22.04'} | ${'9.5.0-1ubuntu1~20.04'} | ${false}
+    ${'9.5.0-1ubuntu1~22.04'} | ${'9.5.0-1ubuntu1~22.04'} | ${true}
+    ${'2.31-13+deb11u5'}      | ${'2.31-13+deb11u5'}      | ${true}
+    ${'2.31-13+deb11u5'}      | ${'2.31-13+deb11u4'}      | ${false}
+    ${'1.4-'}                 | ${'1.4'}                  | ${false}
+    ${'v1.4'}                 | ${'1.4'}                  | ${false}
+    ${'0:1.4'}                | ${'1.4'}                  | ${true}
+    ${'1:1.4'}                | ${'1.4'}                  | ${false}
+    ${'1.4-1'}                | ${'1.4-2'}                | ${false}
+    ${'0:1.4'}                | ${'a:1.4'}                | ${false}
+    ${'a:1.4'}                | ${'0:1.4'}                | ${false}
+  `('equals("$a", "$b") === $expected', ({ a, b, expected }) => {
+    expect(deb.equals(a, b)).toBe(expected);
+  });
+
+  test.each`
+    a                    | b                    | expected
+    ${'2.4.0'}           | ${'2.4'}             | ${true}
+    ${'2.4.2'}           | ${'2.4.1'}           | ${true}
+    ${'2.4.beta'}        | ${'2.4.alpha'}       | ${true}
+    ${'1.9'}             | ${'2'}               | ${false}
+    ${'1.9'}             | ${'1.9.1'}           | ${false}
+    ${'2.4'}             | ${'2.4.beta'}        | ${false}
+    ${'2.4.0'}           | ${'2.4.beta'}        | ${false}
+    ${'2.4.beta'}        | ${'2.4'}             | ${true}
+    ${'2.4.beta'}        | ${'2.4.0'}           | ${true}
+    ${'2.4~'}            | ${'2.4~~'}           | ${true}
+    ${'2.4'}             | ${'2.4~'}            | ${true}
+    ${'2.4a'}            | ${'2.4'}             | ${true}
+    ${'2.31-13+deb11u5'} | ${'2.31-9'}          | ${true}
+    ${'2.31-13+deb11u5'} | ${'2.31-13+deb10u5'} | ${true}
+    ${'2.31-13+deb11u5'} | ${'2.31-13+deb11u4'} | ${true}
+    ${'1.9'}             | ${'1:1.7'}           | ${false}
+    ${'1.9'}             | ${'1.12'}            | ${false}
+    ${'1.12'}            | ${'1.9'}             | ${true}
+    ${'1:1.9'}           | ${'1:1.7'}           | ${true}
+    ${'2.4.0.beta1'}     | ${'2.4.0.Beta1'}     | ${true}
+    ${'1:1.0'}           | ${'1:1.0~'}          | ${true}
+    ${'1:1.0Z0-0'}       | ${'1:1.0'}           | ${true}
+    ${'1:1.0Z0-0'}       | ${'1:1.0A0-0'}       | ${true}
+    ${'1:1.0a0-0'}       | ${'1:1.0Z0-0'}       | ${true}
+    ${'1:1.0z0-0'}       | ${'1:1.0a0-0'}       | ${true}
+    ${'1:1.0+0-0'}       | ${'1:1.0z0-0'}       | ${true}
+    ${'1:1.0-0-0'}       | ${'1:1.0+0-0'}       | ${true}
+    ${'1:1.0.0-0'}       | ${'1:1.0-0-0'}       | ${true}
+    ${'1:1.0:0-0'}       | ${'1:1.0.0-0'}       | ${true}
+    ${'a:1.4'}           | ${'0:1.4'}           | ${true}
+    ${'0:1.4'}           | ${'a:1.4'}           | ${true}
+    ${'a:1.4'}           | ${'a:1.4'}           | ${true}
+    ${'a1'}              | ${'a~'}              | ${true}
+    ${'a0'}              | ${'a~'}              | ${true}
+    ${'aa'}              | ${'a1'}              | ${true}
+    ${'ab'}              | ${'a0'}              | ${true}
+    ${'10'}              | ${'1.'}              | ${true}
+    ${'10'}              | ${'1a'}              | ${true}
+  `('isGreaterThan("$a", "$b") === $expected', ({ a, b, expected }) => {
+    expect(deb.isGreaterThan(a, b)).toBe(expected);
+  });
+
+  test.each`
+    version     | expected
+    ${'1.2.0'}  | ${true}
+    ${'^1.2.0'} | ${false}
+  `('isSingleVersion("$version") === $expected', ({ version, expected }) => {
+    expect(deb.isSingleVersion(version)).toBe(expected);
+  });
+
+  test.each`
+    version              | expected
+    ${'v1.3.0'}          | ${1}
+    ${'2-0-1'}           | ${2}
+    ${'2.31-13+deb11u5'} | ${2}
+    ${'1:2.3.1'}         | ${2}
+    ${'foo'}             | ${null}
+    ${'8'}               | ${8}
+    ${'1.0'}             | ${1}
+  `('getMajor("$version") === $expected', ({ version, expected }) => {
+    expect(deb.getMajor(version)).toBe(expected);
+  });
+
+  test.each`
+    version              | expected
+    ${'v1.3.0'}          | ${3}
+    ${'2-0-1'}           | ${0}
+    ${'2.31-13+deb11u5'} | ${31}
+    ${'1:2.3.1'}         | ${3}
+    ${'foo'}             | ${null}
+    ${'8'}               | ${null}
+    ${'1.0'}             | ${0}
+  `('getMinor("$version") === $expected', ({ version, expected }) => {
+    expect(deb.getMinor(version)).toBe(expected);
+  });
+
+  test.each`
+    version              | expected
+    ${'v1.3.0'}          | ${0}
+    ${'2-0-1'}           | ${1}
+    ${'2.31-13+deb11u5'} | ${13}
+    ${'1:2.3.1'}         | ${1}
+    ${'foo'}             | ${null}
+    ${'8'}               | ${null}
+    ${'1.0'}             | ${null}
+  `('getPatch("$version") === $expected', ({ version, expected }) => {
+    expect(deb.getPatch(version)).toBe(expected);
+  });
+});
diff --git a/lib/modules/versioning/deb/index.ts b/lib/modules/versioning/deb/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..30e9471633bf6d03e25fb449cc853def99e1c810
--- /dev/null
+++ b/lib/modules/versioning/deb/index.ts
@@ -0,0 +1,148 @@
+import { regEx } from '../../../util/regex';
+import { GenericVersion, GenericVersioningApi } from '../generic';
+import type { VersioningApi } from '../types';
+
+export const id = 'deb';
+export const displayName = 'Deb version';
+export const urls = [
+  'https://www.debian.org/doc/debian-policy/ch-controlfields.html#version',
+  'https://manpages.debian.org/unstable/dpkg-dev/deb-version.7.en.html',
+];
+export const supportsRanges = false;
+
+const epochPattern = regEx(/^\d+$/);
+const upstreamVersionPattern = regEx(/^[-+.:~A-Za-z\d]+$/);
+const debianRevisionPattern = regEx(/^[+.~A-Za-z\d]*$/);
+const numericPattern = regEx(/\d+/g);
+const characterOrder =
+  '~ ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-.:';
+const numericChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
+
+export interface DebVersion extends GenericVersion {
+  /**
+   * epoch, defaults to 0 if not present, are used to leave version mistakes and previous
+   * versioning schemes behind.
+   */
+  epoch: number;
+  /**
+   * upstreamVersion is the main version part: it defines the version of origin software
+   * that was packaged.
+   */
+  upstreamVersion: string;
+  /**
+   * debianRevision is used to distinguish between different versions of packaging for the
+   * same upstream version.
+   */
+  debianRevision: string;
+}
+
+class DebVersioningApi extends GenericVersioningApi {
+  protected _parse(version: string): DebVersion | null {
+    /* Splitting version into "[epoch:]upstream-version[-debian-revision]"
+       All found numbers are exported as release info */
+
+    // split of first element by `:` as epoch:
+    const epochSplit = version.split(':');
+    const epochStr = epochSplit.length > 1 ? epochSplit.shift()! : '0';
+    const remainingVersion = epochSplit.join(':');
+
+    // split of last element by `-`
+    if (remainingVersion.endsWith('-')) {
+      // Forbid debian revision (it would result in `2.4.0-` == `2.4.0`)
+      return null;
+    }
+    const debianSplit = remainingVersion.split('-');
+    const debianRevision = debianSplit.length > 1 ? debianSplit.pop()! : '';
+    const upstreamVersion = debianSplit.join('-');
+
+    if (
+      !epochPattern.test(epochStr) ||
+      !upstreamVersionPattern.test(upstreamVersion) ||
+      !debianRevisionPattern.test(debianRevision)
+    ) {
+      return null;
+    }
+    const release = [...remainingVersion.matchAll(numericPattern)].map((m) =>
+      parseInt(m[0], 10)
+    );
+    return {
+      epoch: parseInt(epochStr, 10),
+      upstreamVersion,
+      debianRevision,
+      release,
+      suffix: debianRevision,
+    };
+  }
+
+  protected _compare_string(a: string, b: string): number {
+    /* Special string sorting based on official specification:
+     * https://manpages.debian.org/unstable/dpkg-dev/deb-version.7.en.html#Sorting_algorithm
+     * The string is compared by continuous blocks of a) non-digit and b) digit characters.
+     * Non-digit blocks are compared lexicographically with a custom character order.
+     * Digit blocks are compared numerically.
+     * We are alternating between both modes until a difference is found.
+     */
+    let charPos = 0;
+    while (charPos < a.length || charPos < b.length) {
+      const aChar = a.charAt(charPos);
+      const bChar = b.charAt(charPos);
+      if (numericChars.includes(aChar) && numericChars.includes(bChar)) {
+        // numeric comparison of the whole block
+        let aNumericEnd = charPos + 1;
+        while (numericChars.includes(a.charAt(aNumericEnd))) {
+          aNumericEnd += 1;
+        }
+        let bNumericEnd = charPos + 1;
+        while (numericChars.includes(b.charAt(bNumericEnd))) {
+          bNumericEnd += 1;
+        }
+        const numericCmp = a
+          .substring(charPos, aNumericEnd)
+          .localeCompare(b.substring(charPos, bNumericEnd), undefined, {
+            numeric: true,
+          });
+        if (numericCmp !== 0) {
+          return numericCmp;
+        }
+        charPos = aNumericEnd; // the same as bNumericEnd as both are the same
+        continue;
+      }
+      if (aChar !== bChar) {
+        // Lexicographical comparison
+        // numeric character is treated like end of string (they are part of a new block)
+        const aPriority = characterOrder.indexOf(
+          numericChars.includes(aChar) || aChar === '' ? ' ' : aChar
+        );
+        const bPriority = characterOrder.indexOf(
+          numericChars.includes(bChar) || bChar === '' ? ' ' : bChar
+        );
+        return Math.sign(aPriority - bPriority);
+      }
+      charPos += 1;
+    }
+    return 0;
+  }
+
+  protected override _compare(version: string, other: string): number {
+    const parsed1 = this._parse(version);
+    const parsed2 = this._parse(other);
+    if (!(parsed1 && parsed2)) {
+      return 1;
+    }
+    if (parsed1.epoch !== parsed2.epoch) {
+      return Math.sign(parsed1.epoch - parsed2.epoch);
+    }
+    const upstreamVersionDifference = this._compare_string(
+      parsed1.upstreamVersion,
+      parsed2.upstreamVersion
+    );
+    if (upstreamVersionDifference !== 0) {
+      return upstreamVersionDifference;
+    }
+    return this._compare_string(parsed1.debianRevision, parsed2.debianRevision);
+  }
+}
+
+export const api: VersioningApi = new DebVersioningApi();
+
+export default api;
diff --git a/lib/modules/versioning/deb/readme.md b/lib/modules/versioning/deb/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..1cbfe967baba5a94a88f6c00083f996a502f0b44
--- /dev/null
+++ b/lib/modules/versioning/deb/readme.md
@@ -0,0 +1,3 @@
+Deb versioning compares versions like package managers on Debian-based Linux distributions compare packages (`dpkg`, `apt`).
+Deb versioning supports complicated version numbers, including alphabetical characters almost everywhere.
+Similar to our "loose" versioning, deb versioning is a "best effort" attempt to convert deb versions to SemVer fields like `major`, `minor`, `patch`.