restart git repo

This commit is contained in:
Jeeves 2024-06-24 12:54:49 -06:00
commit 8a816b5e85
16 changed files with 1458 additions and 0 deletions

47
os/db.nix Normal file
View file

@ -0,0 +1,47 @@
{ pkgs, system }: let
sources = {
windows = {
"6.1.7601" = {
professional = let key = "HYF8J-CVRMY-CM74G-RPHKF-PW487"; in {
x86.url = "https://archive.org/download/win-7-pro-32-64-iso/32-bit/GSP1RMCPRXFRER_EN_DVD.ISO";
x86.hash = "sha256-TPG6ryqzCgXJ9K70krterEa6oqqIZyAPDJzsW5SMy5U=";
x86_64.url = "https://archive.org/download/win-7-pro-32-64-iso/64-bit/GSP1RMCPRXFRER_EN_DVD.ISO";
x86_64.hash = "sha256-ug50400prU2W4VW51KngN/0A80d+n8HhVuos2dBykUs=";
x86.extraUnattendConfig.productKey = key;
x86_64.extraUnattendConfig.productKey = key;
};
};
};
};
unattend = import ./windows/unattend.nix { inherit pkgs; };
in {
windows =
builtins.mapAttrs (version: v:
builtins.mapAttrs (edition: vv:
builtins.mapAttrs (arch: vvv: {
installer = derivation {
name = "windows-" + version + "-" + edition + "-" + arch + "-installer";
inherit system;
builder = "${pkgs.fish}/bin/fish";
args = [ ./lib/copy-file.fish "out.iso" ];
src = pkgs.fetchurl { inherit (vvv) url hash; };
inherit (pkgs) coreutils;
};
unattend = derivation {
name = "windows-" + version + "-" + edition + "-" + arch + "-unattend";
inherit system;
builder = "${pkgs.fish}/bin/fish";
args = [ ./lib/mkiso.fish "out.iso" ];
src = pkgs.writeText "Autounattend.xml"
(unattend.genConfig (pkgs.lib.attrsets.recursiveUpdate
unattend.default
vvv.extraUnattendConfig
));
inherit (pkgs) coreutils libisoburn;
};
}) vv
) v
) sources.windows;
ubuntu = {};
}

133
os/lib.nix Normal file
View file

@ -0,0 +1,133 @@
{
pkgs ? import <nixpkgs> {},
system ? builtins.currentSystem,
nixvirt,
}: let
inherit (nixvirt) lib;
vm = import ./lib/vm.nix { inherit pkgs nixvirt; };
osdb = import ./db.nix { inherit pkgs system; };
volumeFn = { name, size }: nixvirt.lib.volume.writeXML {
name = name + ".qcow2";
capacity = { count = size; unit = "GB"; };
target = {
format.type = "qcow2";
};
};
in {
inherit osdb;
mkVM = {
name,
uuid,
arch,
isos,
}: let
base = {
inherit name uuid arch;
volume.index = 0;
volume.bus = "sata";
volume.file = "/var/lib/libvirt/images/${name}.qcow2";
};
idxToDev = i: builtins.substring i 1 "abcdefg";
volume = volumeFn { size = 16; inherit name; };
beforeInstall = isos.beforeInstall; # Required attribute.
afterInstall = if builtins.hasAttr "afterInstall" isos then isos.afterInstall else [];
beforeBoot = if builtins.hasAttr "beforeBoot" isos then isos.beforeBoot else [];
afterBoot = if builtins.hasAttr "afterBoot" isos then isos.afterBoot else [];
beforeInstallDrv = lib.domain.writeXML (vm.genericVM (base // {
cdroms = map (x: {
inherit (x) index file;
bus = "sata";
dev = "sd" + idxToDev x.index;
}) (beforeInstall);
}));
afterInstallDrv = lib.domain.writeXML (vm.genericVM (base // {
cdroms = map (x: {
inherit (x) index file;
bus = "sata";
dev = "sd" + idxToDev x.index;
}) (afterInstall);
}));
beforeBootDrv = lib.domain.writeXML (vm.genericVM (base // {
cdroms = map (x: {
inherit (x) index file;
bus = "sata";
dev = "sd" + idxToDev x.index;
}) (beforeBoot);
}));
afterBootDrv = lib.domain.writeXML (vm.genericVM (base // {
cdroms = map (x: {
inherit (x) index file;
bus = "sata";
dev = "sd" + idxToDev x.index;
}) (afterBoot);
}));
in derivation {
inherit name system;
builder = "${pkgs.fish}/bin/fish";
args = [ ./lib/mkvm.fish ];
start-vm = pkgs.writeScript "start-vm"
''
#!/usr/bin/env fish
function quickExit
virsh destroy ${name}
exit
end
function interrupt_handler --on-signal INT
echo Got INT signal, cleaning up and exiting...
quickExit
end
echo "moving to beforeInstall stage"
# rm /var/lib/libvirt/images/${name}.qcow2
# virsh vol-delete --pool default '${name}.qcow2'
virsh vol-create default ${volume}
virsh define ${beforeInstallDrv}
virsh start '${name}'
fish -c 'virsh console ${name} 2>/dev/null | while read -l out; if test $out = "$(string unescape ready\r\n)"; sleep 60; exit; end; end'
# virsh console '${name}' 2>/dev/null | while read -l out
# # echo out: $out (string unescape \r)
# if test $out = "$(string unescape ready\r\n)"
# echo "waiting 60 seconds"
# sleep 60
# virsh shutdown '${name}'
# end
# end
echo "moving to afterInstall stage"
virsh define ${afterInstallDrv}
virsh snapshot-create-as '${name}' '${builtins.baseNameOf afterInstallDrv}'
virsh console '${name}' 2>/dev/null | while read -l out
if test $out = "$(string unescape ready\r\n)"
echo "waiting 60 seconds"
sleep 60
virsh shutdown '${name}'
end
end
echo "moving to beforeBoot stage"
virsh define ${beforeBootDrv}
virsh snapshot-create-as '${name}' '${builtins.baseNameOf beforeBootDrv}'
virsh console '${name}' 2>/dev/null | while read -l out
if test $out = "$(string unescape ready\r\n)"
echo "waiting 60 seconds"
sleep 60
virsh shutdown '${name}'
end
end
echo "moving to afterBoot stage"
virsh define ${afterBootDrv}
virsh snapshot-create-as '${name}' '${builtins.baseNameOf afterBootDrv}'
'';
};
}

4
os/lib/copy-file.fish Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env fish
fish_add_path $coreutils/bin
mkdir $out
cp $src $out/$argv[1]

6
os/lib/mkiso.fish Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env fish
fish_add_path $coreutils/bin $libisoburn/bin
mkdir $out
mkdir -p $TMP/iso
cp $src $TMP/iso/Autounattend.xml
xorrisofs -v -J -r -o $out/$argv[1] $TMP/iso

378
os/lib/vm.nix Normal file
View file

@ -0,0 +1,378 @@
{ pkgs, nixvirt }: rec {
inherit (pkgs) lib;
inherit (nixvirt) xml;
genericVM = { name, uuid, arch, volume, cdroms, ... }: {
inherit name uuid;
type = "kvm";
memory = { count = 4194304; unit = "KiB"; };
vcpu = { placement = "static"; count = 4; };
os = {
inherit arch;
type = "hvm";
machine = "pc-q35-8.1";
boot = [{ dev = "cdrom"; }]; #{ dev = "hd"; }];
bootmenu.enable = false;
smbios.mode = "sysinfo";
};
sysinfo = {
type = "smbios";
bios.entry = [
{ name = "vendor"; value = "Dell"; }
];
system.entry = [
{ name = "manufacturer"; value = "Dell"; }
{ name = "product"; value = "Dell"; }
{ name = "version"; value = "9.5.4"; }
];
};
features = {
acpi = {};
apic = {};
hyperv = {
mode = "custom";
relaxed.state = true;
vapic.state = true;
spinlocks.state = true;
spinlocks.retries = 8191;
};
kvm.hidden.state = true;
vmport.state = false;
};
cpu = {
mode = "host-passthrough";
check = "none";
migratable = true;
topology = {
sockets = 1;
dies = 1;
cores = 4;
threads = 1;
};
feature = [
{ policy = "disable"; name = "hypervisor"; }
];
};
clock = {
offset = "localtime";
timer = [
{ name = "rtc"; tickpolicy = "catchup"; }
{ name = "pit"; tickpolicy = "delay"; }
{ name = "hpet"; present = false; }
{ name = "hypervclock"; present = true; }
];
};
on_poweroff = "destroy";
on_reboot = "restart";
on_crash = "restart";
pm.suspend-to-mem.enabled = false;
pm.suspend-to-disk.enabled = false;
devices = let
pci_address = bus: slot: function: {
type = "pci";
domain = 0;
bus = bus;
slot = slot;
inherit function;
};
usb_address = port: {
type = "usb";
bus = 0;
inherit port;
};
drive_address = unit: {
type = "drive";
controller = 0;
bus = 0;
target = 0;
inherit unit;
};
mksourcetype = with builtins;
src:
if isAttrs src && src ? "volume" then "volume"
else "file";
mksource = with builtins;
src:
if isString src || isPath src then { file = src; }
else src;
in {
emulator = "/run/current-system/sw/bin/qemu-system-x86_64";
disk = [{
type = mksourcetype volume;
device = "disk";
driver = { name = "qemu"; type = "qcow2"; discard = "unmap"; }; #cache = "writeback"; };
source = mksource volume;
target = { bus = volume.bus; dev = "sda"; };
address = drive_address volume.index;
serial = "SEAG445692";
vendor = if volume.bus == "scsi" then "Seagate" else null;
product = if volume.bus == "scsi" then "HDD" else null;
}] ++ (map (x: {
type = "file";
device = "cdrom";
driver = { name = "qemu"; type = "raw"; };
target = { bus = x.bus; dev = x.dev; };
readonly = true;
address = drive_address x.index;
source = {
inherit (x) file;
# startupPolicy = "mandatory";
};
# inherit (x) serial vendor product;
serial = "WD-WMAP9A966149";
vendor = if x.bus == "scsi" then "WD" else null;
product = if x.bus == "scsi" then "DVDROM" else null;
}) (cdroms));
controller = [
{
type = "usb";
index = 0;
# model = "qemu-xhci";
model = "ich9-ehci1";
# ports = 15;
address = pci_address 0 29 7;
}
{
type = "scsi";
index = 0;
model= "lsisas1068";
address = pci_address 16 1 0;
}
# {
# type = "sata";
# index = 0;
# address = pci_address 0 31 2;
# }
{
type = "pci";
index = 0;
model = "pcie-root";
}
{
type = "virtio-serial";
index = 0;
address = pci_address 1 0 0;
}
# {
# type = "ccid";
# index = 0;
# address = usb_address 1;
# }
{
type = "pci";
index = 1;
model = "pcie-root-port";
address = pci_address 0 2 0 // { multifunction = true; };
}
{
type = "pci";
index = 16;
model = "pcie-to-pci-bridge";
address = pci_address 3 0 0;
}
{
type = "pci";
index = 2;
model = "pcie-root-port";
address = pci_address 0 2 1;
}
{
type = "pci";
index = 3;
model = "pcie-root-port";
address = pci_address 0 2 2;
}
{
type = "pci";
index = 4;
model = "pcie-root-port";
address = pci_address 0 2 3;
}
{
type = "pci";
index = 5;
model = "pcie-root-port";
address = pci_address 0 2 4;
}
{
type = "pci";
index = 6;
model = "pcie-root-port";
address = pci_address 0 2 5;
}
{
type = "pci";
index = 7;
model = "pcie-root-port";
address = pci_address 0 2 6;
}
{
type = "pci";
index = 8;
model = "pcie-root-port";
address = pci_address 0 2 7;
}
{
type = "pci";
index = 9;
model = "pcie-root-port";
address = pci_address 0 3 0 // { multifunction = true; };
}
{
type = "pci";
index = 10;
model = "pcie-root-port";
address = pci_address 0 3 1;
}
{
type = "pci";
index = 11;
model = "pcie-root-port";
address = pci_address 0 3 2;
}
{
type = "pci";
index = 12;
model = "pcie-root-port";
address = pci_address 0 3 3;
}
{
type = "pci";
index = 13;
model = "pcie-root-port";
address = pci_address 0 3 4;
}
{
type = "pci";
index = 14;
model = "pcie-root-port";
address = pci_address 0 3 5;
}
{
type = "pci";
index = 15;
model = "pcie-root-port";
address = pci_address 0 3 6;
}
];
interface = {
type = "network";
mac = { address = "52:54:00:10:c4:28"; };
source = { network = "default"; };
model = { type = "e1000e"; };
address = pci_address 4 0 0;
};
# smartcard = {
# mode = "passthrough";
# type = "spicevmc";
# address = {
# type = "ccid";
# controller = 0;
# slot = 0;
# };
# };
serial = {
type = "pty";
target = {
type = "isa-serial";
port = 0;
model = { name = "isa-serial"; };
};
};
console = {
type = "pty";
target = { type = "serial"; port = 0; };
};
channel = [
{
type = "spicevmc";
target = {
type = "virtio";
name = "com.redhat.spice.0";
};
address = {
type = "virtio-serial";
controller = 0;
bus = 0;
port = 1;
};
}
];
input = [
{
type = "tablet";
bus = "usb";
address = usb_address 2;
}
{
type = "mouse";
bus = "ps2";
}
{
type = "keyboard";
bus = "ps2";
}
];
# tpm = {
# model = "tpm-crb";
# backend = {
# type = "emulator";
# version = "2.0";
# };
# };
graphics = {
type = "spice";
autoport = true;
listen = { type = "address"; address = "127.0.0.1"; };
image = { compression = false; };
gl = { enable = false; };
};
sound = {
model = "ich9";
address = pci_address 0 27 0;
};
audio = {
id = 1;
type = "spice";
};
video = {
model = {
type = "qxl";
ram = 65536;
vram = 65536;
vgamem = 16384;
heads = 1;
primary = true;
acceleration = { accel3d = false; };
};
address = pci_address 0 1 0;
};
# redirdev = [
# {
# bus = "usb";
# type = "spicevmc";
# address = usb_address 3;
# }
# {
# bus = "usb";
# type = "spicevmc";
# address = usb_address 4;
# }
# {
# bus = "usb";
# type = "spicevmc";
# address = usb_address 5;
# }
# {
# bus = "usb";
# type = "spicevmc";
# address = usb_address 6;
# }
# ];
watchdog = {
model = "itco";
action = "reset";
};
};
};
}

13
os/windows/batch.nix Normal file
View file

@ -0,0 +1,13 @@
{ pkgs }: {
stuff = {};
genBatchScript = {
name,
commands,
}: let
# commandsString = pkgs.lib.strings.concatStringsSep "\r\n" commands;
in pkgs.lib.strings.concatStringsSep "\r\n" [
"@echo off"
commands
];
}

247
os/windows/unattend.nix Normal file
View file

@ -0,0 +1,247 @@
{ pkgs }: rec {
xml = import ./xml.nix;
# generate = import ./generate.nix;
settingsPass = name: contents: xml.elem "settings" [ (xml.attr "pass" name) ] contents;
component = name: subelems: xml.elem "component" [
(xml.attr "name" name)
(xml.attr "processorArchitecture" "amd64")
(xml.attr "publicKeyToken" "31bf3856ad364e35")
(xml.attr "language" "neutral")
(xml.attr "versionScope" "nonSxS")
(xml.attr "xmlns:wcm" "http://schemas.microsoft.com/WMIConfig/2002/State")
(xml.attr "xmlns:xsi" "http://www.w3.org/2001/XMLSchema-instance")
] subelems;
listElem = n: v: xml.elem n [ (xml.attr "wcm:action" "add") ] v;
list = name: subname: items: xml.elem name [] (map (item: listElem subname item) items);
elem = name: contents: xml.elem name [] contents;
typeCheck = tname: test: x:
if test x then x else builtins.abort ("expected " + tname + ", found " + builtins.typeOf x);
typeConvert = tname: test: conv: x: conv (typeCheck tname test x);
typeString = typeConvert "string" builtins.isString (x: x);
typeInt = typeConvert "int" builtins.isInt builtins.toString;
typeBool = typeConvert "bool" builtins.isBool (t: if t then "true" else "false");
typeBoolAlwaysNever = typeConvert "bool" builtins.isBool (t: if t then "Always" else "Never");
mkElem = name: type: option: elem name (type option);
optional = config: name: elem: xml.opt (builtins.hasAttr name config) elem;
process = config: xml.elem "unattend" [ (xml.attr "xmlns" "urn:schemas-microsoft-com:unattend") ] [
(settingsPass "specialize" [
(component "Microsoft-Windows-Shell-Setup" [
(optional config "oemInfo" (mkElem "OEMInformation" [
(mkElem "Manufacturer" typeString config.oemInfo.manufacturer)
(mkElem "Model" typeString config.oemInfo.model)
]))
(mkElem "ComputerName" typeString config.name)
(optional config "productKey" (mkElem "ProductKey" typeString config.productKey))
(mkElem "TimeZone" typeString config.locale.timeZone)
])
(component "Microsoft-Windows-Security-SPP-UX" [
(elem "SkipAutoActivation" "true")
])
(component "Microsoft-Windows-Deployment" [
(list "RunSynchronous" "RunSynchronousCommand" [
[
(elem "Description" "Notify Host")
(elem "Order" "1")
(elem "Path" "cmd.exe /C echo specialize>COM1")
]
])
])
])
(settingsPass "windowsPE" [
(component "Microsoft-Windows-Setup" [
(elem "DiskConfiguration" [
(mkElem "WillShowUI" typeBoolAlwaysNever config.diskConfig.showUI)
(xml.elem "Disk" [ (xml.attr "wcm:action" "add") ] [
(list "CreatePartitions" "CreatePartition" [
[
(elem "Order" "1")
(elem "Size" "100")
(elem "Type" "Primary")
]
[
(elem "Order" "2")
(elem "Extend" "true")
(elem "Type" "Primary")
]
])
(list "ModifyPartitions" "ModifyPartition" [
[
(elem "Format" "NTFS")
(elem "Label" "System Reserved")
(elem "Order" "1")
(elem "Active" "true")
(elem "PartitionID" "1")
(elem "TypeID" "0x27")
]
[
(elem "Format" "NTFS")
(elem "Label" "Local Disk")
(elem "Order" "2")
(elem "Active" "true")
(elem "PartitionID" "1")
(elem "Letter" "C")
]
])
(elem "DiskID" "0")
(elem "WillWipeDisk" "true")
])
])
(elem "DynamicUpdate" [
(mkElem "WillShowUI" typeBoolAlwaysNever config.dynamicUpdate.showUI)
])
(elem "ImageInstall" [
(elem "OSImage" [
(elem "InstallTo" [
(elem "DiskID" "0")
(elem "PartitionID" "2")
])
(elem "InstallToAvailablePartition" "false")
(elem "WillShowUI" "Never")
])
])
(elem "UserData" [
(elem "ProductKey" [
(optional config "productKey" (mkElem "Key" typeString config.productKey))
])
(mkElem "AcceptEula" typeBool config.userData.acceptEula)
(mkElem "FullName" typeString config.userData.fullName)
(mkElem "Organization" typeString config.userData.organization)
])
])
(component "Microsoft-Windows-International-Core-WinPE" [
(elem "SetupUILanguage" [
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "WillShowUI" typeBoolAlwaysNever config.locale.showUI)
])
(mkElem "InputLocale" typeString config.locale.input)
(mkElem "SystemLocale" typeString config.locale.language)
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "UserLocale" typeString config.locale.language)
])
])
(settingsPass "generalize" [
(component "Microsoft-Windows-Security-SPP" [
(elem "SkipRearm" "1")
])
])
(settingsPass "oobeSystem" [
(component "Microsoft-Windows-International-Core" [
(mkElem "InputLocale" typeString config.locale.input)
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "UserLocale" typeString config.locale.language)
])
(component "Microsoft-Windows-Shell-Setup" [
(mkElem "RegisteredOwner" typeString config.userData.fullName)
(mkElem "RegisteredOrganization" typeString config.userData.organization)
(elem "DisableAutoDaylightTimeSet" "false")
(elem "OOBE" [
(elem "HideEULAPage" "true")
(elem "HideWirelessSetupInOOBE" "true")
(elem "NetworkLocation" "Home")
(elem "ProtectYourPC" "3")
(elem "SkipMachineOOBE" "true")
(elem "SkipUserOOBE" "true")
])
(list "FirstLogonCommands" "SynchronousCommand" (map (item: [
(mkElem "Description" typeString item.description)
(mkElem "CommandLine" typeString item.command)
(mkElem "Order" typeInt item.order)
]) config.firstLogonCommands))
# TODO make autologin reference the users list
(if builtins.hasAttr "autoLogon" config then
(elem "AutoLogon" [
(elem "Enabled" "true")
(mkElem "Username" typeString config.autoLogon.username)
(elem "Password" [
(mkElem "Value" typeString config.autoLogon.password)
(elem "PlainText" "true")
])
])
else
(elem "AutoLogon" [ (elem "Enabled" "false") ])
)
(xml.elem "UserAccounts" [] [
(list "LocalAccounts" "LocalAccount" (map (user: [
(elem "DisplayName" user.displayName)
(elem "Name" user.name)
(elem "Group" user.group)
(if user.password.enable then
(elem "Password" [
(elem "Value" user.password.value)
(elem "PlainText" user.password.plainText)
])
else
(elem "Password" [
(elem "Value" "")
(elem "PlainText" "true")
])
)
]) config.users))
])
])
])
];
default = let
user = {
name = "idiot";
displayName = "Idiot";
group = "Administrators";
password.enable = false;
};
in {
name = user.displayName + "-PC";
locale = {
language = "en-US";
timeZone = "Mountain Standard Time";
input = "1033:00000409";
showUI = false;
};
users = [ user ];
skipAutoActivation = true;
diskConfig = {
showUI = false;
};
dynamicUpdate.showUI = false;
userData = {
acceptEula = true;
fullName = user.displayName;
organization = "Dumbass Inc.";
};
firstLogonCommands = [
{
order = 1;
description = "Disable Auto Updates";
command = "reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v AUOptions /t REG_DWORD /d 1 /f";
}
{
order = 2;
description = "Notify Host";
command = "cmd.exe /C echo ready>COM1";
}
];
autoLogon = {
username = "idiot";
password = "";
};
};
genConfig = config: builtins.concatStringsSep "" [
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
(xml.toText (process config))
];
}

50
os/windows/xml.nix Normal file
View file

@ -0,0 +1,50 @@
with builtins;
let
indentLine = i: s:
if i == 0 then s + "\r\n" else " " + indentLine (i - 1) s;
escapeText = replaceStrings [ "&" "<" ">" "'" "\"" ] [ "&amp;" "&lt;" "&gt;" "&apos;" "&quot;" ];
concat = concatStringsSep "";
none = i: "";
opt = t: e:
if t then e else none;
many = ee: i: concat (map (e: e i) ee);
attr = n: v: i: " " + n + "=\"" + escapeText v + "\"";
elem = etype: aa: body: i:
let
head = "<" + etype + concat (map (a: a i) aa);
starttag = head + ">";
endtag = "</" + etype + ">";
onlytag = head + "/>";
in
if isNull body
then indentLine i onlytag
else if isString body
then if body == ""
then indentLine i onlytag
else indentLine i (starttag + escapeText body + endtag)
else if isList body
then
let
contents = many body (i + 1);
in
if contents == ""
then indentLine i onlytag
else
indentLine i starttag +
contents +
indentLine i endtag
else throw ("expected null, text, or list; found " + builtins.typeOf body)
;
toText = e: e 0;
in
{
inherit none opt many attr elem toText;
}