Panfactum LogoPanfactum
Developer EnvironmentCustomizing

Customizing

The Panfactum stack comes with a preloaded devenv that contains both essential and convenience utilities for working with the stack. However, it is likely that you will want to include additional utilities that are specific to your organization.

Basics

After completing the getting started guide, you should have a devenv.nix file in the root of your repository.

You can add any option here that you would in a blank devenv setup. For the complete list of options, please review these docs.

We strongly encourage you to go through this brief devenv guide to get a sense for all the possibilities.

Triggering Automatic Updates on New Files

You may find it easier to split out your devenv.nix into multiple files. If you want the devenv to reload automatically when those files change, you need to add new nix_direnv_watch_file directives to your .envrc file.

For example, if you add a new file called node.nix, your .envrc file should contain the line

nix_direnv_watch_file node.nix

Adding New Tools

From nixpkgs

Your devenv.nix should have an input variable called pkgs. This variable represents all packages available in the nixpkgs GitHub repository. nixpkgs is the largest software repository in the world (graph), so an enormous amount of utilities are readily available to you.

To add a package such as nodejs_20, update your devenv.nix with the following:

{ config, pkgs, ... }: {
  packages = with pkgs; [
    nodejs_20
  ];
}

Specific Version from nixpkgs

Since all of nixpkgs is versioned atomically, you may find yourself in the following scenario:

You want a version of utility A that is found at nixpkgs commit XXX and also a version of utility B that is found at commit YYY.

Fortunately, you can create a nix expression that represents a package from a specific commit of nixpkgs rather than the global pkgs variable.

For example, if you wanted the nodejs_20 package from the c8e74c2f83fe12b4e5a8bd1abbc090575b0f7611 commit, you can create the following nix expression in a file called node.nix (make sure you git add it):

let
  system = builtins.currentSystem;
  nixpkgsSrc = builtins.fetchGit {
    url = "https://github.com/NixOS/nixpkgs";
    rev = "c8e74c2f83fe12b4e5a8bd1abbc090575b0f7611";
    shallow = true;
  };
  pkgs = import nixpkgsSrc { inherit system; };
in pkgs.nodejs_20

You would include this in your devenv.nix as follows:

{ config, pkgs, ... }: {
  packages = with pkgs; [
    (import ./node.nix)
  ];
}

Custom Scripts

You may want to include custom shell scripts in your developer environment.

Imagine that you have the following script called foobar.sh that you want users to be able to call by executing foobar anywhere in the developer environment:

#!/usr/bin/env bash

echo "Foobar"

You would include this in your devenv.nix as follows:

{ config, pkgs, ... }: {
  packages = with pkgs; [
    (writeShellScriptBin name (builtins.readFile ./foobar.sh))
  ];
}

Wrapping an Existing Tool

Occasionally, you may want to use a package but automatically pass in default flags or environment variables for users of your developer environment.

There is a handy package called makeWrapper that allows you to do this.

For example, let's say you want to always add -n cilium to calls of the cilium CLI. Simply create the following cilium.nix file (make sure to git add it):

{ pkgs }:
pkgs.symlinkJoin {
  name = "cilium-cli";
  paths = [ pkgs.cilium-cli ];
  buildInputs = [ pkgs.makeWrapper ];
  postBuild = ''
    wrapProgram $out/bin/cilium \
      --add-flags "-n cilium"
  '';
}

You would include this in your devenv.nix as follows:

{ config, pkgs, ... }: {
  packages = with pkgs; [
    (import ./cilium.nix { inherit pkgs; })
  ];
}

Build a Custom Utility

If you are looking to package a custom binary, you will need to learn how nix derivations work.

We strongly encourage you to go through the nix pills tutorial for a good beginner overview.

The nixpkgs manual contains very detailed instructions for best practices in creating nix packages for the most popular language ecosystems.

Best Practices

  • Use devenv to define all of your utilities in order to ensure consistency across developers and machines.

  • Use devenv to define your pre-commit hooks