Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nix for Scala folks

Nix for Scala folks

Quick intro to Nix and optimal usage with the Scala ecosystem in 2022.

Jakub Kozłowski

May 11, 2022
Tweet

More Decks by Jakub Kozłowski

Other Decks in Programming

Transcript

  1. What is Nix? • Package manager • Build system •

    Language • Linux distro (NixOS)
  2. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) What needs to be compiled
  3. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) git, node, awscli, docker-client, ...
  4. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) JAVA_OPTS, SBT_OPTS, ...
  5. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) build.sbt, project/*
  6. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) *.graphql, *.proto, *.smithy
  7. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) runs sbt, compiler, tests...
  8. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) scala-compiler-2.13.6.jar
  9. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) cats-e ff ect-3.3.0.jar fs2-core-3.2.0.jar
  10. But f irst... typical sbt build inputs (let's be honest,

    everyone uses sbt) bin/sbt, sbt-1.6.2.jar
  11. Environment setup with Nix let pkgs = import (builtins.fetchTarball {

    url = "https: / / github.com/NixOS/nixpkgs/archive/20eabe33864104ad9928450e5927ab7835f8f9e8.tar.gz"; sha256 = "0l00xjjd436ddq1llfvpcipz06b6s0zxqrmfm9mgj7c0ig4y4c0r"; }) { }; in pkgs.mkShell { packages = [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }
  12. Why bother? • Doesn't pollute your environment 🌳 • Doesn't

    con f lict with globally installed programs
  13. Why bother? • Doesn't pollute your environment 🌳 • Doesn't

    con f lict with globally installed programs • Project-speci f ic version of the JVM/terraform/awscli/node/...
  14. Why bother? • Doesn't pollute your environment 🌳 • Doesn't

    con f lict with globally installed programs • Project-speci f ic version of the JVM/terraform/awscli/node/... • Share tools with the team (Git)
  15. Why bother? • Doesn't pollute your environment 🌳 • Doesn't

    con f lict with globally installed programs • Project-speci f ic version of the JVM/terraform/awscli/node/... • Share tools with the team (Git) • Same setup locally and in Continuous Integration
  16. Environment variables in Nix shell pkgs.mkShell { packages = [

    pkgs.sbt pkgs.coursier pkgs.nodejs ]; JAVA_OPTS = "-Xmx4G"; }
  17. Bonus: f lakes { devShells.default = pkgs.mkShell { buildInputs =

    [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }; }
  18. Bonus: f lakes { inputs.nixpkgs.url = "github:nixos/nixpkgs"; inputs.flake-utils.url = "github:numtide/flake-utils";

    outputs = { self, nixpkgs, flake-utils, . .. }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; in { devShells.default = pkgs.mkShell { buildInputs = [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }; } ); }
  19. Bonus: f lakes • Uses lock f ile to specify

    hash of Nixpkgs and other repositories { inputs.nixpkgs.url = "github:nixos/nixpkgs"; inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils, . .. }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; in { devShells.default = pkgs.mkShell { buildInputs = [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }; } ); }
  20. Bonus: f lakes • Uses lock f ile to specify

    hash of Nixpkgs and other repositories • Less boilerplate for pinning { inputs.nixpkgs.url = "github:nixos/nixpkgs"; inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils, . .. }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; in { devShells.default = pkgs.mkShell { buildInputs = [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }; } ); }
  21. Bonus: f lakes • Uses lock f ile to specify

    hash of Nixpkgs and other repositories • Less boilerplate for pinning • Still experimental, e ff orts to further simplify { inputs.nixpkgs.url = "github:nixos/nixpkgs"; inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils, . .. }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; in { devShells.default = pkgs.mkShell { buildInputs = [ pkgs.sbt pkgs.coursier pkgs.nodejs ]; }; } ); }
  22. See also: devshell • TOML-based • Nix language not needed

    for 80% use cases • Experimental https://github.com/numtide/devshell [devshell] packages = [ "go" ]
  23. nix pro f ile • Drop-in replacement for $PACKAGE_MANAGER •

    Atomic installation, rollbacks • No transitive con f licts
  24. nix pro f ile • Drop-in replacement for $PACKAGE_MANAGER •

    Atomic installation, rollbacks • No transitive con f licts • User-scoped
  25. nix pro f ile • Drop-in replacement for $PACKAGE_MANAGER •

    Atomic installation, rollbacks • No transitive con f licts • User-scoped • For a declarative approach, see home-manager
  26. nix pro f ile • Drop-in replacement for $PACKAGE_MANAGER •

    Atomic installation, rollbacks • No transitive con f licts • User-scoped • For a declarative approach, see home-manager • Also experimental, see nix-env
  27. Recommendations • Use nix shells in your projects! • Use

    one-time shells to try stu ff out • Flakes + shells + nix-direnv = 🥰
  28. Recommendations • Use nix shells in your projects! • Use

    one-time shells to try stu ff out • Flakes + shells + nix-direnv = 🥰 • Use nix as a normal package manager
  29. Recommendations • Use nix shells in your projects! • Use

    one-time shells to try stu ff out • Flakes + shells + nix-direnv = 🥰 • Use nix as a normal package manager • Use shells in CI
  30. More use cases for Nix • System/user program management •

    Declarative system con f iguration • CI pipelines • Deployment • Building small docker images • ??? • ???
  31. Nix as a build system def makePackage( dependencies: List[Package], src:

    Path, buildScript: String, ): Package = ??? (simpli f ied)
  32. Nix as a build system def makePackage( dependencies: List[Package], src:

    Path, buildScript: String, ): Package = ??? (simpli f ied) • No access to internet*, other f iles on disk • Build script has to output f iles to a speci f ic location
  33. Nix as a build system def makePackage( dependencies: List[Package], src:

    Path, buildScript: String, ): Package = ??? (simpli f ied) • No access to internet*, other f iles on disk • Build script has to output f iles to a speci f ic location * - Internet can be used if you know the output's hash beforehand
  34. State of the art • Single dependency hash • Waste

    of space (duplicated deps) • Slow, non-incremental
  35. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches
  36. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches • Saving space with dependency reuse
  37. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches • Saving space with dependency reuse • Splitting sbt build into modules?
  38. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches • Saving space with dependency reuse • Splitting sbt build into modules? • Direct integration with scalac/bloop?
  39. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches • Saving space with dependency reuse • Splitting sbt build into modules? • Direct integration with scalac/bloop? • Replacing sbt's dependency resolution?
  40. Nix+Scala in a perfect world • Lock f ile generated

    from sbt with a single line • Fast setup, using existing caches • Saving space with dependency reuse • Splitting sbt build into modules? • Direct integration with scalac/bloop? • Replacing sbt's dependency resolution? • New build tool?
  41. Nix+Scala work today • sbt-derivation (not actively developed) • Open

    ticket in sbt-derivation to support lock f iles
  42. Nix+Scala work today • sbt-derivation (not actively developed) • Open

    ticket in sbt-derivation to support lock f iles • Possibly needed: new feature in sbt
  43. How to get started? sh <(curl -L https: // nixos.org/nix/install)

    -- daemon • https://nixos.org/guides/nix-pills + https://nixos.org/manual/nix/stable/ • https://nix.dev • I'm writing a book! Follow https://leanpub.com/nix-book The only time you'll ever have to sh from curl :)