Activation
Activation is the act of making an environment's software dependencies and configuration available to a shell, process, or session without installing them globally. An activated environment prepends its packages to PATH, exports the variables it declares, and runs any hooks or profile scripts it defines. Deactivating restores the prior state; nothing is left behind on the host.
Activation is what distinguishes a declared environment from a conventional install. Because the environment's packages already exist as immutable store objects in the Nix store, activation is a matter of pointing a process at them rather than copying files into system directories. Several environments can be activated on the same machine at once without colliding, and each resolves to exactly the closure its lockfile names.
In Flox, flox activate enters an environment. With no command argument it launches an interactive sub-shell; in scripts and agent harnesses, pass a command explicitly — flox activate -d <dir> -c '<command>' runs it with hooks and profile scripts applied, while flox activate -d <dir> -- <command> is exec mode and skips profile scripts. The same command works against a local path environment, an environment pulled from FloxHub, or one referenced by a Kubernetes pod.
See also: Environment, Closure, Flox environment, Runtime environment.
Air-gapped distribution
Air-gapped distribution is the practice of supplying software to networks that have no route to the public internet. Packages, their dependencies, and the metadata needed to resolve them must be mirrored into the isolated network ahead of time, because nothing inside it can reach an upstream registry or cache on demand.
This is a hard requirement in defense, finance, healthcare, and any regulated environment where egress is prohibited. It is also where conventional package management tends to fail: a build that quietly reaches out to a public index works on a laptop and breaks the moment it runs behind the boundary. A store-based model makes the problem tractable, because a closure is a finite, fully enumerable set of store objects: it can be listed ahead of time, copied wholesale, and checked against its signatures on arrival.
In Flox, an environment's lockfile names every dependency by hash, so the complete closure can be resolved, mirrored, and verified inside the boundary. FloxHub supports private and air-gapped package distribution for organizations that cannot rely on a public catalog or binary cache at runtime.
See also: Closure, Private Catalog, Binary cache, Supply chain security, FloxHub.
Base Catalog
The Base Catalog is Flox’s public catalog of packages. It is derived from Flox’s fork of nixpkgs and is separate from Private Catalogs. Flox populates the Base Catalog by sampling package definitions from branches of its own fork — nixos-unstable (daily), nixos-staging (weekly), nixos-stable (monthly) and nixos-lts (every six months). These are not the upstream branches of the same name; all of them derive from the unstable branch of Flox's fork. Flox’s resolver queries the Base Catalog to discover compatible nixpkgs revisions that can satisfy a requested combination of package versions: e.g., Python 3.11.9 and Node.js 20.15.1.
The Base Catalog is what makes a Flox install prebuilt rather than built-on-demand: packages are built and cached continuously, and when an upstream build breaks the catalog serves the last build that worked. It holds over 215,000 packages with roughly three years of version history.
Sampling several branches of the fork at different cadences is what gives the Base Catalog both currency and stability. nixos-unstable supplies recent versions daily, while nixos-stable and nixos-lts retain older combinations long after upstream has moved past them — so an environment pinned two years ago still resolves.
See also: Flox Catalog, Private Catalog, Nixpkgs, nixpkgs, Binary cache, Substituter.
Binary cache
A binary cache is a Nix store designed to distribute prebuilt store objects. A binary cache serves each object’s filesystem data as a Nix Archive (NAR) and publishes its references, signatures, and other metadata in an accompanying .narinfo file.
Nix uses the public binary cache at cache.nixos.org by default, but can be configured to use a custom or third-party binary cache as a substituter. For example, Nix users can add Flox’s binary cache (cache.flox.dev) as a substituter to retrieve prebuilt CUDA packages that are not available from cache.nixos.org, rather than building them locally.
A binary cache is what makes prebuilt distribution practical. Because a store path is computed from the build inputs before the build runs, a cache can be asked for exactly the path that would have been produced locally. The path encodes the recipe rather than the bytes, though, so it is the signature on the object — not the path alone — that establishes a downloaded result came from somewhere trusted.
See also: Substituter, Store object, Store path, Nix store, Air-gapped distribution.
Build environment
A build environment provides the tools and inputs required to compile, package, or publish an artifact. It typically includes compilers, linkers, build systems, code generators, and the headers and libraries a project links against — software needed to produce an artifact rather than to run it.
A build environment is usually larger than the runtime environment it produces. A compiled Go or Rust binary may need almost nothing at runtime, while building it requires an entire toolchain. Keeping the two separate is what makes small runtime closures possible, and conflating them is a common source of bloated container images that ship a compiler into production for no reason.
In Flox, the build environment is the activated environment itself: the packages a manifest declares are exactly what the build sees. flox build runs against the locked manifest, but by default it runs in the root of the repository with no sandbox and no restriction on filesystem or network access — so a build can still read host state. Setting sandbox = "pure" is what stops a build silently depending on software that happens to be installed on the machine.
See also: Runtime environment, Development environment, Environment, Toolchain, Sandbox, Hermetic build, Flox build.
Closure
A closure is the complete set of software dependencies required to build or run an environment. In general software usage, an environment’s “closure” constitutes its complete transitive dependency set: i.e., all the packages, libraries, frameworks, and other software components a workload needs to run. With Nix and Flox, a “closure” comprises a Nix store object plus every other store object it depends on, directly or indirectly. A runtime closure therefore includes a package and all of its transitive runtime dependencies.
Closures are why "it works on my machine" is answerable rather than merely arguable. Two environments with the same closure contain byte-identical software down to the last transitive dependency; two that differ do so at identifiable store paths. A runtime closure is typically far smaller than the build closure that produced it, which is what allows a deployed artifact to ship without its compiler.
See also: Store object, Store path, Nix store, Lockfile, Runtime environment, Reproducibility.
CUDA in the Flox Catalog
The Flox Catalog includes current and historical versions of NVIDIA CUDA Toolkit components and CUDA-enabled packages such as PyTorch, TensorRT, OpenCV, and FFmpeg. These packages are built using canonical definitions developed by the Nix CUDA Team and maintained in nixpkgs. Flox is officially licensed to redistribute the resulting outputs containing proprietary NVIDIA binaries and libraries.
The Catalog provides the metadata Flox uses to search, resolve, and lock CUDA package versions; Flox’s binary cache distributes the corresponding prebuilt store objects. Flox and Nix users can retrieve prebuilt CUDA packages that are unavailable from cache.nixos.org instead of building or patching them locally. Different CUDA versions can also coexist in separate environments on the same system. These are user-space packages. Running them still requires a compatible NVIDIA Linux driver on the host.
This matters because building CUDA components from source is one of the more expensive operations in the Nix ecosystem — hours of compute for a toolchain that a team may need on every laptop and CI runner. Retrieving prebuilt, licensed outputs from Flox's binary cache turns that into a download, and because different CUDA versions live at different store paths, several can coexist on one machine without the version conflicts that make GPU environments notoriously brittle. See also: Flox Catalog, Binary cache, Substituter, Base Catalog.
CVE
A CVE (Common Vulnerabilities and Exposures) identifier is a public, uniquely numbered reference for a specific security vulnerability in a specific piece of software. CVE records are maintained by the CVE Program and referenced by scanners, advisories, and compliance workflows as the common vocabulary for "which flaw are we talking about."
The identifier is the easy part. The expensive part is answering the operational questions that follow: which of our environments actually contain the affected version, which are merely reported as containing it, and what has to be rebuilt and redeployed to remediate it. Teams without a precise dependency graph answer these by scanning artifacts after the fact, which produces both false positives and missed transitive occurrences.
In Flox, every environment carries a deterministic bill of materials read from its dependency graph rather than inferred from a built artifact, so the set of affected environments is a query rather than an investigation. Remediation is a version bump in the manifest followed by a rebuild and promote, with rollback to a prior generation available in one step if the fix regresses.
See also: SBOM, Supply chain security, Provenance, Closure, Rollback, Generation.
Declarative configuration
Declarative configuration describes the desired end state of a system and lets tooling determine how to reach it, rather than specifying an ordered sequence of steps that mutate the system in place. A declarative file states which packages, variables, and services an environment contains; an imperative script states what to install and in what order.
The practical difference shows up on the second run. An imperative setup script is only correct against the machine state its author assumed, so it rots as that state drifts and must be run in the right order on a sufficiently clean host. A declarative specification is evaluated against the same inputs every time and yields the same result whether it is the first run or the fiftieth, which is what makes it reviewable, diffable, and safe to re-apply.
In Flox and Nix, environments are declared rather than assembled. A Flox environment is declared in a manifest.toml that is checked into source control alongside the code it supports, so an environment change is reviewed like any other change.
See also: Manifest, Nix language, Environment, Reproducibility, Drift, Lockfile.
Derivation
A derivation is Nix’s low-level specification for producing one or more store objects. A derivation specifies an artifact’s inputs, target platform, builder program, arguments, environment variables, and expected outputs.
Nix creates a derivation by evaluating the Nix expressions used to define a package or output. The derivation identifies the expected output store paths. Nix uses these to search its configured binary caches. If a matching output is available, Nix retrieves it; otherwise, Nix uses the derivation to produce the output.
A derivation is the unit at which Nix's guarantees apply. Because its inputs are declared and its output store path is computed before the build runs, Nix can check a binary cache for that path first and build only if no substituter already has it. This is also what makes builds hermetic: the builder runs with the declared inputs available and nothing else.
See also: Nix expression, Store object, Store path, Hermetic build, Substituter, Sandbox.
Dev container
A dev container is a development environment packaged as a container image, usually described by a devcontainer.json file and run by an editor or CLI that builds the image and attaches to the running container. The container supplies the project's toolchain, so contributors do not install it on the host.
Dev containers deliver isolation and a shared baseline, and they carry the costs of the container model: an image must be built and pulled, filesystem and network are virtualized, and on macOS everything runs inside a Linux VM, which is where most of the performance complaints originate. Bind-mounted source trees and host-container permission mismatches are recurring friction. The image is also opaque — reproducing it depends on the base image tag and the ordering of the build steps that produced it.
Flox is an alternative to the dev container model rather than a wrapper around it: the toolchain runs natively on the host with no VM, no image build, and no daemon, while backing services can still run in containers where that is the better fit. A Flox environment can also be exported as a standard OCI image when a container is what a target requires.
See also: Development environment, OCI image, Flox environment, Sandbox.
Development environment
A development environment is the set of software and configuration a developer needs to write, run, test, and debug a project. It typically includes language runtimes and compilers, package managers, linters and formatters, database and message-broker clients, and the environment variables and credentials that wire them together.
Development environments are where "works on my machine" originates. When each contributor assembles their own from a README, versions slide apart quietly: one laptop is a patch behind, CI runs a third combination, and an AI coding agent runs a fourth. The failures surface far from their cause, and every fix is per-machine because there is no shared definition to correct.
In Flox, the development environment is declared in a manifest.toml and resolved to a lockfile that pins every dependency by hash. A new contributor runs flox activate and has the same toolchain as everyone else — including CI runners and agent sandboxes — without a setup document to follow.
See also: Build environment, Runtime environment, Environment, Drift, Dev container, Reproducibility.
Drift
Drift is the gradual divergence of environments that are supposed to be identical. Two machines start from the same setup instructions, then accumulate differences: a patch release installed on one and not the other, a system library upgraded by an OS update, an environment variable set once by hand and never recorded.
Drift is difficult to debug precisely because it is invisible until it is not. The symptom is a test that passes locally and fails in CI, a dependency that resolves to a different version on a colleague's laptop, or a production incident that cannot be reproduced anywhere else. The cause is rarely the code under investigation, so the time is spent comparing environments rather than fixing the defect. Documentation does not prevent it — a setup document begins rotting the moment it ships.
Flox addresses drift by making the environment a versioned artifact rather than a procedure. One manifest resolves to one lockfile, and every target resolves from the same revision to the same package set: laptop, CI runner, cloud VM, container image, or agent sandbox. Lock entries are recorded per system, so a macOS laptop and a Linux runner share a manifest and a revision rather than one identical set of store paths.
See also: Reproducibility, Lockfile, Pinning, Development environment, Declarative configuration.
Environment
An environment is the set of software dependencies and configuration settings made available to a process or session. It can include executables, libraries, environment variables, shell settings, secrets, and services.
Nix and Flox define environments declaratively. Activating a Nix or Flox environment makes its software dependencies and settings available without first having installed or exported them globally.
Environments are often distinguished by their purpose:
- A development environment supports writing, testing, and debugging software;
- A build environment provides the tools and inputs required to compile, package, or publish artifacts; and
- A runtime environment provides what the packaged artifacts needs to run and behave reproducibly.
Because a declared environment is a versioned artifact rather than a machine state, it can be reviewed, shared, and reverted like code. Several environments can be active on the same machine without colliding, and deactivating one leaves nothing behind on the host.
See also: Flox environment, Development environment, Build environment, Runtime environment, Activation, Manifest.
Flox build
flox build compiles or packages software using the environment's locked manifest as its inputs. By default the build is not sandboxed: it runs in the root of the repository with no restriction on network or filesystem access, so it can read machine-specific state such as configuration in $HOME. Sandboxing is opt-in via sandbox = "pure" in the manifest, and even then pure builds on macOS retain network access.
Under a pure build, where the build sees only what the manifest declares, an undeclared dependency fails on the machine where it was written rather than surfacing later on a colleague's laptop or a CI runner. This inverts the usual failure mode, in which a build succeeds locally precisely because the author's machine has something no one else does. The output is produced from the same pinned inputs on every machine that runs it.
Flox builds carry through the rest of the lifecycle without redescribing the environment at each stage: the result can be published to a catalog with flox publish, exported as a standard OCI image, or referenced directly from a Kubernetes pod. The manifest that defined the development environment is the same manifest that defines the build.
See also: Build environment, Sandbox, Hermetic build, Manifest, Lockfile, OCI image, Reproducibility.
Flox Catalog
The Flox Catalog is a searchable collection of packages and their metadata. It records a package’s version plus the systems and architectures it supports, along with its license, outputs, and other details.
Both the Base Catalog and private catalogs are separate Flox Catalogs: Flox maintains the public Base Catalog, while users and organizations publish their own packages to private catalogs.
The catalog is also what Flox's resolver queries when turning a manifest into a lockfile: it supplies the metadata needed to find a combination of package versions that can coexist, and to pin each one by hash.
Catalog metadata is richer than a package index because resolution has to answer a harder question than "does this version exist." Finding a set of packages that can coexist requires knowing which nixpkgs revisions provide which versions for which systems, so the catalog records that mapping across roughly three years of history rather than only the current state.
See also: Base Catalog, Private Catalog, Package Groups, Lockfile, FloxHub.
Flox environment
A Flox environment is a declared, versioned collection of packages, environment variables, services, and build steps, defined in a manifest.toml and resolved to a lockfile that pins every dependency by hash. Activating it makes that exact software available to a shell or process without installing anything globally.
Flox environments come in three forms. A path environment lives in a project directory under .flox/ and is typically checked into source control beside the code it supports. A managed environment is a path environment linked to FloxHub, so changes can be pushed and pulled across machines. A remote environment runs directly from FloxHub without a local copy at all.
Because the lockfile records a resolution per system, the same environment activates identically on a developer laptop, a CI runner, a cloud VM, an exported OCI image, or an AI coding agent's sandbox. Environments pushed to FloxHub are versioned as generations, so changes can be diffed and rolled back there. A purely local path environment has no generations.
See also: Environment, Manifest, Lockfile, Activation, Generation, FloxHub, Closure.
Flox services
Flox services are long-running processes declared in an environment's manifest and managed alongside its packages — databases, caches, message brokers, and the other backing services a project needs while it is being developed or tested.
Declaring services in the same file as the toolchain keeps one definition for the whole environment rather than splitting it between a manifest and a separate orchestration file. The services a project needs, the versions they run, and the variables they are configured with are reviewed together and version-controlled together, and they start from the same pinned inputs on every machine.
In Flox, flox services start brings up an environment's services and flox services status reports on them. Services run as ordinary processes on the host rather than requiring a container runtime, though teams commonly pair Flox with containers where a service is more convenient to run that way — running project runtimes natively while containers handle backing services is a common and well-supported pattern.
See also: Flox environment, Manifest, Activation, Development environment.
FloxHub
FloxHub is the hosted service where Flox environments and privately published packages live once they leave a single machine. It is available at hub.flox.dev, and sign-up is free.
Pushing an environment to FloxHub makes it addressable by name, so a teammate, a CI runner, or a Kubernetes pod can pull exactly the environment that was published rather than reconstructing it. Each change is recorded as a generation with full history and diffs, and any prior generation can be restored in one step. This is what turns an environment from a local artifact into something an organization can standardize on.
For teams and organizations, FloxHub adds the controls needed to govern that standardization: private catalogs, private and air-gapped package distribution, service accounts for CI and automation, single sign-on, and role-based access control. The free personal tier includes unlimited public environments, three private environments, and five private packages.
See also: Flox environment, Generation, Rollback, Private Catalog, Air-gapped distribution, Imageless Kubernetes.
Generation
A generation is an immutable, numbered snapshot of an environment's state at a point in time. For environments pushed to FloxHub, every modification — installing a package, editing the manifest, upgrading a pin — creates a new generation rather than mutating the previous one in place. Local path environments, which is where most people start, do not have generations.
Because prior generations are retained rather than overwritten, the history of an environment is inspectable: FloxHub's History view shows what changed between generations, and any earlier generation can be restored. This makes an environment change behave like a code change, with the same review and revert affordances, instead of an untracked mutation to a machine.
In Flox, generations are recorded for environments pushed to FloxHub, which provides full history and diffs across an organization and rollback to any prior generation in one step. In practice this is what makes an aggressive dependency bump safe to attempt: if a new version regresses, the previous generation is one command away rather than an exercise in reconstructing what was there before.
See also: Rollback, FloxHub, Flox environment, Lockfile, Pinning.
Hermetic build
A hermetic build is one that depends only on inputs it declares explicitly, and is isolated from everything else on the machine running it. It does not read undeclared files, resolve packages from the ambient system, or reach the network for dependencies mid-build.
Hermeticity is the property that makes a build's output a function of its inputs. When a build can silently consume whatever the host provides — a system compiler, a globally installed library, a cached credential — its output depends on machine state that is neither recorded nor reviewed, which is why the same source tree can produce different artifacts on two machines. Enforcing isolation converts that class of failure from a mystery discovered downstream into a build error on the machine where the omission was introduced.
Nix builds are hermetic by construction: a derivation names its inputs, and the builder runs with only those inputs available. Flox does not inherit this by default. flox build runs unsandboxed in the repository root unless the manifest sets sandbox = "pure", which restricts filesystem and network access — and pure builds on macOS still retain network access. Hermeticity in Flox is therefore something to opt into and verify, not something you get for free.
See also: Reproducibility, Sandbox, Derivation, Closure, Flox build, Build environment.
Imageless Kubernetes
Imageless Kubernetes, also called “Kubernetes, Uncontained,” is a deployment model in which a versioned Flox environment (instead of an OCI image) is used to supply a pod’s runtime software. A Flox containerd shim pulls the environment from FloxHub, realizes its packages in an immutable node-local Nix store, and activates it inside a runtime container. Imageless Kubernetes is completely compatible with Kubernetes APIs, pods, networking, and orchestration.
The practical effect is on image build and pull: there is no multi-gigabyte image to produce, push, or pull on every node, which matters most for ML and AI stacks where CUDA and framework layers dominate image size. Because the environment is pulled from FloxHub by reference, the software running in the pod is the same versioned environment developers activate locally.
Because every environment on a node realizes into the same Nix store, environments that share dependencies share store objects rather than duplicating them per image layer — so the marginal cost of a second environment on a node is only what actually differs between them. See also: OCI image, FloxHub, Runtime environment, Flox environment, Nix store.
Layering
Layering is the composition of multiple environments so that their packages and settings apply together, with a defined precedence when they overlap. Rather than defining one environment that contains everything a task needs, a team can maintain smaller environments and activate them in combination.
Layering separates concerns that change at different rates and belong to different owners. A project environment declares what the project needs; a personal environment adds an individual's preferred shell tooling; an organization-wide environment supplies mandated security or observability tools. Each is versioned and reviewed by the people responsible for it, and no one has to fork a shared definition to add something local.
In Flox, activating one environment on top of another layers them, and Flox composition lets a manifest include other environments at build time via [include], so a composed environment resolves to a single lockfile. Package groups govern how packages within an environment resolve against one another when their requirements conflict.
See also: Flox environment, Package Groups, Manifest, Activation.
Lockfile
A lockfile records the exact resolution of a set of declared dependencies: which versions were selected, where they came from, and the hashes that identify them. The declaration states what is wanted; the lockfile states what was actually resolved, so the same resolution can be reproduced later rather than recomputed.
The distinction matters because dependency declarations are usually ranges, and a range resolves differently as upstream publishes new releases. Without a lockfile, two machines running the same install command weeks apart get different software and neither is doing anything wrong. With one, resolution happens once and every subsequent consumer replays it.
In Flox, a manifest.toml resolves to a single lockfile that pins every dependency by hash, including transitive dependencies. Every target then resolves from that same revision rather than re-resolving and hoping the answer matches — laptop, CI runner, cloud VM, container image, or agent sandbox. The lockfile records an entry per system, so targets on different architectures share a manifest and a revision, not a single set of store paths. The lockfile is checked into source control alongside the manifest, so a change in resolved dependencies appears in a diff and is reviewed like any other change.
See also: Manifest, Pinning, Closure, Reproducibility, Drift, Base Catalog.
Manifest
A manifest is the declarative file that defines an environment: the packages it contains, the environment variables it exports, the services it runs, and the build steps it supports. It states the desired end state rather than a sequence of installation commands.
Keeping the manifest in source control alongside the code it supports is what makes an environment reviewable. A change to the toolchain arrives as a diff, goes through the same review as a code change, and is attributable to a commit — as opposed to a setup document that describes what someone did once, or a machine that was configured by hand and cannot be reconstructed.
In Flox, an environment is declared in manifest.toml, stored at .flox/env/manifest.toml. Flox resolves it to a lockfile that pins every dependency by hash, so the manifest expresses intent and the lockfile records exactly what that intent resolved to. The full field reference is documented at flox.dev/docs/man/manifest.toml.md; manifest fields should be checked against it rather than guessed at, which is a common failure mode when an AI coding agent writes one from memory.
See also: Lockfile, Declarative configuration, Flox environment, Package Groups, Flox services.
Nix expression
A Nix expression is a term written in the Nix language that evaluates to a value. That value may be a primitive value, collection, function, or build specification known as a derivation. In other words, a Nix expression is a piece of Nix code that Nix interprets to produce a result. For a given package, evaluating the relevant expressions produces a derivation that specifies its build inputs, builder, and expected outputs.
Expressions are composed rather than executed in sequence: one expression can take another as an argument, so a package definition is a function of its inputs rather than a script that installs something. This is what allows the same definition to be evaluated against different dependency versions and produce a correspondingly different derivation, and it is why a change deep in a dependency graph propagates to a new output path automatically instead of requiring every dependent to be rebuilt by hand.
See also: Nix language, Derivation, Nix flake, Nixpkgs, nixpkgs.
Nix flake
A flake is a Nix abstraction that packages Nix code behind a standardized interface. Its source is a project’s filesystem tree, usually tracked and versioned in source control, with a flake.nix file at its root.
This file declares the flake’s dependencies, called inputs, and also defines an outputs function. Given the resolved inputs, the outputs function returns an attribute set (i.e., a collection of named values) that exposes derivations (package build specifications), development shells (development environments), modules (reusable configuration logic), and system configurations (complete declarative system definitions).
Flakes also pin their inputs in a flake.lock file, which is what makes a flake's evaluation reproducible across machines and over time. Flox does not require flakes — a Flox environment is declared in a manifest.toml and the CLI surface is flox activate, not nix develop — but the two interoperate, and teams with existing flakes commonly keep them.
See also: Nix language, Nix expression, Derivation, Lockfile, Manifest.
Nix language
The Nix language is a lazy, purely functional language used to describe and compose package builds and declarative configurations. Nix expressions and flakes both use the Nix language.
Two properties do most of the work. Being purely functional means an expression's value depends only on its inputs, with no side effects — which is what allows Nix to compute a build's output path before running it, and to cache aggressively. Being lazy means expressions are evaluated only when their values are needed, which is what makes a collection the size of nixpkgs tractable to evaluate at all: a single package can be built without evaluating the other 140,000.
The language is also the main source of Nix's learning curve. It is unlike the configuration formats most engineers arrive with, and reading real nixpkgs code requires fluency in it. Flox is built on Nix but does not require writing Nix: environments are declared in TOML, and the language becomes relevant only when packaging software that the catalog does not already provide.
See also: Nix expression, Nix flake, Derivation, Nixpkgs, nixpkgs, Declarative configuration.
Nixpkgs, nixpkgs
Nixpkgs or nixpkgs, short for the Nix Packages collection, is a version-controlled repository containing Nix expressions for more than 140,000 software packages, including millions of historical package-version combinations. It lives on GitHub under the NixOS organization. Each nixpkgs Git revision pins a compatible set of package-version combinations at a particular point in time. Nix uses the checked-out revision to build packages from source or retrieve pre-built archives from the public Nix binary cache.
Because a revision pins a mutually compatible set of packages, the revision is effectively the unit of compatibility: two packages resolved against the same revision are known to work together, while packages from different revisions may disagree about shared library versions. This is the constraint Flox package groups exist to manage.
Its scale is also its main practical difficulty. Finding the right attribute path, understanding how an override works, or determining which revision has a particular version are all real tasks, and the answers are spread across the repository's own code. Flox's catalog exists largely to make that resolution a search rather than an archaeology exercise. See also: Package Groups, Base Catalog, Nix expression, Nix language, Pinning.
Nix store
A Nix store is a storage system containing immutable store objects and the references between them. A store may be local (e.g., located in**/nix/store**) or remote, as with a binary cache.
Two properties make the store what it is. Objects are immutable — nothing is ever modified in place, so an upgrade adds a new store object rather than overwriting an existing one, and software depending on the old version keeps working. Object paths are input-addressed by default: the path is derived from the recipe that produced the object — its inputs, builder and arguments — not from the resulting bytes. Derivation files and fixed-output derivations are the exception and are content-addressed, where the path does come from the contents. Because an ordinary output path encodes the recipe rather than the bytes, Nix requires a trusted signature before accepting a substituted object.
Together these allow multiple versions of the same package to coexist on one machine without conflict, which is what removes the need for per-project virtual environments or containers purely to isolate dependency versions.
The store is also append-only in practice, which means it grows. Objects no longer referenced by any environment or generation remain on disk until garbage collection removes them, so disk usage is a real operational consideration on long-lived machines and CI runners. See also: Store object, Store path, Closure, Binary cache, Substituter.
OCI image
An OCI image is a container image in the format standardized by the Open Container Initiative. It consists of a stack of filesystem layers plus a manifest and configuration describing how to run them, and it is the interchange format that Docker, containerd, Podman, and Kubernetes all consume.
The format is a distribution mechanism, not a reproducibility mechanism. An image is a fixed set of bytes and pulling one by digest gets exactly those bytes — but rebuilding an equivalent image from the same Dockerfile weeks later routinely produces different content, because the base image tag moved and each RUN step re-resolved packages against whatever the upstream index offered that day. The artifact is reproducible; the process that produced it usually is not.
Flox treats OCI images as an output rather than the source of truth. A locked environment can be exported as a standard OCI image for any target that expects one, while the environment itself remains the reproducible definition. For Kubernetes specifically, imageless Kubernetes skips image build and pull entirely by referencing the environment from the pod.
See also: Imageless Kubernetes, Dev container, Reproducibility, Closure, Flox build.
Package Groups
Package Groups are one of the mechanisms Flox provides to manage dependency conflicts. Each package in a group resolves against the same nixpkgs; this safeguards against runtime ABI incompatibilities and version conflicts. Different groups resolve independently and may use different nixpkgs revisions. This allows packages with otherwise incompatible version requirements to coexist in the same environment.
In practice this is the mechanism that resolves the most common dependency conflict in a polyglot project: two tools that each need a different version of a shared library. Putting them in separate groups lets each resolve against the nixpkgs revision it needs, while packages that must agree — a compiler and its standard library, say — stay in one group.
Groups are declared in the manifest, and packages that are not assigned to one share a default group. The trade-off is deliberate: more groups means more independently resolved nixpkgs revisions and a larger closure, so the useful default is a single group, splitting only when a genuine conflict makes it necessary.
See also: Nixpkgs, nixpkgs, Manifest, Toolchain, Layering, Flox Catalog.
Pinning
Pinning is fixing a dependency to an exact, immutable identifier rather than a range or a moving tag, so that resolving it later returns the same software. A pin may be a precise version, a Git revision, or — most strictly — a content hash of the artifact itself.
The strength of a pin depends on what it names. A version number like 1.4.2 is weaker than it looks: a package can be republished, and a version says nothing about the transitive dependencies resolved alongside it. A Git revision is stronger. A content hash is strongest, because it identifies the bytes rather than a label pointing at them, and any substitution is detectable.
In Flox and Nix, pinning is hash-based and covers the whole dependency graph rather than only direct dependencies. A Flox manifest resolves to a lockfile that pins every dependency by hash, and the resulting store paths are derived from those hashes — so a pinned environment names one exact closure, not a family of closures that happen to satisfy the same constraints.
See also: Lockfile, Store path, Closure, Reproducibility, Drift, Nixpkgs, nixpkgs.
Private Catalog
A private catalog is a Flox catalog that contains packages published by a FloxHub user or organization. An individual user’s catalog is accessible only to that user; an organization’s catalog is shared among its members according to their permissions. Unlike the Base Catalog, private catalogs contain user- or organization-published packages rather than packages derived from nixpkgs.
Private catalogs are how an organization distributes internal software through the same mechanism as open source packages, rather than maintaining a parallel path for it. Combined with air-gapped distribution, this lets a locked environment resolve entirely inside a network boundary with no public egress.
Publishing to a private catalog uses the same mechanism as installing from the public one: flox publish puts an internal package where teammates can resolve it by name, and it is pinned and cached like any other. Access follows FloxHub roles, so an organization's packages are visible to its members according to their permissions rather than to anyone with the name.
See also: Base Catalog, Flox Catalog, FloxHub, Air-gapped distribution, Supply chain security.
Provenance
Provenance is verifiable evidence of where an artifact came from: which sources and dependencies went into it, which build process produced it, and on what inputs that process ran. It answers "can we prove this is what we think it is," rather than "does the label say so."
Provenance is difficult to reconstruct after the fact. Scanning a finished container image infers what is probably inside it from filenames and package databases, which yields both false positives and missed transitive components. Evidence that is generated as a property of how software is built — rather than inferred once it exists — is both more complete and harder to forge, which is why supply chain frameworks increasingly require attestations emitted by the build system itself.
In Flox, provenance follows from the model rather than being bolted on. Every environment carries a deterministic bill of materials read from its dependency graph, pinned and signed, and store paths are input-addressed, so an artifact's identity is derived from the recipe that produced it, and signatures are what let a consumer trust a prebuilt object rather than rebuilding it. Flox is SOC 2 Type II and ISO/IEC 27001:2022 certified.
See also: SBOM, Supply chain security, CVE, Store path, Hermetic build, Derivation.
Reproducibility
Reproducibility is the property that the same declared inputs yield the same result every time, on any machine, regardless of when the operation runs or what else is installed on the host.
It is worth distinguishing from two weaker properties it is often confused with. Repeatability means the same machine gives the same answer twice, which says nothing about a colleague's laptop. Determinism in the strictest sense — bit-for-bit identical build outputs — is a stronger goal that embedded timestamps, build paths, and parallel-build nondeterminism can defeat even when the inputs are pinned. The practical target for most teams sits between them: the same closure of the same software, resolved identically everywhere.
Nix and Flox achieve this by declaring inputs explicitly, resolving them once into a lockfile pinned by hash, and building in isolation from ambient system state. One manifest resolves to one lock, and every target resolves from the same revision to the same package set — a developer laptop, a CI runner, a cloud VM, an exported container image, or an AI coding agent's sandbox — rather than a lookalike that happens to work today. Across architectures that means the same manifest, revision and resolution, with store paths appropriate to each system.
See also: Hermetic build, Lockfile, Pinning, Closure, Drift, Declarative configuration.
Rollback
A rollback restores an environment to an earlier known-good state after a change causes a problem. Because prior states are retained as immutable snapshots rather than overwritten, a rollback is a switch back to something that still exists, not a reconstruction of something that was lost.
This is what makes it fundamentally different from reinstalling. Reinstalling from a manifest re-resolves dependencies and may not reproduce the environment that was working, particularly if the failure came from a transitive dependency that moved. Restoring a retained snapshot returns the exact closure, so the recovery path does not depend on the resolver agreeing with itself across time.
In FloxHub, every change to a pushed environment produces a new generation, and any prior generation can be restored in one step. Path environments have no generations, so this applies once an environment has been pushed. The practical effect is on risk appetite: upgrading a compiler or bumping a pinned dependency is cheap to attempt when reverting is a single command, so teams patch more readily than they do when a failed upgrade means an afternoon of reconstruction.
See also: Generation, FloxHub, Closure, Lockfile, CVE.
Runtime environment
A runtime environment provides what a packaged artifact needs in order to run and behave reproducibly: interpreters, shared libraries, certificates, environment variables, and the configuration the process reads at start-up.
It is usually much smaller than the build environment that produced the artifact, and keeping the two distinct is what keeps deployments lean — a compiled binary rarely needs the compiler that produced it. The runtime environment is also where reproducibility most often breaks in practice: an artifact built against one version of a shared library and run against another fails at load time or, worse, behaves subtly differently, which is the class of bug that "works in staging" is usually hiding.
In Flox, the runtime environment is the same declared environment used for development and builds, activated in run mode rather than redescribed for deployment. A runtime closure includes a package and all of its transitive runtime dependencies, so what runs in production is the same closure that was tested — including inside a Kubernetes pod, where the environment can be referenced directly with no container image.
See also: Build environment, Development environment, Closure, Activation, Imageless Kubernetes.
Sandbox
A sandbox is a restricted execution context that limits what a process can read, write, and reach. In a build system, sandboxing means the build runs with only its declared inputs visible, no access to the wider filesystem, and typically no network.
Sandboxing is how a build system enforces hermeticity rather than merely requesting it. Without it, a build that forgets to declare a dependency still succeeds on any machine that happens to provide it, and the omission is discovered later by someone whose machine does not. With it, the omission fails immediately, on the machine of the person who introduced it, where it is cheapest to fix.
Sandboxing is also increasingly relevant to AI coding agents, which execute code as part of their normal operation. Giving an agent a sandboxed environment with the same pinned toolchain as the rest of the team constrains what it can reach while ensuring what it runs matches what CI will run.
In Flox, sandboxing is opt-in rather than the default: flox build runs in the repository root unless the manifest sets sandbox = "pure", which restricts filesystem and network access — with the caveat that pure builds on macOS keep network access. Separately, Flox environments are used to give agent harnesses a deterministic, bounded toolchain.
See also: Hermetic build, Flox build, Build environment, Dev container, Derivation.
SBOM
An SBOM (Software Bill of Materials) is a formal, machine-readable inventory of the components in a piece of software, including transitive dependencies, their versions, and their suppliers. Common formats are SPDX and CycloneDX, and an SBOM is increasingly a procurement and regulatory requirement rather than an internal nicety.
The value of an SBOM depends entirely on how it was produced. One generated by scanning a finished artifact is an inference — it reports what a scanner could recognize from filenames and package metadata, which misses vendored code and statically linked components while flagging things that are present but unreachable. One read directly from the dependency graph that produced the artifact is a record rather than a guess.
In Flox, the bill of materials is a property of the environment rather than a post-hoc scan: every environment carries a deterministic bill of materials, pinned and signed, read from its dependency graph. Because the lockfile already names the complete closure by hash, the inventory and the software are the same fact expressed two ways.
See also: Provenance, Supply chain security, CVE, Closure, Lockfile.
Store object
A store object is an entity in the Nix store’s data model. Every store object consists of:
- an identity: a unique store path that identifies the object and locates its filesystem data;
- data: a filesystem object, such as a file, symlink, or directory tree; and
- references: a set of store paths representing references from the object to other store objects;
In a typical local Nix store, a store object’s data resides under /nix/store, while Nix maintains the references and other object metadata separately in its SQLite store database.
Separating identity, data, and references is what makes the store analyzable. Because every object's references are recorded rather than inferred, the complete set of things an object depends on can be computed exactly — which is what a closure is, and what makes a bill of materials a query against the store rather than a scan of a finished artifact. See also: Store path, Nix store, Closure, Derivation, Binary cache.
Store path
A store path is a name (such as /nix/store/<hash>-<name>) that identifies a Nix store object. In a local Nix store, it is also that object’s filesystem location. In a remote store or binary cache, the store path still identifies the object, even though its data may be stored and transmitted in another form, such as a Nix Archive (NAR). Store objects use store paths to reference one another.
A store path consists of:
- store directory: the root of the store’s namespace, typically
/nix/store; in a local store, this is also a filesystem directory; - a digest: a 20-byte, hash-derived identifier rendered as 32 characters using Nix’s Base32 encoding; and
- a name: a human-readable label for the store object.
For example: /nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1. Here, /nix/store is the store directory, b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z is the digest, and firefox-33.1 is the name.
Because the digest is derived from the inputs that produced the object, a store path identifies a recipe rather than a location that happens to hold something. It does not, on its own, guarantee that two machines holding the same path hold identical bytes — that only follows for content-addressed objects. For ordinary input-addressed outputs, the signature on a substituted object is what makes its origin checkable rather than asserted.
See also: Store object, Nix store, Closure, Pinning, Provenance, Substituter.
Substituter
A substituter is a source of prebuilt store objects that Nix consults before building anything locally. When Nix evaluates a derivation it computes the output store path first, then asks each configured substituter whether it already has that path; if one does, Nix downloads the result instead of running the build.
This is what makes Nix's build model practical rather than merely correct. Building a modern toolchain from source takes hours; retrieving the same store paths from a cache takes minutes. Because the store path is derived from the build inputs, a substituter can offer an object for exactly the path that would have been built. The path encodes the recipe rather than the bytes, though, so it is the signature on the object — not the path alone — that establishes the result came from somewhere trusted. Substituters are consulted in priority order, lowest value first, which is separate from trust: trusted-substituters governs which ones an unprivileged user may use.
Nix uses cache.nixos.org by default. Flox operates its own binary cache at cache.flox.dev, which serves prebuilt packages that are unavailable upstream — most notably the full NVIDIA CUDA toolkit, which is otherwise an expensive local build.
See also: Binary cache, Store path, Store object, Derivation, CUDA in the Flox Catalog.
Supply chain security
Supply chain security is the practice of securing everything that contributes to a software artifact — source code, dependencies, build tooling, and the systems that assemble and distribute the result — rather than only the finished product. Its premise is that an attacker does not need to compromise your code if they can compromise something your code depends on, or the machine that builds it.
The attacks that motivated the field are instructive: a compromised build server injecting a backdoor into a signed update, a maintainer account takeover publishing a malicious release to a public registry, a typosquatted package name pulled in transitively. None are caught by reviewing the application's own source, because none of them are in it.
Defending this surface requires knowing exactly what goes into an artifact and being able to prove it. In Flox, every environment carries a deterministic bill of materials, pinned and signed, read from its dependency graph rather than inferred afterwards — so the inventory, the provenance, and the software are the same fact. Flox is SOC 2 Type II and ISO/IEC 27001:2022 certified.
See also: SBOM, Provenance, CVE, Pinning, Air-gapped distribution.
Toolchain
A toolchain is the coordinated set of tools used to turn source code into a running program: compiler or interpreter, linker, standard library, build system, and the package manager that supplies them. The parts are coordinated because they must agree — a compiler emits object code a specific linker understands, against headers from a matching standard library.
That coupling is why toolchain versions are load-bearing rather than incidental. Mixing a compiler from one release with a standard library from another produces failures that look like application bugs but are not, and the resulting error messages rarely point at the mismatch. It is also why "install the latest" is poor guidance for a team: the latest is a moving target, and two developers following it a month apart get different toolchains.
In Flox, the toolchain is declared in the manifest and pinned in the lockfile like any other dependency, and package groups ensure packages that must agree resolve against the same nixpkgs revision. Every laptop, CI runner, and agent sandbox gets the same toolchain rather than one that happens to be close.
See also: Package Groups, Build environment, Lockfile, Pinning, Drift, Development environment.


