Skip to content

Commit

Permalink
Merge pull request #273 from barrucadu/provision-machine
Browse files Browse the repository at this point in the history
Add a script to provision a new machine
  • Loading branch information
barrucadu authored Mar 16, 2024
2 parents 1d4de86 + 6179f32 commit 124dd6b
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 77 deletions.
123 changes: 46 additions & 77 deletions docs/src/runbooks/set-up-a-new-host.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,84 +5,75 @@ Set up a new host
See also [the NixOS installation instructions](https://nixos.org/manual/nixos/stable/index.html#ch-installation).
```

1. Create & format partitions
1. **Optional:** Configure wiping / on boot (pre-first-boot steps)
1. Install NixOS with the standard installer
1. Reboot into the installed system
1. Clone this repo to `/etc/nixos`
1. Move the generated configuration to `hosts/<hostname>/` and edit to fit repo conventions
1. Add an entry for the host to `flake.nix`
1. **Optional:** Add DNS records
1. **Optional:** Configure secrets
1. **Optional:** Configure wiping / on boot (post-first-boot steps)
1. **Optional:** Configure alerting
1. **Optional:** Configure backups
1. **Optional:** Generate SSH key
1. Build the new system configuration with `sudo nixos-rebuild switch --flake '.#<hostname>'`
1. Reboot
1. Commit, push, & merge
1. **Optional:** Configure Syncthing

Optional: Configure wiping / on boot
------------------------------------

Before installing NixOS, create the `local` pool and datasets:
Install NixOS
-------------

Boot into the ISO and install NixOS with `tools/provision-machine.sh`:

```bash
zpool create -o autotrim=on local <device>
sudo -i
nix-env -f '<nixpkgs>' -iA git
curl https://raw.githubusercontent.com/barrucadu/nixfiles/master/tools/provision-machine.sh > provision-machine.sh
bash provision-machine.sh gpt /dev/sda
```

zfs create -o mountpoint=legacy local/volatile
zfs create -o mountpoint=legacy local/volatile/root
Then:

zfs create -o mountpoint=legacy local/persistent
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/home
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/nix
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/persist
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true -o xattr=sa -o acltype=posix local/persistent/var-log
```
1. Rename `/mnt/persist/etc/nixos/hosts/new` after the new hostname
2. Add the host to `/mnt/persist/etc/nixos/flake.nix`
3. Add the new files to git
4. Run `nixos-install --flake /mnt/persist/etc/nixos#hostname`
5. Reboot

Take a snapshot of the empty root dataset:

First boot
----------

Generate an age public key from the host SSH key:

```bash
zfs snapshot local/volatile/root@blank
nix-shell -p ssh-to-age --run 'ssh-keyscan localhost | ssh-to-age'
```

Mount all the filesystems under `/mnt`:
Add a new section with this key to `/persist/etc/nixos/.sops.yaml`:

```yaml
creation_rules:
...
- path_regex: hosts/<hostname>/secrets(/[^/]+)?\.yaml$
key_groups:
- age:
- *barrucadu
- '<key>'
```
Add a `users/barrucadu` secret with the hashed user password:

```bash
mount -t zfs local/volatile/root /mnt

mkdir /mnt/boot
mkdir /mnt/home
mkdir /mnt/nix
mkdir /mnt/persist
mkdir -p /mnt/var/log

mount /dev/<boot device> /mnt/boot
mount -t zfs local/persistent/home /mnt/home
mount -t zfs local/persistent/nix /mnt/nix
mount -t zfs local/persistent/persist /mnt/persist
mount -t zfs local/persistent/var-log /mnt/var/log
nix run .#secrets
```

Then run the installer, making sure to add ZFS details to the generated configuration:
Copy the host SSH keys to `/etc/persist`:

```nix
networking.hostId = "<random 32-bit hex value>";
boot.supportedFilesystems = [ "zfs" ];
```bash
mkdir /persist/etc/ssh
cp /etc/ssh/ssh_host_rsa_key /persist/etc/ssh/ssh_host_rsa_key
cp /etc/ssh/ssh_host_ed25519_key /persist/etc/ssh/ssh_host_ed25519_key
```

**After first boot:** copy any needed files (eg, SSH host keys) to the
appropriate place in `/persist`, add the user password to the secrets, and set
up `nixfiles.eraseYourDarlings`:
Enable `nixfiles.eraseYourDarlings`:

```nix
nixfiles.eraseYourDarlings.enable = true;
nixfiles.eraseYourDarlings.machineId = "<contents of /etc/machine-id>";
nixfiles.eraseYourDarlings.barrucaduPasswordFile = config.sops.secrets."users/barrucadu".path;
sops.secrets."users/barrucadu".neededForUsers = true;
```

Then:

1. Rebuild the system: `sudo nixos-rebuild boot --flake /persist/etc/nixos`
2. Reboot


Optional: Add DNS records
-------------------------
Expand All @@ -94,28 +85,6 @@ Add `A` / `AAAA` records to [the ops repo][] and apply the change via
[Concourse]: https://cd.barrucadu.dev/


Optional: Configure secrets
---------------------------

After first boot, generate an age public key from the host SSH key:

```bash
nix-shell -p ssh-to-age --run 'ssh-keyscan localhost | ssh-to-age'
```

Add a new section with this key to `.sops.yaml`:

```yaml
creation_rules:
...
- path_regex: hosts/<hostname>/secrets(/[^/]+)?\.yaml$
key_groups:
- age:
- *barrucadu
- '<key>'
```
Optional: Configure alerting
----------------------------

Expand Down
131 changes: 131 additions & 0 deletions tools/provision-machine.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env bash

set -e

# see https://nixfiles.docs.barrucadu.co.uk/runbooks/set-up-a-new-host.html

MODE="$1"
DEVICE="$2"

if ! [ "$(id -u)" -eq 0 ]; then
echo "please run as root"
exit 1
fi

if ! command -v git &>/dev/null; then
echo "git not found in the PATH"
exit 1
fi

if ! command -v nixos-generate-config &>/dev/null; then
echo "nixos-generate-config not found in the PATH"
exit 1
fi

if ! [ -e "$DEVICE" ]; then
echo "${DEVICE} not found"
exit 1
fi

# create partitions
case "$MODE" in
"gpt")
parted "$DEVICE" -- mklabel gpt
parted "$DEVICE" -- mkpart ESP fat32 1MB 512MB
parted "$DEVICE" -- mkpart root 512MB 100%
parted "$DEVICE" -- set 1 esp on
;;
"msdos")
parted "$DEVICE" -- mklabel msdos
parted "$DEVICE" -- mkpart primary 1MB 512MB
parted "$DEVICE" -- mkpart primary 512MB 100%
parted "$DEVICE" -- set 1 boot on
;;
*)
echo "${MODE} should be gpt or msdos"
exit 1
;;
esac

BOOTDEV="${DEVICE}1"
ROOTDEV="${DEVICE}2"

# create /boot filesystem
mkfs.fat -F 32 -n boot "$BOOTDEV"

# create zfs datasets & snapshot for erase-your-darlings
zpool create -o autotrim=on local "$ROOTDEV"

zfs create -o mountpoint=legacy local/volatile
zfs create -o mountpoint=legacy local/volatile/root

zfs create -o mountpoint=legacy local/persistent
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/home
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/nix
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true local/persistent/persist
zfs create -o mountpoint=legacy -o com.sun:auto-snapshot=true -o xattr=sa -o acltype=posix local/persistent/var-log

zfs snapshot local/volatile/root@blank

# mount filesystems
mount -t zfs local/volatile/root /mnt

mkdir /mnt/boot
mkdir /mnt/home
mkdir /mnt/nix
mkdir /mnt/persist
mkdir -p /mnt/var/log

mount -t vfat "$BOOTDEV" /mnt/boot
mount -t zfs local/persistent/home /mnt/home
mount -t zfs local/persistent/nix /mnt/nix
mount -t zfs local/persistent/persist /mnt/persist
mount -t zfs local/persistent/var-log /mnt/var/log

# generate config
mkdir /mnt/persist/etc
pushd /mnt/persist/etc
git clone https://github.com/barrucadu/nixfiles.git nixos
popd

mkdir /mnt/persist/etc/nixos/hosts/new
cat <<EOF > /mnt/persist/etc/nixos/hosts/new/header.nix
# This is {...}.
#
# It runs {...}.
#
# **Alerting:** disabled
#
# **Backups:** disabled
#
# **Public hostname:** n/a
#
# **Role:** server
{ config, lib, pkgs, ... }:
with lib;
{
networking.hostId = "$(head -c 4 /dev/urandom | xxd -p)";
boot.supportedFilesystems = [ "zfs" ];
###############################################################################
## GENERATED CONFIG BELOW THIS LINE
###############################################################################
EOF

nixos-generate-config --root /mnt
cat /mnt/persist/etc/nixos/hosts/new/header.nix /mnt/etc/nixos/configuration.nix > /mnt/persist/etc/nixos/hosts/new/configuration.nix
rm /mnt/etc/nixos/configuration.nix
mv /mnt/etc/nixos/hardware-configuration.nix /mnt/persist/etc/nixos/hardware.nix
rmdir /mnt/etc/nixos

nano /mnt/persist/etc/nixos/hosts/new/configuration.nix
nano /mnt/persist/etc/nixos/hosts/new/hardware.nix

echo ""
echo "1. rename /mnt/persist/etc/nixos/hosts/new for new hostname"
echo "2. add to /mnt/persist/etc/nixos/flake.nix"
echo "3. add to git"
echo "4. run nixos-install --flake /mnt/persist/etc/nixos#hostname"
echo "5. reboot"

0 comments on commit 124dd6b

Please sign in to comment.