Getting started
haskell.nix can automatically translate your Cabal or Stack project and its dependencies into Nix code.
The first steps are to ensure you have Nix installed and the binary cache set up on your machine.
Then you have the choice to set-up your project using the experimental Flake feature or Niv, which are 2 ways to pin nixpkgs with Nix.
If you have an existing Haskell project that you want to build with haskell.nix, you might prefer to use hix. hix is a more easy and user-friendly way to use haskell.nix, using it reduce considerably the size of the Nix expression you will have to maintain in your project codebase.
Setting up the binary cache
IMPORTANT: you must do this or you will build several copies of GHC!
You can configure Nix to use our binary cache, which is pushed to by CI, so should contain the artifacts that you need.
You need to add the following sections to /etc/nix/nix.conf or, if you are a trusted user, ~/.config/nix/nix.conf (if you don't know what a "trusted user" is, you probably want to do the former). [...] denote any existing entries.
extra-trusted-public-keys = [...] hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= [...]
extra-substituters = [...] https://cache.iog.io [...]
If you're running NixOS, you need to add/update the following in your /etc/nixos/configuration.nix files instead.
# Binary Cache for haskell.nix
nix.settings.trusted-public-keys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
];
nix.settings.substituters = [
"https://cache.iog.io"
];
NixOS-21.11 and older use slightly different settings.
# Binary Cache for haskell.nix
nix.binaryCachePublicKeys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
];
nix.binaryCaches = [
"https://cache.iog.io"
];
This can be tricky to get setup properly. If you're still having trouble getting cache hits, consult the corresponding troubleshooting section.
Create a project using Flakes
This section assumes you choose to uses the experimental flakes features, and so that you have added experimental-features = [ "nix-command" "flakes" ]; in your Nix configuration. You can look at the Wiki for more instructions.
The following nix flake init command creates a template hello package containing a flake.nix and nix/hix.nix file. The project can be used with
regular nix tools. This template is defined in the NixOS/templates repository.
nix flake init --template templates#haskell-nix --impure
# `--impure` is required by `builtins.currentSystem`
nix develop
cabal build
To view the contents of the flake run:
nix flake show
To build a component with nix:
nix build .#hello:exe:hello
To build and run a component:
nix run .#hello:exe:hello
Scaffolding
The following code could be capy-pasted and will work with stack.yaml and cabal.project based projects.
Edit your flake.nix as:
{
description = "A very basic flake";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
let
overlays = [ haskellNix.overlay
(final: _prev: {
# This overlay adds our project to pkgs
helloProject =
final.haskell-nix.project' {
src = ./.;
compiler-nix-name = "ghc96";
# This is used by `nix develop .` to open a shell for use with
# `cabal`, `hlint` and `haskell-language-server`
shell.tools = {
cabal = {};
# hlint = {};
# haskell-language-server = {};
};
# Non-Haskell shell tools go here
shell.buildInputs = with pkgs; [
nixpkgs-fmt
];
# This adds `js-unknown-ghcjs-cabal` to the shell.
# shell.crossPlatforms = p: [p.ghcjs];
};
})
];
pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; };
flake = pkgs.helloProject.flake {
# This adds support for `nix build .#js-unknown-ghcjs:hello:exe:hello`
# crossPlatforms = p: [p.ghcjs];
};
in flake // {
# Built by `nix build .`
packages.default = flake.packages."hello:exe:hello";
});
}
Note: Git dependencies
If you have git dependencies in your project, you'll need to calculate sha256 hashes for them.
Working with a project
Top-level attributes are Haskell packages (incl. dependencies) part of your project.
This section will show side by side the commands using Flakes experimental new-command API and legacy Nix commands.
To build the library component of a package in the project run:
nix build .#your-package-name:lib:your-package-name
There are also other components such as exes, tests, benchmarks and all.
To build an executable:
nix build .#your-package-name:exe:your-exe-name
Flakes provide a devShell attribute that allow you to spawn a developer shell, here with cabal, hlint and haskell-language-server:
nix develop .
cabal repl your-package-name:lib:your-package-name
cabal build your-package-name
To open a shell for use with stack see the following issue.
Getting started with Hix
Hix is a command line tool that provides an easy way to add haskell.nix support to existing haskell projects.
The hix init command adds a flake.nix and nix/hix.nix file. After that the project can be used with regular nix tools.
For instance to run cabal build on the hello package from hackage:
cabal unpack hello
cd hello-1.0.0.2
nix run "github:input-output-hk/haskell.nix#hix" -- init
nix develop
cabal build
To view the contents of the flake run:
nix flake show
To build a component with nix:
nix build .#hello:exe:hello
To build and run a component:
nix run .#hello:exe:hello
Installing Hix
To use the other Hix features first install Hix with:
nix-env -iA hix -f https://github.com/input-output-hk/haskell.nix/tarball/master
To update run to the latest version run:
hix update
Using hix develop, hix flake, hix build and hix run
These commands work the same as the nix versions without using the flake.nix. Instead a boiler plate haskell.nix flake.nix file is added to .hix-flake/flake.nix and used from there.
The is can be useful if the project already includes a flake.nix or if you do not intend to maintain one.
Then all of these should work without the need to run hix init:
hix develop
hix flake show
hix build .#hello:exe:hello
hix run .#hello:exe:hello
Using hix-shell and hix-build
These commands behave like nix-build and hix-shell would if a boiler plate default.nix and shell.nix we present.
hix-shell --run 'cabal build all'
hix-build -A hsPkgs.hello.components.exes.hello
Going forward
Read through project function reference to see how the API works.
There are a number of things to explore further in the tutorials section.