From cdd2c8d9503065fac99a21a5350dc27ca2234ec1 Mon Sep 17 00:00:00 2001 From: Dennis Frieberg Date: Tue, 26 Sep 2023 14:17:45 +0200 Subject: [PATCH] [#7] polished the README --- README.md | 81 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index c2455c9..cf45a40 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ # nixConfig +This repository contains the configuration of all our machines running NixOS. ## Build a machine There are multiple ways to build and deploy a machine configuration. Which is the most appropriate depends on the context and scenario. So first there will be a general explanation how this works and afterwards we will talk about some scenarios. -If you run `nix flake show` you should get an output similiar to this +If you run `nix flake show` you should get an output similar to this ``` $ nix flake show git+file:///home/nerf/git/nixConfig?ref=refs%2fheads%2fnyarlathtop&rev=9d0eb749287d1e9e793811759dfa29469ab706dc @@ -25,7 +26,7 @@ git+file:///home/nerf/git/nixConfig?ref=refs%2fheads%2fnyarlathtop&rev=9d0eb7492 └───packages └───x86_64-linux ``` -we can see there is an output callled `nixosConfigurations.nyarlathotep`. Which contains the config of the machine +we can see there is an output called `nixosConfigurations.nyarlathotep`. Which contains the configuration of the machine called nyarlathotep. `nixosConfigurations` is special in that sense, that `nixos-rebuild` will automatically look for this key and assume how it is structured. The interesting part for us is the derivation `config.system.build.toplevel`. Its closure contains the whole system and the resulting derivation a script that changes the current system to @@ -36,8 +37,8 @@ So what we want to archive is populate the nix store of the target machine with ### Local -It has multiple benefits to build the system config on the local computer and push it to the target server. -For example one doesn't stress the server with the load coming with evaluating the expression. Also the server +It has multiple benefits to build the system configuration on the local computer and push it to the target server. +For example one doesn't stress the server with the load of evaluating the expression and building the closure. Also the server doesn't need to fetch the build dependencies this way. One has a local check if at least the nix syntax was correct. And so on... @@ -47,7 +48,7 @@ If you have this repository local in your current directory you can just run: $ nix build .#nixosConfigurations..config.system.build.toplevel ``` -But you don't need to clone this repository for more on flake urls see the `nix flake --help` documentation. +But you don't need to clone this repository, for more see the `nix flake --help` documentation about flake urls. #### Copy After we build the derivation we need to get the closure onto the target system. Luckily nix has tools to do that @@ -55,25 +56,26 @@ via ssh. We could just run: ``` $ nix copy -s --to .#nixosConfigurations..config.system.build.toplevel ``` -we do not need the flake anymore, instead of specifying the derivation name we could also give the store path -directly. +This will evaluate the flake again to get the store path of the given derivation. If we want to avoid this +we might supply the corresponding store path directly. The `-s` is important it makes the target machine substitute all derivations it can (by default from chache.nixos.org). -So you only upload config files and self build things. +So you only upload configuration files and self build things. To be able to copy things to a machine they need to be signed by someone trusted. Additional trusted nix keys are handled in `./nixos/roles/nix_keys.nix`. So to get yourself trusted you either need to install one derivation from the machine itself, -or find someone who is already trusted. +or find someone who is already trusted, to push your key. For more information on signing and key creation see `nix store sign --help` and `nix key --help`. #### Activate -Log into the remote machine and execute +Log into the remote machine and execute (with root privileges) ``` # /nix/store//bin/switch-to-configuration boot ``` That will setup a configuration switch at reboot. You can also switch the configuration live. For more -details consider the `--help` output of that script. +details consider the `--help` output of that script. The storepath (or at least the hash of the derivation) +is exactly the same it was on your machine. If you have a `nixos-rebuild` available on your system it can automatize these things with the `--flake` and @@ -81,31 +83,41 @@ If you have a `nixos-rebuild` available on your system it can automatize these t ### On the machine -clone this repo to `/etc/nixos/` and `nixos-rebuild boot` or `nixos-rebuild switch` that will select +clone this repository to `/etc/nixos/` and `nixos-rebuild boot` or `nixos-rebuild switch` that will select the appropriate machine based on hostname. If the hostname is not correct, or you don't want to clone this flake you can also use the `--flake` parameter. -In any case, to switch the system configuration you will need to have root priviledges on the target machine. +In any case, to switch the system configuration you will need to have root privileges on the target machine. ## How this flake is organized This flake uses `flake-parts` see [flake.parts](https://flake.parts) for more details. It makes handling -`system` and some other moudles related things more convenient. -For the general layout of nixos system config and modules, please see the corresponding documentation. +`system` and some other modules related things more convenient. +For the general layout of nixos system configuration and modules, please see the corresponding documentation. -The toplevel `flake.nix` contains the flake inputs as usual and only calls a file `flake-module.nix` -this toplevel `flake-module.nix` imports further more specialiesed `flake-modules.nix` files from subdirectories. -Right now the only one is `nixos/flake-module.nix`. +The toplevel `flake.nix` contains the flake inputs as usual and only calls a file `flake-module.nix`. +This toplevel `flake-module.nix` imports further more specialized `flake-modules.nix` files from sub-directories. +Right now the only one is `nixos/flake-module.nix`. But if we start to ship our own software (or software versions, +with specific build flags), this might get more. -the `nixos` folder contains all machine configurations. It sepreates in two folders `nixos/machines` and `nixos/roles`. +### nixos +The `nixos` folder contains all machine configurations. It separates in two folders `nixos/machines` and `nixos/roles`. +The corresponding `flake-module.nix` file automatically searches for `machines//configuration.nix`, and evalutes +those as nixos configurations, and populates the flake. -`nixos/machines` contains all machine specific configuration (in a subfolder per machine). Like hardware configuration, specific -network configuration. And service configuration that are too closely intervowen with the rest of that machine. It also -contains the root config for that machine called `configuration.nix`. This file usually only includes other modules. +#### machines +`nixos/machines` contains all machine specific configuration (in a sub-folder per machine). Like hardware configuration, specific +network configuration. And service configuration that are too closely interwoven with the rest of that machine (for example +mailserver configuration depends heavily on network settings). It also +contains the root configuration for that machine called `configuration.nix`. This file usually only includes other modules. +These `configuration.nix` files are almost usual nix configurations. The only difference is, that they take as an extra argument +the flake inputs. This allows them to load modules from these flakes. For example nyarlathotep loads the simple-nixos-mailserver +module that way. -`nixos/roles` contains config that is pontentially shared by some machines. It is expected that `nixos/roles/default.nix` +#### roles +`nixos/roles` contains configuration that is potentially shared by some machines. It is expected that `nixos/roles/default.nix` is imported as (`../../roles`) in every machine. Notable are the files `nixos/roles/admins.nix` which contains common admin accounts for these machines and `nixos/roles/nix_keys.nix` which contains the additional trusted keys for the nix store. @@ -115,20 +127,25 @@ keys for the nix store. We are sharing secrets using [`sops`](https://github.com/getsops/sops) and [`sops-nix`](https://github.com/Mic92/sops-nix) As of right now we use only `age` keys. The machine keys are derived from their server ssh keys, that they generate at first boot. +To read out a machines public key run the following command on the corresponding machine. +``` +$ nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age' +``` User keys are generated by the users. -New keys and machines need entries into the `.sops.yaml` file within the root directory of this repo. +New keys and machines need entries into the `.sops.yaml` file within the root directory of this repository. -To make a secret available on a given machine you need to do the following. Configure the following keys +To make a secret available on a given machine you need to configure the following: ``` sops.secrets.example-key = { - sopsFile = "relative path to file in the repo containing the secrets (optional else the sops.defaultSopsFile is used) - path = "optinal path where the secret gets symlinked to, practical if some programm expects a specific path" - owner = user that owns the secret file: config.users.users.nerf.name (for example) - group = same as user just with groups: config.users.users.nerf.group - mode = "premission in usual octet: 0400 (for example)" + sopsFile = "relative path to file in the repo containing the secrets (optional else the sops.defaultSopsFile is used)"; + path = "optinal path where the secret gets symlinked to, practical if some program expects a specific path"; + owner = user that owns the secret file: config.users.users.nerf.name (for example); + group = same as user just with groups: config.users.users.nerf.group; + mode = "permission in usual octet: 0400 (for example)"; +}; ``` -afterwards the secret should be available in `/run/secrets/example-key`. +Afterwards the secret should be available in `/run/secrets/example-key`. If the accessing process is not root it must be member of the group `config.users.groups.keys` for systemd services this can be archived by setting `serviceConfig.SupplementaryGroups = [ config.users.groups.keys.name ];` -it the service config. +it the service configuration.