commit 09edc28b0a3fb4f12a5a0d1ad8b747753202f0cd Author: Yadunand Prem Date: Wed Aug 14 11:27:36 2024 +0800 feat: add flake to create iso and create VMs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f4ce10 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +nixos/result diff --git a/nixos/flake.lock b/nixos/flake.lock new file mode 100644 index 0000000..0ba8683 --- /dev/null +++ b/nixos/flake.lock @@ -0,0 +1,201 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723426710, + "narHash": "sha256-yrS9al6l3fYfFfvovnyBWnyELDQOdfKyai4K/jKgoBw=", + "owner": "nix-community", + "repo": "disko", + "rev": "0d510fe40b56ed74907a021d7e1ffd0042592914", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1722732880, + "narHash": "sha256-do2Mfm3T6SR7a5A804RhjQ+JTsF5hk4JTPGjCTRM/m8=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "8bebd4c74f368aacb047f0141db09ec6b339733c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723444610, + "narHash": "sha256-WzhuUR2ZwafNzBh0VAbk3+320xd2sNWdZdjZa0S9ydY=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "a220fc3a6e144f12f0c3dc3e4d01d44c2e6b0b85", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1723221148, + "narHash": "sha256-7pjpeQlZUNQ4eeVntytU3jkw9dFK3k1Htgk2iuXjaD8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "154bcb95ad51bc257c2ce4043a725de6ca700ef6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "disko": "disko", + "flake-utils": "flake-utils", + "nixos-generators": "nixos-generators", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/nixos/flake.nix b/nixos/flake.nix new file mode 100644 index 0000000..85548ab --- /dev/null +++ b/nixos/flake.nix @@ -0,0 +1,72 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + flake-utils = { + url = "github:numtide/flake-utils"; + }; + nixos-generators = { + url = "github:nix-community/nixos-generators"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { flake-utils,nixpkgs, disko, agenix, nixos-generators, ... }: let + nodes = ["premhome-falcon-1" "premhome-falcon-2"]; + in { + packages = builtins.listToAttrs(map (system: { + name=system; + value={ + generate-iso = nixos-generators.nixosGenerate { + format = "iso"; + system = "x86_64-linux"; + modules = [ + ./proxmox/iso.nix # base configuration of the image + ]; + }; + }; + }) + ["x86_64-linux" "aarch64-darwin"]) // + { + x86_64-linux = { + create-vm = let + pkgs = import nixpkgs { system = "x86_64-linux"; }; + script-name = "create-vm"; + src = builtins.readFile ./proxmox/create-vm.sh; + script = (pkgs.writeScriptBin script-name src).overrideAttrs(old: { + buildCommand = "${old.buildCommand}\n patchShebangs $out"; + }); + buildInputs = with pkgs; [ gum jq ]; + in pkgs.symlinkJoin { + name = script-name; + paths = [ script ] ++ buildInputs; + nativeBuildInputs = with pkgs; [makeWrapper]; + postBuild = "wrapProgram $out/bin/${script-name} --prefix PATH : $out/bin"; + + }; + + }; + }; + + } // flake-utils.lib.eachDefaultSystem (system: + let pkgs = import nixpkgs { + inherit system; + }; in + { + devShells = { + default = pkgs.mkShell { + buildInputs = with pkgs; [ + colmena + shellcheck + ]; + }; + }; + }); +} diff --git a/nixos/proxmox/create-vm.sh b/nixos/proxmox/create-vm.sh new file mode 100755 index 0000000..f94d070 --- /dev/null +++ b/nixos/proxmox/create-vm.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) + + +function cleanup() { + trap - SIGINT SIGTERM ERR EXIT + echo "Cleaning Up" +} +trap cleanup SIGINT SIGTERM ERR EXIT + +function main() { + VMID="$(sudo pvesh get /cluster/nextid)" + + # NODE="$(sudo pvesh get /nodes --output-format json | jq -r '.[].node' | gum choose --select-if-one --cursor="Select Node > ")" + NODE="falcon" + echo "Selected ${NODE}" + + STORAGE="$(sudo pvesh get /nodes/${NODE}/storage --output-format json --human-readable true | jq -r '.[] | select((.enabled == 1) and (.content | contains("images"))).storage' | gum choose --select-if-one)" + echo "Selected ${STORAGE} for storage" + + EXISTING_NODES=$(sudo pvesh get /nodes/${NODE}/qemu --output-format json | jq -r "map(.name | select(startswith(\"premhome-${NODE}\")))") + + printf "\nexisting Nodes: %s\n" "${EXISTING_NODES}" + + DEFAULT_NAME=$(jq -r "map(capture(\"(?.*-)(?[0-9]+)$\") | .num |= (tonumber + 1) | \"\(.base)\(.num)\") | max" <<< "$EXISTING_NODES") + + NAME="$(gum input --prompt="VM Name > " --value="${DEFAULT_NAME}")" + echo "creating VM with id: ${VMID} on ${NODE} stored on ${STORAGE} with name: ${NAME}" + sudo qm create "${VMID}" \ + --agent 1 \ + --bios "ovmf" \ + --boot "order=scsi0;ide2" \ + --cores 2 \ + --cpu "host" \ + --efidisk0 "${STORAGE}:1,efitype=4m" \ + --ide2 "local:iso/nixos-yadunut.iso,media=cdrom" \ + --machine q35 \ + --memory 2048 \ + --name "${NAME}" \ + --net0 "virtio,bridge=vmbr0" \ + --ostype "l26" \ + --scsi0 "${STORAGE}:50,iothread=on" \ + --scsihw "virtio-scsi-single" + + echo "Created VM, starting..." + sudo qm start "${VMID}" + echo "Started VM ${VMID}" + + echo "Attempting to retrieve IP Address" + start_time=$(date +%s) + while true; do + if IP_ADDRESS="$(sudo qm agent "${VMID}" network-get-interfaces 2>/dev/null | jq -r '.[] | select(.name != "lo") | .["ip-addresses"][] | select(.["ip-address-type"] == "ipv4")')"; then + if [ -n "${IP_ADDRESS}" ]; then + echo "Retrieved IP Address: ${IP_ADDRESS}" + break + fi + fi + + echo "Failed to retrieve IP, trying again" + + current_time=$(date +%s) + elapsed_time=$((current_time - start_time)) + + if [ $elapsed_time -ge 60 ]; then + echo "1 minute has elapsed. Failing" + cleanup + break + fi + + sleep 3 + done + # try to retrieve IP address +} + +main "$@" diff --git a/nixos/proxmox/iso.nix b/nixos/proxmox/iso.nix new file mode 100644 index 0000000..34c13e1 --- /dev/null +++ b/nixos/proxmox/iso.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, meta, ...}: +{ + imports = [./users.nix]; + + nix = { + settings.experimental-features = ["nix-command" "flakes"]; + }; + + isoImage = { + isoName = "${config.system.nixos.distroId}-yadunut.iso"; + }; + services.openssh.enable = true; + + services.qemuGuest.enable = true; + + environment.systemPackages = with pkgs; [ + git + neovim + wget + ]; + + system.stateVersion = "24.05"; +} diff --git a/nixos/proxmox/users.nix b/nixos/proxmox/users.nix new file mode 100644 index 0000000..14c57a1 --- /dev/null +++ b/nixos/proxmox/users.nix @@ -0,0 +1,8 @@ +{ + users.users.yadunut = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXOpmWsAnl2RtOuJJMRUx+iJTwf2RWJ1iS3FqXJFzFG" ]; + }; + security.sudo.wheelNeedsPassword = false; +}