#!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail if [[ "$#" -ne 1 ]]; then echo "Usage: $0 " exit 1 fi host="$1" mkdir -p "./hosts/$host/secrets" ssh-keygen -t ed25519 -f "./hosts/$host/secrets/ssh_host_ed25519_key" -C "root@$host" -N "" age_key=$(ssh-to-age < "./hosts/$host/secrets/ssh_host_ed25519_key.pub") cat < "./hosts/$host/secrets/sops.yaml" keys: - hosts: - &$host $age_key - namespaces: - &personal $(age-keygen -y ./secrets/personal/key.txt | tr -d '\n') creation_rules: - path_regex: .+\.(yaml|yml|json|env|ini|bin) key_groups: - age: - *$host - *personal EOF luks="" luks_confirm="" until [[ "$luks" == "$luks_confirm" && -n "$luks" ]]; do read -r -s -p "Enter LUKS passphrase for $host: " luks echo read -r -s -p "Confirm LUKS passphrase for $host: " luks_confirm echo if [[ "$luks" != "$luks_confirm" ]]; then echo "They didn't match. Let's try again." fi done machine_id=$(uuidgen -r | tr -d -) cat < "./hosts/$host/secrets/.decrypted~secrets.yaml" luks: '$luks' machineId: $machine_id EOF tmp_age_key="$(mktemp)" echo "$age_key" > "$tmp_age_key" export SOPS_AGE_KEY_FILE="$tmp_age_key" sops --config "./hosts/$host/secrets/sops.yaml" --encrypt "./hosts/$host/secrets/.decrypted~secrets.yaml" > "./hosts/$host/secrets/secrets.yaml" unset SOPS_AGE_KEY_FILE rm -f "$tmp_age_key" rm -f "./hosts/$host/secrets/.decrypted~secrets.yaml" mkdir -p "./hosts/$host/hardware" cat <<'EOF' > "./hosts/$host/hardware/default.nix" { ... }: { } EOF cat <<'EOF' > "./hosts/$host/format.nix" { disko.devices = { disk.main = { device = ""; # Set this to the device you want to install to type = "disk"; content = { type = "gpt"; partitions = { boot = { name = "boot"; size = "1M"; type = "EF02"; }; esp = { name = "esp"; size = "512M"; type = "EF00"; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; mountOptions = [ "umask=0077" ]; }; }; root = { name = "root"; size = "100%"; content = { name = "main"; type = "luks"; passwordFile = "/tmp/keyfile"; settings = { allowDiscards = true; }; content = { type = "btrfs"; extraArgs = [ "-f" ]; subvolumes = { "@" = { mountpoint = "/"; }; "@persist" = { mountpoint = "/persist"; mountOptions = [ "compress=zstd" "noatime" ]; }; "@nix" = { mountpoint = "/nix"; mountOptions = [ "compress=zstd" "noatime" ]; }; "@cache" = { mountpoint = "/cache"; mountOptions = [ "compress=zstd" "noatime" ]; }; }; }; }; }; }; }; }; }; } EOF cat < "./hosts/$host/default.nix" { inputs, ... }: { imports = [ ../../lib inputs.disko.nixosModules.disko ./format.nix ./hardware ../common/configs/system/boot ../common/configs/system/btrfs ../common/configs/system/documentation ../common/configs/system/impermanence ../common/configs/system/nix ../common/configs/system/nix-cleanup ../common/configs/system/nixpkgs ../common/configs/system/ntp ../common/configs/system/sops ../common/configs/system/system ../common/configs/system/users ../common/configs/system/zsh ]; networking.hostName = "$host"; i18n.defaultLocale = "en_US.UTF-8"; sops.defaultSopsFile = ./secrets/secrets.yaml; } EOF cat < "./hosts/$host/README.md" # $host ## Post-Install Checklist EOF new_entry="| \`$host\` | [hosts/$host/README.md](./hosts/$host/README.md) |" last_table_line=$(grep -n "^| " README.md | tail -n 1 | cut -d: -f1) sed -i "${last_table_line}a$new_entry" README.md sed -i "/knownHosts = {/a\\ $host.publicKeyFile = ../../../../$host/secrets/ssh_host_ed25519_key.pub;" ./hosts/common/configs/system/ssh/default.nix nix fmt echo "Host $host has been successfully added." echo "Age Public Key: $age_key" echo echo "If you need user-level SSH keys, generate them like this:" echo " ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_${host}_"