--- marp: true lang: en-US title: Marp CLI example description: Hosting Marp slide deck on the web theme: nix_talk transition: fade paginate: true _paginate: false --- # Nix for Rustaceans #### Kateřina "Kate" Churanová --- # What is Nix - Purely functional programming language - Package manager - Linux distribution (NixOS) - multiplatform (Linux, Mac OS, BSD-ish) --- # What is Nix NOT - Easy to learn - Well documented - Opinionated --- # Nix derivation - "Package" - evaluates to store derivation in `/nix/store/` - `2n45ikclc8d5fhzkvg1197qlc2zk3s64-rustc-1.77.2.drv` --- # 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 --- # 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/) --- # Flake parts - Minimal modular framework ## Dev environment management - Devshell - Devenv ## Rust project building - NCI (Nix cargo integration) --- # Basic flake parts project ```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 ### flake.nix ```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; }; }; ``` --- ### crates.nix ```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 --- ```nix packages.container = pkgs.dockerTools.streamLayeredImage { name = crateName; tag = "latest"; contents = [ ]; config = { Cmd = [ "${crateOutputs.packages.release}/bin/my-crate" ]; }; }; ```