updates to make morph transparently available when building images

This commit is contained in:
James Andariese 2022-09-26 07:27:59 -06:00
parent f1493c5bb0
commit 429f846f9b
10 changed files with 125 additions and 23 deletions

View File

@ -26,6 +26,81 @@ In order to discover your network and configure hosts, this configuration manage
* Proxmox running on the local host * Proxmox running on the local host
* Proxmox should have a local filesystem called hdd-fs * Proxmox should have a local filesystem called hdd-fs
## The Future (or how to not Proxmox)
### Or how it works without the script
Proxmox is not _at all_ a requirement for using this.
Neither is Samba. They are requirements for the mkvirt function in shell.nix.
This may be replaced or not used at all. The image created in result/nixos.img will boot on most hypervisors.
After the image is created and booted, it must be morphed.
The first step in morphing is making the machine resolveable. This is done with Samba but may be done with
another DNS system. The key is that it must be resolveable _immediately_ after the record is created because
morph then uses that record to find the machine. Reworking this to use IPs would require changing morph's
defaults or explicitly setting the deployment target address to be something other than the hostname.
After the host is resolveable, morph.
### Interesting Places
* `custom-image.nix`
* nixos.img disk size, format, partition table, etc
* `common/ssh.nix`
* configure ssh package (such as `openssh_gssapi` vs `openssh`)
* `common/users.nix`
* the deploy user, ssh keys, shell, etc.
* `functions/*.nix`
* a function per file
* load default.nix to load all functions by name in a set
* `hosts/*`
* hosts deployed via morph are pulled from here automatically
* files in this folder should be informational only. they _do not_ return a function.
* functionality which requires access to config or pkgs should be implemented in `profiles/` and loaded by name in imports.
* `profiles/*`
* profiles for describing machines of a certain class.
* profiles may represent hardware such as `api` and `qemu-vm` or a configuration pattern such as `dhcp-server` or `base`.
* the `base` profile is special in that it _should_ always be loaded. it is generally included by the hardware profile.
* `shell.nix`
* shell functions and configuration to build and deploy machines
* `env_cascade`
* discover domain, and realm config such as domain controller (samba) to send DNS updates to
* sanitize config
* returns env vars
* `$DOMAIN`
* domain name (from hostname -d), lowercase
* `$REALM`
* domain name (from hostname -d), uppercase
* `$workgroup`
* workgroup (first domain segment), lowercase
* `$WORKGROUP`
* workgroup (first domain segment), uppercase
* `$DC`
* lookup PTR of (lookup A of $DOMAIN)
* this will find a domain controller in a "normal" domain such as is created by default in Samba
* `env_name`
* sanitize hostname
* returns env vars
* `$name` hostname, lowercase
* `$NAME` hostname, uppercase
* `samba-create-ipv4-records`
* create DNS records
* `wait-for-vm-ipv4`
* wait for a VM to have an ipv4 address in a private subnet
* `mkvirt`
* `morph build`
* get an unused VMID from Proxmox
* create a new virt with discovered VMID
* wait for IP
* create DNS record with IP
* morph deploy to single machine
* `destroy-host`
* removes hosts/$name.nix
* removes DNS entry for $name.$DOMAIN
NIX: https://www.nixos.org NIX: https://www.nixos.org
PVE: https://www.proxmox.com/en/proxmox-ve PVE: https://www.proxmox.com/en/proxmox-ve

View File

@ -1,6 +1,8 @@
with builtins;
{}: {}:
let let
myisoconfig = import ./custom-image-configuration.nix; myisoconfig = import ./hosts/_basic.nix;
copyChannel = true; copyChannel = true;
system = "x86_64-linux"; system = "x86_64-linux";

3
hosts/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.nix
!_*.nix
!default.nix

View File

@ -1,8 +1,10 @@
{ nodes, config, pkgs, ... }: { {
imports = [ imports = [
(toString ../profiles/qemu-vm) (toString ../profiles/qemu-vm)
]; ];
config = { config = {
deployment.tags = [ ]; #deployment.targetHost = "";
#deployment.targetUser = "";
#deployment.targetPort = "";
}; };
} }

View File

@ -2,4 +2,12 @@ let _ = builtins.trace "${toString ./.}/default.nix"; in
with builtins; with builtins;
with import (toString ../functions); with import (toString ../functions);
import-folder {path = "${toString ./.}"; filenameMatch = ".*[.]nix"; filenameBadMatch = ".*_.*";} let hosts = import-folder {path = "${toString ./.}"; filenameMatch = ".*[.]nix"; filenameBadMatch = ".*_.*";};
in
{...}:
mapAttrs (hostname: hostdef:
{...}: hostdef
) hosts

View File

@ -1,11 +1,12 @@
with builtins; with builtins;
with import ./functions;
let pkgs = import <nixpkgs> {}; let pkgs = import <nixpkgs> {};
network = { network = {
inherit pkgs; inherit pkgs;
description = "cascade"; description = "cascade";
}; };
hosts = import (toString ./hosts); hosts = import (toString ./hosts) {};
in in
hosts // { hosts // {

View File

@ -7,7 +7,7 @@
imports = [ (toString ../base) ]; imports = [ (toString ../base) ];
config = { config = {
deployment.targetUser = "root"; deployment.targetUser = lib.mkDefault "root";
boot.initrd.availableKernelModules = [ "xhci_pci" "dwc3_pci" "usbhid" "usb_storage" "uas" "sd_mod" "sdhci_acpi" ]; boot.initrd.availableKernelModules = [ "xhci_pci" "dwc3_pci" "usbhid" "usb_storage" "uas" "sd_mod" "sdhci_acpi" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];

View File

@ -2,6 +2,9 @@
{ {
imports = [ imports = [
(toString ../../common) (toString ../../common)
<morph-options> # we include the options here to ensure that we can build with or without morph.
# morph-lib must be NIX_PATH and point to the lib path of the morph that is being
# used for deployment. This is done automatically with shell.nix.
]; ];
config = { config = {
environment.systemPackages = with pkgs; [ bridge-utils ]; environment.systemPackages = with pkgs; [ bridge-utils ];
@ -9,6 +12,19 @@
programs.neovim.vimAlias = true; programs.neovim.vimAlias = true;
programs.neovim.viAlias = true; programs.neovim.viAlias = true;
environment.binbash.enable = true;
services.getty.autologinUser = "root";
services.sshd.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
system.stateVersion = "22.11"; system.stateVersion = "22.11";
nix.nixPath = with pkgs; [
"nixpkgs=/usr/src/nixpkgs"
"home-manager=/usr/src/nixpkgs"
"morph-options=${morph.lib}/options.nix"
];
}; };
} }

View File

@ -1,11 +1,12 @@
{lib, ...}: {lib, config, ...}:
with lib; with lib;
{ {
imports = [ (toString ../base) ]; imports = [ (toString ../base) ];
config = { config = {
deployment.targetUser = "root"; deployment.targetUser = lib.mkDefault "root";
cascade.bridge-interface = "ens18";
fileSystems."/" = { fileSystems."/" = {
device = "/dev/disk/by-label/nixos"; device = "/dev/disk/by-label/nixos";
fsType = "ext4"; fsType = "ext4";
@ -24,11 +25,7 @@ with lib;
networking.useNetworkd = mkForce true; networking.useNetworkd = mkForce true;
networking.networkmanager.enable = false; networking.networkmanager.enable = false;
#networking.interfaces.ens18.useDHCP = false;
#networking.bridges.br0.interfaces = [ "ens18" ];
#networking.interfaces.br0.useDHCP = lib.mkDefault true;
# hardware.cpu.amd.updateMicrocode = lib.config.hardware.enableRedistributableFirmware;
boot.initrd.availableKernelModules = [ "virtio_net" "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_scsi" "9p" "9pnet_virtio" ]; boot.initrd.availableKernelModules = [ "virtio_net" "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_scsi" "9p" "9pnet_virtio" ];
boot.initrd.kernelModules = [ "virtio_balloon" "virtio_console" "virtio_rng" ]; boot.initrd.kernelModules = [ "virtio_balloon" "virtio_console" "virtio_rng" ];
@ -46,6 +43,5 @@ with lib;
services.qemuGuest.enable = true; services.qemuGuest.enable = true;
cascade.bridge-interface = "ens18";
}; };
} }

19
shell.nix Executable file → Normal file
View File

@ -13,20 +13,16 @@ stdenv.mkDerivation {
buildInputs = [ terraform vault coreutils-full dig bash samba4Full morph ]; buildInputs = [ terraform vault coreutils-full dig bash samba4Full morph ];
shellHook = '' shellHook = ''
export NIX_PATH="nixpkgs=${toString <nixpkgs>}" export NIX_PATH="nixpkgs=${toString <nixpkgs>}:morph-options=${morph.lib}/options.nix"
export LD_LIBRARY_PATH="${libvirt}/lib:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH="${libvirt}/lib:$LD_LIBRARY_PATH"
export VAULT_ADDR=${escapeShellArg vault_addr} export VAULT_ADDR=${escapeShellArg vault_addr}
export DOMAIN="$(hostname -d)" export DOMAIN="$(hostname -d)"
PROXMOX_STORAGE=hdd-fs
MEMORY=2048 MEMORY=2048
name="$1"
rebuild-nixos-image() { rebuild-nixos-image() {
echo "$(nix-build \ echo "$(nix-build custom-image.nix)/nixos".img
-I nixos-config=custom-image-configuration.nix \
-I hardware-config=profiles/qemu-vm/default.nix \
custom-image.nix)/nixos".img
} }
mkvirt() { mkvirt() {
@ -56,7 +52,7 @@ mkvirt() {
--net0 virtio,bridge=vmbr0 \ --net0 virtio,bridge=vmbr0 \
--ipconfig0 ip=dhcp \ --ipconfig0 ip=dhcp \
--agent enabled=1,type=virtio \ --agent enabled=1,type=virtio \
--virtio0 hdd-fs:0,import-from="$IMG",discard=on,format=raw \ --virtio0 "$PROXMOX_STORAGE":0,import-from="$IMG",discard=on,format=raw \
--boot c \ --boot c \
--bootdisk virtio0 \ --bootdisk virtio0 \
--vga serial0 \ --vga serial0 \
@ -187,10 +183,11 @@ deploy() {
} }
destroy-host() { destroy-host() {
eval "$(env_cascade)"
while [ $# -gt 0 ];do while [ $# -gt 0 ];do
eval "$(env_name "$1")"
VMID="$(sudo qm list | awk -v N="$1" '$2 == N {print $1}')" VMID="$(sudo qm list | awk -v N="$1" '$2 == N {print $name}')"
echo "destroying hosts/$1.nix and VM #$VMID" 1>&2 echo "destroying hosts/$1.nix and VM #$VMID" 1>&2
sleep 1 sleep 1
@ -199,6 +196,8 @@ destroy-host() {
sudo qm destroy $VMID sudo qm destroy $VMID
rm -f hosts/"$1".nix rm -f hosts/"$1".nix
samba-tool dns cleanup -k yes "$DC" "$name"."$DOMAIN"
shift shift
done done
} }