diff --git a/lib/modules/manager/nix/extract.spec.ts b/lib/modules/manager/nix/extract.spec.ts
index 9645744c2a9208..035a495eb0670f 100644
--- a/lib/modules/manager/nix/extract.spec.ts
+++ b/lib/modules/manager/nix/extract.spec.ts
@@ -1,74 +1,603 @@
+import { fs } from '../../../../test/util';
 import { GitRefsDatasource } from '../../datasource/git-refs';
 import { id as nixpkgsVersioning } from '../../versioning/nixpkgs';
 import { extractPackageFile } from '.';
 
+jest.mock('../../../util/fs');
+
 describe('modules/manager/nix/extract', () => {
-  it('returns null when no nixpkgs', () => {
-    const content = `{
-  inputs = {};
-}`;
-    const res = extractPackageFile(content);
+  const flake1Lock = `{
+    "nodes": {
+      "root": {}
+    },
+    "root": "root",
+    "version": 7
+  }`;
+  const flake1Nix = `{
+    inputs = {};
+  }`;
 
-    expect(res).toBeNull();
+  it('returns null when no nixpkgs input exists', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake1Lock);
+    expect(await extractPackageFile(flake1Nix, 'flake.nix')).toBeNull();
   });
 
-  it('returns nixpkgs', () => {
-    const content = `{
-  inputs = {
-    nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11";
-  };
-}`;
+  const flake2Nix = `{
+    inputs = {
+      nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11";
+    };
+  }`;
+
+  it('match nixpkgs input', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake1Lock);
+    expect(await extractPackageFile(flake2Nix, 'flake.nix')).toEqual({
+      deps: [
+        {
+          depName: 'nixpkgs',
+          currentValue: 'nixos-21.11',
+          datasource: GitRefsDatasource.id,
+          packageName: 'https://github.com/NixOS/nixpkgs',
+          versioning: nixpkgsVersioning,
+        },
+      ],
+    });
+  });
 
-    const res = extractPackageFile(content);
+  const flake3Nix = `{
+    inputs = {
+      nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
+    };
+  }`;
 
-    expect(res?.deps).toEqual([
-      {
-        depName: 'nixpkgs',
-        currentValue: 'nixos-21.11',
-        datasource: GitRefsDatasource.id,
-        packageName: 'https://github.com/NixOS/nixpkgs',
-        versioning: nixpkgsVersioning,
+  it('match nixpkgs input case insensitive', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake1Lock);
+    expect(await extractPackageFile(flake3Nix, 'flake.nix')).toEqual({
+      deps: [
+        {
+          depName: 'nixpkgs',
+          currentValue: 'nixos-21.11',
+          datasource: GitRefsDatasource.id,
+          packageName: 'https://github.com/NixOS/nixpkgs',
+          versioning: nixpkgsVersioning,
+        },
+      ],
+    });
+  });
+
+  const flake4Nix = `{
+    inputs = {
+      nixpkgs.url = "github:NixOS/nixpkgs";
+    };
+  }`;
+
+  it('includes nixpkgs input with no explicit ref', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake1Lock);
+    expect(await extractPackageFile(flake4Nix, 'flake.nix')).toEqual({
+      deps: [
+        {
+          currentValue: undefined,
+          datasource: 'git-refs',
+          depName: 'nixpkgs',
+          packageName: 'https://github.com/NixOS/nixpkgs',
+          versioning: 'nixpkgs',
+        },
+      ],
+    });
+  });
+
+  it('returns null when no inputs', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake1Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toBeNull();
+  });
+
+  const flake2Lock = `{
+    "nodes": {
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1720031269,
+          "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6",
+          "type": "github"
+        },
+        "original": {
+          "owner": "NixOS",
+          "ref": "nixos-unstable",
+          "repo": "nixpkgs",
+          "type": "github"
+        }
       },
-    ]);
+      "root": {
+        "inputs": {
+          "nixpkgs": "nixpkgs"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('returns nixpkgs input', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake2Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toEqual({
+      deps: [
+        {
+          depName: 'nixpkgs',
+          currentDigest: '9f4128e00b0ae8ec65918efeba59db998750ead6',
+          currentValue: 'nixos-unstable',
+          datasource: GitRefsDatasource.id,
+          packageName: 'https://github.com/NixOS/nixpkgs',
+        },
+      ],
+    });
   });
 
-  it('is case insensitive', () => {
-    const content = `{
-  inputs = {
-    nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
-  };
-}`;
+  const flake3Lock = `{
+    "nodes": {
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1728650607,
+          "narHash": "sha256-0lOnVTzRXzpk5uxbHLm3Ti3tyPAvirAIQDfwEUd8arg=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "612ee628421ba2c1abca4c99684862f76cb3b089",
+          "type": "github"
+        },
+        "original": {
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "type": "github"
+        }
+      },
+      "root": {
+        "inputs": {
+          "nixpkgs": "nixpkgs"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
 
-    const res = extractPackageFile(content);
+  it('includes nixpkgs with no explicit ref', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake3Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: '612ee628421ba2c1abca4c99684862f76cb3b089',
+          datasource: 'git-refs',
+          depName: 'nixpkgs',
+          packageName: 'https://github.com/NixOS/nixpkgs',
+        },
+      ],
+    });
+  });
 
-    expect(res?.deps).toEqual([
-      {
-        depName: 'nixpkgs',
-        currentValue: 'nixos-21.11',
-        datasource: GitRefsDatasource.id,
-        packageName: 'https://github.com/NixOS/nixpkgs',
-        versioning: nixpkgsVersioning,
+  const flake4Lock = `{
+    "nodes": {
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1672057183,
+          "narHash": "sha256-GN7/10DNNvs1FPj9tlZA2qgNdFuYKKuS3qlHTqAxasQ=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "b139e44d78c36c69bcbb825b20dbfa51e7738347",
+          "type": "github"
+        },
+        "original": {
+          "id": "nixpkgs",
+          "ref": "nixpkgs-unstable",
+          "type": "indirect"
+        }
       },
-    ]);
+      "patchelf": {
+        "inputs": {
+          "nixpkgs": "nixpkgs"
+        },
+        "locked": {
+          "lastModified": 1718457448,
+          "narHash": "sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=",
+          "ref": "refs/heads/master",
+          "rev": "a0f54334df36770b335c051e540ba40afcbf8378",
+          "revCount": 844,
+          "type": "git",
+          "url": "https://github.com/NixOS/patchelf.git"
+        },
+        "original": {
+          "type": "git",
+          "url": "https://github.com/NixOS/patchelf.git"
+        }
+      },
+      "root": {
+        "inputs": {
+          "patchelf": "patchelf"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes patchelf from HEAD', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake4Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: 'a0f54334df36770b335c051e540ba40afcbf8378',
+          datasource: 'git-refs',
+          depName: 'patchelf',
+          packageName: 'https://github.com/NixOS/patchelf.git',
+        },
+      ],
+    });
   });
 
-  it('includes nixpkgs with no explicit ref', () => {
-    const content = `{
-  inputs = {
-    nixpkgs.url = "github:NixOS/nixpkgs";
-  };
-}`;
+  const flake5Lock = `{
+    "nodes": {
+      "ijq": {
+        "flake": false,
+        "locked": {
+          "lastModified": 1723569650,
+          "narHash": "sha256-Ho/sAhEUeSug52JALgjrKVUPCBe8+PovbJj/lniKxp8=",
+          "owner": "~gpanders",
+          "repo": "ijq",
+          "rev": "88f0d9ae98942bf49cba302c42b2a0f6e05f9b58",
+          "type": "sourcehut"
+        },
+        "original": {
+          "owner": "~gpanders",
+          "repo": "ijq",
+          "type": "sourcehut"
+        }
+      },
+      "root": {
+        "inputs": {
+          "ijq": "ijq"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
 
-    const res = extractPackageFile(content);
+  it('includes ijq from sourcehut without a flake', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake5Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: '88f0d9ae98942bf49cba302c42b2a0f6e05f9b58',
+          datasource: 'git-refs',
+          depName: 'ijq',
+          packageName: 'https://git.sr.ht/~gpanders/ijq',
+        },
+      ],
+    });
+  });
 
-    expect(res).toMatchObject({
+  const flake6Lock = `{
+    "nodes": {
+      "home-manager": {
+        "flake": false,
+        "locked": {
+          "lastModified": 1728650932,
+          "narHash": "sha256-mGKzqdsRyLnGNl6WjEr7+sghGgBtYHhJQ4mjpgRTCsU=",
+          "owner": "rycee",
+          "repo": "home-manager",
+          "rev": "65ae9c147349829d3df0222151f53f79821c5134",
+          "type": "gitlab"
+        },
+        "original": {
+          "owner": "rycee",
+          "repo": "home-manager",
+          "type": "gitlab"
+        }
+      },
+      "root": {
+        "inputs": {
+          "home-manager": "home-manager"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes home-manager from gitlab', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake6Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
       deps: [
         {
-          currentValue: undefined,
+          currentDigest: '65ae9c147349829d3df0222151f53f79821c5134',
+          datasource: 'git-refs',
+          depName: 'home-manager',
+          packageName: 'https://gitlab.com/rycee/home-manager',
+        },
+      ],
+    });
+  });
+
+  const flake7Lock = `{
+    "nodes": {
+      "root": {}
+    },
+    "root": "root",
+    "version": 6
+  }`;
+
+  it('test other version', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake7Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toBeNull();
+  });
+
+  const flake8Lock = `{
+    "nodes": {
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1728492678,
+          "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=",
+          "ref": "nixos-unstable",
+          "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7",
+          "shallow": true,
+          "type": "git",
+          "url": "https://github.com/NixOS/nixpkgs"
+        },
+        "original": {
+          "ref": "nixos-unstable",
+          "shallow": true,
+          "type": "git",
+          "url": "https://github.com/NixOS/nixpkgs"
+        }
+      },
+      "root": {
+        "inputs": {
+          "nixpkgs": "nixpkgs"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes nixpkgs with ref and shallow arguments', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake8Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: '5633bcff0c6162b9e4b5f1264264611e950c8ec7',
           datasource: 'git-refs',
           depName: 'nixpkgs',
           packageName: 'https://github.com/NixOS/nixpkgs',
-          versioning: 'nixpkgs',
+        },
+      ],
+    });
+  });
+
+  const flake9Lock = `{
+    "nodes": {
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1728538411,
+          "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
+          "type": "github"
+        },
+        "original": {
+          "id": "nixpkgs",
+          "type": "indirect"
+        }
+      },
+      "root": {
+        "inputs": {
+          "nixpkgs": "nixpkgs"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes nixpkgs but using indirect type that cannot be updated', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake9Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toBeNull();
+  });
+
+  const flake10Lock = `{
+    "nodes": {
+      "flake-utils": {
+        "inputs": {
+          "systems": "systems"
+        },
+        "locked": {
+          "lastModified": 1726560853,
+          "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
+          "owner": "numtide",
+          "repo": "flake-utils",
+          "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
+          "type": "github"
+        },
+        "original": {
+          "owner": "numtide",
+          "repo": "flake-utils",
+          "type": "github"
+        }
+      },
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1728492678,
+          "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7",
+          "type": "github"
+        },
+        "original": {
+          "owner": "NixOS",
+          "ref": "nixos-unstable",
+          "repo": "nixpkgs",
+          "type": "github"
+        }
+      },
+      "nixpkgs-extra-pkgs": {
+        "inputs": {
+          "flake-utils": "flake-utils",
+          "nixpkgs": "nixpkgs"
+        },
+        "locked": {
+          "host": "github.corp.example.com",
+          "lastModified": 1728666512,
+          "narHash": "sha256-p+l16Zzyl2DXG695yks6KQP7NkjsnEksu5GBvtL1QYg=",
+          "owner": "my-org",
+          "repo": "nixpkgs-extra-pkgs",
+          "rev": "6bf2706348447df6f8b86b1c3e54f87b0afda84f",
+          "type": "github"
+        },
+        "original": {
+          "host": "github.corp.example.com",
+          "owner": "my-org",
+          "repo": "nixpkgs-extra-pkgs",
+          "type": "github"
+        }
+      },
+      "root": {
+        "inputs": {
+          "nixpkgs-extra-pkgs": "nixpkgs-extra-pkgs"
+        }
+      },
+      "systems": {
+        "locked": {
+          "lastModified": 1681028828,
+          "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+          "owner": "nix-systems",
+          "repo": "default",
+          "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+          "type": "github"
+        },
+        "original": {
+          "owner": "nix-systems",
+          "repo": "default",
+          "type": "github"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes flake from GitHub Enterprise', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake10Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: '6bf2706348447df6f8b86b1c3e54f87b0afda84f',
+          datasource: 'git-refs',
+          depName: 'nixpkgs-extra-pkgs',
+          packageName:
+            'https://github.corp.example.com/my-org/nixpkgs-extra-pkgs',
+        },
+      ],
+    });
+  });
+
+  const flake11Lock = `{
+    "nodes": {
+      "data-mesher": {
+        "inputs": {
+          "flake-parts": "flake-parts",
+          "nixpkgs": "nixpkgs",
+          "treefmt-nix": "treefmt-nix"
+        },
+        "locked": {
+          "lastModified": 1727355895,
+          "narHash": "sha256-grZIaLgk5GgoDuTt49RTCLBh458H4YJdIAU4B3onXRw=",
+          "rev": "c7e39452affcc0f89e023091524e38b3aaf109e9",
+          "type": "tarball",
+          "url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/c7e39452affcc0f89e023091524e38b3aaf109e9.tar.gz"
+        },
+        "original": {
+          "type": "tarball",
+          "url": "https://git.clan.lol/clan/data-mesher/archive/main.tar.gz"
+        }
+      },
+      "flake-parts": {
+        "inputs": {
+          "nixpkgs-lib": [
+            "data-mesher",
+            "nixpkgs"
+          ]
+        },
+        "locked": {
+          "lastModified": 1726153070,
+          "narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=",
+          "owner": "hercules-ci",
+          "repo": "flake-parts",
+          "rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a",
+          "type": "github"
+        },
+        "original": {
+          "owner": "hercules-ci",
+          "repo": "flake-parts",
+          "type": "github"
+        }
+      },
+      "nixpkgs": {
+        "locked": {
+          "lastModified": 1726871744,
+          "narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=",
+          "owner": "NixOS",
+          "repo": "nixpkgs",
+          "rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2",
+          "type": "github"
+        },
+        "original": {
+          "owner": "NixOS",
+          "ref": "nixpkgs-unstable",
+          "repo": "nixpkgs",
+          "type": "github"
+        }
+      },
+      "root": {
+        "inputs": {
+          "data-mesher": "data-mesher"
+        }
+      },
+      "treefmt-nix": {
+        "inputs": {
+          "nixpkgs": [
+            "data-mesher",
+            "nixpkgs"
+          ]
+        },
+        "locked": {
+          "lastModified": 1726734507,
+          "narHash": "sha256-VUH5O5AcOSxb0uL/m34dDkxFKP6WLQ6y4I1B4+N3L2w=",
+          "owner": "numtide",
+          "repo": "treefmt-nix",
+          "rev": "ee41a466c2255a3abe6bc50fc6be927cdee57a9f",
+          "type": "github"
+        },
+        "original": {
+          "owner": "numtide",
+          "repo": "treefmt-nix",
+          "type": "github"
+        }
+      }
+    },
+    "root": "root",
+    "version": 7
+  }`;
+
+  it('includes flake with tarball type', async () => {
+    fs.readLocalFile.mockResolvedValueOnce(flake11Lock);
+    expect(await extractPackageFile('', 'flake.nix')).toMatchObject({
+      deps: [
+        {
+          currentDigest: 'c7e39452affcc0f89e023091524e38b3aaf109e9',
+          datasource: 'git-refs',
+          depName: 'data-mesher',
+          packageName: 'https://git.clan.lol/clan/data-mesher',
         },
       ],
     });
diff --git a/lib/modules/manager/nix/extract.ts b/lib/modules/manager/nix/extract.ts
index 5170e23a07dfe0..cfe99ead002906 100644
--- a/lib/modules/manager/nix/extract.ts
+++ b/lib/modules/manager/nix/extract.ts
@@ -1,11 +1,28 @@
+import { logger } from '../../../logger';
+import { getSiblingFileName, readLocalFile } from '../../../util/fs';
 import { regEx } from '../../../util/regex';
 import { GitRefsDatasource } from '../../datasource/git-refs';
 import { id as nixpkgsVersioning } from '../../versioning/nixpkgs';
 import type { PackageDependency, PackageFileContent } from '../types';
+import { NixFlakeLock } from './schema';
 
 const nixpkgsRegex = regEx(/"github:nixos\/nixpkgs(\/(?<ref>[a-z0-9-.]+))?"/i);
 
-export function extractPackageFile(content: string): PackageFileContent | null {
+// as documented upstream
+// https://github.com/NixOS/nix/blob/master/doc/manual/source/protocols/tarball-fetcher.md#gitea-and-forgejo-support
+const lockableHTTPTarballProtocol = regEx(
+  '^https://(?<domain>[^/]+)/(?<owner>[^/]+)/(?<repo>[^/]+)/archive/(?<rev>.+).tar.gz$',
+);
+
+export async function extractPackageFile(
+  content: string,
+  packageFile: string,
+): Promise<PackageFileContent | null> {
+  const packageLockFile = getSiblingFileName(packageFile, 'flake.lock');
+  const lockContents = await readLocalFile(packageLockFile, 'utf8');
+
+  logger.trace(`nix.extractPackageFile(${packageLockFile})`);
+
   const deps: PackageDependency[] = [];
 
   const match = nixpkgsRegex.exec(content);
@@ -20,6 +37,118 @@ export function extractPackageFile(content: string): PackageFileContent | null {
     });
   }
 
+  const flakeLockParsed = NixFlakeLock.safeParse(lockContents);
+  if (!flakeLockParsed.success) {
+    logger.debug(
+      { packageLockFile, error: flakeLockParsed.error },
+      `invalid flake.lock file`,
+    );
+    return null;
+  }
+
+  const flakeLock = flakeLockParsed.data;
+  const rootInputs = flakeLock.nodes['root'].inputs;
+
+  if (!rootInputs) {
+    logger.debug(
+      { packageLockFile, error: flakeLockParsed.error },
+      `flake.lock is missing "root" node`,
+    );
+
+    if (deps.length) {
+      return { deps };
+    }
+    return null;
+  }
+
+  for (const [depName, flakeInput] of Object.entries(flakeLock.nodes)) {
+    // the root input is a magic string for the entrypoint and only references other flake inputs
+    if (depName === 'root') {
+      continue;
+    }
+
+    // skip all locked and transitivie nodes as they cannot be updated by regular means
+    if (!(depName in rootInputs)) {
+      continue;
+    }
+
+    const flakeLocked = flakeInput.locked;
+    const flakeOriginal = flakeInput.original;
+
+    // istanbul ignore if: if we are not in a root node then original and locked always exist which cannot be easily expressed in the type
+    if (flakeLocked === undefined || flakeOriginal === undefined) {
+      logger.debug(
+        { packageLockFile, flakeInput },
+        `Found empty flake input, skipping`,
+      );
+      continue;
+    }
+
+    // indirect inputs cannot be reliable updated because they depend on the flake registry
+    if (flakeOriginal.type === 'indirect') {
+      continue;
+    }
+
+    switch (flakeLocked.type) {
+      case 'github':
+        deps.push({
+          depName,
+          currentValue: flakeOriginal.ref,
+          currentDigest: flakeLocked.rev,
+          datasource: GitRefsDatasource.id,
+          packageName: `https://${flakeOriginal.host ?? 'github.com'}/${flakeOriginal.owner}/${flakeOriginal.repo}`,
+        });
+        break;
+      case 'gitlab':
+        deps.push({
+          depName,
+          currentValue: flakeOriginal.ref,
+          currentDigest: flakeLocked.rev,
+          datasource: GitRefsDatasource.id,
+          packageName: `https://${flakeOriginal.host ?? 'gitlab.com'}/${flakeOriginal.owner}/${flakeOriginal.repo}`,
+        });
+        break;
+      case 'git':
+        deps.push({
+          depName,
+          currentValue: flakeOriginal.ref,
+          currentDigest: flakeLocked.rev,
+          datasource: GitRefsDatasource.id,
+          packageName: flakeOriginal.url,
+        });
+        break;
+      case 'sourcehut':
+        deps.push({
+          depName,
+          currentValue: flakeOriginal.ref,
+          currentDigest: flakeLocked.rev,
+          datasource: GitRefsDatasource.id,
+          packageName: `https://${flakeOriginal.host ?? 'git.sr.ht'}/${flakeOriginal.owner}/${flakeOriginal.repo}`,
+        });
+        break;
+      case 'tarball':
+        deps.push({
+          depName,
+          currentValue: flakeLocked.ref,
+          currentDigest: flakeLocked.rev,
+          datasource: GitRefsDatasource.id,
+          // type tarball always contains this link
+          packageName: flakeOriginal.url!.replace(
+            lockableHTTPTarballProtocol,
+            'https://$<domain>/$<owner>/$<repo>',
+          ),
+        });
+        break;
+      // istanbul ignore next: just a safeguard
+      default:
+        logger.debug(
+          { packageLockFile },
+          `Unknown flake.lock type "${flakeLocked.type}", skipping`,
+        );
+        break;
+    }
+  }
+
   if (deps.length) {
     return { deps };
   }
diff --git a/lib/modules/manager/nix/index.ts b/lib/modules/manager/nix/index.ts
index 35fa06494f17eb..abbe3e6ec3e84f 100644
--- a/lib/modules/manager/nix/index.ts
+++ b/lib/modules/manager/nix/index.ts
@@ -9,7 +9,7 @@ export const url = 'https://nix.dev';
 
 export const defaultConfig = {
   fileMatch: ['(^|/)flake\\.nix$'],
-  commitMessageTopic: 'nixpkgs',
+  commitMessageTopic: 'nix',
   commitMessageExtra: 'to {{newValue}}',
   enabled: false,
 };
diff --git a/lib/modules/manager/nix/readme.md b/lib/modules/manager/nix/readme.md
index 3a196a34445c0e..af3d80c5b0b05e 100644
--- a/lib/modules/manager/nix/readme.md
+++ b/lib/modules/manager/nix/readme.md
@@ -1,4 +1,9 @@
 The [`nix`](https://github.com/NixOS/nix) manager supports:
 
 - [`lockFileMaintenance`](../../../configuration-options.md#lockfilemaintenance) updates for `flake.lock`
-- [nixpkgs](https://github.com/NixOS/nixpkgs) updates
+- input updates for `flake.lock`
+
+For specifying `packageRules` it is important to know how `depName` and `packageName` are defined for nix updates:
+
+- The `depName` field is equal to the nix flake input name, eg. `nix.inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";` would have the `depName` of `nixpkgs`
+- The `packageName` field is equal to the fully-qualified root URL of the package source, eg. `https://github.com/NixOS/nixpkgs` for the above example.
diff --git a/lib/modules/manager/nix/schema.ts b/lib/modules/manager/nix/schema.ts
new file mode 100644
index 00000000000000..af8e0e33e95dbf
--- /dev/null
+++ b/lib/modules/manager/nix/schema.ts
@@ -0,0 +1,41 @@
+import { z } from 'zod';
+import { Json } from '../../../util/schema-utils';
+
+const InputType = z.enum([
+  'git',
+  'github',
+  'gitlab',
+  'indirect',
+  'sourcehut',
+  'tarball',
+]);
+
+const LockedInput = z.object({
+  ref: z.string().optional(),
+  rev: z.string(),
+  type: InputType,
+});
+
+const OriginalInput = z.object({
+  host: z.string().optional(),
+  owner: z.string().optional(),
+  repo: z.string().optional(),
+  ref: z.string().optional(),
+  type: InputType,
+  url: z.string().optional(),
+});
+
+const NixInput = z.object({
+  inputs: z.record(z.string(), z.string().or(z.array(z.string()))).optional(),
+  locked: LockedInput.optional(),
+  original: OriginalInput.optional(),
+});
+
+export const NixFlakeLock = Json.pipe(
+  z.object({
+    nodes: z.record(z.string(), NixInput),
+    version: z.literal(7),
+  }),
+);
+
+export type NixFlakeLock = z.infer<typeof NixFlakeLock>;