Daml + Nix

We (Obsidian Systems) generally use Nix/Nixos for declarative package and system management. With Nix, everything from our development environments to our production deployments are built in a reliable and reproducible way. If you’re not familiar with nix, I encourage you to check it out.

We made nix-daml-sdk to make it easy to work with the daml sdk and canton with Nix. To try it out, clone it and run nix-shell path/to/nix-daml-sdk and you’ll end up with a shell that provides you:

  • The daml sdk, daml command, and all dependencies
  • VSCode with the daml extension pre-installed
  • Canton and all dependencies (e.g., java)

To integrate it into a larger nix project, you can import nix-daml-sdk and use the sdk, jdk, and canton fields that it provides as buildInputs in your own nix derivation. For example:

{ jdkVersion ? "jdk17"
, sdkVersion ? "2.7.1"
, pkgs ? import ./nixpkgs {}
}:
let
  damlSdk = import ./nix-daml-sdk { inherit jdkVersion sdkVersion; };
in pkgs.stdenvNoCC.mkDerivation {
    name = "My Daml Project";
    src = pkgs.lib.cleanSource ./.;
    buildInputs = [ damlSdk.jdk damlSdk.sdk ];
    buildPhase = ''
      mkdir dist
      daml build -o dist.dar
    '';
    installPhase = ''
      mkdir $out
      cp dist.dar $out/
    '';
  }

As you can see from the above, you can specify the daml sdk and jdk versions you want to use. Currently available sdk versions can be found here, but it’s easy to add more. You can also specify whether you want to use canton enterprise or open source. nix-daml-sdk makes sure that the versions of the sdk and canton line up.

You can mix nix-daml-sdk into the shell for your specific project like this:

{}:
let
  pkgs = impore ./nixpkgs {};
  nix-daml-sdk = import ./nix/nix-daml-sdk {};
in
  pkgs.mkShell {
    name = "My Full-Stack Project";
    buildInputs = [
      pkgs.cabal-install
      pkgs.ghcid
      pkgs.yarn
      nix-daml-sdk.sdk
      nix-daml-sdk.vscode
      nix-daml-sdk.canton
    ];
  }

We’ve had a lot of success with this approach. We favor it because it provides completely reproducible builds, the ability to spin up duplicate environments trivially, fast CI, and binary caching to save developer time.

Let me know you’d like to try it out or have questions or feature suggestions.

3 Likes