# Portable Haskell executables, anyone doing that (possibly using Nix)?

**URL:** <https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816>\
**Category:** Uncategorized\
**Created:** [July 22, 2022, 7:07am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816 "2022-07-22T07:07:45Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![pmiddend](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmiddend/32/2550_2.png) [@pmiddend](https://discourse.haskell.org/u/pmiddend)\
**Post date:** [July 22, 2022, 7:07am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/1 "2022-07-22T07:07:45Z")

</div>

I want to write a few smaller tools in Haskell that are to be run on a very old machine (to which I have no access right now).

I’m already dreading the low glibc version on there which make it virtually impossible to just compile something and transfer to the machines. My question is, then, does anyone build Haskell binaries that don’t depend on glibc? I found

- https://github.com/utdemir/ghc-musl which is inside a Docker container, which might cause trouble with dependencies that, in turn, depend on something other than musl (I might need libhdf5, for example)
- https://github.com/nh2/static-haskell-nix which uses Nix, which I’m totally fine with, but it seems a bit abandoned, which is a no-go for me.

Am I missing a solution here? The nixpkgs manual doesn’t offer any more advice on this, as far as I can see.

---

<div class="post-metadata">

**Author:** ![angerman](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/angerman/32/892_2.png) [@angerman](https://discourse.haskell.org/u/angerman)\
**Post date:** [July 22, 2022, 7:30am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/2 "2022-07-22T07:30:10Z")

</div>

If you don’t want to depend on `glibc`, you are bound to find an alternative `libc` indeed. This could be musl, diet, or any alternative libc (even bionic in principle). You also most likely want a static one, so you can just drop and deploy them.

Using muslc, you are pretty much bound by the syscalls the kernel provides. Thus on a _very_ _very_ old linux, you might run into issues. There are also some issues if you use e.g. the `dns` package from hackage with `muslc` on systems that messed up their file system layout, see [https://github.com/kazu-yamamoto/dns/pull/166](https://github.com/kazu-yamamoto/dns/pull/166)

I _am_ building [fully static haskell applications for linux using haskell.nix](https://github.com/input-output-hk/tools/blob/master/arm-test/default.nix); and even deploy them to platforms like Synology NASs. This is arguably _way_ more complex than anything you’d likely need though.

---

<div class="post-metadata">

**Author:** ![robx](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/robx/32/1900_2.png) [@robx](https://discourse.haskell.org/u/robx)\
**Post date:** [July 22, 2022, 7:30am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/3 "2022-07-22T07:30:22Z")

</div>

PostgREST builds static binaries using static-haskell-nix, but I concur that it seems a bit abandoned – we’re maintaining [some patches](https://github.com/PostgREST/postgrest/tree/main/nix/patches) to keep it working with recent nixpkgs.

Judging by [this comment](https://github.com/NixOS/nixpkgs/issues/43795#issuecomment-1092029035), `pkgsStatic` in nixpkgs directly might be a better option, but I couldn’t figure out how to make that work yet with PostgREST.

---

<div class="post-metadata">

**Author:** ![angerman](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/angerman/32/892_2.png) [@angerman](https://discourse.haskell.org/u/angerman)\
**Post date:** [July 22, 2022, 7:33am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/4 "2022-07-22T07:33:37Z")

</div>

[This](https://github.com/zw3rk/mobile-core/blob/master/flake.nix) might be a slightly better example; even though it also contains more than just static musl.

---

<div class="post-metadata">

**Author:** ![BardurArantsson](https://avatars.discourse-cdn.com/v4/letter/b/8dc957/32.png) [@BardurArantsson](https://discourse.haskell.org/u/BardurArantsson)\
**Post date:** [July 22, 2022, 7:38am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/5 "2022-07-22T07:38:25Z")

</div>

I’ve had pretty good success with ghc-musl + stack + cabal. The project itself builds using stack (when just building on the host), but with stack2cabal I was able to get Cabal building the project inside the ghc-musl container. (I can’t recall exactly why I couldn’t get Stack working inside the container.) A bit messy overall, but it does work.

If you need further libraries, it’s just an “apk add” away – assumming of course that the libraries are packaged for Alpine Linux. (I can’t recall exactly which I’m using off the top of my head, but I seem to remember there was some LDAP and SASL stuff in there, so decently advanced stuff.)

---

<div class="post-metadata">

**Author:** ![gilmi](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/gilmi/32/45_2.png) [@gilmi](https://discourse.haskell.org/u/gilmi)\
**Post date:** [July 22, 2022, 9:39am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/6 "2022-07-22T09:39:00Z")

</div>

I’ve had success with ghc-musl and stack without using cabal. This is how I do it: [λm.me - Building a bulletin board using twain and friends](https://gilmi.me/blog/post/2022/04/24/learn-twain-bulletin-app#deploying)

---

<div class="post-metadata">

**Author:** ![BardurArantsson](https://avatars.discourse-cdn.com/v4/letter/b/8dc957/32.png) [@BardurArantsson](https://discourse.haskell.org/u/BardurArantsson)\
**Post date:** [July 22, 2022, 10:22am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/7 "2022-07-22T10:22:24Z")

</div>

I can’t recall exactly, but I believe I’ve tried the same thing. I think the issues mostly stemmed from not being able to use “docker: true” because we were already running in a CI container. I think.

---

<div class="post-metadata">

**Author:** ![hasufell](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/hasufell/32/1250_2.png) [@hasufell](https://discourse.haskell.org/u/hasufell)\
**Post date:** [July 22, 2022, 11:32am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/8 "2022-07-22T11:32:29Z")

</div>

Use an alpine linux docker container and build your binaries with `cabal build --enable-executable-static`. Don’t use `cabal install`. That’s all there is to it. GHCup, cabal and HLS all do this to build static executables.

---

<div class="post-metadata">

**Author:** ![pmidden](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmidden/32/2426_2.png) [@pmidden](https://discourse.haskell.org/u/pmidden)\
**Post date:** [July 22, 2022, 6:05pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/9 "2022-07-22T18:05:08Z")

</div>

> [@robx](#):
>
> Judging by [this comment](https://github.com/NixOS/nixpkgs/issues/43795#issuecomment-1092029035), `pkgsStatic` in nixpkgs directly might be a better option, but I couldn’t figure out how to make that work yet with PostgREST.

pkgsStatic looks interesting indeed! But I guess we’ll have to wait for some more documentation. I cannot figure it out either.

---

<div class="post-metadata">

**Author:** ![pmidden](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmidden/32/2426_2.png) [@pmidden](https://discourse.haskell.org/u/pmidden)\
**Post date:** [July 22, 2022, 6:05pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/10 "2022-07-22T18:05:52Z")

</div>

That’s what I did now, and it’s actually working fine. I’m a bit baffled by this being possible and pretty easy as well.

---

<div class="post-metadata">

**Author:** ![cdepillabout](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/cdepillabout/32/1168_2.png) [@cdepillabout](https://discourse.haskell.org/u/cdepillabout)\
**Post date:** [July 23, 2022, 1:33pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/11 "2022-07-23T13:33:41Z")

</div>

> [@pmidden](#):
>
> pkgsStatic looks interesting indeed! But I guess we’ll have to wait for some more documentation. I cannot figure it out either.

`pkgsStatic.haskellPackages` is mostly usable just like the normal (non-static) Nixpkgs Haskell package set. Here’s a small example of using it (assuming you’re already familiar with Nix):

First, get into a repl with a recent Nixpkgs. For example, here’s the `nixpkgs-unstable` channel from today. I think 22.05 would probably work as well:

```console
$ nxi repl 'https://github.com/NixOS/nixpkgs/archive/52dd719bbd13d9f0974e5c3c29c74aa249e5b091.tar.gz'

```

Then, build any Haskell executable from `pkgsStatic`. For example, here’s `hlint` compiled statically:

```console
nix-repl> :b pkgsStatic.haskellPackages.hlint

This derivation produced the following outputs:
  data -> /nix/store/2d4gbwkb577wsj46bqqf9738wf2l0r18-hlint-static-x86_64-unknown-linux-musl-3.3.6-data
  out -> /nix/store/8xjirxkl8n2lxz1qikdap6bvpmxrgdq0-hlint-static-x86_64-unknown-linux-musl-3.3.6

```

Checkout that it is actually statically-linked:

```console
$ file /nix/store/8xjirxkl8n2lxz1qikdap6bvpmxrgdq0-hlint-static-x86_64-unknown-linux-musl-3.3.6/bin/hlint
/nix/store/8xjirxkl8n2lxz1qikdap6bvpmxrgdq0-hlint-static-x86_64-unknown-linux-musl-3.3.6/bin/hlint: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

```

Then run it:

```console
$ /nix/store/8xjirxkl8n2lxz1qikdap6bvpmxrgdq0-hlint-static-x86_64-unknown-linux-musl-3.3.6/bin/hlint --version
HLint v3.3.6, (C) Neil Mitchell 2006-2021

```

* * *

If you’re not able to build your library statically (due to system library dependencies that can’t be built statically?), there are a couple other options:

- for simple executables, manually rewrite library paths with [`patchelf`](https://github.com/NixOS/patchelf). For more complicated executables, use some sort of bundler like [`exodus`](https://github.com/intoli/exodus)
- a user\_namespaces-based bundler like [`nix bundle`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-bundle.html)

---

<div class="post-metadata">

**Author:** ![pmiddend](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmiddend/32/2550_2.png) [@pmiddend](https://discourse.haskell.org/u/pmiddend)\
**Post date:** [July 24, 2022, 10:55am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/12 "2022-07-24T10:55:59Z")

</div>

Thanks for the extensive description! With that, I was able to set up a static build. It fails, though:

```haskell
Configuring vty-5.33...

Setup: Encountered missing or private dependencies:
terminfo >=0.3 && <0.5

```

Is this a known problem, or shall I add a comment to the PR that’s open?

---

<div class="post-metadata">

**Author:** ![cdepillabout](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/cdepillabout/32/1168_2.png) [@cdepillabout](https://discourse.haskell.org/u/cdepillabout)\
**Post date:** [July 25, 2022, 4:25am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/14 "2022-07-25T04:25:13Z")

</div>

I took a look at this.

It appears that the underlying problem is that the GHC used when building things from `pkgsStatic.haskellPackages` is not compiled with the `terminfo` boot library.

(I’ve used commit 2fd68ed753 from `haskell-updates` for the following commands.)

Here’s how to confirm that `terminfo` is actually a boot library:

```haskell
$ nix-shell -I nixpkgs=./. -p haskellPackages.ghc --command 'ghc-pkg list | grep terminfo'
    terminfo-0.4.1.5
$

```

But it is not built in `pkgsStatic`:

```haskell
$ nix-shell -I nixpkgs=./. -p pkgsStatic.haskellPackages.ghc --command 'x86_64-unknown-linux-musl-ghc-pkg list | grep terminfo'
$

```

One way to work around is to explicitly pass `terminfo` when building `vty`:

```haskell
$ nix repl ./.
nix-repl> :b pkgsStatic.haskellPackages.vty.override { terminfo = pkgsStatic.haskellPackages.terminfo_0_4_1_5; }
This derivation produced the following outputs:
  out -> /nix/store/kb2rhmaan57ij5n1qykrkljc5hw7r4m1-vty-static-x86_64-unknown-linux-musl-5.33

```

If you’re interested in fixing this though, I’d suggest first creating an issue about it in Nixpkgs (and pinging @NixOS/haskell). And then trying to either figure out why `terminfo` isn’t built for the static GHC, or just removing the Nix code that assumes `terminfo` is a boot library when building statically.

---

<div class="post-metadata">

**Author:** ![pmiddend](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmiddend/32/2550_2.png) [@pmiddend](https://discourse.haskell.org/u/pmiddend)\
**Post date:** [July 25, 2022, 7:22am UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/15 "2022-07-25T07:22:43Z")

</div>

Thanks for the debugging! It works now, and I have created an issue on GitHub as well, like you mentioned:

> <https://github.com/NixOS/nixpkgs/issues/182785>
>
> \### Describe the bug
> I'm trying to build my application with \`pkgsStatic\`. This… fails because I am depending on \`vty\`, which gives me an error about the \`terminfo\` dependency:
> 
> \`\`\`
> Configuring vty-5.33...
> 
> Setup: Encountered missing or private dependencies:
> terminfo \>=0.3 && \<0.5
> \`\`\`
> 
> I can fix this via:
> 
> \`\`\`
> hp = nixpkgs.pkgsStatic.haskellPackages.override {
> overrides = self: super: {
> vty = (super.vty.override {
> terminfo = super.terminfo\_0\_4\_1\_5;
> });
> };
> };
> \`\`\`
> 
> Thanks @cdepillabout for figuring this out!
> 
> I'm using the latest master from yesterday: https://github.com/NixOS/nixpkgs/archive/28e2fa05340c0c20f16edddc51c5e953adf659b3.tar.gz
> 
> I'd assume to reproduce this, you can just create a derivation that depends on \`vty\`.
> 
> \### Notify maintainers
> 
> @NixOS/haskell 
> 
> \### Metadata
> Please run \`nix-shell -p nix-info --run "nix-info -m"\` and paste the result.
> 
> - system: \`"x86\_64-linux"\`
> - host os: \`Linux 5.15.0-39-generic, Ubuntu, 22.04 LTS (Jammy Jellyfish), nobuild\`
> - multi-user?: \`no\`
> - sandbox: \`yes\`
> - version: \`nix-env (Nix) 2.3.8\`
> - channels(pmidden): \`"home-manager, nixgl, nixpkgs-22.11pre393322.e2b34f0f11e"\`
> - nixpkgs: \`/home/pmidden/.nix-defexpr/channels/nixpkgs\`

---

<div class="post-metadata">

**Author:** ![benz0li](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/benz0li/32/3654_2.png) [@benz0li](https://discourse.haskell.org/u/benz0li)\
**Post date:** [September 15, 2023, 12:32pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/16 "2023-09-15T12:32:53Z")

</div>

There is [GHC musl](https://github.com/benz0li/ghc-musl) ([`glcr.b-data.ch/ghc/ghc-musl`](https://gitlab.b-data.ch/ghc/ghc-musl/container_registry)).

---

<div class="post-metadata">

**Author:** ![benz0li](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/benz0li/32/3654_2.png) [@benz0li](https://discourse.haskell.org/u/benz0li)\
**Post date:** [September 15, 2023, 12:33pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/17 "2023-09-15T12:33:26Z")

</div>

The multi-arch (`linux/amd64`, `linux/arm64/v8`) docker image used to build the _statically linked_ Linux amd64 and arm64 binary releases of

- [Pandoc](https://github.com/jgm/pandoc)
- [Stack](https://github.com/commercialhaskell/stack)
- Juvix

---

<div class="post-metadata">

**Author:** ![benz0li](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/benz0li/32/3654_2.png) [@benz0li](https://discourse.haskell.org/u/benz0li)\
**Post date:** [September 15, 2023, 12:34pm UTC](https://discourse.haskell.org/t/portable-haskell-executables-anyone-doing-that-possibly-using-nix/4816/18 "2023-09-15T12:34:03Z")

</div>

The GHC musl repository now also provides Dev Containers.

* * *

A [Development Container](https://containers.dev) (or Dev Container for short) allows you to use a container as a full‑featured development environment.

You can run Dev Containers locally/remotely (with VS Code), or create a [Codespace](https://github.com/features/codespaces) for a branch in a repository to develop online.
