Overlays Pattern¶
Overview¶
An overlay is a two-argument function final: prev: { ... } that returns a fragment of a package set—replacements and new attributes. Nixpkgs folds a list of overlays into one fixed-point set: layers compose left to right, each stage sees earlier results as prev, and final is the completed fixed point after every layer.
This page is the language / nixpkgs composition idiom—final vs prev, stacking order, shallow merge, and extends / composeManyExtensions. It is not the same as .override / .overrideAttrs, which change one package and return a single derivation; see Overlay vs Override. For the concept and when to reach for overlays, see Overlay. For install paths and longer how-tos, see Writing overlays.
Details¶
Shape¶
Newer code names the arguments final / prev; older code often uses self / super. Same roles either way. The return value should look like a slice of pkgs (top-level names to derivations or nested sets), similar in spirit to pkgs/top-level/all-packages.nix.
final vs prev¶
| Argument | Meaning | Use for |
|---|---|---|
final |
The composed set after this overlay and all later overlays (the fixed point) | Dependencies of packages you define or override |
prev |
The set from nixpkgs and overlays before this one | The package you are replacing; helpers already on the previous stage (callPackage, …) |
Canonical pattern from the nixpkgs manual—take the original recipe and helpers from prev, resolve dependencies against final:
final: prev: {
boost = prev.boost.override { python = final.python3; };
rr = prev.callPackage ./pkgs/rr { stdenv = final.stdenv_32bit; };
}
prev does not contain attributes introduced by this overlay or by later ones. final does—laziness makes that safe (see Laziness). Swapping the two is a common footgun; see Anti-patterns.
Composition¶
Overlays in a list apply in order. Later overlays replace top-level attrs from earlier ones. Nested attrsets are not merged recursively—composition uses // (shallow). To keep nested keys, merge manually (prev.python3.pkgs // { ... }) or override a specific attr.
Under the hood, lib.extends overlay f builds a new fixed-point function; lib.fix evaluates it. Several overlays stack with lib.composeManyExtensions (or composeExtensions for two). List order matches overlays = [ ... ].
Overlay vs override¶
.override re-invokes a package function with different arguments; .overrideAttrs changes the mkDerivation attrset. Both return one derivation. An overlay wires such changes into the package set so everything that reads final.someAttr sees them. Prefer overlays for set-wide consistency; prefer a bare override for a one-off in a shell or module. Details: Overlay vs Override.
Where to apply¶
import nixpkgs { overlays = [ ... ]; }— whenoverlaysis passed, nixpkgs does not look up path-based overlay files- NixOS:
nixpkgs.overlays(system evaluation only; does not affect standalonenix-env/ ad-hoc imports unless you share the same list) - User path lookup (only if
overlayswas not passed):<nixpkgs-overlays>onNIX_PATH, else~/.config/nixpkgs/overlays.nixor~/.config/nixpkgs/overlays/(error if both exist) - Runtime:
pkgs.extend/appendOverlays— these recompute the fixed point and are costly; avoid inside nixpkgs itself
packageOverrides¶
The older config.packageOverrides is roughly an overlay that only sees prev. Prefer overlays.
Examples¶
Minimal concrete overlay (same shape as the nixpkgs Overlays chapter):
final: prev: {
hello = prev.hello.overrideAttrs (old: {
pname = old.pname + "-patched";
});
myTool = prev.callPackage ./my-tool.nix { };
}
Wire it in with import nixpkgs { overlays = [ thatOverlay ]; } or NixOS nixpkgs.overlays. Dependents that resolve through the composed set see hello / myTool from final.
Fixed-point composition (from lib.fixedPoints; verified with nix-instantiate --eval --strict):
f = final: { a = 1; b = final.a + 2; };
# lib.fix f => { a = 1; b = 3; }
# after overlay:
lib.fix (lib.extends (final: prev: { a = prev.a + 10; }) f)
# => { a = 11; b = 13; }
a is updated via prev; b still depends on final.a, so it picks up 11. Stacking more layers is the same idea with lib.composeManyExtensions [ ov1 ov2 ... ] before extends.
Shallow merge pitfall (composeManyExtensions uses //):
# later overlay replaces the whole attr — nested keys from earlier are gone
final: prev: { foo = { b = 2; }; }
# if an earlier overlay set foo = { a = 1; }, result is only { b = 2; }
See also¶
- Overlay — definition and when to use overlays
- Overlay vs Override — set-level vs package-level
- callPackage — usual way to introduce packages inside an overlay
- Anti-patterns —
final/prevmixups, shallow//, costlyextend - rec and Fixed Points —
fix/ recursive sets without overlays - Writing overlays — install paths and longer nixpkgs guide