A minimal and reproducible development environment for Elixir and Erlang projects using devenv and Nix.
- Always uses the latest stable Elixir (currently 1.18.3) and Erlang/OTP (currently 27.3)
- Automatic environment activation with direnv (optional but recommended)
- Zero system-wide installations required (except Nix itself)
- Consistent developer experience across all platforms (macOS, Linux, WSL)
- Click "Use this template" to create a new repository based on this template
- Clone your new repository
- Navigate to the project directory
- Run
direnv allow
to activate the environment (if using direnv), or rundevenv shell
manually
# After cloning your new repository:
cd your-project-name
# If using direnv (recommended):
direnv allow
# Or manually enter the environment:
devenv shell
# You should see output showing your Elixir and Erlang versions
This template uses:
devenv.nix
- Defines the development environment with Elixir and Erlangdevenv.yaml
- Configures devenv to use nixpkgs-unstable for the latest packages.envrc
- Configures direnv to use devenv (optional, but provides automatic activation)
By default, devenv uses github:cachix/devenv-nixpkgs/rolling
as its nixpkgs source. However, this template intentionally uses github:NixOS/nixpkgs/nixpkgs-unstable
for several reasons:
-
Latest Elixir versions: The nixpkgs-unstable channel typically includes the most recent versions of Elixir and Erlang soon after they're released. For example, Elixir 1.18.3 was available in nixpkgs-unstable before it appeared in the default devenv nixpkgs.
-
Broader package selection: Access to the complete set of packages in the main nixpkgs repository, which may be useful when adding dependencies to your project.
-
Community updates: The main nixpkgs repository receives more frequent updates for language-specific packages from the broader Nix community.
This approach prioritizes having the latest language features over the potential stability benefits of the default channel. For most Elixir development, this trade-off is worthwhile as it provides access to the newest language capabilities.
If you encounter issues with our direct method (replacing the nixpkgs source in devenv.yaml), you can follow the official devenv approach for using packages from nixpkgs-unstable:
-
Keep the default nixpkgs source and add nixpkgs-unstable as an additional input in
devenv.yaml
:inputs: nixpkgs: url: github:cachix/devenv-nixpkgs/rolling nixpkgs-unstable: url: github:nixos/nixpkgs/nixpkgs-unstable
-
Use the unstable package in
devenv.nix
:{ pkgs, inputs, ... }: let pkgs-unstable = import inputs.nixpkgs-unstable { system = pkgs.stdenv.system; }; in { languages.elixir = { enable = true; package = pkgs-unstable.beam.packages.erlang_27.elixir; }; languages.erlang.enable = true; }
This method keeps the stability benefits of the default devenv nixpkgs for most packages while still allowing specific access to newer versions from unstable when needed.
For more information:
- Devenv documentation on using nixpkgs-unstable
- Discussion about package versioning in Nix
- NixOS search for Elixir packages
To add additional packages to your environment, modify the devenv.nix
file:
{ pkgs, ... }:
{
# Add packages you need in your environment
packages = [
pkgs.postgresql
# Add more packages here
];
languages.elixir = {
enable = true;
package = pkgs.beam.packages.erlang_27.elixir_1_18 or pkgs.elixir;
};
languages.erlang.enable = true;
# Enable PostgreSQL service
# services.postgres.enable = true;
enterShell = ''
echo "Elixir version: $(elixir --version)"
echo "Erlang version: $(erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell)"
'';
}
If you need a specific version of Elixir, modify the package line in devenv.nix
:
languages.elixir = {
enable = true;
package = pkgs.beam.packages.erlang_27.elixir_1_17;
};
Contributions are welcome! Feel free to open an issue or submit a pull request.