Building Packages with Nix
Nix provides powerful tools for building, packaging, and distributing software in a reproducible manner. This guide details practical approaches to building packages with Nix in a DevOps context.
Anatomy of a Nix Package
A Nix package is defined by a derivation, which specifies all inputs needed to build the package:
{ stdenv, fetchurl, perl }:
stdenv.mkDerivation {
name = "hello-2.12";
# Source code
src = fetchurl {
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.tar.gz"\;
hash = "sha256-zoJ2IvKo2ioO2U13kTX780rP2MaGwIGcbFOvG+Oi17Y=";
};
# Build-time dependencies
buildInputs = [ perl ];
# Configuration flags
configureFlags = [ "--with-debug" ];
# Custom build steps (if default is insufficient)
buildPhase = ''
make -j $NIX_BUILD_CORES
'';
# Installation instructions
installPhase = ''
make install
mkdir -p $out/share/doc
cp README* $out/share/doc/
'';
# Meta information for package discovery and maintenance
meta = {
description = "A program that produces a friendly greeting";
homepage = "https://www.gnu.org/software/hello/"\;
license = stdenv.lib.licenses.gpl3Plus;
maintainers = [ "example@example.com" ];
platforms = stdenv.lib.platforms.all;
};
}Common Build Phases in Nix
unpackPhase
Extract source archive
tar -xf $src; cd myproject-*
patchPhase
Apply patches
patch -p1 < $patchfile
configurePhase
Run ./configure
./configure --prefix=$out --enable-feature
buildPhase
Run make
make -j $NIX_BUILD_CORES CFLAGS="-O3"
checkPhase
Run tests
make test
installPhase
Run make install
make install DESTDIR=$out
fixupPhase
Fix runtime paths
Automatic
Fetching Source Code
Nix provides several fetchers to obtain source code:
Real-World Package Examples
Simple Python Application
Node.js Web Application
Go CLI Tool
DevOps Patterns for Package Management
Creating a Private Package Repository
You can create a private Nix package repository for your organization:
Patching Existing Packages
Sometimes you need to patch an existing package from nixpkgs:
Creating Runtime Wrappers
Wrap executables to set environment variables or provide configuration:
Versioning and Dependency Management
Pinning Dependencies
To ensure reproducible builds, pin your nixpkgs version:
Managing Multiple Versions
Maintain multiple versions of the same package:
Testing and CI Integration
Testing Packages in Isolation
Test packages in isolation using nix-build or nix build:
CI Configuration for Package Building
Example GitHub Actions workflow for building Nix packages:
Advanced Topics
Cross-Compilation
Build packages for different architectures:
Static Linking
Create statically linked binaries for containerized environments:
Creating Minimal Docker Images
Use Nix to create minimal Docker images:
Best Practices for Package Maintainability
Follow the Nixpkgs Contribution Guidelines: Even for private packages, following the Nixpkgs contribution guidelines ensures high-quality packages.
Properly Set Metadata: Always include complete
metaattributes:Version Management: Use
recpattern for version propagation:Avoid Hard-Coded Paths: Use variables like
$outinstead of hard-coded paths:Minimize Closure Size: For deployments, especially in containers, minimize runtime dependencies:
Conclusion
Building packages with Nix provides a powerful, reproducible approach to software packaging for DevOps environments. By following these patterns and best practices, you can create reliable builds that work consistently across development, testing, and production environments.
Further Resources
Last updated