Fast, Declarative, Reproducible and Composable Developer Environments using Nix

Develop natively • Deploy containers • 100.000+ packages • Write scripts and tasks • 50+ supported languages • Define processes • Reuse services • Run tests • Enforce git hooks

Simple JSON-like language

Declaratively define your development environment by toggling basic options.

Environment variables.
Use env attribute set to define environment variables.

If you'd like to also include secrets from .env file, set dotenv.enable = true;.

Packages.
Pick from 80000+ prebuilt packages for Linux/macOS and X64/Arm64. Works with WSL2.
Run script(s) when entering the environment.
Prepare your environment when entering the shell that has environment already loaded.
Automatically load the environment when entering the project.
Using direnv will automatically load the environment when you enter the project directory.
devenv.nix
{ pkgs, config, ... }: {
  env.GREET = "determinism";

  packages = [
    pkgs.ncdu
  ];

  enterShell = ''
    echo hello ${config.env.GREET}
    ncdu --version
  '';
}
devenv shell
hello determinism
ncdu 2.3

devenv.nix
{ pkgs, ... }: {
  packages = [ pkgs.yarn ];

  scripts.build.exec = "yarn build";

  tasks = {
    "myapp:build".exec = "build";
    "devenv:enterShell".after = [ "myapp:build" ];
  };

  # Runs on `git commit` and `devenv test`
  pre-commit.hooks = {
    black.enable = true;
    # Your custom hooks
    generate-css = {
      enable = true;
      name = "generate-css";
      entry = "build";
    };
  };
}
devenv shell
...
Running tasks     devenv:enterShell
Succeeded         devenv:pre-commit:install 15ms
Succeeded         myapp:build               23ms
Succeeded         devenv:enterShell         23ms
3 Succeeded                                 50.14ms
$

Scripts and Tasks

Define scripts, tasks and git hooks to automate your development workflow.

Scripts.
Define scripts that can be invoked inside the environment, using all the packages and environment variables.
Tasks.
Form dependencies between automation code, executed in parallel and written in your favorite language.
Git hooks.
Pick from builtin and language specific linters and formatters using git-hooks.nix.

Search packages and options

Explore packages and options to customize your environment.

devenv search devenv
+--------------+---------------+------------------------------------------------------------------------+
| Package      | Version       | Description                                                            |
+--------------+---------------+------------------------------------------------------------------------+
| pkgs.devenv  | 1.0.3         | Fast, Declarative, Reproducible, and Composable Developer Environments |
+--------------+---------------+------------------------------------------------------------------------+
+--------------------------+---------+-----------+------------------------------------------------------------+
| Option                   | Type    | Default   | Description                                                |
+--------------------------+---------+-----------+------------------------------------------------------------+
| devenv.debug             | boolean | false     | Whether to enable debug mode of devenv enterShell script.  |
+--------------------------+---------+-----------+------------------------------------------------------------+
| devenv.warnOnNewVersion  | boolean | true      | Whether to warn when a new version of devenv is available. |
+--------------------------+---------+-----------+------------------------------------------------------------+
| devenv.latestVersion     | string  | "1.0.3"   | The latest version of devenv.                              |
+--------------------------+---------+-----------+------------------------------------------------------------+
• Found 1 package and 3 options for 'devenv'.

Languages

Supports over 50 programming languages.

Packed with tooling.
Comes with commonly used tooling for each language. Including LSP servers, formatters, linters, and compilers.
Version support.
Languages like Python, Terraform, Rust, PHP and Ruby all have version support.
Examples
Checkout examples collection to get started.
devenv.nix
{ pkgs, config, ... }: {
  languages.python = {
    enable = true;
    version = "3.11";
    venv.enable = true;
    venv.requirements = ''
      requests
      torch
    '';
    uv.enable = true;
  };

  languages.rust = {
    enable = true;
    channel = "nightly";
    rustflags = "-Z threads=8";
    targets = [ "wasm32-unknown-unknown" ];
  };

  languages.php = {
    enable = true;
    version = "8.1";
    ini = ''
      memory_limit = 256M
    '';
    fpm.pools.web = {
      settings = {
        "pm" = "dynamic";
      };
    };
  };
}
devenv.nix
{ pkgs, ... }: {
  packages = [
    pkgs.mkdocs
    pkgs.watchexec
  ];

  processes = {
    docs.exec = "mkdocs serve";
    tailwind.exec = "watchexec -e html,css,js npx tailwindcss build extra.css -o output.css";
  };
}
devenv up
• Building processes ...
• Starting processes ...
...

Run processes

Define your processes in a declarative way and start them with devenv up.

Processes
Inspired by Procfile, declare development processes that have access to your environment.
process-compose
By default process-compose is used to manage processes, giving you a simple interface to inspect logs and restart processes (ctrl-r).

Run services

Pick from a number of community maintained services like PostgreSQL, Redis, MySQL, RabbitMQ, WireMock, MinIO, Caddy, ElasticSearch, OpenTelemetry Collector, and more are being added each day.

Pre-configured processes
Services define processes that are started when the service is enabled as part of devenv up.
Configuration
Each service provides a number of options how to configure it and a hook to pass extra configuration, whatever the format.
Extendable
Define your development processes as a service, allowing reuse and simplicity of a few lines of configuration.
devenv.nix
{ pkgs, ... }: {
  services.postgres = {
    enable = true;
    package = pkgs.postgresql_15;
    initialDatabases = [{ name = "mydb"; }];
    extensions = extensions: [
      extensions.postgis
      extensions.timescaledb
    ];
    settings.shared_preload_libraries = "timescaledb";
    initialScript = "CREATE EXTENSION IF NOT EXISTS timescaledb;";
  };
}
devenv up
...

devenv.nix
{ pkgs, ... }: {
  packages = [
    pkgs.mkdocs
    pkgs.curl
  ];

  processes = {
    docs.exec = "mkdocs serve";
  };

  enterTest = ''
    wait_for_port 8000
    curl http://localhost:8000 | grep "Hello, world!"
  '';
}

devenv test
...

Run tests

Running a script inside your development environment with all processes running should be as simple as devenv test.

enterTest
Execute your favorite language test runner or a simple script to verify your environment.

All process management is taken care for you.

Container interoperability

Generate containers from your development environment and build/copy/run them.

Containerize your environment.
shell container allows you to run your environment in a container.

Use devenv container run shell to enter your environment in a container.

Containerize your processes.
processes container allows you to run your processes in a container.

Use devenv container run processes to run your processes in a container.

Custom containers.
Define containers.mycontainer.* to customize your container.
devenv.nix
{ pkgs, ... }: {
  packages = [
    pkgs.mkdocs
    pkgs.curl
  ];

  processes = {
    docs.exec = "mkdocs serve";
  };
}

devenv container build processes
...
devenv container copy processes
...
devenv container run processes
...

devenv.yaml
inputs:
  myorg-devenv:
    url: github:myorg/myorg-devenv
imports:
  - ./frontend
  - ./backend
  - myorg-devenv/service1
  - myorg-devenv/service2

Poly/Mono repo composability

Compose multiple environments into a single environment.

Local imports
If you're working on a monorepo, define environment per folder and import them to merge them into a single environment.
Remote imports
If you're working on a polyrepo, define environment per repository and import them to merge them into a single environment.

A great way to get started is to use central repository with all the shared configuration until your team is comfortable maintaining their own environments.

Built by