Skip to content

Composing using imports

You can compose environments either locally or by referencing inputs.

Imagine you’re building a typical web application, with separate frontend and backend components that live in separate folders.

devenv.yaml
inputs:
nixpkgs:
url: github:cachix/devenv-nixpkgs/rolling
devenv:
url: github:cachix/devenv
flake: false
imports:
- ./frontend
- ./backend
- devenv/examples/supported-languages
- devenv/examples/scripts

If you enter the frontend directory, the environment will activate based on what’s in the frontend/devenv.nix file.

If you enter the top-level project, the environment is combined with what’s defined in backend/devenv.nix and frontend/devenv.nix. For example, devenv up will start both the frontend and backend processes.

Local devenv.yaml composition was added in 1.10. Remote input composition is supported in 2.4.1 and later.

Sharing configuration from another repository

Section titled “Sharing configuration from another repository”

To keep your devenv configuration in a separate repository, declare it as an input and import the directory containing its devenv.yaml and devenv.nix:

devenv.yaml
inputs:
shared-config:
url: github:my-org/shared-devenv-config
flake: false
imports:
- shared-config/profiles/backend

This uses the existing input import syntax; no additional YAML option is required. Imports inside the remote devenv.yaml are composed recursively, and relative path: inputs declared there resolve inside the fetched source.

The importing project’s devenv.lock is the single lock file for the composed environment. A devenv.lock in the imported repository is not merged. Input declarations use the same precedence as local YAML composition, so a declaration in the root project wins when both configurations use the same name. In particular, when the shared configuration also declares nixpkgs, the root project’s pinned nixpkgs is reused instead of creating a second one. Use distinct input names when the versions must remain independent.

devenv update shared-config also discovers configuration from the updated revision and locks any inputs it adds or changes before writing devenv.lock. An update without an input name updates dependencies declared by imported YAML as well. Configuration discovery writes no intermediate lock files; a failed import leaves the previous lock unchanged.

For a sibling checkout, use url: path:../shared-config/ in the same example. The shared repository may also contain only a devenv.nix file. Combine this with profiles to define one shared configuration that adapts to each project.

See devenv.yaml reference for all supported import options.