Nixify your haskell project: Introduction

Hey all, I would like to announce a blog post that I wrote for people who want to use Nix in their Haskell projects. It is first in the series of blog posts that also explains related development workflows (such as running services locally via Nix)

Why I wrote it?

When I first started with Haskell, my toolchain of choice was stack with GHCup and for most of the projects it would work just fine but it wasn’t always reproducible mostly because of either ~/.stack or ~/<project-path>/.stack-work getting corrupted. That’s when I was exploring alternatives and bumped into Nix.

At first I had a tough time, like any other Nixer out there, but soon I had a development environment that not just made the builds reproducible but also let me configure everything I will ever need to contribute to the project. For example, treefmt-nix to configure formatters, flake-parts for bringing NixOS like module system to Flakes, services-flake to run and configure service dependencies like Postgresql and much more.

I can’t cover all of this in one post and hence I have divided them up into a series of posts. The first post starts Nixifying a Haskell project from scratch, which anyone with a basic understanding of Nix and flakes can follow along. Considering this is my first blog post, it might still be a lot of iterations away from being beginner friendly. So, please feel free to provide any feedback!

Credits to @srid for the numerous feedback.


You might be interested in having a look at one of my projects. This is only a small example but makes it easier to see what’s going on and it’s basically the same as my larger project.

It uses overmind (uses the Procfile) to start the services like postgres and the webserver.
In addition it uses direnv (configured with the .envrc) to automatically setup the devshell. Combined with extensions for your favourite editor you then don’t have to start the editor from the terminal, instead it loads the environment automatically.
I then use a simple shell script ( to have unified interface. E.g. dev run to start the application in development mode.

The whole thing is inspired by this post:

I would love to see more people creating this kind of setups as I feel they would be way more ergonomic than containers.

@Nebucatnetzer That’s precisely the kind of experience we hope to achieve by the end of the last post in the series.

The post, “Ditching Docker for Local Development” was an enjoyable read. The end goal remains the same here: a hassle-free development setup for a quicker contribution cycle.

The only difference being we will eventually use services-flake to run services like postgres. The end result might look the same, but with services-flake you can also test the services.


Interesting, haven’t seen that yet.
Might be a good replacement for overmind.

1 Like