docs: write initial documentation

This commit is contained in:
technofab 2025-04-28 13:06:28 +02:00
parent 94aa02b9e3
commit b75456810f
6 changed files with 274 additions and 4 deletions

116
docs/creation.md Normal file
View file

@ -0,0 +1,116 @@
# Creating Nixlets
Nixlets need a `default.nix` and a `values.nix` (a `nixlet.nix` containing the metadata is also recommended).
Check out the existing [nixlets](https://gitlab.com/technofab/nixlets/-/tree/main/nixlets) to understand how they work.
There is also a bare-bones [template](https://gitlab.com/technofab/nixlets/-/tree/main/template/).
## `nixlet.nix`
```nix title="Example"
{
name = "attic";
version = "0.0.1";
description = "Multi-tenant Nix Binary Cache";
defaultProject = "attic";
}
```
<!-- TODO: more description, also show how it works without this file -->
It's best to create a file `nixlet.nix` for your Nixlet. It's possible to create
Nixlets without this file, by passing the metadata directly to `mkNixlet`, but
when you intend to package the Nixlet this won't work, because when fetching
Nixlets it expects the metadata.
```nix title="Usage without nixlet.nix"
mkNixlet {
name = "";
version = "";
# etc.
}
```
```nix title="Usage with nixlet.nix"
mkNixlet ./path;
```
Metadata:
- `name`: Name of the Nixlet
- `version`: Version of the Nixlet itself (like Helm Chart version)
- `description`: Short description of the Nixlet
- `defaultProject`: Kubenix has the concept of projects.
This makes it possible to use the same Nixlet multiple times by specifying
different projects. This is typically included in the resources' names.
(see also `uniqueName` below)
## `values.nix`
```nix title="Template"
{
lib,
utils,
nixlet,
...
}:
with lib;
with utils;
with nixlet; {
# for some basic values see https://github.com/helm/examples/blob/4888ba8fb8180dd0c36d1e84c1fcafc6efd81532/charts/hello-world/values.yaml
options = {
# define values here
};
}
```
In `values.nix` you declare options the end-user can set.
This uses the NixOS/nixpkgs module system.
To create a simple string input you can add this in the `options = {}` above:
```nix title="Simple string value"
hello = mkOption {
type = types.str;
default = "World";
description = "Hello world!";
}
```
The end-user using your Nixlet can then do this:
```nix title="Usage"
nixlet.render {
# ...
values = {
hello = "Nixlets";
};
}
```
It is recommended to use an option like seen below to create a unique name for the Nixlet's resources.
```nix
# internal
uniqueName = mkOption {
internal = true;
type = types.str;
default = "${project}-atticd"; # example for atticd
};
```
Then use that in your resource names like seen below.
## `default.nix`
This file is the entrypoint to your Nixlet. You can define all the resources
in this file directly or import other files.
```nix
{nixlet, ...}:
with nixlet; {
imports = [./some-resource.nix];
# or directly
kubernetes.resources.configMaps."${values.uniqueName}-config".data.hello = values.hello;
}
```

View file

@ -1 +1,12 @@
Hello World! # Nixlets
Nixlets are like Helm Charts, but instead created using [Nix](https://nixos.org).
They are based on [KubeNix](https://kubenix.org)
(this [fork](https://github.com/TECHNOFAB11/kubenix) specifically).
## Features
- supports importing Helm Charts, Kustomizations and YAML files if needed
- reproducible thanks to Nix
- versionable (eg. by uploading to GitLab Package Registry)
- utilities for secret management

44
docs/packaging.md Normal file
View file

@ -0,0 +1,44 @@
# Packaging Nixlets
## GitLab Package Registry
To package and upload Nixlets to the GitLab Package Registry there is a helper script available.
Use it like so:
```nix title="flake.nix"
apps.upload = {
type = "app";
program = pkgs.callPackage nixlet-lib.uploadNixletsToGitlab {
projectId = "<GitLab Project ID>";
nixlets = [
# list of Nixlets
];
};
};
```
You can then run this:
```sh
nix run .#upload --impure
```
`--impure` is needed because the Script needs to access the env variable `AUTH_HEADER`.
`AUTH_HEADER` needs to contain the Header GitLab expects for auth.
In GitLab CI this should for example be `JOB-TOKEN: $CI_JOB_TOKEN`.
A personal access token requires this format instead: `PRIVATE-TOKEN: <your token>`.
!!! note
The script only uploads a version once. If the version already exists it will skip that Nixlet.
## General
Nixlets are self contained and receive all their dependencies etc. from the
caller rendering it.
This means that you can just compress any Nixlet directory to a tarball, upload
it somewhere and then fetch it later where you intend to use/render it
(the upload script for GitLab CI does basically that).
See [Usage](./usage.md) for information on how to fetch and render it later.

27
docs/secrets.md Normal file
View file

@ -0,0 +1,27 @@
# Secrets
When using Nixlets together with tools like [FluxCD](https://fluxcd.io) and
[SOPS](https://github.com/getsops/sops) it makes sense to apply the secrets on
their own (eg. with their own FluxCD's `Kustomization`).
To make secret management easier, Nixlets allow you to specify encrypted secret
files in your configuration like this:
```nix title="some_resource.nix"
# ...
kubernetes.secrets."name" = ./secret.sops.yaml;
kubernetes.resources.configMaps. # ...
# ...
```
In CI for example you can then retrieve all of these files at once and put them
in an OCI image for FluxCD to deploy:
```nix title="flake.nix"
packages.secrets = (<some nixlet>).secretsCombined; # (derivation)
```
```sh
nix build .#secrets
# result/ contains all yaml secret files
```

62
docs/usage.md Normal file
View file

@ -0,0 +1,62 @@
# Using Nixlets
## Fetching
You can fetch Nixlets you uploaded somewhere [earlier](./packaging.md) using an URL to the tarball and the sha256 hash:
```nix
nixlet-lib.fetchNixlet "<URL>" "<sha>"
```
For the GitLab Package Registry there is a helper function:
```nix
nixlet-lib.fetchNixletFromGitlab {
project = "<org>/<project>"; # eg "TECHNOFAB/nixlets"
name = "<nixlet>";
version = "<version>";
sha256 = "<sha>";
}
```
## Metadata
A Nixlet's metadata can easily be accessed:
```nix
(<some nixlet>).description # version, name, etc.
```
## Rendering
Rendering a Nixlet will produce a YAML file which contains all the resources.
```nix
(<some nixlet>).render {
inherit system;
# values = {};
# project = "";
# overrides = ({...}: {});
}
```
Parameters:
- `system`: needed for Kubenix to work.
- `values`: values to pass to the Nixlet, gets validated by the Nixlets options
- `project`: project to use, makes it possible to use the same Nixlet multiple
times without conflicts
- `overrides`: custom module which can override configuration
## Just evaluating
Instead of directly rendering a Nixlet it's also possible to just evaluate it
and access all kinds of data inside it.
```nix
(<some nixlet>).eval {
# see above
}
```
It accepts the same parameters as `render`.

View file

@ -38,6 +38,13 @@
alejandra.enable = true; alejandra.enable = true;
mdformat.enable = true; mdformat.enable = true;
}; };
settings.formatter.mdformat.command = let
pkg = pkgs.python3.withPackages (p: [
p.mdformat
p.mdformat-mkdocs
]);
in
lib.mkForce "${pkg}/bin/mdformat";
}; };
devenv.shells.default = { devenv.shells.default = {
containers = lib.mkForce {}; containers = lib.mkForce {};
@ -90,9 +97,11 @@
}; };
plugins = ["search" "material-umami"]; plugins = ["search" "material-umami"];
nav = [ nav = [
{ {"Introduction" = "index.md";}
"Introduction" = "index.md"; {"Creating Nixlets" = "creation.md";}
} {"Packaging" = "packaging.md";}
{"Usage" = "usage.md";}
{"Secrets" = "secrets.md";}
]; ];
markdown_extensions = [ markdown_extensions = [
{ {
@ -102,6 +111,7 @@
"pymdownx.snippets" "pymdownx.snippets"
"pymdownx.superfences" "pymdownx.superfences"
"fenced_code" "fenced_code"
"admonition"
]; ];
extra.analytics = { extra.analytics = {
provider = "umami"; provider = "umami";