Files
reterminal-dm4/chromium-setup/emmc-provisioning/scripts/deploy-to-proxmox.sh

140 lines
7.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Deploy CM4 eMMC provisioning to a Proxmox host (creates LXC 201, installs scripts on host and in LXC).
# Usage: ./deploy-to-proxmox.sh [proxmox_host]
# Example: ./deploy-to-proxmox.sh root@10.130.60.224
# Optional: DEPLOY_ROOTFS_STORAGE=local-lvm (or local-zfs, etc.) — storage for LXC rootfs
# Optional: CM4_BACKUPS_HOST_PATH=/mnt/storage/cm4-backups — host dir for backup images; bind-mounted into LXC so images are stored on the host
# Requires: ssh key access to root@<host>
# Logging: set DEPLOY_LOG=1 to also write to deploy-YYYYMMDD-HHMMSS.log in the script dir.
set -e
PROXMOX="${1:-root@10.130.60.224}"
ROOTFS_STORAGE="${DEPLOY_ROOTFS_STORAGE:-local-lvm}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(dirname "$SCRIPT_DIR")"
LOG_FILE=""
if [[ -n "${DEPLOY_LOG:-}" ]]; then
LOG_FILE="$SCRIPT_DIR/deploy-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "[$(date -Iseconds)] Logging to $LOG_FILE"
fi
log() { echo "[$(date -Iseconds)] $*"; }
log "Deploying to $PROXMOX ..."
# Use a clean staging dir (remove if present so we never write into a symlink or bad state)
log "[1/4] Cleaning remote staging dir ..."
ssh "$PROXMOX" "rm -rf /tmp/emmc-provisioning-deploy"
log "[2/4] Rsync repo to $PROXMOX ..."
rsync -a "$REPO_DIR/" "$PROXMOX:/tmp/emmc-provisioning-deploy/" --exclude='.git' --exclude='scripts/deploy-to-proxmox.sh'
log "[3/4] Running remote install (host + LXC) ..."
ssh "$PROXMOX" "ROOTFS_STORAGE='$ROOTFS_STORAGE' CM4_BACKUPS_HOST_PATH='${CM4_BACKUPS_HOST_PATH:-}'" bash -s << 'REMOTE'
set -e
DEPLOY=/tmp/emmc-provisioning-deploy
ROOTFS_STORAGE="${ROOTFS_STORAGE:-local-lvm}"
BACKUPS_HOST_PATH="${CM4_BACKUPS_HOST_PATH:-}"
log() { echo "[$(date -Iseconds)] $*"; }
# Ensure LXC 201 exists (create if not)
if ! pct status 201 &>/dev/null; then
# Use Debian 12 template: prefer one in cache, else download latest
VZTMPL_DIR=/var/lib/vz/template/cache
DEBIAN12_TMPL=$(ls "$VZTMPL_DIR"/debian-12-standard_*.tar.zst 2>/dev/null | head -1)
if [[ -z "$DEBIAN12_TMPL" ]]; then
log "Downloading Debian 12 LXC template..."
pveam download local debian-12-standard_12.12-1_amd64.tar.zst || pveam download local debian-12-standard_12.7-1_amd64.tar.zst
DEBIAN12_TMPL=$(ls "$VZTMPL_DIR"/debian-12-standard_*.tar.zst 2>/dev/null | head -1)
fi
TMPL_NAME=$(basename "$DEBIAN12_TMPL")
log "Creating LXC 201 (cm4-provisioning) (rootfs on ${ROOTFS_STORAGE}, template ${TMPL_NAME})..."
pct create 201 "local:vztmpl/${TMPL_NAME}" \
--hostname cm4-provisioning --memory 1024 --swap 0 --cores 1 \
--rootfs "${ROOTFS_STORAGE}:8" --net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 0 --features nesting=1 -tag cm4-provisioning
mkdir -p /var/lib/cm4-provisioning
pct set 201 -mp0 /var/lib/cm4-provisioning,mp=/var/lib/cm4-provisioning
log "LXC 201 created and mount configured."
else
log "LXC 201 already exists."
fi
# Optional: bind-mount a host directory for backup images (so they are stored on the host, not LXC rootfs)
if [[ -n "$BACKUPS_HOST_PATH" ]]; then
mkdir -p "$BACKUPS_HOST_PATH"
pct stop 201 2>/dev/null || true
pct set 201 -mp1 "$BACKUPS_HOST_PATH",mp=/var/lib/cm4-provisioning/backups
pct start 201 2>/dev/null || true
log "Backups mount: host $BACKUPS_HOST_PATH -> LXC /var/lib/cm4-provisioning/backups"
fi
# Host: install scripts and udev (from host/)
log "Host: installing scripts and udev ..."
mkdir -p /opt/cm4-provisioning /etc/cm4-provisioning
cp "$DEPLOY/host/flash-emmc-on-connect.sh" /opt/cm4-provisioning/
chmod +x /opt/cm4-provisioning/flash-emmc-on-connect.sh
cp "$DEPLOY/host/build-cloudinit-image.sh" /opt/cm4-provisioning/
chmod +x /opt/cm4-provisioning/build-cloudinit-image.sh
cp "$DEPLOY/host/cm4-flash-trigger.sh" /usr/local/bin/
chmod +x /usr/local/bin/cm4-flash-trigger.sh
cp "$DEPLOY/host/cm4-flash.service" /etc/systemd/system/
cp "$DEPLOY/host/cm4-build-cloudinit.path" /etc/systemd/system/
cp "$DEPLOY/host/cm4-build-cloudinit.service" /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now cm4-build-cloudinit.path 2>/dev/null || true
cp "$DEPLOY/host/89-cm4-boot-mode-permissions.rules" /etc/udev/rules.d/ 2>/dev/null || true
cp "$DEPLOY/host/90-cm4-boot-mode.rules" /etc/udev/rules.d/
udevadm control --reload-rules
log "Host: env and dirs ..."
cat > /opt/cm4-provisioning/env << 'ENV'
GOLDEN_IMAGE=/var/lib/cm4-provisioning/golden.img
RPIBOOT_DIR=/opt/usbboot
EMMC_SIZE_BYTES=8589934592
ENV
[[ -n "$BACKUPS_HOST_PATH" ]] && echo "BACKUPS_DIR=$BACKUPS_HOST_PATH" >> /opt/cm4-provisioning/env
touch /etc/cm4-provisioning/enabled
mkdir -p /var/lib/cm4-provisioning/backups
[[ -n "$BACKUPS_HOST_PATH" ]] && mkdir -p "$BACKUPS_HOST_PATH"
# Start LXC if stopped
log "Starting LXC 201 if stopped ..."
pct start 201 2>/dev/null || true
# LXC: install scripts (from host/)
log "LXC: installing flash scripts ..."
pct exec 201 -- mkdir -p /opt/cm4-provisioning /etc/cm4-provisioning
pct push 201 "$DEPLOY/host/flash-emmc-on-connect.sh" /opt/cm4-provisioning/flash-emmc-on-connect.sh
pct exec 201 -- chmod +x /opt/cm4-provisioning/flash-emmc-on-connect.sh
pct push 201 "$DEPLOY/host/cm4-flash-trigger.sh" /usr/local/bin/cm4-flash-trigger.sh
pct exec 201 -- chmod +x /usr/local/bin/cm4-flash-trigger.sh
pct exec 201 -- bash -c 'echo -e "GOLDEN_IMAGE=/var/lib/cm4-provisioning/golden.img\nRPIBOOT_DIR=/opt/usbboot\nEMMC_SIZE_BYTES=8589934592" > /opt/cm4-provisioning/env'
# LXC: install dashboard
log "LXC: installing dashboard ..."
pct exec 201 -- mkdir -p /opt/cm4-provisioning/dashboard/templates
pct push 201 "$DEPLOY/dashboard/app.py" /opt/cm4-provisioning/dashboard/app.py
pct push 201 "$DEPLOY/dashboard/templates/index.html" /opt/cm4-provisioning/dashboard/templates/index.html
pct push 201 "$DEPLOY/dashboard/cm4-dashboard.service" /opt/cm4-provisioning/dashboard/cm4-dashboard.service
# LXC: install Flask and enable dashboard service
log "LXC: installing python3-flask and enabling cm4-dashboard service ..."
pct exec 201 -- bash -c 'apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3-flask'
pct exec 201 -- cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/
pct exec 201 -- systemctl daemon-reload
pct exec 201 -- systemctl enable --now cm4-dashboard
log "LXC: cm4-dashboard enabled and started."
log "Deploy done (remote)."
echo "Next: Install usbboot on host when online: ssh <host> 'bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh'"
REMOTE
log "[4/4] Deploy finished."
echo ""
echo "Done. Put golden.img in /var/lib/cm4-provisioning/ on the host (or scp to LXC 201 at /var/lib/cm4-provisioning/)."
[[ -n "${CM4_BACKUPS_HOST_PATH:-}" ]] && echo "Backup images are stored on the host at: $CM4_BACKUPS_HOST_PATH (bind-mounted into LXC at /var/lib/cm4-provisioning/backups)."
echo "When the host has internet, run on the host: bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh"
echo "Dashboard: install flask in LXC 201 and enable cm4-dashboard.service (see docs/PROXMOX-LXC-DEPLOYMENT.md)."
if [[ -n "$LOG_FILE" ]]; then
echo "Log written to: $LOG_FILE"
fi