README
ΒΆ
Nixy
Simple, powerful Nix development environments without the complexity.
Why Nixy?
Nixy bridges the gap between Nix's powerful reproducibility and developer-friendly simplicity. Write a simple YAML file, get a fully reproducible development environment - no Nix knowledge required.
Quick Start
# Initialize a new project
nixy init
# Enter development shell
nixy shell
Auto Jump into nixy shell
Automatically enter the nixy shell when you navigate to a directory with a nixy.yml file.
Shell Integration
Add the following to your shell configuration file:
Fish Shell
Append to ~/.config/fish/config.fish:
nixy shell:hook fish | source
Bash
Append to ~/.bashrc:
eval "$(nixy shell:hook bash)"
Zsh
Append to ~/.zshrc:
eval "$(nixy shell:hook zsh)"
Features
- Supports auto-entering the nixy shell when
nixy.ymlis in the current directory - Shows interactive prompt with 2-second timeout
- Press ENTER to launch, any other key to skip
- Auto-launches after timeout if no input
- Prevents duplicate activation when already in nixy shell
- Optional fancy styling with gum
Installation
Pre-built Binary (Recommended)
Download from releases page
From Source
go install github.com/nxtcoder17/nixy/cmd@latest
Using Nix
nix run github:nxtcoder17/nixy -- shell
Core Features
π― Simple YAML Configuration
No more complex Nix expressions. Just list what you need:
# Define multiple nixpkgs versions (default is required)
nixpkgs:
default: abc123
unstable: def456
packages:
- nodejs # Uses default nixpkgs
- python3
- unstable#go # Uses unstable nixpkgs
libraries: # System libraries
- zlib
- openssl
onShellEnter: | # Shell initialization
echo "Welcome to your dev environment!"
π¦ Advanced Package Management
Nixpkgs Packages
# Define multiple nixpkgs versions
nixpkgs:
default: dfb2f12e899db4876308eba6d93455ab7da304cd
stable: abc123
unstable: def456
packages:
- nodejs # Latest from default nixpkgs
- go_1_21 # Specific version from default
- stable#golang # Package from stable nixpkgs
- unstable#python314 # Package from unstable nixpkgs
URL Packages
Download and install packages directly from URLs with environment variable expansion:
packages:
- name: kubectl
sources:
linux/amd64:
url: https://dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl
sha256: "abc123..." # Optional, auto-fetched if not provided
- name: terraform
sources:
linux/amd64:
url: https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
# Automatically detects archive type and extracts
# Environment variables are expanded in URLs
- name: my-tool
sources:
linux/amd64:
url: https://github.com/org/tool/releases/download/v${MY_VERSION}/tool-${NIXY_OS}-${NIXY_ARCH}.tar.gz
# Uses MY_VERSION from env section and built-in NIXY_* vars
env:
MY_VERSION: "1.2.3" # Custom env vars can be used in URLs
Built-in environment variables available:
NIXY_OS- Operating system (e.g., linux, darwin)NIXY_ARCH- Architecture (e.g., amd64, arm64)NIXY_ARCH_FULL- Full architecture string (e.g., x86_64)
π§ Build System
Define reproducible runtime bundles that can be used outside nixy shell (for example in Docker images):
builds:
runtime:
dir: .
command: |
go build -o ./bin/my-app ./cmd/my-app
packages:
- python314
- curl
- nginx
paths:
- bin/my-app
- scripts/
- config/
Run a target:
nixy build runtime
Generate a target-specific Dockerfile while building:
nixy build runtime --dockerfile
Output layout:
<dir>/.nixy/dist/app- symlink to built output in/nix/store<dir>/.nixy/dist/nix/store- copied recursive store closure for that output
dir is optional and defaults to .. It controls where the generated Dockerfile and .nixy/dist directory are written.
This makes it easy to copy the runtime bundle into container images and run the binaries without entering a nix shell.
Docker usage pattern:
- Run
nixy build <target> --dockerfilein your project. - Build the image using the target's
diras the Docker build context. - Add
<copied-app>/bintoPATH.
GitHub Actions (build + artifact)
name: Build runtime bundle
on:
push:
branches: [main]
jobs:
build-runtime:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v31
- name: Install nixy
run: |
mkdir -p "$HOME/.local/bin"
curl -fsSL -o "$HOME/.local/bin/nixy" \
https://github.com/nxtcoder17/nixy/releases/latest/download/nixy-linux-amd64
chmod +x "$HOME/.local/bin/nixy"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Build target
working-directory: example/docker-build
run: nixy build runtime --dockerfile
- name: Build Docker image from runtime bundle
run: |
docker build \
-f example/docker-build/Dockerfile \
-t nixy-runtime:ci \
example/docker-build
- uses: actions/upload-artifact@v4
with:
name: nixy-runtime
path: example/docker-build/.nixy/dist/
π Multiple Execution Backends
Local (Default)
Uses your system's Nix installation and inherits host environment:
nixy shell
Local (Pure Environment)
Uses your system's Nix installation but creates a pure environment (ignores host environment variables):
NIXY_EXECUTOR=local-ignore-env nixy shell
Docker
Perfect for CI/CD pipelines:
NIXY_EXECUTOR=docker nixy shell
Bubblewrap (Sandboxed)
Strong isolation with automatic static nix binary download - no systemwide Nix installation required:
NIXY_EXECUTOR=bubblewrap nixy shell
[!NOTE] Read more at Enable kernel.unprivileged_userns_clone check output of
sysctl kernel.unprivileged_userns_cloneif it is not set to 1. Set it to 1, otherwise you won't be able to use bubblewrap
echo "1" > /proc/sys/kernel/sysrq
### π€ Profile Management
> [!NOTE]
> Profiles provide runtime isolation. Different dev shells within the same profile share runtime filesystems like nix-store and fake-home.
> Profile-level `nixy.yml` config is loaded only when `NIXY_USE_PROFILE=true`.
Keep separate development profiles:
```bash
# Create profiles
nixy profile create work
nixy profile create personal
# Use a profile
NIXY_PROFILE=work nixy shell
# List profiles
nixy profile list
# Edit profile config
nixy profile edit work
Advanced Features
π Mixed Package Sources
Combine packages from different nixpkgs versions:
nixpkgs:
default: dfb2f12e899db4876308eba6d93455ab7da304cd
older: 9d1fa9fa266631335618373f8faad570df6f9ede
packages:
- nodejs # From default nixpkgs
- older#python311 # Python from older nixpkgs version
- name: custom-tool
sources:
linux/amd64:
url: https://example.com/tool.tar.gz
ποΈ Smart Archive Packages Handling
Automatically detects and extracts from various archive formats:
.tar,.tar.gz,.tar.xz,.tar.bz2.zip,.7z,.rar.gz,.xz,.bz2
π Pure Environments
All execution backends provide pure, reproducible environments with:
- Isolated dependencies
- Consistent behavior across machines
- No global state pollution
β‘ Intelligent Caching
- Configuration change detection via SHA256
- Rebuilds only when necessary
- Fast subsequent shells
π Inspectable Generated Files
Nixy writes generated workspace files to the project-local .nixy/ directory:
.nixy/flake.nix- generated Nix flake used for the shell/build environment.nixy/flake.lock- generated lock file for the workspace flake.nixy/shell-enter.sh- generated script fromonShellEnter.nixy/shell-env.sh- generated environment fromnix print-dev-env.nixy/build.<target>.sh- generated build script for a target (/and:are replaced with_).nixy/config.hash- hash used to decide when generated files need refreshing
Build outputs remain under each build target directory, for example <build.dir>/.nixy/dist.
.nixy/ should be gitignored because these files are regenerated from nixy.yml.
π¨ Environment Customization
onShellEnter: |
export EDITOR=vim
alias ll='ls -la'
echo "Environment ready!"
env:
NODE_ENV: development
DATABASE_URL: postgresql://localhost/myapp
# Use $$ for literal dollar signs
MY_VAR: "some-value-$$-with-dollar"
# Reference other env vars (expands at runtime)
PATH: "$PATH:/custom/bin"
# Mount additional directories (Docker/Bubblewrap only)
mounts:
- source: /host/path
dest: /container/path
readonly: true
Commands
Core Commands
nixy init- Initialize a new nixy.ymlnixy shell- Enter development shellnixy build [target]- Build defined targetsnixy shell:hook <shell>- Output shell hook script for auto-activation (supports: bash, zsh, fish)
Profile Commands
nixy profile create <name>- Create a profile namespacenixy profile edit [name]- Edit profile-level confignixy profile list- List all profiles
Examples
Full-Stack Development
nixpkgs:
default: dfb2f12e899db4876308eba6d93455ab7da304cd
packages:
# Backend
- nodejs
- postgresql_15
# Frontend
- pnpm
- cypress
# Tools
- name: stripe-cli
sources:
linux/amd64:
url: https://github.com/stripe/stripe-cli/releases/download/v1.19.1/stripe_1.19.1_linux_x86_64.tar.gz
libraries:
- postgresql
Python Data Science
nixpkgs:
default: dfb2f12e899db4876308eba6d93455ab7da304cd
cuda: abc123 # Specific version for CUDA
packages:
- python311
- poetry
- jupyter
- cuda#cudaPackages.cudatoolkit # CUDA from cuda nixpkgs
libraries:
- zlib
- blas
- lapack
env:
JUPYTER_ENABLE_LAB: "true"
Go with Kubernetes
packages:
- go_1_21
- golangci-lint
- gopls
# Kubernetes tools
- name: kubectl
sources:
linux/amd64:
url: https://dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl
- name: helm
sources:
linux/amd64:
url: https://get.helm.sh/helm-v3.13.0-linux-amd64.tar.gz
- name: k9s
sources:
linux/amd64:
url: https://github.com/derailed/k9s/releases/download/v0.27.4/k9s_Linux_amd64.tar.gz
onShellEnter: |
export KUBECONFIG=$HOME/.kube/config
Configuration Reference
nixy.yml
# Define nixpkgs versions (default is required)
nixpkgs:
default: <commit-hash> # Required
stable: <commit-hash> # Optional
unstable: <commit-hash> # Optional
# Package list
packages:
- <package-name> # Simple package (uses default)
- <key>#<package> # From specific nixpkgs key
- name: <name> # URL package
sources:
linux/amd64:
url: <url>
sha256: <hash> # Optional
binPaths:
- <relative-bin-dir> # Optional
installHook: | # Optional
<shell commands>
# System libraries
libraries:
- <library-name>
# Environment variables
env:
KEY: value # Static value
PATH: "$PATH:/custom" # Variable expansion
ESCAPED: "value-$$-literal" # Use $$ for literal $
# Additional mounts (Docker/Bubblewrap only)
mounts:
- source: /host/path
dest: /container/path
readonly: true # Optional, defaults to false
# Shell initialization
onShellEnter: |
<bash commands>
# Build targets
builds:
<target>:
dir: . # Optional Docker/output context directory, defaults to .
command: | # Optional command run before packaging paths
<shell commands>
packages: # Optional nix packages in output
- <package>
paths:
- <file-path-1> # Optional project paths to include
- <file-path-2>
Environment Variables
NIXY_EXECUTOR- Execution backend (local, local-ignore-env, docker, bubblewrap)NIXY_PROFILE- Profile namespace to useNIXY_USE_PROFILE- Load profile-level config when set totrueor1
Troubleshooting
"No Nix installation found"
- Install Nix, or use
NIXY_EXECUTOR=bubblewrapfor automatic Nix download
"Package not found"
- Check package name at search.nixos.org
- Try updating nixpkgs commit hash
"Archive extraction failed"
- Verify URL is accessible
- Check if SHA256 matches
- Ensure archive isn't corrupted
Performance Issues
- Use local executor for fastest performance
Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
License
MIT
Acknowledgments
Built with β€οΈ using:
- Nix - The powerful package manager
- Go - The programming language
- bubblewrap - Unprivileged Sandboxing tool
Making Nix accessible to everyone, one YAML at a time.