Prepare beryllium deployment

This commit is contained in:
Christopher Mühl 2025-09-18 14:03:37 +02:00
parent 54e67cf2de
commit a043874145
No known key found for this signature in database
GPG key ID: E919B0F59E14FD47
13 changed files with 268 additions and 17 deletions

View file

@ -19,6 +19,9 @@ deploy:
europium: europium:
nixos-rebuild switch --flake .#europium --target-host europium --build-host europium --use-remote-sudo nixos-rebuild switch --flake .#europium --target-host europium --build-host europium --use-remote-sudo
beryllium:
nixos-rebuild switch --flake .#beryllium --target-host beryllium --build-host beryllium --use-remote-sudo
# Opens the elements configuration in the default editor # Opens the elements configuration in the default editor
edit: edit:
{{editor}} {{shell('pwd')}} {{editor}} {{shell('pwd')}}
@ -35,7 +38,7 @@ repl:
# Enter a flake dev shell # Enter a flake dev shell
[group('nix')] [group('nix')]
shell name: shell name:
nix develop .#{{name}} nix develop --extra-experimental-features "flakes nix-command" .#{{name}}
# Updates nix flakes # Updates nix flakes
[group('nix')] [group('nix')]

View file

@ -15,13 +15,70 @@ depending on the context. In order to enter one of the configured devshells, one
can use either the command `elements shell <name>` (if elements is already can use either the command `elements shell <name>` (if elements is already
available) or run `nix develop .#name` in the flake root directory. available) or run `nix develop .#name` in the flake root directory.
## How to deploy a new host
Boot into a install medium. Since this repository is public, we don't need to mess
with any SSH keys yet. Clone the repository and enter it.
```
git clone https://github.com/padarom/elements.git
cd elements
```
Then install just, which is the only explicit requirement for this deployment which
you must install manually. All other dependencies are installed via the dev shell.
After installing just, enter the deployment shell.
```
nix-shell -p just
just shell deploy
```
Now, a basic host configuration (with a disko module) is required. This can either
be prepared on another host and comitted, or created now, in the install media.
Depending on how many hosts I will still onboard, I might end up creating helper
functionality in the dev shell specifically for this use case.
Now, say the host we want to deploy is configured as `hydrogen`. Inspect the
compiled disko disk configuration for the host:
```
elements disk-test hydrogen
```
If that configuration seems fine, you can deploy it. This will wipe and reformat
the configured drives. Disko will ask you whether you want to confirm.
```
elements disk hydrogen
```
Your disk is now ready and you can install NixOS onto the disk. Run the following:
```
elements install hydrogen
```
Now NixOS is ready and can be booted. You can decide whether you also want to
copy the elements config into a user's home directory. Alternatively, the host can
simply be remote-managed via another host, so this step isn't always necessary.
```
elements config hydrogen {username}
```
Ideally in the future we'll be able to set an encrypted password file and deploy
the host with that. Since the host does not yet have a SSH key to decrypt any
(rekeyed) secrets that might already be present, that is not yet possible. Therefore
the following is still required:
```
# Exit from all dev shells to get back to your original shell
sudo nixos-enter
passwd {username}
```
### Todo ### Todo
Since this is pretty much always a work-in-progress I do not expect it to be in the Since this is pretty much always a work-in-progress I do not expect it to be in the
most presentable state at all times. Whenever I have time I try to streamline some of most presentable state at all times. Whenever I have time I try to streamline some of
the config, but especially when trying out new tools the code could be a bit wild. the config, but especially when trying out new tools the code could be a bit wild.
There's a couple of ideas I have for this: There's a couple of ideas I have for this:
- [ ] Build a deployment dev shell
- [ ] Deploy base tooling to all hosts. This mainly includes `nushell` and `helix` configs. They should still be configurable per-host. Potential issue here could be hosts where I don't use home manager - [ ] Deploy base tooling to all hosts. This mainly includes `nushell` and `helix` configs. They should still be configurable per-host. Potential issue here could be hosts where I don't use home manager
- [ ] Make everything more composable. Can make use of the `elements` config some more, like how it's done for `quirks` - [ ] Make everything more composable. Can make use of the `elements` config some more, like how it's done for `quirks`

View file

@ -1,4 +1,4 @@
{lib, ...}: rec { {lib, ...}: {
rootPath = ./..; rootPath = ./..;
secret = name: ./../secrets/${name}; secret = name: ./../secrets/${name};

View file

@ -10,6 +10,15 @@ in {
options.services = { options.services = {
beszel-agent = { beszel-agent = {
enable = mkEnableOption "Enable the Beszel Agent"; enable = mkEnableOption "Enable the Beszel Agent";
key = mkOption {
type = types.str;
description = "The public key to bind the agent to";
};
port = mkOption {
type = types.int;
description = "The port to bind the agent to";
default = 45876;
};
}; };
}; };
@ -24,8 +33,8 @@ in {
description = "Beszel Agent (remote monitoring)"; description = "Beszel Agent (remote monitoring)";
environment = { environment = {
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkUPOw28Cu2LMuzfmvjT/L2ToNHcADwGyGvSpJ4wH2T"; KEY = cfg.key;
LISTEN = "45876"; LISTEN = builtins.toString cfg.port;
}; };
serviceConfig = { serviceConfig = {

View file

@ -1,5 +1,40 @@
# TODO: Figure out how to link to the root Justfile and import default:
# it with `import '../../Justfile`. @just --list --justfile {{justfile()}}
say word: # Inspect the disk configuration compiled by disko.
@cowsay {{word}} [no-cd]
disk-test host:
#!/usr/bin/env bash
set -euxo pipefail
build_path=$(disko --dry-run --flake "$(pwd)#{{host}}" | tail -n 1)
less $build_path
# Deploys the disk configuration. This will reformat and mount the disk.
[no-cd]
disk host:
sudo disko --flake "$(pwd)#{{host}}" -m destroy,format,mount
# Mounts the configured disk. Useful for when the disk is already formatted.
[no-cd]
mount host:
sudo disko --flake "$(pwd)#{{host}}" -m mount
# Installs NixOS onto the drives previously mounted by disko.
[no-cd]
install host:
#!/usr/bin/env bash
sudo nixos-install --flake "$(pwd)#{{host}}"
# Deploys the dotfile repository to a user's home dir.
[no-cd]
config host user:
#!/usr/bin/env bash
set -euxo pipefail
home=$(nix eval --extra-experimental-features "nix-command flakes" --impure --expr "(builtins.getFlake \"$(pwd)\").nixosConfigurations.{{host}}.config.users.users.{{user}}.home" | tail -n 1 | tr -d \")
cp -R $(pwd) "/mnt$home/.dotfiles"
# send-key:
# croc send ~/.ssh/id_key
# receive-key phrase:
# croc {{phrase}}

View file

@ -1,13 +1,20 @@
{pkgs, ...}: {
lib,
inputs,
pkgs,
...
}:
pkgs.mkShell { pkgs.mkShell {
packages = with pkgs; [ packages = with pkgs; [
just just
cowsay croc
inputs.disko.packages.${pkgs.system}.disko
helix
]; ];
# Define an alias to use a Justfile specifically with # Define an alias to use a Justfile specifically with
# deployment tooling enabled. # deployment tooling enabled.
shellHook = '' shellHook = ''
alias elements="just -f ${././Justfile} -d ${../..}" alias elements="just -f ${././Justfile}"
''; '';
} }

View file

@ -1,11 +1,70 @@
# ++ 4_Be: Beryllium # ++ 4_Be: Beryllium
# #
# NUC environment # NUC / HomeLab environment
{lib, ...}: { {
lib,
pkgs,
...
}: {
imports = [
./hardware.nix
./disko.nix
];
# Set up two main drives for RAID 1
disko.devices.disk = {
one.device = "/dev/sda";
two.device = "/dev/sdb";
};
boot = {
loader = {
efi.canTouchEfiVariables = true;
grub = {
enable = true;
efiSupport = true;
device = "nodev";
mirroredBoots = [
{
devices = ["/dev/sda"];
path = "/boot";
}
{
devices = ["/dev/sdb"];
path = "/boot2";
}
];
};
};
# Set up mdmon to notify me when one of the drives fails
swraid.mdadmConf = ''
MAILADDR raid@muehl.dev
'';
};
elements = { elements = {
hostname = "beryllium"; hostname = "beryllium";
users = ["christopher"];
secrets = { secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEp5oRV7VbOlQ172/mLskChJwK6snXD9P4ZeROxniJtJ"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBUKDCjB0VpQubi8BfnYKbh4MIE1tcvKQesdoPE4NXAf";
}; };
}; };
users.users.christopher.openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVKJfY6B9TsUPdPXy3tkqL42sJgJRz3NOOKTqhytMMf christopher@cobalt"];
services = {
openssh.enable = true;
openssh.ports = [7319];
openssh.settings.PasswordAuthentication = false;
beszel-agent.enable = true;
beszel-agent.key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkUPOw28Cu2LMuzfmvjT/L2ToNHcADwGyGvSpJ4wH2T";
};
virtualisation.podman.enable = true;
environment.systemPackages = with pkgs; [
podman-compose
];
} }

View file

@ -0,0 +1,63 @@
let
mkDrive = bootMountpoint: {
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = bootMountpoint;
mountOptions = ["umask=0077"];
};
};
swap = {
size = "8G";
content = {
type = "swap";
discardPolicy = "both";
};
};
mdadm = {
size = "100%";
content = {
type = "mdraid";
name = "raid1";
};
};
};
};
};
in {
disko.devices = {
disk = {
one = mkDrive "/boot";
two = mkDrive "/boot2";
};
mdadm = {
raid1 = {
type = "mdadm";
level = 1;
content = {
type = "gpt";
partitions.primary = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
}

View file

@ -0,0 +1,17 @@
{
config,
lib,
...
}: {
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "rtsx_pci_sdmmc"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-intel"];
boot.extraModulePackages = [];
boot.swraid.enable = true;
networking.useDHCP = lib.mkDefault true;
virtualisation.virtualbox.guest.enable = true;
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -10,7 +10,7 @@
with lib._elements; { with lib._elements; {
imports = [ imports = [
./hardware.nix ./hardware.nix
./disk-config.nix ./disko.nix
]; ];
elements = { elements = {
@ -100,6 +100,7 @@ with lib._elements; {
# Linux link via MQTT # Linux link via MQTT
lnxlink.enable = true; lnxlink.enable = true;
beszel-agent.enable = true; beszel-agent.enable = true;
beszel-agent.key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkUPOw28Cu2LMuzfmvjT/L2ToNHcADwGyGvSpJ4wH2T";
pipewire = { pipewire = {
enable = lib.mkForce true; enable = lib.mkForce true;

View file

@ -10,7 +10,7 @@
with lib._elements; { with lib._elements; {
imports = [ imports = [
./hardware.nix ./hardware.nix
./disk-config.nix ./disko.nix
]; ];
elements = { elements = {