Files
ngit-grasp/docs/learnings/nix-flakes.md
T
DanConwayDev 22557f15d6 docs: major cleanup and reorganization
- Archive 30 completed session documents to docs/archive/
- Extract learnings to docs/learnings/ (nix-flakes, nostr-sdk, grasp-audit)
- Create CURRENT_STATUS.md as single source of truth
- Create AGENTS.md with documentation guidelines
- Create docs/archive/README.md for archive organization
- Clean root directory: 32 files → 4 files

Root directory now contains only:
- README.md (project overview)
- AGENTS.md (documentation guidelines)
- CURRENT_STATUS.md (current state)
- CLEANUP_SUMMARY.md (cleanup report)

All historical documents preserved in docs/archive/ with proper dating.
All reusable knowledge extracted to docs/learnings/.

Benefits:
- Easy to find current information
- Clear document lifecycle
- No more documentation sprawl
- Learnings are accessible and reusable
- Better onboarding for new developers/agents

File counts:
- Root: 4 (was 32)
- Permanent docs: 7
- Learnings: 3 (new)
- Archive: 32 (new)
- Total: 49 well-organized docs
2025-11-04 09:31:57 +00:00

424 lines
8.2 KiB
Markdown

# Nix Flakes - Learnings and Gotchas
**Purpose:** Document Nix flake patterns, gotchas, and best practices learned during ngit-grasp development
**Last Updated:** November 4, 2025
---
## Critical Gotchas
### Always Use `nix develop`, Not `nix-shell`
**Problem:** We use `flake.nix`, not `shell.nix`. Using `nix-shell` will fail or use the wrong environment.
```bash
# ✅ Correct - for flake.nix
cd grasp-audit
nix develop
nix develop -c cargo build
# ❌ Wrong - for shell.nix (we don't use this)
nix-shell
nix-shell --run "cargo build"
```
**Why:**
- `nix-shell` looks for `shell.nix` or `default.nix`
- `nix develop` looks for `flake.nix`
- We migrated from `shell.nix` to `flake.nix` on November 4, 2025
**Related:** See `docs/archive/2025-11-04-flake-migration.md`
---
## Flake Structure
### Our Standard Flake Pattern
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { nixpkgs, rust-overlay, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
manifest = pkgs.lib.importTOML ./Cargo.toml;
in with pkgs; {
# Development shell
devShells.default = mkShell {
nativeBuildInputs = [
rust-bin.stable.latest.default
pkg-config
gitlint
];
buildInputs = [
openssl
];
shellHook = ''
echo "🦀 Development environment loaded"
export RUST_SRC_PATH=${pkgs.rustPlatform.rustLibSrc}
'';
};
# Package output
packages.default = pkgs.rustPlatform.buildRustPackage {
pname = manifest.package.name;
version = manifest.package.version;
src = ./.;
cargoLock = { lockFile = ./Cargo.lock; };
buildInputs = [ openssl ];
nativeBuildInputs = [ pkg-config ];
doCheck = false; # Run tests separately
};
});
}
```
### Key Components
1. **rust-overlay**: Provides latest stable Rust toolchain
2. **flake-utils**: Cross-platform support helper
3. **manifest**: Auto-read version from Cargo.toml
4. **devShells.default**: Development environment
5. **packages.default**: Buildable package
---
## Common Flake Commands
### Essential Commands
```bash
# Enter development shell
nix develop
# Run command in dev shell (one-off)
nix develop -c cargo build
# Show flake outputs
nix flake show
# Check flake validity
nix flake check
# Update flake inputs (like updating dependencies)
nix flake update
# Build the package directly
nix build
# Run without installing
nix run
# Show flake metadata
nix flake metadata
```
### Debugging Commands
```bash
# Show detailed evaluation trace
nix develop --show-trace
# Print flake evaluation
nix eval .#devShells.x86_64-linux.default
# Check what's in the store
nix path-info .#packages.x86_64-linux.default
```
---
## Subproject Flakes
### grasp-audit Has Its Own Flake
**Important:** `grasp-audit/` is a subproject with its own `flake.nix` and `Cargo.toml`.
```bash
# ✅ Correct - enter grasp-audit environment
cd grasp-audit
nix develop
cargo build
# ❌ Wrong - can't build from root
cd ngit-grasp
cargo build # This won't find grasp-audit dependencies
```
**Why:**
- Each Rust workspace needs its own Nix environment
- Dependencies are project-specific
- Flake inputs are locked per-project
---
## Migration from shell.nix to flake.nix
### What Changed
**Before (shell.nix):**
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
rustc
cargo
openssl
pkg-config
];
}
```
**After (flake.nix):**
- Locked inputs (reproducible)
- Multi-output (dev shell + package)
- Cross-platform by default
- Better tooling integration
### Migration Steps
1. Create `flake.nix` with standard structure
2. Run `nix flake check` to validate
3. Update all documentation: `nix-shell` → `nix develop`
4. Test that build works: `nix develop -c cargo build`
5. Remove `shell.nix`
6. Commit changes
**Reference:** See `docs/archive/2025-11-04-flake-migration.md`
---
## Benefits of Flakes
### Reproducibility
**Locked inputs** ensure everyone gets the same environment:
```bash
# flake.lock contains exact commits
$ cat flake.lock
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1698611440,
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
"rev": "23e89e0c8c5e2d9cf5b5e7c3e8e8e8e8e8e8e8e8"
}
}
}
}
```
Everyone running `nix develop` gets **exactly** this version of nixpkgs.
### Multi-Output
Single flake provides:
- **devShells.default**: Development environment
- **packages.default**: Buildable package
- **apps.default**: Runnable application (optional)
### Composability
Flakes can use other flakes as inputs:
```nix
{
inputs = {
grasp-audit.url = "path:./grasp-audit";
};
}
```
---
## Common Issues
### Issue: "error: getting status of '/nix/store/...': No such file or directory"
**Cause:** Flake inputs need to be updated or fetched
**Solution:**
```bash
nix flake update
nix develop
```
### Issue: "error: experimental feature 'nix-command' is not enabled"
**Cause:** Nix flakes are experimental and need to be enabled
**Solution:**
Add to `~/.config/nix/nix.conf`:
```
experimental-features = nix-command flakes
```
### Issue: Changes to flake.nix not taking effect
**Cause:** Flake evaluation is cached
**Solution:**
```bash
# Clear evaluation cache
nix flake update
# Or force re-evaluation
nix develop --refresh
```
### Issue: "error: cannot find flake 'flake:self' in the flake registries"
**Cause:** Not in a git repository or flake.nix not committed
**Solution:**
```bash
git add flake.nix flake.lock
git commit -m "Add flake"
```
**Note:** Flakes require git. Uncommitted files are ignored by default.
---
## Best Practices
### 1. Always Commit flake.lock
```bash
git add flake.lock
git commit -m "Update flake inputs"
```
**Why:** Ensures reproducibility across machines and CI/CD
### 2. Use Specific Rust Versions When Needed
```nix
# Latest stable (default)
rust-bin.stable.latest.default
# Specific version
rust-bin.stable."1.75.0".default
# Nightly
rust-bin.nightly."2024-01-01".default
```
### 3. Include Helpful Shell Hooks
```nix
shellHook = ''
echo "🦀 GRASP Audit development environment"
echo ""
echo "Common commands:"
echo " cargo build - Build project"
echo " cargo test - Run tests"
echo " cargo run - Run binary"
echo ""
export RUST_SRC_PATH=${pkgs.rustPlatform.rustLibSrc}
'';
```
### 4. Separate Build and Runtime Dependencies
```nix
# Build-time only
nativeBuildInputs = [
pkg-config
rustc
cargo
];
# Runtime needed
buildInputs = [
openssl
];
```
### 5. Disable Tests in Package Build
```nix
packages.default = pkgs.rustPlatform.buildRustPackage {
# ...
doCheck = false; # Run tests separately with cargo test
};
```
**Why:** Faster builds, tests run via `cargo test` in dev shell
---
## Workflow Examples
### Daily Development
```bash
# Start work
cd grasp-audit
nix develop
# Inside nix shell
cargo build
cargo test
cargo run -- --help
# Exit shell
exit
```
### CI/CD
```bash
# One-off commands (no interactive shell)
nix develop -c cargo build
nix develop -c cargo test --lib
nix develop -c cargo test -- --ignored
```
### Building Release
```bash
# Build package directly
nix build
# Result is in ./result/bin/
./result/bin/grasp-audit --version
```
---
## References
- **Nix Flakes Manual**: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html
- **rust-overlay**: https://github.com/oxalica/rust-overlay
- **flake-utils**: https://github.com/numtide/flake-utils
- **Our Migration**: `docs/archive/2025-11-04-flake-migration.md`
---
## Quick Reference
| Task | Command |
|------|---------|
| Enter dev shell | `nix develop` |
| Run one command | `nix develop -c <command>` |
| Show outputs | `nix flake show` |
| Validate flake | `nix flake check` |
| Update inputs | `nix flake update` |
| Build package | `nix build` |
| Run package | `nix run` |
---
*Last updated: November 4, 2025*
*Status: Living document - update as we learn more*