bootstrap: implement automated VM bootstrap mechanism for Phase 3
Add systemd service that automatically bootstraps freshly deployed VMs with their host-specific NixOS configuration from the flake repository. Changes: - hosts/template2/bootstrap.nix: New systemd oneshot service that: - Runs after cloud-init completes (ensures hostname is set) - Reads hostname from hostnamectl (set by cloud-init from Terraform) - Checks network connectivity via HTTPS (curl) - Runs nixos-rebuild boot with flake URL - Reboots on success, fails gracefully with clear errors on failure - hosts/template2/configuration.nix: Configure cloud-init datasource - Changed from NoCloud to ConfigDrive (used by Proxmox) - Allows cloud-init to receive config from Proxmox - hosts/template2/default.nix: Import bootstrap.nix module - terraform/vms.tf: Add cloud-init disk to VMs - Configure disks.ide.ide2.cloudinit block - Removed invalid cloudinit_cdrom_storage parameter - Enables Proxmox to inject cloud-init configuration - TODO.md: Mark Phase 3 as completed This eliminates the manual nixos-rebuild step from the deployment workflow. VMs now automatically pull and apply their configuration on first boot. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
66
hosts/template2/bootstrap.nix
Normal file
66
hosts/template2/bootstrap.nix
Normal file
@@ -0,0 +1,66 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
let
|
||||
bootstrap-script = pkgs.writeShellApplication {
|
||||
name = "nixos-bootstrap";
|
||||
runtimeInputs = with pkgs; [ systemd curl nixos-rebuild jq git ];
|
||||
text = ''
|
||||
set -euo pipefail
|
||||
|
||||
# Read hostname set by cloud-init (from Terraform VM name via user-data)
|
||||
# Cloud-init sets the system hostname from user-data.txt, so we read it from hostnamectl
|
||||
HOSTNAME=$(hostnamectl hostname)
|
||||
echo "DEBUG: Hostname from hostnamectl: '$HOSTNAME'"
|
||||
|
||||
echo "Starting NixOS bootstrap for host: $HOSTNAME"
|
||||
echo "Waiting for network connectivity..."
|
||||
|
||||
# Verify we can reach the git server via HTTPS (doesn't respond to ping)
|
||||
if ! curl -s --connect-timeout 5 --max-time 10 https://git.t-juice.club >/dev/null 2>&1; then
|
||||
echo "ERROR: Cannot reach git.t-juice.club via HTTPS"
|
||||
echo "Check network configuration and DNS settings"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Network connectivity confirmed"
|
||||
echo "Fetching and building NixOS configuration from flake..."
|
||||
|
||||
# Build and activate the host-specific configuration
|
||||
FLAKE_URL="git+https://git.t-juice.club/torjus/nixos-servers.git#''${HOSTNAME}"
|
||||
|
||||
if nixos-rebuild boot --flake "$FLAKE_URL"; then
|
||||
echo "Successfully built configuration for $HOSTNAME"
|
||||
echo "Rebooting into new configuration..."
|
||||
sleep 2
|
||||
systemctl reboot
|
||||
else
|
||||
echo "ERROR: nixos-rebuild failed for $HOSTNAME"
|
||||
echo "Check that flake has configuration for this hostname"
|
||||
echo "Manual intervention required - system will not reboot"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
systemd.services."nixos-bootstrap" = {
|
||||
description = "Bootstrap NixOS configuration from flake on first boot";
|
||||
|
||||
# Wait for cloud-init to finish setting hostname and network to be online
|
||||
after = [ "cloud-config.service" "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
requires = [ "cloud-config.service" ];
|
||||
|
||||
# Run on boot
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${bootstrap-script}/bin/nixos-bootstrap";
|
||||
|
||||
# Logging to journald
|
||||
StandardOutput = "journal+console";
|
||||
StandardError = "journal+console";
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user