{ 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..." # Read git branch from environment, default to master BRANCH="''${NIXOS_FLAKE_BRANCH:-master}" echo "Using git branch: $BRANCH" # Build and activate the host-specific configuration FLAKE_URL="git+https://git.t-juice.club/torjus/nixos-servers.git?ref=$BRANCH#''${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"; # Read environment variables from /etc/environment (set by cloud-init) EnvironmentFile = "-/etc/environment"; # Logging to journald StandardOutput = "journal+console"; StandardError = "journal+console"; }; }; }