diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000000000000000000000000000000000000..b7024e3be9ab5a38ee842b67a4fa0d39d72ebb53
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,17 @@
+{ pkgs ? import <nixpkgs> {},
+}:
+with pkgs;
+let
+  firmware = subdir:
+    callPackage ./nix/firmware.nix { inherit subdir; };
+in
+{
+  ble = firmware "ble";
+  bmatest = firmware "bmatest";
+  bmetest = firmware "bmetest";
+  ecgtest = firmware "ecgtest";
+  Hello_World = firmware "Hello_World";
+  Hello_World_FreeRTOS = firmware "Hello_World_FreeRTOS";
+  imutest = firmware "imutest";
+  ips = firmware "ips";
+}
diff --git a/nix/firmware.nix b/nix/firmware.nix
new file mode 100644
index 0000000000000000000000000000000000000000..2e0f2cff643c35c51e412af833ca6d921ee78ee9
--- /dev/null
+++ b/nix/firmware.nix
@@ -0,0 +1,22 @@
+{ pkgsCross, python3, callPackage, subdir }:
+
+let
+  crc16 = callPackage ./python-crc16.nix {};
+in
+pkgsCross.arm-embedded.stdenv.mkDerivation {
+  name = "firmware-${subdir}";
+  src = ./..;
+  buildInputs = [ crc16 ];
+  hardeningDisable= [ "all" ];
+  buildPhase = ''
+    cd ${subdir}
+    make clean
+    make -j ''$NIX_BUILD_CORES APP=1
+    make -j ''$NIX_BUILD_CORES build/max32665.bin
+    ${python3}/bin/python ../bootloader/crc_patch.py build/max32665.bin
+  '';
+  installPhase = ''
+    mkdir -p $out/lib
+    cp build/max32665.bin $out/lib/card10.bin
+  '';
+}
diff --git a/nix/python-crc16.nix b/nix/python-crc16.nix
new file mode 100644
index 0000000000000000000000000000000000000000..1c1a017022b17d3c3f09bf7ccff5fb1e74a0cad2
--- /dev/null
+++ b/nix/python-crc16.nix
@@ -0,0 +1,10 @@
+{ python3Packages }:
+
+python3Packages.buildPythonPackage rec {
+  pname = "crc16";
+  version = "0.1.1";
+  src = python3Packages.fetchPypi {
+    inherit pname version;
+    sha256 = "15nkx0pa4lskwin84flpk8fsw3jqg6wic6v3s83syjqg76h6my61";
+  };
+}
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000000000000000000000000000000000000..ee89290b3b9cbc6f946b6e394e2f781f11ad7139
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,6 @@
+with import <nixpkgs> {};
+pkgsCross.arm-embedded.stdenv.mkDerivation {
+  name = "env";
+  buildInputs = [ bashInteractive ];
+  hardeningDisable= [ "all" ];
+}