CASCADE/shell.nix

227 lines
6.2 KiB
Nix
Raw Normal View History

2022-09-24 03:24:58 +00:00
{ pkgs ? import <nixpkgs> {}, ... }:
let
vault_addr = "http://vault:8200";
in
with pkgs;
with lib;
stdenv.mkDerivation {
name = "commands-nix";
buildInputs = [ terraform vault coreutils-full dig bash samba4Full morph ];
shellHook = ''
export NIX_PATH="nixpkgs=${toString <nixpkgs>}:morph-options=${morph.lib}/options.nix"
2022-09-24 03:24:58 +00:00
export LD_LIBRARY_PATH="${libvirt}/lib:$LD_LIBRARY_PATH"
export VAULT_ADDR=${escapeShellArg vault_addr}
export DOMAIN="$(hostname -d)"
PROXMOX_STORAGE=hdd-fs
2022-09-24 03:24:58 +00:00
MEMORY=2048
rebuild-nixos-image() {
echo "$(nix-build custom-image.nix)/nixos".img
2022-09-24 03:24:58 +00:00
}
mkvirt() {
eval "$(env_cascade)" || return 3
eval "$(env_name "$1")" || return 4
if [ -f "./hosts/$name"".nix" ];then
1>&2 echo "there is already a file at ./hosts/$name"".nix. move it or remove it."
return 1
fi
cp "./hosts/_basic.nix" "./hosts/""$name"".nix"
morph build network.nix --on="$name" &
[ -f "result/nixos.img" ] || (
1>&2 echo "you do not seem to have a result/nixos.img file. building one now."
rebuild-nixos-image || errcho "could not build result/nixos.img." || return $?
)
[ -f "result/nixos.img" ] || errcho "there must be a file in result/nixos.img. make one with rebuild-nixos-image." || return $?
IMG="$(realpath result/nixos.img)"
[ -f "$IMG" ] || errcho "result/nixos.img must be resolveable to a file. rebuild the image link with rebuild-nixos-image." || return $?
[ $? -eq 0 ] || return 5
VMID=$(sudo pvesh get /cluster/nextid)
[ $? -eq 0 ] || return 6
sudo qm create $VMID \
--memory "$MEMORY" \
--net0 virtio,bridge=vmbr0 \
--ipconfig0 ip=dhcp \
--agent enabled=1,type=virtio \
--virtio0 "$PROXMOX_STORAGE":0,import-from="$IMG",discard=on,format=raw \
2022-09-24 03:24:58 +00:00
--boot c \
--bootdisk virtio0 \
--vga serial0 \
--serial0 socket \
--name "$name" \
--start 1
[ $? -eq 0 ] || return 7
IP="$(wait-for-vm-ipv4 $VMID)"
[ $? -eq 0 ] || return 8
samba-create-ipv4-records "$IP" "$name" "$DOMAIN"
[ $? -eq 0 ] || return 9
1>&2 echo "removing any stale ssh keys"
2022-09-24 16:42:31 +00:00
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "$name"
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "$name.$DOMAIN"
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "$IP"
2022-09-24 03:24:58 +00:00
1>&2 echo "scanning for new ssh keys"
# head -1 allows us to grab the ed25519 key before the rsa key.
# at worst, it will yield a single key of some sort which is also fine.
(
echo
ssh-keyscan "$IP" | sort | head -1
echo
ssh-keyscan "$name" | sort | head -1
echo
ssh-keyscan "$name.$DOMAIN" | sort | head -1
echo
) 2> /dev/null >> ~/.ssh/known_hosts
1>&2 echo "waiting for morph build to finish"
wait
1>&2 echo "morphing host"
morph deploy network.nix switch --on="$name"
}
samba-create-ipv4-records() {
eval "$(env_cascade)"
IP="$1"
HOST="$2"
:;:;:;:;:;:;:;:;: ;_IP_R="$IP"
IP1="''${_IP_R%%.*}";_IP_R="''${_IP_R#*.}"
IP2="''${_IP_R%%.*}";_IP_R="''${_IP_R#*.}"
IP3="''${_IP_R%%.*}";_IP_R="''${_IP_R#*.}"
IP4="''${_IP_R}" ;_IP_R="''${_IP_R#*.}"
# at the end, the last fragment has no . so if we try to remove another dotted-quad/4,
# we simply get no changes. the _desired end state_ is to have _IP_R = IP4.
[ x"$IP4" = x"$_IP_R" ] || errcho "error parsing IPv4"
samba-tool dns cleanup -k yes "$DC" "$HOST"."$DOMAIN"
samba-tool dns add -k yes "$DC" "$DOMAIN" "$HOST" A "$IP"
samba-tool dns zonecreate "$DC" "$IP3.$IP2.$IP1.in-addr.arpa." -k yes || true
samba-tool dns add -k yes "$DC" "$IP3.$IP2.$IP1.in-addr.arpa." "$IP4.$IP3.$IP2.$IP1.in-addr.arpa." PTR "$HOST.$DOMAIN."
}
wait-for-vm-ipv4() {
set -x
VMID="$1"
while true;do
IP="$( sudo qm guest cmd $VMID network-get-interfaces | \
jq -r '
.[]
|select(.["hardware-address"] != "00:00:00:00:00:00")
|.["ip-addresses"] | select(.) | .[]
|select(.["ip-address-type"] == "ipv4")
|.["ip-address"]' \
2> /dev/null \
| grep -E '172|10|192' || true)"
if [ x != x"$IP" ];then
echo "$IP"
break
fi
sleep 1
done
set +x
}
env_cascade() {
DOMAIN="$(hostname -d)"
#calculate some other variables
REALM="$(echo "$DOMAIN" | tr a-z A-Z)"
WORKGROUP="$(echo "$DOMAIN" | cut -d . -f 1)"
#and recalculate others to fix caps
DOMAIN="$(echo "$REALM" | tr A-Z a-z)"
DC="$(dig +short -x "$(dig +short "$DOMAIN")")"
DC="''${DC%.}" # just in case, let's drop the absolution dot
workgroup="$(echo "$WORKGROUP" | tr A-Z a-z)"
WORKGROUP="$(echo "$workgroup" | tr a-z A-Z)"
printf '%q=%q\n' \
DOMAIN "$DOMAIN" \
REALM "$REALM" \
WORKGROUP "$WORKGROUP" \
DC "$DC" \
workgroup "$workgroup"
}
env_name() {
# protect thy stdout
(
exec 18>&1-
exec 1>&2
NAME="$1"
[ x"$NAME" != x ] || errcho "you need to provide a hostname"
exec 1>&18
printf '%q=%q\n' name "$(echo "$NAME" | tr A-Z a-z)"
printf '%q=%q\n' NAME "$(echo "$NAME" | tr a-z A-Z)"
)
}
errcho() {
RC=$?
if [ $RC -ne 0 ];then
1>&2 printf '%s\n' "$@"
return $RC
fi
}
guestbash() {
VMID="$1"
CMD="$2"
shift;shift
echo -n "$CMD" | sudo qm guest exec --pass-stdin=1 --timeout=300 "$VMID" -- /run/wrappers/bin/sudo -i bash -s "$@"
}
deploy() {
nix-build network.nix && morph build network.nix && morph deploy network.nix "$@"
}
destroy-host() {
eval "$(env_cascade)"
2022-09-24 03:24:58 +00:00
while [ $# -gt 0 ];do
eval "$(env_name "$1")"
VMID="$(sudo qm list | awk -v N="$1" '$2 == N {print $name}')"
2022-09-24 03:24:58 +00:00
echo "destroying hosts/$1.nix and VM #$VMID" 1>&2
sleep 1
sudo qm stop $VMID
sudo qm destroy $VMID
rm -f hosts/"$1".nix
samba-tool dns cleanup -k yes "$DC" "$name"."$DOMAIN"
2022-09-24 03:24:58 +00:00
shift
done
}
cat << EOF
Welcome! You've entered the cascade shell.
You may make a virt on the local proxmox host using:
mkvirt hostname-here
You may also register an existing host in DNS using:
samba-create-ipv4-records IP hostname-here
Then morph may be used to deploy:
# Create a hosts/hostname-here.nix file based on hosts/basic.nix.sample
deploy test # this is an alias which runs morph on network.nix.
deploy switch # the argument is the same as to morph deploy and nixos-rebuild
EOF
'';
}