#!/bin/bash # build-wsl2-image.sh — Configure WSL2 instance as governed jumphost # # Usage: # ./scripts/build-wsl2-image.sh # Configure current instance # ./scripts/build-wsl2-image.sh --export # Configure + export hint # # Idempotent: safe to run multiple times. No sudo required for gsh setup. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" GSH_DIR="$(dirname "$SCRIPT_DIR")" CORPUS_CID="sha256:dev-jumphost" CORPUS_DIR="$HOME/.gsh/corpus/$CORPUS_CID" echo "=== Guildhouse WSL2 Jumphost Builder ===" echo "" # ─── Step 1: System packages ───────────────────────────── echo "[1/7] Checking system packages..." MISSING="" for pkg in curl git jq openssh-client ca-certificates; do dpkg -s "$pkg" &>/dev/null || MISSING="$MISSING $pkg" done if [ -n "$MISSING" ]; then echo " Missing:$MISSING" if sudo -n true 2>/dev/null; then sudo apt-get update -qq sudo apt-get install -y -qq $MISSING 2>/dev/null else echo " Run: sudo apt-get install -y$MISSING" fi else echo " All present" fi # ─── Step 2: kubectl ───────────────────────────────────── echo "[2/7] kubectl..." if command -v kubectl &>/dev/null; then echo " $(kubectl version --client 2>/dev/null | head -1)" else echo " Installing kubectl..." curl -sLo "$HOME/.local/bin/kubectl" "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x "$HOME/.local/bin/kubectl" echo " Installed: $(kubectl version --client 2>/dev/null | head -1)" fi # ─── Step 3: helm ──────────────────────────────────────── echo "[3/7] helm..." if command -v helm &>/dev/null; then echo " $(helm version --short 2>/dev/null)" else echo " Installing helm..." curl -fsSL https://get.helm.sh/helm-v3.17.3-linux-amd64.tar.gz | tar xz -C /tmp linux-amd64/helm mv /tmp/linux-amd64/helm "$HOME/.local/bin/helm" chmod +x "$HOME/.local/bin/helm" rm -rf /tmp/linux-amd64 echo " Installed: $(helm version --short 2>/dev/null)" fi # ─── Step 4: gsh binary ───────────────────────────────── echo "[4/7] gsh..." if [ -f "$GSH_DIR/target/release/gsh" ]; then mkdir -p "$HOME/.local/bin" cp "$GSH_DIR/target/release/gsh" "$HOME/.local/bin/gsh" chmod +x "$HOME/.local/bin/gsh" echo " Installed to ~/.local/bin/gsh" elif command -v gsh &>/dev/null; then echo " Already on PATH: $(which gsh)" else echo " ERROR: gsh binary not found. Build first: cd ~/projects/gsh && cargo build --release" exit 1 fi # Ensure ~/.local/bin on PATH if ! echo "$PATH" | grep -q "$HOME/.local/bin"; then export PATH="$HOME/.local/bin:$PATH" fi # ─── Step 5: Corpus directory ──────────────────────────── echo "[5/7] Corpus..." mkdir -p "$CORPUS_DIR" for tool in kubectl helm; do REAL_PATH=$(which $tool 2>/dev/null || true) if [ -n "$REAL_PATH" ]; then # Symlink to the real binary (simpler than wrapper scripts) ln -sf "$REAL_PATH" "$CORPUS_DIR/$tool" 2>/dev/null || true echo " $tool → $REAL_PATH" fi done echo " Corpus at: $CORPUS_DIR" # ─── Step 6: SSH config ───────────────────────────────── echo "[6/7] SSH config..." mkdir -p "$HOME/.ssh" chmod 700 "$HOME/.ssh" # Generate SSH key if none exists if [ ! -f "$HOME/.ssh/id_ed25519" ]; then ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -N "" -q echo " Generated SSH key: ~/.ssh/id_ed25519" fi # Add gsh SSH aliases if not present add_ssh_host() { local name="$1" host="$2" port="$3" if ! grep -q "Host $name" "$HOME/.ssh/config" 2>/dev/null; then cat >> "$HOME/.ssh/config" << EOF Host $name HostName $host Port $port User \$(whoami) StrictHostKeyChecking no UserKnownHostsFile /dev/null EOF echo " Added: $name → $host:$port" else echo " Exists: $name" fi } touch "$HOME/.ssh/config" chmod 600 "$HOME/.ssh/config" add_ssh_host "dev.gsh" "127.0.0.1" "2223" add_ssh_host "stg.gsh" "178.104.110.197" "30222" # ─── Step 7: Environment + shell config ────────────────── echo "[7/7] Environment..." # .gshrc — governed shell defaults cat > "$HOME/.gshrc" << GSHRC # Guildhouse Governed Shell environment # Sourced by .bashrc export GSAP_CORPUS_CID="$CORPUS_CID" export GSH_CORPUS_DIR="\$HOME/.gsh/corpus" # Add gsh to PATH export PATH="\$HOME/.local/bin:\$PATH" GSHRC echo " Created ~/.gshrc" # Source from .bashrc if not already if ! grep -q "gshrc" "$HOME/.bashrc" 2>/dev/null; then echo '' >> "$HOME/.bashrc" echo '# Guildhouse governed shell' >> "$HOME/.bashrc" echo '[ -f ~/.gshrc ] && source ~/.gshrc' >> "$HOME/.bashrc" echo " Added .gshrc to .bashrc" fi # ─── Done ──────────────────────────────────────────────── echo "" echo "=== Jumphost configured ===" echo "" echo " gsh: $(which gsh 2>/dev/null || echo '~/.local/bin/gsh')" echo " kubectl: $(which kubectl)" echo " helm: $(which helm)" echo " corpus: $CORPUS_DIR/" echo "" echo "Connect:" echo " ssh dev.gsh — governed shell (local Docker Desktop)" echo " ssh stg.gsh — governed shell (Hetzner staging)" echo " gsh — local ungoverned shell" echo "" # ─── Optional: Export hint ─────────────────────────────── if [ "${1:-}" = "--export" ]; then echo "=== Export ===" echo "" echo "Clean build artifacts to reduce size:" echo " rm -rf ~/projects/gsh/target/debug" echo " rm -rf ~/projects/substrate-project/substrate/target/debug" echo " sudo apt-get clean" echo "" DISTRO_NAME=$(hostname 2>/dev/null || echo "gsh-jumphost") echo "From PowerShell:" echo " wsl --export $DISTRO_NAME gsh-jumphost.tar" echo "" echo "Import on another machine:" echo " wsl --import gsh-jumphost C:\\WSL\\gsh-jumphost gsh-jumphost.tar" echo " wsl -d gsh-jumphost" fi