nix-freeze-tree: Convert a tree of files into fixed-output derivations

[ agpl, application, library, nix, program ] [ Propose Tags ]

nix-freeze-tree walks a directory tree and generates a tree of Nix expressions that recreate the tree from fixed-output derivations, one derivation per file in the source tree. See to get started.

[Skip to Readme]
Versions [RSS] [faq]
Change log
Dependencies base (>=4.9 && <4.15), binary (>= && <0.9), bytestring (>= && <0.11), data-fix (>=0.2.0 && <0.4), directory (>= && <1.4), directory-tree (>=0.12.1 && <0.13), hnix (>=0.6.1 && <0.12), hnix-store-core (>= && <0.3), optparse-applicative (>= && <0.16), path (>=0.6.1 && <0.8), prettyprinter (>= && <1.8), raw-strings-qq (==1.1.*), text (>= && <1.3), transformers (>= && <0.6) [details]
License AGPL-3.0-or-later
Copyright (c) 2020 Jack Kelly
Author Jack Kelly
Revised Revision 1 made by jack at 2020-11-29T10:06:25Z
Category Application, Nix
Home page
Bug tracker
Source repo head: git clone
Uploaded by jack at 2020-01-25T04:37:42Z
Distributions NixOS:
Executables nix-freeze-tree
Downloads 220 total (7 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs not available [build log]
All reported builds failed as of 2020-01-25 [all 2 reports]


Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

For package maintainers and hackage trustees


Readme for nix-freeze-tree-

[back to package description]

nix-freeze-tree status AGPLv3

nix-freeze-tree is a utility that walks a directory tree, and writes out Nix expressions which rebuild that tree. The generated expressions have two important properties:

  1. Each file in the tree is built by a separate fixed-output derivation, and

  2. Directories are built by derivations that symlink their contents recursively.

If you are using nix copy to ship a derivation between nix stores, copying the derivation built by evaluating the output of nix-freeze-tree can reuse existing files in the destination store, as fixed-output derivations can be checked against a hash before copying.

I use this to speed up deploys to my personal website. Running nix-freeze-tree on the output from my site generator and importing the result means that nix copy only uploads new files, instead of copying a single giant derivation containing every image on the site.



If you use Nix, you can install the command into your local environment by running nix-env -f -iA command.


If you have GHC installed, you can also build and install the binary by running cabal v2-install nix-freeze-tree. You can also run the binary from the build directory with cabal v2-run nix-freeze-tree -- ARGS.


Usage: nix-freeze-tree [--version] [-f|--force] [-v|--verbose]
                       [-o|--out-root OUT_ROOT] [IN_DIR]
  Write a tree of nix expressions to OUT_ROOT that build a derivation,
  symlinking every file in IN_DIR as a separate fixed-output derivation.

Available options:
  --version                Display version information and exit.
  -h,--help                Show this help text
  -f,--force               If any default.nix exist in the output directory,
                           remove them and generate anyway
  -v,--verbose             Display messages while working.
  -o,--out-root OUT_ROOT   Where to write the nix files (default: IN_DIR)
  IN_DIR                   Directory to freeze (default: .)

Calling from Nix

This repository's default.nix gives access to a function freeze, which can be used to freeze the output of an existing derivation.

You can use it with Nix code that looks a bit like:

  # Some nixpkgs from somewhere
  nixpkgs = ...;

  # Whether you get it from a channel, a local checkout,
  # builtins.fetchTarball or builtins.fetchgit is up to you
  nix-freeze-tree-repo = builtins.fetchTarball { ... };

  # Derivation to freeze
  drv = mkDerivation { ... };

  # Evaluate default.nix from nix-freeze-tree-repo and hold onto the
  # freeze function
  freeze = (import nix-freeze-tree-repo { inherit nixpkgs; }).freeze;
  freeze drv


Q: Why didn't you use symlinkJoin to tie all the subtrees together?

A: I had the program mostly working before I remembered that symlinkJoin existed. I thought about making each file's derivation contain the directories leading up to it and then symlinkJoining them all together, but decided against it for three reasons:

  1. You can easily build subtrees using the Nix expressions generated by nix-freeze-tree;
  2. Building the output of nix-freeze-tree will correctly create empty directories present in the input; and
  3. Files are hashed based on their content alone, not their position in the tree-to-be-frozen (reducing duplication).

Other Resources