2024-07-09 20:55:42 +02:00
|
|
|
---
|
|
|
|
marp: true
|
|
|
|
lang: en-US
|
2024-07-11 13:49:04 +02:00
|
|
|
title: Reproducible development environments with Nix
|
2024-07-09 20:55:42 +02:00
|
|
|
theme: nix_talk
|
|
|
|
transition: fade
|
|
|
|
paginate: true
|
|
|
|
_paginate: false
|
|
|
|
---
|
|
|
|
|
2024-07-11 13:49:04 +02:00
|
|
|
# Reproducible development environments with Nix
|
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
#### Kateřina "Kate" Churanová
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# What is Nix
|
|
|
|
|
|
|
|
- Purely functional programming language
|
|
|
|
- Package manager
|
|
|
|
- multiplatform (Linux, Mac OS, BSD-ish)
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# What is Nix NOT
|
|
|
|
|
|
|
|
- Easy to learn
|
|
|
|
- Well documented
|
|
|
|
- Opinionated
|
|
|
|
|
2024-07-11 13:49:04 +02:00
|
|
|
---
|
|
|
|
# What is it for
|
|
|
|
|
|
|
|
- Access to huge repository of various packages
|
|
|
|
- Declarative way to define builds and build enviroment and their configuration
|
|
|
|
- Coexistence of various versions of software and libraries on the same system
|
|
|
|
|
|
|
|
*Every simple configuration language will eventually end up being turing complete*
|
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
# Nix derivation
|
|
|
|
|
|
|
|
- "Package"
|
|
|
|
- evaluates to store derivation in `/nix/store/`
|
|
|
|
- `2n45ikclc8d5fhzkvg1197qlc2zk3s64-rustc-1.77.2.drv`
|
|
|
|
<!-- This prevents conflicts and allows various versions to be installed at ones. -->
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Nix flake
|
|
|
|
|
|
|
|
- Unstable, but widely used
|
|
|
|
- New way of creating nix derivations
|
|
|
|
- Lock file version pinning
|
|
|
|
- Allows reproducibility
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
```nix
|
|
|
|
{
|
|
|
|
inputs = {
|
|
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
|
|
};
|
|
|
|
outputs =
|
|
|
|
{ self, nixpkgs }:
|
|
|
|
{
|
|
|
|
packages.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.hello;
|
|
|
|
packages.x86_64-linux.foobar = nixpkgs.legacyPackages.x86_64-linux.fortune;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
![bg width:80%](../assets/pictures/flake_relations.svg)
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Nix developer shell
|
|
|
|
|
|
|
|
- `nix develop`
|
|
|
|
- builds all flake dependencies, but not the flake itself
|
|
|
|
- sets up the development environment
|
|
|
|
|
2024-07-11 13:49:04 +02:00
|
|
|
---
|
2024-07-09 20:55:42 +02:00
|
|
|
|
|
|
|
# Nix direnv
|
|
|
|
|
|
|
|
- https://github.com/nix-community/nix-direnv
|
|
|
|
- Activates developer shell automatically
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Frameworks
|
|
|
|
|
|
|
|
- Pure nix solution is usable, but tedious with ugly boilerplate
|
|
|
|
- [Numtide: flake-utils](https://github.com/ursi/numtide-flake-utils)
|
|
|
|
- [Hercules CI: Flake Parts](https://flake.parts/)
|
|
|
|
|
|
|
|
<!-- Both are fairly lightweight and remove boilerplate. -->
|
|
|
|
|
2024-07-11 13:49:04 +02:00
|
|
|
---
|
2024-07-09 20:55:42 +02:00
|
|
|
|
|
|
|
# Flake parts - Minimal modular framework
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
## Dev environment management
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
- Devshell
|
|
|
|
- Devenv
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
## Rust project building
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
- NCI (Nix cargo integration)
|
|
|
|
|
|
|
|
---
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
# Basic flake parts project
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
```nix
|
|
|
|
{
|
|
|
|
inputs = {
|
|
|
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
|
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
|
|
};
|
|
|
|
|
|
|
|
outputs = inputs@{ flake-parts, ... }:
|
|
|
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
|
|
|
imports = [
|
|
|
|
# Modules go here
|
|
|
|
];
|
|
|
|
systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
|
|
|
|
perSystem = { config, self', inputs', pkgs, system, ... }: {
|
|
|
|
packages.default = pkgs.hello;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Fun begins with Rust
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
### flake.nix
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
```nix
|
|
|
|
inputs = {
|
|
|
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
|
|
|
nci = {
|
|
|
|
url = "github:yusdacra/nix-cargo-integration";
|
|
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
|
|
};
|
|
|
|
flake-parts = {
|
|
|
|
url = "github:hercules-ci/flake-parts";
|
|
|
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
```nix
|
|
|
|
outputs = inputs @ {
|
|
|
|
flake-parts,
|
|
|
|
nci,
|
|
|
|
...
|
|
|
|
}:
|
|
|
|
flake-parts.lib.mkFlake {inherit inputs;} {
|
|
|
|
systems = ["x86_64-linux"];
|
|
|
|
imports = [
|
|
|
|
nci.flakeModule
|
|
|
|
./crates.nix
|
|
|
|
];
|
|
|
|
perSystem = {
|
|
|
|
pkgs,
|
|
|
|
config,
|
|
|
|
...
|
|
|
|
}: let
|
|
|
|
crateName = "my-crate"
|
|
|
|
crateOutputs = config.nci.outputs.${crateName};
|
|
|
|
in {
|
|
|
|
devShells.default = crateOutputs.devShell;
|
|
|
|
packages.default = crateOutputs.packages.release;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
### crates.nix
|
2024-07-11 13:49:04 +02:00
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
```nix
|
|
|
|
{...}: {
|
|
|
|
perSystem = {
|
|
|
|
pkgs,
|
|
|
|
config,
|
|
|
|
...
|
|
|
|
}: let
|
|
|
|
crateName = "my-crate";
|
|
|
|
in {
|
|
|
|
nci.projects."simple".path = ./.;
|
|
|
|
nci.crates.${crateName} = {};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Why all of this though?
|
|
|
|
|
|
|
|
- Reproducible environment with pinned Rust version
|
|
|
|
- Predictable dependencies
|
|
|
|
- Plenty of other tools for your disposal
|
|
|
|
- Extremely simple generation of lightweight OCI containers
|
|
|
|
|
2024-07-11 13:49:04 +02:00
|
|
|
---
|
|
|
|
|
2024-07-09 20:55:42 +02:00
|
|
|
```nix
|
|
|
|
packages.container = pkgs.dockerTools.streamLayeredImage {
|
|
|
|
name = crateName;
|
|
|
|
tag = "latest";
|
|
|
|
contents = [ ];
|
|
|
|
config = {
|
|
|
|
Cmd = [ "${crateOutputs.packages.release}/bin/my-crate" ];
|
|
|
|
};
|
|
|
|
};
|
2024-07-11 13:49:04 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Other learning materials
|
|
|
|
### Fasterthanlime's series on Rust development with Nix
|
|
|
|
[https://fasterthanli.me/series/building-a-rust-service-with-nix](https://fasterthanli.me/series/building-a-rust-service-with-nix)
|
|
|
|
### Nix pills
|
|
|
|
[https://nixos.org/guides/nix-pills/](https://nixos.org/guides/nix-pills/)
|
|
|
|
### This presentation and examples
|
|
|
|
[https://code.nolog.cz/shine/nix_for_rustaceans](https://code.nolog.cz/shine/nix_for_rustaceans)
|