diff --git a/lib/modules/versioning/api.ts b/lib/modules/versioning/api.ts
index 211c3f8740fe292367bb8286afae0564a25b6fc6..454d0f631ade1a1c746622a08f7acfcbb4e7f48d 100644
--- a/lib/modules/versioning/api.ts
+++ b/lib/modules/versioning/api.ts
@@ -6,6 +6,7 @@ import * as composer from './composer';
 import * as conan from './conan';
 import * as deb from './deb';
 import * as debian from './debian';
+import * as devbox from './devbox';
 import * as docker from './docker';
 import * as git from './git';
 import * as glasskube from './glasskube';
@@ -52,6 +53,7 @@ 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(devbox.id, devbox.api);
 api.set(docker.id, docker.api);
 api.set(git.id, git.api);
 api.set(glasskube.id, glasskube.api);
diff --git a/lib/modules/versioning/devbox/index.spec.ts b/lib/modules/versioning/devbox/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..542a28eeed6a4dcf91ad2343913ed60da2d09b7e
--- /dev/null
+++ b/lib/modules/versioning/devbox/index.spec.ts
@@ -0,0 +1,103 @@
+import devbox from '.';
+
+describe('modules/versioning/devbox/index', () => {
+  it.each`
+    version           | expected
+    ${'1'}            | ${false}
+    ${'01'}           | ${false}
+    ${'1.01'}         | ${false}
+    ${'1.1'}          | ${false}
+    ${'1.3.0'}        | ${true}
+    ${'2.1.20'}       | ${true}
+    ${'v1.4'}         | ${false}
+    ${'V0.5'}         | ${false}
+    ${'3.5.0'}        | ${true}
+    ${'4.2.21.Final'} | ${false}
+    ${'1234'}         | ${false}
+    ${'foo'}          | ${false}
+    ${'latest'}       | ${false}
+    ${''}             | ${false}
+    ${'3.5.0-beta.3'} | ${false}
+    ${'*'}            | ${false}
+    ${'x'}            | ${false}
+    ${'X'}            | ${false}
+    ${'~1.2.3'}       | ${false}
+    ${'>1.2.3'}       | ${false}
+    ${'^1.2.3'}       | ${false}
+    ${'1.2.3-foo'}    | ${false}
+    ${'1.2.3foo'}     | ${false}
+  `('isVersion("$version") === $expected', ({ version, expected }) => {
+    expect(!!devbox.isVersion(version)).toBe(expected);
+  });
+
+  it.each`
+    version           | isValid
+    ${'1'}            | ${true}
+    ${'01'}           | ${false}
+    ${'1.01'}         | ${false}
+    ${'1.1'}          | ${true}
+    ${'1.3.0'}        | ${true}
+    ${'2.1.20'}       | ${true}
+    ${'v1.4'}         | ${false}
+    ${'V0.5'}         | ${false}
+    ${'3.5.0'}        | ${true}
+    ${'4.2.21.Final'} | ${false}
+    ${'1234'}         | ${true}
+    ${'foo'}          | ${false}
+    ${'latest'}       | ${true}
+    ${''}             | ${false}
+    ${'3.5.0-beta.3'} | ${false}
+    ${'*'}            | ${false}
+    ${'x'}            | ${false}
+    ${'X'}            | ${false}
+    ${'~1.2.3'}       | ${false}
+    ${'>1.2.3'}       | ${false}
+    ${'^1.2.3'}       | ${false}
+    ${'1.2.3-foo'}    | ${false}
+    ${'1.2.3foo'}     | ${false}
+  `('isValid("$version") === $isValid', ({ version, isValid }) => {
+    expect(!!devbox.isValid(version)).toBe(isValid);
+  });
+
+  it.each`
+    version      | range        | expected
+    ${'1'}       | ${'1'}       | ${false}
+    ${'1'}       | ${'0'}       | ${false}
+    ${'1.2.3'}   | ${'1'}       | ${true}
+    ${'1.2'}     | ${'1'}       | ${false}
+    ${'1.0.0'}   | ${'1'}       | ${true}
+    ${'1.2.0'}   | ${'1.2'}     | ${true}
+    ${'1.2.3'}   | ${'1.2'}     | ${true}
+    ${'0'}       | ${'latest'}  | ${false}
+    ${'1.2.3'}   | ${'latest'}  | ${true}
+    ${'1.2.3.5'} | ${'1.2.3.5'} | ${false}
+    ${'1.2'}     | ${'1.2.3'}   | ${false}
+  `(
+    'matches("$version", "$range") === $expected',
+    ({ version, range, expected }) => {
+      expect(devbox.matches(version, range)).toBe(expected);
+    },
+  );
+
+  it.each`
+    version      | range        | expected
+    ${'1'}       | ${'1'}       | ${true}
+    ${'1'}       | ${'0'}       | ${false}
+    ${'1.2.3'}   | ${'1'}       | ${true}
+    ${'1.2'}     | ${'1'}       | ${true}
+    ${'1.0.0'}   | ${'1'}       | ${true}
+    ${'1.2.0'}   | ${'1.2'}     | ${true}
+    ${'1.2.3'}   | ${'1.2'}     | ${true}
+    ${'0'}       | ${'latest'}  | ${true}
+    ${'1.2.3'}   | ${'latest'}  | ${true}
+    ${'1.2.3.5'} | ${'1.2.3.5'} | ${false}
+    ${'latest'}  | ${'latest'}  | ${false}
+    ${'latest'}  | ${'1.2.3'}   | ${false}
+    ${'1.2'}     | ${'1.2.3'}   | ${true}
+  `(
+    'equals("$version", "$range") === $expected',
+    ({ version, range, expected }) => {
+      expect(devbox.equals(version, range)).toBe(expected);
+    },
+  );
+});
diff --git a/lib/modules/versioning/devbox/index.ts b/lib/modules/versioning/devbox/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..153f01f4f4de3018d89daea8d10ff76a4ada18f1
--- /dev/null
+++ b/lib/modules/versioning/devbox/index.ts
@@ -0,0 +1,74 @@
+import { regEx } from '../../../util/regex';
+import type { GenericVersion } from '../generic';
+import { GenericVersioningApi } from '../generic';
+import type { VersioningApi } from '../types';
+
+export const id = 'devbox';
+export const displayName = 'devbox';
+export const urls = [];
+export const supportsRanges = false;
+
+const validPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){0,2})$/);
+const versionPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){2})$/);
+
+class DevboxVersioningApi extends GenericVersioningApi {
+  protected _parse(version: string): GenericVersion | null {
+    const matches = validPattern.exec(version);
+    if (!matches) {
+      return null;
+    }
+    const release = matches[0].split('.').map(Number);
+    return { release };
+  }
+
+  override isValid(version: string): boolean {
+    if (version === 'latest') {
+      return true;
+    }
+    return this._parse(version) !== null;
+  }
+
+  override isVersion(version: string): boolean {
+    if (version === 'latest') {
+      return false;
+    }
+    const matches = versionPattern.exec(version);
+    return !!matches;
+  }
+
+  override matches(version: string, range: string): boolean {
+    return this.isVersion(version) && this.equals(version, range);
+  }
+
+  protected override _compare(version: string, other: string): number {
+    const parsed1 = this._parse(version);
+    const parsed2 = this._parse(other);
+
+    // Treat "latest" as * and always return equal
+    if (other === 'latest' && parsed1) {
+      return 0;
+    }
+
+    // If either version is invalid, return unequal
+    if (!(parsed1 && parsed2)) {
+      return 1;
+    }
+    // support variable length compare
+    const length = Math.max(parsed1.release.length, parsed2.release.length);
+    for (let i = 0; i < length; i += 1) {
+      // 2.1 and 2.1.0 are equivalent
+      const part1 = parsed1.release[i];
+      const part2 = parsed2.release[i];
+      // if part1 or part2 is undefined, we should treat them as equal
+      // e.g. 1.0.0 === 1.0
+      if (part1 !== undefined && part2 !== undefined && part1 !== part2) {
+        return part1 - part2;
+      }
+    }
+    return 0;
+  }
+}
+
+export const api: VersioningApi = new DevboxVersioningApi();
+
+export default api;
diff --git a/lib/modules/versioning/devbox/readme.md b/lib/modules/versioning/devbox/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..e7eff534d5cfeff03fce04f628c68fba89326f43
--- /dev/null
+++ b/lib/modules/versioning/devbox/readme.md
@@ -0,0 +1,2 @@
+Devbox's Nixhub uses fairly strict versioning, characters such as ~, ^ and >= are not allowed.
+The semver values must not include "\*" or "x". "1.2.3" "1.2" and "1" are the only valid formats.