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
nixy init creates the project config and local workspace scaffold:
nixy.yml- shared project confignixy.local.yml- machine-local config for personal tools, mounts, and env vars.gitignoreentries for.nixy/andnixy.local.yml
Before writing, nixy init shows the project files and runtime directories it will create or update, then asks for confirmation.
nixy.local.yml is loaded by nixy shell only. It may define its own nixpkgs entries, but nixy.yml takes precedence when keys overlap. nixy build uses the shared nixy.yml project config.
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: nxtcoder17/nixy@v1
- name: Build target
working-directory: example/docker-build
run: nixy build runtime
- name: Build Docker image from runtime bundle
working-directory: example/docker-build
run: |
docker build \
-f Dockerfile \
-t nixy-runtime:ci \
.
- 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 metadata lives in `profile.yaml` and stores values such as the default nixpkgs pin. Profiles do not inject packages, mounts, or env vars into project shells.
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/nixy-merged.yml- effective config used to generate the current 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 metadatanixy 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 use
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.