1{
2 lib,
3 fetchFromGitHub,
4 stdenv,
5 python,
6 systemd,
7 pandoc,
8 kmod,
9 gnutar,
10 util-linux,
11 cpio,
12 bash,
13 coreutils,
14 btrfs-progs,
15 libseccomp,
16 replaceVars,
17 udevCheckHook,
18
19 # Python packages
20 setuptools,
21 setuptools-scm,
22 wheel,
23 buildPythonApplication,
24 pytestCheckHook,
25
26 # Optional dependencies
27 withQemu ? false,
28 qemu,
29
30 # Workaround for supporting providing additional package manager
31 # dependencies in the recursive use in the binary path.
32 # This can / should be removed once the `finalAttrs` pattern is
33 # available for Python packages.
34 extraDeps ? [ ],
35}:
36let
37 # For systemd features used by mkosi, see
38 # https://github.com/systemd/mkosi/blob/19bb5e274d9a9c23891905c4bcbb8f68955a701d/action.yaml#L64-L72
39 systemdForMkosi = systemd.override {
40 withRepart = true;
41 withBootloader = true;
42 withSysusers = true;
43 withFirstboot = true;
44 withEfi = true;
45 withUkify = true;
46 withKernelInstall = true;
47 };
48
49 pythonWithPefile = python.withPackages (ps: [ ps.pefile ]);
50
51 deps = [
52 bash
53 btrfs-progs
54 coreutils
55 cpio
56 gnutar
57 kmod
58 systemdForMkosi
59 util-linux
60 ]
61 ++ extraDeps
62 ++ lib.optionals withQemu [
63 qemu
64 ];
65in
66buildPythonApplication rec {
67 pname = "mkosi";
68 version = "25.3-unstable-2025-04-01";
69 format = "pyproject";
70
71 outputs = [
72 "out"
73 "man"
74 ];
75
76 src = fetchFromGitHub {
77 owner = "systemd";
78 repo = "mkosi";
79 rev = "21850673a7f75125d516268ce379dae776dd816a";
80 hash = "sha256-3dhr9lFJpI8aN8HILaMvGuuTbmTVUqdaLAGxSpqciTs=";
81 };
82
83 patches = [
84 (replaceVars ./0001-Use-wrapped-binaries-instead-of-Python-interpreter.patch {
85 UKIFY = "${systemdForMkosi}/lib/systemd/ukify";
86 PYTHON_PEFILE = lib.getExe pythonWithPefile;
87 NIX_PATH = toString (lib.makeBinPath deps);
88 MKOSI_SANDBOX = null; # will be replaced in postPatch
89 })
90 (replaceVars ./0002-Fix-library-resolving.patch {
91 LIBC = "${stdenv.cc.libc}/lib/libc.so.6";
92 LIBSECCOMP = "${libseccomp.lib}/lib/libseccomp.so.2";
93 })
94 ]
95 ++ lib.optional withQemu (
96 replaceVars ./0003-Fix-QEMU-firmware-path.patch {
97 QEMU_FIRMWARE = "${qemu}/share/qemu/firmware";
98 }
99 );
100
101 postPatch = ''
102 # As we need the $out reference, we can't use `replaceVars` here.
103 substituteInPlace mkosi/{run,__init__}.py \
104 --replace-fail '@MKOSI_SANDBOX@' "\"$out/bin/mkosi-sandbox\""
105 '';
106
107 nativeBuildInputs = [
108 pandoc
109 setuptools
110 setuptools-scm
111 wheel
112 udevCheckHook
113 ];
114
115 dependencies = deps;
116
117 postBuild = ''
118 ./tools/make-man-page.sh
119 '';
120
121 checkInputs = [
122 pytestCheckHook
123 ];
124
125 postInstall = ''
126 mkdir -p $out/share/man/man1
127 mv mkosi/resources/man/mkosi.1 $out/share/man/man1/
128 '';
129
130 meta = with lib; {
131 description = "Build legacy-free OS images";
132 homepage = "https://github.com/systemd/mkosi";
133 changelog = "https://github.com/systemd/mkosi/releases/tag/v${version}";
134 license = licenses.lgpl21Only;
135 mainProgram = "mkosi";
136 maintainers = with maintainers; [
137 malt3
138 msanft
139 ];
140 platforms = platforms.linux;
141 };
142}