Skip to content

Hermetic dev environment with Nix flakes

Will Bush edited this page Apr 9, 2023 · 2 revisions

On Linux and OS-X one can install the Nix package manager:

The unofficial installer has better capability to roll back the installation and enables nix flakes by default. The official installer requires extra steps to enable flakes.

Here is an example of a flake.nix that sets up a dev environment for odbc-api for use with the ODBC Driver 17 for SQL Server. The example also uses oxalica/rust-overlay to install the latest nightly rust toolchain. This is useful if you want a more hermetic dev environment, but not necessary.

{
  description = "Setup a devShell for odbc-api";

  inputs = {
    flake-utils.url = "github:numtide/flake-utils";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
          config.allowUnfree = true;
        };
      in
      with pkgs;
      {
        devShell = mkShell {

          buildInputs = [
            unixODBC
            rust-bin.nightly.latest.default
            rust-analyzer
          ];

          shellHook = ''
            export LD_LIBRARY_PATH="${unixODBC}/lib:${openssl_1_1.out}/lib";

            # see https://www.systutorials.com/docs/linux/man/7-unixODBC/
            # Overloads path to unixODBC configuration files. By default equals to '/etc'.
            export ODBCSYSINI=$(realpath ./)

            echo "[ODBC Driver 17 for SQL Server]" > ./odbcinst.ini
            echo "Description = ODBC Driver 17 for SQL Server" >> ./odbcinst.ini
            echo "Driver = ${unixODBCDrivers.msodbcsql17}/lib/libmsodbcsql-17.7.so.1.1" >> ./odbcinst.ini
          '';
        };
      });
}

Add this as flake.nix to the root of your rust project, stage it in git, and run nix develop to enter the devShell.

For example:

$ cargo new odbc-tester
$ cd odbc-tester
$ cargo add odbc-api
$ touch flake.nix # And paste the above flake.nix into it
$ echo "odbcinst.ini" >> .gitignore
$ git add -A
$ nix develop

Nix flakes depend on git and are not aware of files not staged or committed, this is why git add -A is needed to stage the flake.nix file. Otherwise, nix develop will fail.

When you first perform nix develop it will create a flake.lock file. This file is used to pin the versions of the inputs into the flake. Also, if all your changes haven't been committed it will emit warnings about the Git tree .. is dirty which is nothing to worry about.

The flake.nix above will require some modifications to work with other ODBC drivers. For example, replacing ODBC Driver 17 for SQL Server with one of PostgreSQL, MariaDB, or SQLite. And unixODBCDrivers.msodbcsql17 with one of the other drivers such as mariadb, psql or sqlite.

The hard coded driver path will need to be changed as well for other drivers. One can figure out the path by a combination of looking at the nixpkgs source and / or evaluating the package:

$ nix-build '<nixpkgs>' -A unixODBCDrivers.mariadb
$ cd ./result
$ ls

The openssl version may need to change as well or may not be needed at all for other drivers. I have not tested the above flake.nix with other drivers or on OS-X. At a minimum in OS-X, the LD_LIBRARY_PATH will need to change to DYLD_FALLBACK_LIBRARY_PATH.

Editor support

Great! But now rust-analyzer won't work in your favorite editor.

A good way to solve this is with direnv. Install that tool globally and then add the following to your project:

$ echo "use flake ." > .envrc
$ echo ".direnv/" >> .gitignore

Now add add editor-integration.

Also check out:

Clone this wiki locally