Skip to content

Commit

Permalink
init docs
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliButz committed Sep 2, 2024
1 parent fc8598f commit 1c1e415
Show file tree
Hide file tree
Showing 17 changed files with 930 additions and 485 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/render-options.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Docs
on:
push:
branches:
- main
jobs:
render:
name: Render and Deploy

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@ab6bcb2d5af0e904d04aea750e2089e9dc4cbfdd
with:
diagnostic-endpoint: ""

- uses: DeterminateSystems/magic-nix-cache-action@b46e247b898aa56e6d2d2e728dc6df6c84fdb738
with:
diagnostic-endpoint: ""

- run: nix build -L ./docs#packages.x86_64-linux.docs

- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./result
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
result*
/.direnv
/tests/.nixos-test-history
*.html
38 changes: 7 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,23 @@ Nix tooling to enable declarative management of non-volatile system state.
Inspired and heavily influenced by [impermanence](https://github.com/nix-community/impermanence) but not
meant to be a drop-in replacement.

## Work in Progress
## Documentation

🚧 still under construction 🚧
Docs are available at <https://willibutz.github.io/preservation>

Check out [the test](tests/basic.nix) for a usage example 👀
## Prerequisites

Depends on https://github.com/NixOS/nixpkgs/pull/307528 (merged)

## How does it compare to impermanence

* Preservation does not attempt to be a very generic solution, it tries to fill a specific niche.
Specifically Preservation does not support non-NixOS systems via home-manager, which is supported
by impermanence.

* Preservation only creates static configuration for
[systemd-tmpfiles](https://www.freedesktop.org/software/systemd/man/latest/systemd-tmpfiles.html)
and systemd [mount units](https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html).
This makes Preservation a potential candidate for state management on interpreter-less systems.

Impermanence makes use of NixOS activation scripts and custom systemd services with bash (at the point
of writing this), to create and configure files and directories.

* Preservation must be precisely configured, there is no [special runtime logic](https://github.com/nix-community/impermanence/blob/23c1f06316b67cb5dabdfe2973da3785cfe9c34a/mount-file.bash#L31-L42)
in place. This means that the user must define:
* when the preservation should be set up: either in the initrd, or after (the default)
* how the preservation should be set up: either by symlink, or bindmount (the default)
* whether or not parent directories of the persisted files require special permissions

* Preservation's configuration is based on, and very similar to that of impermanence.

* Preservation uses a global `enable` option, impermanence does not (see https://github.com/nix-community/impermanence/pull/171)
Depends on <https://github.com/NixOS/nixpkgs/pull/307528> (merged, available on nixos-unstable).

## Why?

This aims to provide a declarative state management solution for NixOS systems without resorting to
interpreters to do the heavy lifting. This should enable impermanence-like state management on
an "interpreter-less" system.
an "interpreter-less" NixOS system.

Related:
- https://github.com/NixOS/nixpkgs/issues/265640
- https://github.com/nix-community/projects/blob/main/proposals/nixpkgs-security-phase2.md#boot-chain-security
- <https://github.com/NixOS/nixpkgs/issues/265640>
- <https://github.com/nix-community/projects/blob/main/proposals/nixpkgs-security-phase2.md#boot-chain-security>

## License

Expand Down
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
10 changes: 10 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[book]
title = "Preservation"
authors = ["Willi Butz"]
language = "en"
src = "src"

[output.html]
additional-css = ["custom.css"]
git-repository-url = "https://github.com/willibutz/preservation"
edit-url-template = "https://github.com/willibutz/preservation/edit/main/docs/{path}"
4 changes: 4 additions & 0 deletions docs/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:root {
/* accommodate long option paths on big screens */
--content-max-width: 1000px;
}
27 changes: 27 additions & 0 deletions docs/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions docs/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

outputs = inputs: {
packages.x86_64-linux =
let
pkgs = import inputs.nixpkgs { system = "x86_64-linux"; };
in
{
optionsManualMD =
let
eval = pkgs.lib.evalModules {
modules = [
../options.nix
(args: {
options._module.args = args.lib.mkOption { internal = true; };
})
];
};
optionsDoc = pkgs.nixosOptionsDoc {
inherit (eval) options;
transformOptions =
o:
o
// {
declarations = map (
declaration:
let
flakeOutPath = inputs.self.sourceInfo.outPath;
name = pkgs.lib.removePrefix "${flakeOutPath}/" declaration;
in
if pkgs.lib.hasPrefix "${flakeOutPath}/" declaration then
{
inherit name;
url = "https://github.com/willibutz/preservation/blob/main/${name}";
}
else
declaration
) o.declarations;
};
};
in
optionsDoc.optionsCommonMark;

docs = pkgs.stdenv.mkDerivation {
name = "preservation-docs";
src = pkgs.lib.cleanSource ../.;
nativeBuildInputs = [ pkgs.mdbook ];
patchPhase = ''
cat ${inputs.self.packages.x86_64-linux.optionsManualMD} > docs/src/configuration-options.md
'';
buildPhase = ''
cd docs
mdbook build
'';
installPhase = "cp -vr book $out";
};
};
};
}
9 changes: 9 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Summary

[Preservation](../../README.md)
- [Configuration Options](./configuration-options.md)
- [Examples](./examples.md)
- [Impermanence](./impermanence.md)
- [Comparison](./impermanence-comparison.md)
- [Migration](./impermanence-migration.md)
- [Library and Testing](./library-and-testing.md)
131 changes: 131 additions & 0 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Examples

See [Configuration Options](./configuration-options.md) for all available options.

## Simple

```nix
# configuration.nix
{
config,
lib,
pkgs,
...
}:
{
preservation = {
enable = true;
preserveAt."/persistent" = {
files = [
# auto-generated machine ID
{ file = "/etc/machine-id"; inInitrd = true; }
];
directories = [
"/var/lib/systemd/timers"
# NixOS user state
"/var/lib/nixos"
# preparing /var/log early (inInitrd) avoids a dependency cycle (see TODO.md)
{ directory = "/var/log"; inInitrd = true; }
];
};
};
}
```

## Complex

```nix
# configuration.nix
{
config,
lib,
pkgs,
...
}:
{
preservation = {
# the module doesn't do anything unless it is enabled
enable = true;
preserveAt."/persistent" = {
# preserve system directories
directories = [
"/etc/secureboot"
"/var/lib/bluetooth"
"/var/lib/fprint"
"/var/lib/fwupd"
"/var/lib/libvirt"
"/var/lib/power-profiles-daemon"
"/var/lib/systemd/coredump"
"/var/lib/systemd/rfkill"
"/var/lib/systemd/timers"
{ directory = "/var/lib/nixos"; inInitrd = true; }
# preparing /var/log early (inInitrd) avoids a dependency cycle (see TODO.md)
{ directory = "/var/log"; inInitrd = true; }
];
# preserve system files
files = [
{ file = "/etc/machine-id"; inInitrd = true; }
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_rsa_key"
"/var/lib/usbguard/rules.conf"
# creates a symlink on the volatile root
# creates an empty directory on the persistent volume, i.e. /persistent/var/lib/systemd
# does not create an empty file at the symlink's target (would require `createLinkTarget = true`)
{ file = "/var/lib/systemd/random-seed"; how = "symlink"; inInitrd = true; configureParent = true; }
];
# preserve user-specific files, implies ownership
users = {
butz = {
directories = [
{ directory = ".ssh"; mode = "0700"; }
".config/syncthing"
".config/Element"
".local/state/nvim"
".local/state/wireplumber"
".local/share/direnv"
".local/state/nix"
".mozilla"
];
files = [
".histfile"
];
};
users.root = {
# specify user home when it is not `/home/${user}`
home = "/root";
directories = [
{ directory = ".ssh"; mode = "0700"; }
];
};
};
};
};
# Create some directories with custom permissions.
#
# In this configuration the path `/home/butz/.local` is not an immediate parent
# of any persisted file, so it would be created with the systemd-tmpfiles default
# ownership `root:root` and mode `0755`. This would mean that the user `butz`
# could not create other files or directories inside `/home/butz/.local`.
#
# Therefore systemd-tmpfiles is used to prepare such directories with
# appropriate permissions.
#
# Note that immediate parent directories of persisted files can also be
# configured with ownership and permissions from the `parent` settings if
# `configureParent = true` is set for the file.
systemd.tmpfiles.settings.preservation = {
"/home/butz/.config".d = { user = "butz"; group = "users"; mode = "0755"; };
"/home/butz/.local".d = { user = "butz"; group = "users"; mode = "0755"; };
"/home/butz/.local/share".d = { user = "butz"; group = "users"; mode = "0755"; };
"/home/butz/.local/state".d = { user = "butz"; group = "users"; mode = "0755"; };
};
}
```
35 changes: 35 additions & 0 deletions docs/src/impermanence-comparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# How does Preservation compare to [impermanence](https://github.com/nix-community/impermanence)

### Preservation does not attempt to be a very generic solution

Preservation tries to fill a specific niche.
For instance, Preservation does not support non-NixOS systems via home-manager, which is supported
by impermanence. See [Migration](./impermanence-migration.md) for more technical details.

### Preservation only generates static configuration

That is configuration for [systemd-tmpfiles](https://www.freedesktop.org/software/systemd/man/latest/systemd-tmpfiles.html)
and systemd [mount units](https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html).
This makes Preservation a potential candidate for state management on interpreter-less NixOS systems.

Impermanence makes use of NixOS activation scripts and custom systemd services with bash (at the point
of writing this), to create files and directories, setup mounts and configure ownership and permissions (see next point).

### Preservation must be precisely configured
There is no [special runtime logic](https://github.com/nix-community/impermanence/blob/23c1f06316b67cb5dabdfe2973da3785cfe9c34a/mount-file.bash#L31-L42)
in place. This means that the user must define:
* when the preservation should be set up: either in the initrd, or after (the default)
* how the preservation should be set up: either by symlink, or bindmount (the default)
* whether or not parent directories of the persisted files require special permissions

See [Migration](./impermanence-migration.md) for specifics that need to be considered when coming from an impermanence setup.

### Similar configuration

Preservation's configuration is based on, and very similar to that of impermanence. See [Migration](./impermanence-migration.md) for technical details.

### Global `enable` option

Preservation uses a global `enable` option, impermanence does not.

For thoughts on the `enable` option, see the discussion at <https://github.com/nix-community/impermanence/pull/171> and for available configuration options see [Configuration Options](./configuration-options.md).
Loading

0 comments on commit 1c1e415

Please sign in to comment.