This commit is contained in:
Robert Hensing 2024-11-12 14:38:34 +01:00
commit eab042ab18
8 changed files with 555 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
slides.html

58
flake.lock generated Normal file
View file

@ -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
}

51
flake.nix Normal file
View file

@ -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
'';
};
};
}

BIN
nixops2-wip.xcf Normal file

Binary file not shown.

BIN
nixops2.png Normal file

Binary file not shown.

After

(image error) Size: 540 KiB

BIN
nixops2.xcf Normal file

Binary file not shown.

139
nixops4.svg Normal file
View file

@ -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>

After

(image error) Size: 4.6 KiB

305
slides.md Normal file
View file

@ -0,0 +1,305 @@
---
marp: true
# theme: gaia
class: invert
headingDivider: 1
---
# NixOps4
![bg left:40% 80%](nixops4.svg)
<!--
_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 - ...
![bg right:66% height:80%](nixops2.png)
<!--
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`