Nix migraines: NIX_SSL_CERT_FILE
Published 2025-02-28 on Farid Zakaria's Blog
This will be a self-post to describe nixpkgs#issue385955. I refused to just “copy code” from other packages and wanted to better understand what was going on.
If you’re on a “proper” operating system (i.e. Linux), Nix protects you from accidental impurities by enforcing a filesystem and network sandbox.
This is not the case in MacOS. You can optionally enable the sandbox but it does not include a network sandbox.
🤔 I have some pretty strong opinions here. Although I am using Nix on MacOS, I would advocate for Nix/Nixpkgs dropping MacOS (& eventual Windows/BSD) support. Constraints are when you can find simplicity and beauty.
I had packaged up my personal blog (this site right here! 📝) into a flake.nix that worked on Linux but was failing on MacOS.
Turns out that one of the jekyll plugins I am using, jekyll-github-metadata
, tries to contact github.com to fetch a bunch of data I don’t even need 😤.
It would immediately fail with a cryptic SSL error.
SSL_connect SYSCALL returned=5 errno=0
peeraddr=140.82.116.5:443 state=error:
certificate verify failed
(unable to get local issuer certificate)
(Faraday::SSLError)
I was able to replicate this on NixOS with
nix build --no-sandbox
Okay 🤔 it’s failing to verify the SSL certificate chain.
Let’s add curl
to our derivation to debug and see what that says.
> curl: (77) error setting certificate file: /no-cert-file.crt
Okay, so we need to set the SSL certificate file which might not be present.
Searching some exmaples and the documentation of OpenSSL looks like we should set SSL_CERT_FILE
.
env = {
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
};
Now curl
passes, so it seems to successfully validate the TLS certificate chain but the jekyll build is still failing 🤦♂️.
Looking further online, there seems to be a second environment variable, NIX_SSL_CERT_FILE
. Let’s set that one too.
env = rec {
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
NIX_SSL_CERT_FILE = SSL_CERT_FILE
};
Okay great now everything builds 🎉.
Turns out that if you add the package cacert
it includes a setup-hook that sets both of these environment variables.
nativeBuildInputs = with pkgs; [
cacert
];
But, why are there 2 environment variables !?… 🤷
It’s not particularly clear which packages respect one rather than the other. If you have insight into this, please comment on nixpkgs#issue385955.
NIX_SSL_CERT_FILE
is clear that it should work with OpenSSL via this patch in nixpkgs that leverages it.
curl
and ruby
both use OpenSSL so why are their behavior divergent.
Nix migraine 🤕.
Improve this page @ bc4b4d8
The content for this site is
CC-BY-SA.