Connect
Reference

Glossary

Plain definitions of the terms behind Flox and Nix.

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 pins every declared dependency by hash, and those pins determine the full closure — so it 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.

Auto-activation

Auto-activation makes a Flox environment activate as soon as you enter a directory containing a .flox subdirectory, and deactivate when you leave it. Packages, environment variables and hooks are ready without a manual step.

It works through a prompt hook installed in your shell startup file — in Bash, eval "$(flox activate -D)" in ~/.bashrc, with equivalents for Zsh, Fish and Tcsh. The hook runs on every prompt to discover environments, check whether they are allowed, activate them in order, and deactivate them on the way out.

Because activating an environment runs its hook and profile scripts, auto-activation is gated on trust rather than enabled blindly. An environment must be explicitly allowed before it will auto-activate; an unrecognised one prompts interactively — Auto-activate the environment in '/path/to/project'? [y/N] — and environments can be allowed or denied ahead of time. Reviewing a manifest's hook and profile scripts matters most for repositories you have cloned rather than written, where entering a directory would otherwise run someone else's code.

See also: Activation, Flox environment, Manifest, Plugin.

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 samples package definitions only from nixos-unstable. Those packages enter the Base Catalog’s unstable branch, then progress through Flox-managed staging, stable, and lts branches at successively longer cadences. These are Flox’s branch names, not the upstream nixpkgs branches of the same name. 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.

Catalog Store

A Catalog Store is the storage backend holding the package artifacts an organization publishes: an AWS S3 bucket, or any S3-compatible service such as MinIO or Backblaze B2.

Publishing splits into two parts. Package metadata goes to Flox's servers, where it becomes searchable and installable by name. The artifact itself goes to a Catalog Store, and that is where a consumer downloads it from at install time.

Most organizations never configure one: Flox provides a pre-configured Catalog Store by default, and the customer documentation is explicit that a custom store is only relevant if an organization has chosen to provide its own. Doing so means running S3-compatible storage and configuring an ingress URI for uploads, an egress URI for downloads, and a signing key pair — the private half distributed to whoever publishes, the public half to whoever installs.

The reason to take that on is control: the bytes never leave infrastructure the organization operates, which is what makes it viable where egress to a vendor-hosted store is not.

See also: Publishing, Signing key, Private Catalog, Flox Catalog, Air-gapped distribution.

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 name the same store paths, produced by the same recipes, over the same dependency graph — down to the last transitive dependency; two that differ do so at identifiable store paths. Identical paths do not by themselves prove identical bytes: that follows for content-addressed outputs, or where both machines fetched the object from the same cache, which in practice is nearly always cache.flox.dev. Locally built outputs land in the same store without that guarantee. 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.

Composition

Composition lets one Flox environment include and merge others, so an environment becomes a reusable building block rather than something copied between projects.

The composing environment declares an [include] section with an environments array, each entry naming either a local dir or a remote, optionally with a name override:

[include]
environments = [
  { dir = "../myenv" },
  { remote = "myuser/base-toolchain" },
]

Later manifests override earlier ones, and the composing environment's own manifest is applied last, so it always wins. How a conflict resolves depends on the field: install, services and vars take the union, with a conflicting entry overriding outright; hook.on-activate and profile scripts append in sequence rather than replacing one another; options is overridden wholesale, deliberately, so an included environment cannot quietly escalate permissions.

Included environments are not tracked automatically. flox include upgrade checks each one for changes and rebuilds the composed environment against the updated manifests.

See also: Layering, Flox environment, Manifest, Package Groups.

Containerize

flox containerize exports a Flox environment as a container image, so the same declared environment can run wherever an OCI image is expected without being described a second time in a Dockerfile.

By default it detects the first container runtime available on PATH and loads the image into it; {name}-container.tar is the fallback, written when no runtime is specified or detected. --runtime names Docker or Podman explicitly instead of detecting, and -f - streams to stdout for piping into docker load. Running the resulting image interactively opens a bash subshell that mirrors flox activate; running it with a command executes directly, like flox activate --.

On macOS a supported container runtime is required, because a proxy container performs the build — you may be prompted to share files into it. A flox-nix Docker or Podman volume caches files between runs and is safe to remove when no containerize command is in flight.

The [containerize.config] manifest table exposes OCI metadata such as user, exposed ports, volumes, working directory, labels and stop signal. It is experimental and its behaviour is subject to change.

See also: OCI image, Flox environment, Imageless Kubernetes, Dev container.

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.

Enterprise SSO

Enterprise SSO lets an organization's members sign in to FloxHub and the Flox CLI with their work accounts, through the organization's own identity provider, instead of through GitHub, Google or GitLab.

Which providers are available depends on the deployment. Hosted FloxHub supports Entra ID and Okta. Self-hosted FloxHub runs Dex, where the connectors are configured by whoever operates the deployment, so any OIDC or SAML provider can be used — the self-hosted documentation covers Okta, Entra ID, AD FS and LDAP.

Either way, sign-in is driven entirely by email domain: a member enters their work address and is redirected to their provider, with nothing to configure on their side.

Only organization owners can set it up, from the organization's settings page, through a guided flow that includes verifying the email domain.

On first sign-in a member joins the organization automatically with the Reader role — the least privileged one — and an owner promotes them from the Users tab afterwards. That default is deliberate: domain-based sign-in means anyone with a company address can arrive, so arriving grants read access rather than write.

See also: Organization, Service account, Personal access token, FloxHub.

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 live once they leave a single machine, and where the metadata for privately published packages is held — the package artifacts themselves live in a Catalog Store. 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, enterprise SSO, and role-based access control across three roles. The free personal tier includes unlimited public environments, three private environments, and five private packages.

See also: Flox environment, Generation, Organization, Catalog Store, Private Catalog, 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 declared dependency by hash. Transitive dependencies are not listed in the file; the pinned store paths determine them. 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 references the environment from the pod rather than building and pulling an image for it. A pod spec still requires an image:, so the documented examples use the tiny flox/empty stub to satisfy it — nothing meaningful is pulled, though an air-gapped cluster still has to mirror that stub.

See also: Imageless Kubernetes, Dev container, Reproducibility, Closure, Flox build.

Organization

An organization is a shared FloxHub workspace for a team, providing a private catalog, scoped access control, and shared ownership of environments and packages. It is a paid feature, available through Flox for Teams.

Access is governed by three roles:

  • Owner — full administrative access, including managing members and settings. At least one owner must remain at all times; beyond that an owner may change their own role or step down. The UI hides those controls on your own row, which makes the constraint look stricter than it is.
  • Writer — can create and update environments and packages, but not manage members or organization settings.
  • Reader — can view and pull environments and install packages, but not create or modify them.

Environments and packages created in an organization are visible to all its members, with access governed by that role assignment. Ownership sits with the organization rather than the individual who created something, which is the point: work does not become inaccessible when a person changes team or leaves.

See also: Enterprise SSO, Service account, Personal access token, Private Catalog, FloxHub.

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.

Personal access token

A personal access token authenticates the Flox CLI as you, without an interactive browser sign-in.

It exists for contexts where a browser flow is not available — an SSH session, a container, a machine with no browser. Tokens are generated from your FloxHub profile page, carry a flox_pat_ prefix, and are given an expiry of 30 days, 90 days, a year, or none. They are supplied either as a file, with flox auth login --token-file ./token, or through the FLOX_FLOXHUB_TOKEN environment variable.

A token is shown once and cannot be retrieved afterwards. It can be revoked from the same page, taking effect on the next request. The token carries your identity and your access, so anything done with it is done as you.

That is the distinction from a service account, and it matters more than it first appears. A personal access token belongs to an individual account; a service account belongs to an organization and is managed by its owners. Automation authenticated with a personal token stops working when that person's access is removed, and revoking the token to contain a leak also disrupts whatever else that person was running. Automation that outlives any one person's involvement belongs on a service account.

See also: Service account, Organization, Enterprise SSO, FloxHub.

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.

Plugin

A plugin packages reusable, manifest-configured behaviour as an installable component, so a convention can be distributed rather than copied into every environment that wants it.

A plugin has two halves: configuration in the manifest's [plugins.<name>] table, and behaviour delivered by a profile.d script inside the package itself. Install the package that provides it, then add its table — using the Vault secrets plugin as an example:

[install]
plugin-vault.pkg-path = "flox/plugin-vault"

[plugins.plugin-vault]
GH_TOKEN = "secret/github-work"

The script reads its own configuration through flox_plugin_data, which prints the [plugins.<name>] table from the locked manifest as compact JSON, or fails if the table is missing. It runs during activation, after Flox's own setup scripts and before hook.on-activate.

Secrets retrieval is the most developed use, but not the only one: a plugin can standardize linter or formatter configuration across every environment in an organization, or toggle a package's optional behaviour such as verbose logging or a telemetry opt-out.

Plugins require schema-version 1.14.0 or higher and are currently experimental.

See also: Secrets management, Manifest, Schema version, Activation.

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.

Publishing

Publishing uploads a package built with flox build to a catalog, so it can be installed by name into any environment that has access to it.

Four conditions must hold first: the environment lives in a git repository, the repository is clean, it has a remote defined with the current revision pushed to it, and at least one package is installed. Together these tie a published artifact to an exact, retrievable point in the project's history — a package you can find the source for.

A published package has two parts. Metadata goes to Flox's servers, making it discoverable through flox search, flox show and flox install. The artifact goes to a Catalog Store, which is where a consumer downloads it from.

Packages published by a user are prefixed with their username, as in myuser/hello. flox publish --org <organization> publishes into an organization instead, where the package is visible only to its members.

See also: Flox build, Catalog Store, Signing key, Private Catalog, Organization.

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. The lockfile pins what the manifest declares rather than enumerating the closure, but those pins determine it, so the inventory is derived from the graph rather than guessed at. The inventory and the software are the same fact expressed two ways.

See also: Provenance, Supply chain security, CVE, Closure, Lockfile.

Schema version

schema-version records which version of the manifest schema a Flox environment's manifest is written against. It was introduced in CLI 1.10.0, replacing the earlier version field, and a new schema version takes the version string of the CLI release it shipped with.

It exists so that the manifest format can change without stranding environments written against an older one. When a backwards-incompatible change lands — the outputs field for package descriptors is the documented example — the manifest is migrated to the latest schema version automatically rather than failing to load.

Changes that are not schema changes leave it alone. Editing an activation hook, adding a package, adjusting a variable: none of these alter the schema version, because none of them depend on the format having changed.

The practical consequence is that a manifest's schema version tells you what the format guarantees, not when the file was last edited.

See also: Manifest, Flox environment, Plugin, Systems.

Secrets management

Flox handles secrets by just-in-time retrieval: a secret is fetched when the environment activates, rather than stored anywhere Flox controls.

The manifest holds retrieval instructions, never values. No secret values, no dotenv file, nothing in shell history — which is what makes a manifest safe to commit alongside the code it describes. Retrieved secrets are exported as environment variables that exist only in the active Flox shell and are gone when it exits.

The problem this addresses is that the usual alternatives leave copies behind. A dotenv file lives on disk and gets committed by accident; a value pasted into a shell survives in history; a secret baked into an image travels wherever the image does. Retrieval at activation leaves nothing to find later.

There are two routes. A secrets plugin (Flox 1.14.0 and later) bundles a store's CLI together with a retrieval script and is configured through a [plugins.<name>] table; flox/plugin-vault and flox/plugin-1password are examples. Where no plugin exists, an on-activate hook calls the store's CLI directly.

Plugins currently cover 1Password, HashiCorp Vault, OpenBao and Infisical. Hook-based retrieval is used for macOS Keychain, AWS Secrets Manager, Doppler, Pass and the Linux keyring.

See also: Plugin, Manifest, Activation, Flox environment.

Service account

A service account is an identity your automation signs in with — a nightly test run, a release pipeline — that belongs to an organization rather than to a person.

The reason to use one is continuity and containment. CI authenticated as an individual breaks when that individual's access is removed, and revoking their credential after a leak disrupts everything else they were running. A service account is owned by the organization, so neither happens.

Only organization owners can create them, from FloxHub's Service accounts tab, choosing read-only or read and write access for the whole organization. Tokens are prefixed flox_sat_ and supplied to CI through the FLOX_FLOXHUB_TOKEN environment variable.

A token is displayed once, at creation, and cannot be retrieved afterwards. Several can be active at the same time, which is what makes rotation possible without downtime: issue a new token, deploy it, then revoke the old one.

See also: Organization, Personal access token, Enterprise SSO, FloxHub.

Signing key

A signing key is the key pair used to sign packages published to a Flox Catalog and to verify them at install time. A package must be signed before it can be uploaded, and installing one requires configuring your system to trust the public key it was signed with.

The pair is generated with Nix's own tooling — nix key generate-secret --key-name signing-key for the private half, nix key convert-secret-to-public to derive the public half. Flox is pointed at the private key with flox config --set publish.signing_private_key, which must be given an absolute path. Consumers add the public key to Nix's extra-trusted-public-keys.

For an organization running its own Catalog Store, an administrator creates the pair once, distributes the private key to whoever is authorized to publish, and the public key to whoever is authorized to install.

This is what makes a downloaded artifact checkable rather than merely addressable: a store path names the recipe that produced an object, and the signature is what establishes it came from somewhere trusted.

See also: Publishing, Catalog Store, Provenance, Supply chain security, Substituter.

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.

Systems

A system is a platform a Flox environment can be resolved for, named as an architecture-and-operating-system pair. Flox recognises four: aarch64-darwin, x86_64-darwin, aarch64-linux and x86_64-linux.

One environment serves several systems at once. Installing a package installs it for every system that supports it and skips the rest — install something Linux-only and Apple machines simply do not receive it, without the install failing. The manifest's systems attribute states this explicitly where it matters, as in systemd.systems = ["aarch64-linux", "x86_64-linux"], and on an unsupported system the package is absent from the activated environment rather than broken within it.

This is the detail behind "the same environment everywhere". A lockfile records a resolution per system, so a macOS laptop and a Linux CI runner share a manifest and a revision — not one identical set of store paths. What is guaranteed across architectures is the same declared inputs resolved the same way, with paths appropriate to each.

See also: Lockfile, Manifest, Flox environment, Reproducibility, Closure.

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.