commit eab042ab187a7aa53419c09af4a3662f9468db2e Author: Robert Hensing <robert@roberthensing.nl> Date: Tue Nov 12 14:38:34 2024 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d16cf89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +slides.html + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ffb7d86 --- /dev/null +++ b/flake.lock @@ -0,0 +1,58 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1730504152, + "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..26110bd --- /dev/null +++ b/flake.nix @@ -0,0 +1,51 @@ +{ + description = "Description for the project"; + + 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 = [ + ]; + systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ]; + perSystem = { config, self', inputs', pkgs, system, ... }: { + devShells.default = pkgs.mkShell { + nativeBuildInputs = [ + pkgs.marp-cli + ]; + shellHook = '' + echo "$motd" >&2 + ''; + motd = '' + Hello! The following commands are available: + + - live + + ''; + }; + packages.default = pkgs.stdenv.mkDerivation { + name = "nixops4-quick-intro"; + nativeBuildInputs = [ + pkgs.marp-cli + ]; + src = ./.; + buildPhase = '' + ls -al + marp slides.md + ''; + installPhase = '' + mkdir $out + cp slides.html $out/ + cp *.png *.svg $out/ + ''; + }; + apps.default.program = pkgs.writeScriptBin "open-slides" '' + #!${pkgs.runtimeShell} + ${if pkgs.stdenv.hostPlatform.isDarwin then "open" else "xdg-open"} ${config.packages.default}/slides.html + ''; + }; + }; +} diff --git a/nixops2-wip.xcf b/nixops2-wip.xcf new file mode 100644 index 0000000..b1ac624 Binary files /dev/null and b/nixops2-wip.xcf differ diff --git a/nixops2.png b/nixops2.png new file mode 100644 index 0000000..e8367a2 Binary files /dev/null and b/nixops2.png differ diff --git a/nixops2.xcf b/nixops2.xcf new file mode 100644 index 0000000..e3e0cd9 Binary files /dev/null and b/nixops2.xcf differ diff --git a/nixops4.svg b/nixops4.svg new file mode 100644 index 0000000..9e2cf90 --- /dev/null +++ b/nixops4.svg @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="514.33069" + height="527.11523" + viewBox="0 0 514.33069 527.11523" + version="1.1" + id="svg1" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs1"> + <linearGradient + id="linearGradient73"> + <stop + style="stop-color:#415e9a;stop-opacity:1;" + offset="0" + id="stop73" /> + <stop + style="stop-color:#4a6baf;stop-opacity:1;" + offset="0.23" + id="stop77" /> + <stop + style="stop-color:#5277c3;stop-opacity:1;" + offset="1" + id="stop74" /> + </linearGradient> + <linearGradient + id="linearGradient71"> + <stop + style="stop-color:#699ad7;stop-opacity:1;" + offset="0" + id="stop71" /> + <stop + style="stop-color:#7eb1dd;stop-opacity:1;" + offset="0.22531722" + id="stop75" /> + <stop + style="stop-color:#7ebae4;stop-opacity:1;" + offset="1" + id="stop72" /> + </linearGradient> + <linearGradient + id="linearGradient68"> + <stop + style="stop-color:#415e9a;stop-opacity:1;" + offset="0" + id="stop69" /> + <stop + style="stop-color:#4a6baf;stop-opacity:1;" + offset="0.23" + id="stop76" /> + <stop + style="stop-color:#5277c3;stop-opacity:1;" + offset="1" + id="stop70" /> + </linearGradient> + <linearGradient + id="linearGradient66"> + <stop + style="stop-color:#699ad7;stop-opacity:1;" + offset="0" + id="stop66" /> + <stop + style="stop-color:#7eb1dd;stop-opacity:1;" + offset="0.28229418" + id="stop68" /> + <stop + style="stop-color:#7ebae4;stop-opacity:1;" + offset="1" + id="stop67" /> + </linearGradient> + <linearGradient + xlink:href="#linearGradient66" + id="linearGradient67" + x1="386.29163" + y1="527.11523" + x2="214.33086" + y2="319.26953" + gradientUnits="userSpaceOnUse" /> + <linearGradient + xlink:href="#linearGradient68" + id="linearGradient70" + x1="218.03917" + y1="-4.4999979e-06" + x2="450.00012" + y2="311.76953" + gradientUnits="userSpaceOnUse" /> + <linearGradient + xlink:href="#linearGradient71" + id="linearGradient72" + x1="-4.9999999e-06" + y1="-5e-07" + x2="261.34012" + y2="311.76953" + gradientUnits="userSpaceOnUse" /> + <linearGradient + xlink:href="#linearGradient73" + id="linearGradient74" + x1="514.33069" + y1="319.26953" + x2="342.99097" + y2="527.11523" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + id="g4" + style="display:inline" + transform="translate(-12.834648,-6.4423828)"> + <g + id="g79" + transform="translate(12.834653,6.4423872)"> + <g + id="g78"> + <path + style="display:inline;fill:url(#linearGradient70);fill-opacity:1;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:1" + d="m 235.35948,59.999996 48.1875,83.462884 7.17187,12.42188 -55.35937,95.88477 -17.32031,30 17.32031,30 h 34.64062 l 55.35938,-95.88477 55.35931,95.88477 h 69.28132 L 360.0001,155.88476 270.0001,-4.499998e-6 Z" + id="path5" /> + <path + style="display:inline;fill:url(#linearGradient72);fill-opacity:1;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:1" + d="M 261.34013,-5e-7 H 200.71874 89.999995 L -5e-6,155.88476 l 90,155.88477 H 226.69891 L 209.3782,281.76917 226.6985,251.76953 H 124.64062 L 69.281245,155.88476 124.64062,60 h 102.0585 z" + id="path1" /> + </g> + <g + id="g77"> + <path + style="display:inline;fill:url(#linearGradient67);fill-opacity:1;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:1" + d="m 368.97133,467.11523 -25.35938,-43.92187 25.35938,-43.92383 17.32031,-30 -17.32031,-30 H 334.3307 l -25.35937,43.92383 -25.36238,-43.92383 h -69.27809 l 59.99984,103.92383 60,103.92187 z" + id="path66" /> + <path + style="display:inline;fill:url(#linearGradient74);fill-opacity:1;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:1" + d="M 342.99096,527.11523 H 454.3307 l 60,-103.92187 -60,-103.92383 h -50.71875 -25.98047 l 17.32031,30 -17.32031,30 h 42.0586 l 25.35937,43.92383 -25.35937,43.92187 h -42.05811 z" + id="path4" /> + </g> + </g> + </g> +</svg> diff --git a/slides.md b/slides.md new file mode 100644 index 0000000..444ab31 --- /dev/null +++ b/slides.md @@ -0,0 +1,305 @@ +--- +marp: true +# theme: gaia +class: invert +headingDivider: 1 +--- + + +# NixOps4 + + + + +<!-- +_class: invert lead +--> + +- Why +- What +- How +- Demo + + +# Why + +- NixOps 1 is a tool to deploy NixOS systems +- Provisioning +- Secrets +- Other resources, such as AWS Route53, etc +- Python program +- Call Nix evaluator twice + +<!-- + calling the evaluator twice is not good enough +--> + + +# Architecture + +NixOps 2 + +2013 - 2020 - ... + + + +<!-- + +I sincerely apologize to the authors and previous maintainers. +They did a good job with the architecture they had. + +- Plugin system +- Ossified the architecture +--> + + +# Architecture + +Nix + +``` + + + + +┌────────────┐ ┌────────────────────┐ +│ Nix │---- instantiate ---->│ Derivations │ ↺ store path +│ expression │ └────────────────────┘ +│ language │ ⇑ builds +│ │ ┌────────────────────┐ +│ │ │ Nix sandbox, store │ +└────────────┘ └────────────────────┘ +``` + +<!-- + Explain thoroughly +--> + +# Architecture + +NixOps4 + +``` +┌────────────┐ ┌────────────────────┐ +│ Nix │---- configure ------>│ Resources │ ↺ nix value +│ expression │ └────────────────────┘ +│ language │ ⇑ run output +│ │ ┌────────────────────┐ +│ │---- instantiate ---->│ Derivations │ ↺ store path +│ │ └────────────────────┘ +│ │ ⇑ builds +│ │ ┌────────────────────┐ +│ │ │ Nix sandbox, store │ +└────────────┘ └────────────────────┘ +``` + +<!-- +Adds new layer on top + +Focus on `nix value` => precisely that; no tight coupling between NixOps and its resources + +NixOps4 just manages the data flows generically + +Another benefit + - resource can be implemented in any language, with any library + +Not comparable to NixOps 2 architecture image. NixOps 2 is "just a script" that grew until it failed to scale and then ossified with plugins. + +--> + + +# Resource + +- Declares the existence of a real world object +- Operations + - Create + - Read + - Update + - Delete + +# Resource Provider + +- Separate process +- executable obtained with Nix. + +# Operations + +- CRUD + +- "`nix run`" + - backup + - key rotation + +<!-- + a. Arbitrary callable methods in resource provider + b. Scripts depending on resource outputs +--> + +# Process Architecture + +- NixOps4 + - `nixops4-eval` -> `libnixexpr` etc (internal) + - resource providers + - `nixops4-resources-local` + - `nixops4-resources-opentofu` (planned) + - ... + +# Expressions + +Simplified + +```nix +{ # flake.nix + outputs = inputs: { + nixops4Deployments.default = { resources, ... }: { + resources = { + "state" = { + ... + }; + }; + }; + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + resources = { + "state" = { + type = "s3.object"; + inputs = { + endpoint = "https://garage.example.com"; + bucket = "nixops4-my-project"; + }; + }; + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + resources = { + "state" = ...; + + + + + + + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + resources = { + "state" = ...; + "sshkey" = { + type = "ssh.key"; + inputs = { + state = resources.state.handle; + }; + }; + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + resources = { + "state" = ...; + "sshkey" = ...; + "nixos" = { + imports = [ inputs.nixos.modules.nixops4Resource.nixos ]; + inputs = { + ssh.privateKey = resources.sshkey.privateKey; + ssh.host = resources.host; + module = ./configuration.nix; + }; + }; + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + options.customers = mkOption { + type = attrsOf (submodule ./customer.nix); + }; + config.resources = { + "state" = ...; + "sshkey" = ...; + "nixos" = ...; + }; +} +``` + +# Expressions + +```nix +{ resources, ... }: { + imports = [ + ./data-model.nix + ./applications/pixelfed.nix + ./applications/mastodon.nix + ./applications/peertube.nix + ]; +} +``` + +# Expressions + +- `resources` monoid in the category of endofunctors :wink: +- Structural composition like `attrsOf` or `submodule` + - `imports` is mix-ins + +```nix +top@{ resources, ... }: { + resources = { + "state" = ...; + "my-host" = mkSequence ({ resources, ... }: { + "sshkey" = ... top.resources.state.handle ...; + "nixos" = ... resources.sshkey.privateKey ...; + }); + }; +} +``` + +# Module author benefits + +- All-Nix development experience +- No glue code +- All declarative + +# Application benefits + +"NixPanel" + +- Structured logging + +- Separate evaluator for stability + +# Operator benefits + +CLI interface for the backend + +Integrate arbitrary scripts, no glue code + +# Demo? + +# Not discussed + +- Resource naming within the state + - read multiple => migrations + +- `resourceProviderSystem`