Install it at first logon from the Win32-OpenSSH zip on the seed ISO via Configure-Windows.ps1 -InstallOpenSSH, replacing the manual 05/06 batch files. The administrator public key now comes from the host (SSH_PUBLIC_KEY_FILE or ~/.ssh/id_*.pub) instead of being hardcoded. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
63 lines
2.5 KiB
Bash
Executable File
63 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
output="${1:-${script_dir}/seed.iso}"
|
|
arch="${2:-${VM_IMAGE_ARCH:-$(uname -m)}}"
|
|
case "$arch" in
|
|
arm64|aarch64) answer_arch=arm64 ;;
|
|
x86_64|amd64) answer_arch=amd64 ;;
|
|
*) printf 'Error: unsupported architecture: %s\n' "$arch" >&2; exit 1 ;;
|
|
esac
|
|
|
|
# The OpenSSH zip for the target architecture comes from the shared image
|
|
# helper, which downloads it when missing.
|
|
image_helper="${VM_IMAGE_HELPER:-$script_dir/../../vm-images/download-images.sh}"
|
|
openssh_zip="$(VM_IMAGE_ARCH="$answer_arch" "$image_helper" --print-path openssh-win)"
|
|
[[ -s "$openssh_zip" ]] || VM_IMAGE_ARCH="$answer_arch" "$image_helper" openssh-win
|
|
[[ -s "$openssh_zip" ]] || { printf 'Error: %s was not downloaded.\n' "$openssh_zip" >&2; exit 1; }
|
|
|
|
# The public key for administrator SSH login: SSH_PUBLIC_KEY_FILE, else the
|
|
# first default key of the invoking user. The guest skips it when absent.
|
|
ssh_key="${SSH_PUBLIC_KEY_FILE:-}"
|
|
if [[ -z "$ssh_key" ]]; then
|
|
for candidate in "$HOME"/.ssh/id_ed25519.pub "$HOME"/.ssh/id_ecdsa.pub "$HOME"/.ssh/id_rsa.pub; do
|
|
[[ -f "$candidate" ]] && { ssh_key="$candidate"; break; }
|
|
done
|
|
fi
|
|
[[ -z "$ssh_key" || -f "$ssh_key" ]] || { printf 'Error: %s does not exist.\n' "$ssh_key" >&2; exit 1; }
|
|
|
|
# The answer file's components name the processor architecture, so render a
|
|
# copy for the target architecture.
|
|
work_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$work_dir"' EXIT
|
|
sed "s/processorArchitecture=\"amd64\"/processorArchitecture=\"${answer_arch}\"/" \
|
|
"$script_dir/Autounattend.xml" >"$work_dir/Autounattend.xml"
|
|
|
|
seed_files=(
|
|
"$work_dir/Autounattend.xml"
|
|
"$script_dir/Configure-Windows.ps1"
|
|
"$openssh_zip"
|
|
)
|
|
if [[ -n "$ssh_key" ]]; then
|
|
cp -- "$ssh_key" "$work_dir/authorized_keys"
|
|
seed_files+=("$work_dir/authorized_keys")
|
|
fi
|
|
# Numbered installer scripts (10-Install-Git-Admin.bat, 20-..., in install order).
|
|
shopt -s nullglob
|
|
seed_files+=("$script_dir"/[0-9][0-9]-*.bat)
|
|
shopt -u nullglob
|
|
|
|
mkdir -p "$(dirname -- "$output")"
|
|
if command -v xorriso >/dev/null 2>&1; then
|
|
xorriso -as mkisofs -quiet -o "$output" -V CIDATA -J -r "${seed_files[@]}"
|
|
elif command -v genisoimage >/dev/null 2>&1; then
|
|
genisoimage -quiet -o "$output" -V CIDATA -J -r "${seed_files[@]}"
|
|
elif command -v mkisofs >/dev/null 2>&1; then
|
|
mkisofs -quiet -o "$output" -V CIDATA -J -r "${seed_files[@]}"
|
|
else
|
|
printf 'Error: install xorriso, genisoimage, or mkisofs.\n' >&2
|
|
exit 1
|
|
fi
|
|
printf 'Built Windows 11 answer-file ISO: %s\n' "$output"
|