cargo2nix Skill
Expert guidance for packaging Rust applications with Nix Granular per-crate builds with reproducible, cacheable dependencies
cargo2nix is a tool that brings Nix dependency management to Rust projects, enabling reproducible builds, efficient per-crate caching, and complete control over the build environment. Unlike simpler approaches, cargo2nix creates individual Nix derivations for each crate, allowing fine-grained dependency sharing across projects and optimal build caching.
Key Features:
Project Status:
The Rust/Nix ecosystem offers 8+ different solutions. Understanding when to use cargo2nix is critical:
| Tool | Derivations | Generated Files | Best For | Trade-offs |
|---|---|---|---|---|
| buildRustPackage | 1 (monolithic) | None | Simple projects, nixpkgs integration | No dependency caching |
| naersk | 2 (deps + project) | None | Better caching than buildRustPackage | Less granular than cargo2nix |
| crane | Composable | None | Modern approach, Cargo-driven | Bundles dependencies together |
| crate2nix | Per-crate | Yes (Cargo.nix) | Fine-grained caching | Experimental cross-compilation |
| cargo2nix | Per-crate | Yes (Cargo.nix) | Shared deps, custom toolchains | Requires Cargo.nix maintenance |
| dream2nix | Varies | Varies | Multi-language projects | Additional abstraction layer |
Shared Dependencies Across Projects
Fine-Grained Build Control
Advanced Caching Requirements
Custom Rust Toolchains
Use buildRustPackage if:
Use crane if:
Use naersk if:
Use crate2nix if:
Cargo.toml and Cargo.lockGenerate Cargo.nix (one-time):
# Using nix run
nix run github:cargo2nix/cargo2nix
# Or in development shell
nix develop github:cargo2nix/cargo2nix#bootstrap
cargo2nix
# Commit the generated file
git add Cargo.nix
git commit -m "Add Cargo.nix for cargo2nix"
Update Cargo.nix (when Cargo.lock changes):
nix run github:cargo2nix/cargo2nix
git add Cargo.nix
git commit -m "Update Cargo.nix"
Specify cargo2nix version in flake.nix:
{
inputs = {
# Latest release (recommended)
cargo2nix.url = "github:cargo2nix/cargo2nix";
# Specific version (stable)
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
# Development version (unstable)
cargo2nix.url = "github:cargo2nix/cargo2nix/main";
};
}
Update specific version:
nix flake lock --update-input cargo2nix
{
description = "Rust project using cargo2nix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
cargo2nix = {
url = "github:cargo2nix/cargo2nix/release-0.12";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
# Build Rust package set
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
};
in {
packages = {
# Expose your binary
myapp = rustPkgs.workspace.myapp {};
default = self.packages.${system}.myapp;
};
# Development shell
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
cargo-watch
cargo-edit
];
};
}
);
}
# Build your project
nix build
# Run the binary
./result/bin/myapp
# Enter development shell
nix develop
# Inside dev shell
cargo build
cargo test
cargo run
cargo2nix fully supports Cargo workspaces:
# Cargo.toml (workspace root)
[workspace]
members = [
"crates/mylib",
"crates/mybin",
"crates/common",
]
Flake Configuration:
{
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
# Workspace-wide features
rootFeatures = [ "mylib/default" "mybin/cli" ];
};
in {
packages = {
# Expose individual workspace members
mylib = rustPkgs.workspace.mylib {};
mybin = rustPkgs.workspace.mybin {};
common = rustPkgs.workspace.common {};
# Default to main binary
default = self.packages.${system}.mybin;
};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
cargo-nextest # Modern test runner
];
};
}
);
}
# Workspace crates
rustPkgs.workspace.myapp {}
rustPkgs.workspace.mylib {}
# Registry crates (dependencies)
rustPkgs."registry+https://github.com/rust-lang/crates.io-index".serde."1.0.193" {}
rustPkgs."registry+https://github.com/rust-lang/crates.io-index".tokio."1.35.1" {}
# Git dependencies
rustPkgs."git+https://github.com/user/repo".mycrate."0.1.0" {}
rustPkgs = pkgs.rustBuilder.makePackageSet {
# Rust version (REQUIRED)
rustVersion = "1.75.0"; # Specific version
# OR
rustVersion = "2024-01-15"; # Nightly date
# Rust channel (default: "stable")
rustChannel = "stable"; # or "beta", "nightly"
# Rust profile (default: "default")
rustProfile = "minimal"; # or "default" (includes docs, rustfmt)
# Additional components
extraRustComponents = [
"rust-analyzer"
"clippy"
"rustfmt"
"miri"
];
# Package function (REQUIRED)
packageFun = import ./Cargo.nix;
# Workspace source override
workspaceSrc = ./.; # Default: uses Cargo.toml location
# Root features
rootFeatures = [
"default"
"mylib/serde"
"mybin/cli"
];
# Package overrides
packageOverrides = pkgs: [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "openssl-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.openssl
pkgs.pkg-config
];
};
})
];
# Cross-compilation target
target = "x86_64-unknown-linux-musl";
};
# Stable (specific version)
rustVersion = "1.75.0";
# Stable (latest from nixpkgs)
rustVersion = pkgs.rustc.version;
# Nightly (specific date)
rustVersion = "2024-01-15";
rustChannel = "nightly";
# Beta
rustChannel = "beta";
# Using rust-overlay for latest nightly
inputs.rust-overlay.url = "github:oxalica/rust-overlay";
rustToolchain = pkgs.rust-bin.nightly.latest.default.override {
extensions = [ "rust-src" "rust-analyzer" ];
};
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
# OpenSSL
(pkgs.rustBuilder.rustLib.makeOverride {
name = "openssl-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.openssl
pkgs.pkg-config
];
};
})
# libsqlite3
(pkgs.rustBuilder.rustLib.makeOverride {
name = "libsqlite3-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.sqlite
];
};
})
# onig (for syntect)
(pkgs.rustBuilder.rustLib.makeOverride {
name = "onig_sys";
overrideAttrs = drv: {
buildInputs = drv.buildInputs or [] ++ [ pkgs.oniguruma ];
};
})
# PostgreSQL
(pkgs.rustBuilder.rustLib.makeOverride {
name = "pq-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.postgresql
];
};
})
# libgit2
(pkgs.rustBuilder.rustLib.makeOverride {
name = "libgit2-sys";
overrideAttrs = drv: {
buildInputs = drv.buildInputs or [] ++ [
pkgs.libgit2
pkgs.pkg-config
];
};
})
];
Use Existing Overrides:
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all;
Combine with Custom Overrides:
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "my-custom-crate";
overrideAttrs = drv: {
# Custom build dependencies
nativeBuildInputs = drv.nativeBuildInputs or [] ++ [
pkgs.cmake
pkgs.protobuf
];
# Environment variables
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
# Pre-build script
preConfigure = ''
export CUSTOM_VAR="value"
'';
};
})
];
packageOverrides = pkgs: [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "ring";
overrideAttrs = drv: {
# Only on aarch64-darwin
buildInputs = drv.buildInputs or [] ++
pkgs.lib.optionals pkgs.stdenv.isDarwin [
pkgs.darwin.apple_sdk.frameworks.Security
];
};
})
];
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
# Cross-compile to x86_64 musl (static binary)
target = "x86_64-unknown-linux-musl";
};
# Static Linux binary (musl)
target = "x86_64-unknown-linux-musl";
# ARM 64-bit Linux
target = "aarch64-unknown-linux-gnu";
# Windows
target = "x86_64-pc-windows-gnu";
# macOS ARM (M1/M2)
target = "aarch64-apple-darwin";
# WebAssembly
target = "wasm32-unknown-unknown";
{
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
mkApp = target:
(pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
inherit target;
}).workspace.myapp {};
in {
packages = {
default = mkApp null; # Native
linux-musl = mkApp "x86_64-unknown-linux-musl";
linux-arm = mkApp "aarch64-unknown-linux-gnu";
windows = mkApp "x86_64-pc-windows-gnu";
};
}
);
}
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
# Development tools
rust-analyzer
cargo-watch
cargo-edit
cargo-udeps
cargo-audit
# Additional utilities
just # Command runner
bacon # Background Rust compiler
];
};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
cargo-nextest
cargo-llvm-cov # Code coverage
];
shellHook = ''
echo "š¦ Rust development environment loaded"
echo "Rust version: ${rustPkgs.rustVersion}"
# Set up environment
export RUST_BACKTRACE=1
export RUST_LOG=debug
# Aliases
alias t='cargo nextest run'
alias b='cargo build'
alias r='cargo run'
alias c='cargo check'
# Display workspace info
echo ""
echo "Workspace members:"
cargo metadata --no-deps | jq -r '.workspace_members[]'
'';
};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
postgresql_15
diesel-cli
];
shellHook = ''
# Set up PostgreSQL
export PGDATA="$PWD/.pgdata"
export DATABASE_URL="postgresql://localhost/myapp_dev"
if [ ! -d "$PGDATA" ]; then
echo "Initializing PostgreSQL database..."
initdb --no-locale --encoding=UTF8
echo "unix_socket_directories = '$PWD/.pgdata'" >> "$PGDATA/postgresql.conf"
pg_ctl start -l "$PGDATA/server.log"
psql -d postgres -c "CREATE DATABASE myapp_dev;"
else
pg_ctl start -l "$PGDATA/server.log"
fi
echo "Database ready at $DATABASE_URL"
'';
};
Enter the exact build environment cargo2nix uses:
# Get derivation path
nix build --print-out-paths .#myapp
# Enter isolated build environment
nix develop --ignore-environment /nix/store/...-myapp-0.1.0
# Inside, run build hooks
runHook preConfigure
runHook configureCargo
runHook runCargo
# Check what Cargo.nix was generated from
head -n 20 Cargo.nix
# Verify Cargo.lock hash matches
nix eval .#rustPkgs.workspace.myapp.cargoLockHash
# Inspect package set
nix repl
> :lf .
> rustPkgs.workspace
> rustPkgs."registry+https://github.com/rust-lang/crates.io-index".serde
# Build with verbose output
nix build -L # Show build logs
nix log .#myapp # View previous build log
# Add debug output to overrides
packageOverrides = pkgs: [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "problematic-crate";
overrideAttrs = drv: {
# Print all environment variables
preBuild = ''
echo "=== Build Environment ==="
env | sort
echo "=== Build Inputs ==="
echo "nativeBuildInputs: $nativeBuildInputs"
echo "buildInputs: $buildInputs"
'';
};
})
];
Problem: Error: "Cargo.lock needs to be updated but --locked was passed"
Solution:
# Update Cargo.lock
cargo update
# Regenerate Cargo.nix
nix run github:cargo2nix/cargo2nix
# Commit both files
git add Cargo.lock Cargo.nix
git commit -m "Update dependencies"
Problem: Cargo.nix hash doesn't match Cargo.lock
Temporary Workaround:
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
# Disable hash check (NOT RECOMMENDED for production)
ignoreLockHash = true;
};
Proper Solution:
# Regenerate Cargo.nix from current Cargo.lock
nix run github:cargo2nix/cargo2nix
Problem: build.rs fails with "library not found"
Solution: Add package override
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "failing-crate-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.the-missing-library
pkgs.pkg-config
];
};
})
];
Problem: Can't fetch private git dependencies
Solution:
# Use builtins.fetchGit with SSH
packageOverrides = pkgs: [
(pkgs.rustBuilder.rustLib.makeOverride {
name = "private-crate";
overrideAttrs = drv: {
src = builtins.fetchGit {
url = "git@github.com:org/private-repo.git";
ref = "main";
rev = "abc123...";
};
};
})
];
Note: Cannot use with --restrict-eval
Problem: Binary output differs between builds
Solution:
rustPkgs.workspace.myapp {
# Prefer local build (don't use binary cache)
preferLocalBuild = true;
}
Problem: Complex cfg() attributes fail to parse
Solution: Use newer cargo2nix version
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
Problem: Specific Rust version not in nixpkgs
Solution: Use rust-overlay
{
inputs = {
rust-overlay.url = "github:oxalica/rust-overlay";
};
outputs = { nixpkgs, rust-overlay, cargo2nix, ... }:
let
pkgs = import nixpkgs {
overlays = [
rust-overlay.overlays.default
cargo2nix.overlays.default
];
};
rustPkgs = pkgs.rustBuilder.makePackageSet {
# Use rust-overlay for any version
rustToolchain = pkgs.rust-bin.stable."1.75.0".default;
packageFun = import ./Cargo.nix;
};
in { ... };
}
Problem: Slow builds in CI/CD
Solutions:
# 1. Use binary cache
nix.settings = {
substituters = [ "https://cache.nixos.org" ];
trusted-public-keys = [ "cache.nixos.org-1:..." ];
};
# 2. Enable distributed builds
nix.distributedBuilds = true;
nix.buildMachines = [ ... ];
# 3. Optimize build cores
nix.settings = {
max-jobs = "auto";
cores = 0; # Use all cores
};
Do: Version control the generated file
git add Cargo.nix
git commit -m "Add/update Cargo.nix"
Why: Essential for reproducible builds, team collaboration
Do: Use specific release branch
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
Why: Avoid breaking changes, ensure stability
Do: Start with built-in overrides
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
# Your custom overrides
];
Why: Handles 90% of common system dependencies
Do: Update Cargo.nix when dependencies change
cargo update
nix run github:cargo2nix/cargo2nix
git add Cargo.lock Cargo.nix
Why: Keeps Nix expressions in sync with Cargo
Do: Leverage generated dev shell
devShells.default = rustPkgs.workspaceShell {
packages = [ pkgs.rust-analyzer ];
};
Why: Automatically includes all dependencies
Do: Add cross-compile targets in CI
packages = {
default = rustPkgs.workspace.myapp {};
static = mkApp "x86_64-unknown-linux-musl";
};
Why: Catch platform issues before release
Do: Add comments explaining why overrides exist
packageOverrides = pkgs: [
# Required for OpenSSL 3.0 compatibility
(pkgs.rustBuilder.rustLib.makeOverride {
name = "openssl-sys";
# ...
})
];
Why: Future maintainers understand decisions
Do: Commit flake.lock
git add flake.lock
git commit -m "Lock dependencies"
Why: Ensures identical builds across machines
Do: Use dev-dependencies in Cargo.toml
[dev-dependencies]
criterion = "0.5" # Benchmarking
proptest = "1.4" # Property testing
Why: Production builds exclude dev dependencies
Do: Test nix builds in CI pipeline
- name: Build with Nix
run: nix build -L
- name: Run tests
run: nix develop -c cargo test
Why: Catch Nix-specific issues early
Don't: Update Cargo.lock without updating Cargo.nix
# Bad
cargo update
git add Cargo.lock
git commit # Missing Cargo.nix update!
Why: Builds will fail with hash mismatches
Do Instead:
cargo update
nix run github:cargo2nix/cargo2nix
git add Cargo.lock Cargo.nix
Don't: Disable hash verification
# Bad: Disables safety checks
rustPkgs = pkgs.rustBuilder.makePackageSet {
ignoreLockHash = true;
};
Why: Loses reproducibility guarantees
Do Instead: Fix root cause (regenerate Cargo.nix)
Don't: Use floating reference
# Bad: Could break unexpectedly
cargo2nix.url = "github:cargo2nix/cargo2nix";
Why: Unstable, breaking changes
Do Instead: Pin to release branch
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
Don't: Ignore existing overrides
# Bad: Reinventing the wheel
packageOverrides = pkgs: [
# Manually writing openssl-sys override...
];
Why: Duplicates work, misses updates
Do Instead: Use pkgs.rustBuilder.overrides.all
Don't: Track result symlinks
# Bad
git add result
Why: Not reproducible, wastes space
Do Instead: Add to .gitignore
result
result-*
Don't: Use rustup inside nix shell
# Bad: In nix develop
rustup install nightly
Why: Defeats Nix reproducibility
Do Instead: Use cargo2nix's rustVersion/rustToolchain
Don't: Use absolute paths in overrides
# Bad: Not portable
LIBCLANG_PATH = "/usr/lib/llvm-15/lib";
Why: Breaks on other systems
Do Instead: Use Nix packages
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
Don't: Only build, never test
# Bad: No testing
- run: nix build
Why: Misses test failures
Do Instead: Run tests in Nix environment
- run: nix develop -c cargo test
Don't: Rely on impure evaluation
# Bad: Breaks reproducibility
nix build --impure
Why: Not reproducible, defeats Nix purpose
Do Instead: Fix evaluation to be pure
Don't: Suppress or ignore warnings
# Bad: Hiding problems
RUSTFLAGS = "-A warnings"
Why: Masks real issues
Do Instead: Fix warnings, use deny in CI
RUSTFLAGS = "-D warnings" # Deny warnings
Project Structure:
my-cli/
āāā Cargo.toml
āāā Cargo.lock
āāā Cargo.nix # Generated
āāā flake.nix
āāā flake.lock
āāā src/
āāā main.rs
Cargo.toml:
[package]
name = "my-cli"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.4", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
flake.nix:
{
description = "My CLI tool";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
};
in {
packages = {
my-cli = rustPkgs.workspace.my-cli {};
default = self.packages.${system}.my-cli;
};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [ rust-analyzer ];
};
apps.default = {
type = "app";
program = "${self.packages.${system}.my-cli}/bin/my-cli";
};
}
);
}
Usage:
# Generate Cargo.nix
nix run github:cargo2nix/cargo2nix
git add Cargo.nix
# Build
nix build
# Run
nix run
# Development
nix develop
cargo run -- --help
Project Structure:
my-workspace/
āāā Cargo.toml # Workspace root
āāā Cargo.lock
āāā Cargo.nix # Generated
āāā flake.nix
āāā crates/
ā āāā server/
ā ā āāā Cargo.toml
ā ā āāā src/main.rs
ā āāā client/
ā ā āāā Cargo.toml
ā ā āāā src/main.rs
ā āāā common/
ā āāā Cargo.toml
ā āāā src/lib.rs
āāā flake.lock
flake.nix:
{
description = "My multi-binary workspace";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.12";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
rootFeatures = [
"server/default"
"client/default"
"common/default"
];
};
in {
packages = {
server = rustPkgs.workspace.server {};
client = rustPkgs.workspace.client {};
common = rustPkgs.workspace.common {};
default = self.packages.${system}.server;
# Bundle both binaries
all = pkgs.symlinkJoin {
name = "my-workspace-all";
paths = [
self.packages.${system}.server
self.packages.${system}.client
];
};
};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
cargo-nextest
cargo-watch
];
};
apps = {
server = {
type = "app";
program = "${self.packages.${system}.server}/bin/server";
};
client = {
type = "app";
program = "${self.packages.${system}.client}/bin/client";
};
};
}
);
}
flake.nix (PostgreSQL + OpenSSL):
{
outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ cargo2nix.overlays.default ];
};
rustPkgs = pkgs.rustBuilder.makePackageSet {
rustVersion = "1.75.0";
packageFun = import ./Cargo.nix;
# System dependency overrides
packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
# PostgreSQL native library
(pkgs.rustBuilder.rustLib.makeOverride {
name = "pq-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.postgresql
];
};
})
# OpenSSL
(pkgs.rustBuilder.rustLib.makeOverride {
name = "openssl-sys";
overrideAttrs = drv: {
propagatedBuildInputs = drv.propagatedBuildInputs or [] ++ [
pkgs.openssl
pkgs.pkg-config
];
};
})
];
};
in {
packages.default = rustPkgs.workspace.myapp {};
devShells.default = rustPkgs.workspaceShell {
packages = with pkgs; [
rust-analyzer
postgresql_15
diesel-cli
];
shellHook = ''
export DATABASE_URL="postgresql://localhost/myapp_dev"
echo "Database: $DATABASE_URL"
'';
};
}
);
}
Remember: cargo2nix provides fine-grained per-crate builds at the cost of maintaining Cargo.nix. For simpler projects, consider buildRustPackage or crane. For maximum caching and shared dependencies across projects, cargo2nix is the right choice.