Remove obsolete audio and buzzer control documentation files, including detailed guides and HTML interfaces, to streamline the repository and eliminate redundancy. This cleanup enhances maintainability and focuses on essential resources for the reTerminal DM4 audio and buzzer functionalities.
This commit is contained in:
387
emmc-provisioning/scripts/deploy-to-proxmox.sh
Executable file
387
emmc-provisioning/scripts/deploy-to-proxmox.sh
Executable file
@@ -0,0 +1,387 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy CM4 eMMC provisioning to a Proxmox host: host scripts, udev, systemd units,
|
||||
# LXC container (dashboard), usbboot (rpiboot), and PiShrink. Uses hostname "cm4-provisioning"
|
||||
# to find the container on redeploy; creates with next available ID if not found.
|
||||
#
|
||||
# Redeploy (re-run) behaviour: checks first if the cm4-provisioning container exists;
|
||||
# if so, skips storage selection. Skips other steps that are already configured so you
|
||||
# can update only what changed. Always updates: host scripts, dashboard files, env,
|
||||
# systemd/udev. Skips when present: LXC creation, backups bind-mount (if same path),
|
||||
# usbboot, PiShrink, LXC python3-flask and openssh-server apt installs. Set
|
||||
# DEPLOY_ROOTFS_STORAGE to avoid storage prompt on first deploy (when container is new).
|
||||
#
|
||||
# With host internet: installs usbboot and PiShrink so USB flash/backup and dashboard
|
||||
# Shrink/Compress work. The only manual step left is to add a golden image for Deploy.
|
||||
#
|
||||
# Usage: ./deploy-to-proxmox.sh [proxmox_host]
|
||||
# Example: ./deploy-to-proxmox.sh root@10.20.30.152
|
||||
#
|
||||
# Optional env:
|
||||
# DEPLOY_ROOTFS_STORAGE=name — LXC rootfs storage (if set and valid, skips interactive choice; otherwise script lists storages and asks for number)
|
||||
# CM4_BACKUPS_HOST_PATH=/path — host dir for backups; bind-mounted into LXC
|
||||
# DEPLOY_LXC_ROOT_PASSWORD=secret — set root password in LXC and enable SSH
|
||||
# DEPLOY_LXC_SSH_KEY=/path/to/pub — copy this key to LXC root (default: ~/.ssh/id_ed25519.pub or id_rsa.pub)
|
||||
# DEPLOY_LOG=1 — also log to deploy-YYYYMMDD-HHMMSS.log
|
||||
#
|
||||
# Requires: ssh key access to root@<host>. For full install (usbboot, PiShrink), host needs internet.
|
||||
|
||||
set -e
|
||||
PROXMOX="${1:-root@10.130.60.224}"
|
||||
# ROOTFS_STORAGE set later: from DEPLOY_ROOTFS_STORAGE (if in host list) or from interactive choice
|
||||
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)] $*"; }
|
||||
|
||||
# Optional: gather SSH key and LXC root password for setup inside deploy
|
||||
# Default LXC root password (base64); override with DEPLOY_LXC_ROOT_PASSWORD. Not secure if repo is shared.
|
||||
DEFAULT_LXC_PWD_B64="c2gxcGIweDE="
|
||||
DEPLOY_SSH_KEY_B64=""
|
||||
DEPLOY_LXC_PWD_B64=""
|
||||
if [[ -n "${DEPLOY_LXC_ROOT_PASSWORD:-}" ]]; then
|
||||
DEPLOY_LXC_PWD_B64=$(echo -n "$DEPLOY_LXC_ROOT_PASSWORD" | base64 -w 0 2>/dev/null || base64 2>/dev/null | tr -d '\n')
|
||||
log "Will set LXC root password (from DEPLOY_LXC_ROOT_PASSWORD)."
|
||||
else
|
||||
DEPLOY_LXC_PWD_B64="$DEFAULT_LXC_PWD_B64"
|
||||
log "Will set LXC root password (default)."
|
||||
fi
|
||||
KEY_FILE="${DEPLOY_LXC_SSH_KEY:-}"
|
||||
if [[ -z "$KEY_FILE" ]]; then
|
||||
for f in ~/.ssh/id_ed25519.pub ~/.ssh/id_rsa.pub; do
|
||||
[[ -f "$f" ]] && { KEY_FILE="$f"; break; }
|
||||
done
|
||||
fi
|
||||
if [[ -n "$KEY_FILE" && -f "$KEY_FILE" ]]; then
|
||||
DEPLOY_SSH_KEY_B64=$(base64 -w 0 < "$KEY_FILE" 2>/dev/null || base64 < "$KEY_FILE" 2>/dev/null | tr -d '\n')
|
||||
log "Will copy SSH key to LXC: $KEY_FILE"
|
||||
fi
|
||||
|
||||
log "Deploying to $PROXMOX ..."
|
||||
log "[1/5] Checking if cm4-provisioning container exists and listing storage ..."
|
||||
REMOTE_CHECK=$(ssh "$PROXMOX" "bash -s" << 'REMOTECHECK'
|
||||
LXC_HOSTNAME="cm4-provisioning"
|
||||
LXC_EXISTS=0
|
||||
for id in $(pct list 2>/dev/null | awk 'NR>1 {print $1}'); do
|
||||
h=$(pct config "$id" 2>/dev/null | sed -n 's/^hostname: *//p')
|
||||
if [[ "$h" == "$LXC_HOSTNAME" ]]; then LXC_EXISTS=1; break; fi
|
||||
done
|
||||
echo "LXC_EXISTS=$LXC_EXISTS"
|
||||
pvesm status 2>/dev/null | awk 'NR>1 { sub(/^[ \t]+/, ""); if ($2!="pbs" && $3~/active/) print $1 }'
|
||||
REMOTECHECK
|
||||
)
|
||||
|
||||
first_line=
|
||||
storages=()
|
||||
while IFS= read -r line; do
|
||||
if [[ -z "$first_line" ]]; then
|
||||
first_line="$line"
|
||||
else
|
||||
[[ -n "$line" ]] && storages+=("$line")
|
||||
fi
|
||||
done <<< "$REMOTE_CHECK"
|
||||
|
||||
if [[ "$first_line" == "LXC_EXISTS=1" ]]; then
|
||||
LXC_ALREADY_EXISTS=1
|
||||
log "Container cm4-provisioning already exists; no storage selection needed."
|
||||
if [[ ${#storages[@]} -eq 0 ]]; then
|
||||
log "Error: no Proxmox storage found on host (needed for validation). Run on host: pvesm status"
|
||||
exit 1
|
||||
fi
|
||||
ROOTFS_STORAGE="${storages[0]}"
|
||||
log "Using storage $ROOTFS_STORAGE for validation only."
|
||||
else
|
||||
LXC_ALREADY_EXISTS=0
|
||||
if [[ ${#storages[@]} -eq 0 ]]; then
|
||||
log "Error: no Proxmox storage found on host (PBS excluded). Run on host: pvesm status"
|
||||
exit 1
|
||||
fi
|
||||
# --- Ask user to select LXC rootfs storage only when creating new container ---
|
||||
if [[ -n "${DEPLOY_ROOTFS_STORAGE:-}" ]]; then
|
||||
for s in "${storages[@]}"; do
|
||||
if [[ "$s" == "$DEPLOY_ROOTFS_STORAGE" ]]; then
|
||||
ROOTFS_STORAGE="$DEPLOY_ROOTFS_STORAGE"
|
||||
log "Using storage: $ROOTFS_STORAGE (from DEPLOY_ROOTFS_STORAGE)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ -z "${ROOTFS_STORAGE:-}" ]]; then
|
||||
echo ""
|
||||
echo "Available storage on $PROXMOX (PBS excluded):"
|
||||
for i in "${!storages[@]}"; do echo " $((i+1))) ${storages[i]}"; done
|
||||
echo ""
|
||||
if [[ ${#storages[@]} -eq 1 ]]; then
|
||||
ROOTFS_STORAGE="${storages[0]}"
|
||||
log "Using only available storage: $ROOTFS_STORAGE"
|
||||
elif [[ ! -t 0 ]]; then
|
||||
ROOTFS_STORAGE="${storages[0]}"
|
||||
log "No TTY: using first storage $ROOTFS_STORAGE"
|
||||
else
|
||||
while true; do
|
||||
read -r -p "Select storage (1-${#storages[@]}): " num
|
||||
if [[ "$num" =~ ^[0-9]+$ ]] && [[ "$num" -ge 1 ]] && [[ "$num" -le ${#storages[@]} ]]; then
|
||||
ROOTFS_STORAGE="${storages[num-1]}"
|
||||
log "Using storage: $ROOTFS_STORAGE"
|
||||
break
|
||||
fi
|
||||
echo "Invalid choice. Enter a number from 1 to ${#storages[@]}."
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
log "[2/5] Cleaning remote staging dir ..."
|
||||
ssh "$PROXMOX" "rm -rf /tmp/emmc-provisioning-deploy"
|
||||
log "[3/5] Rsync repo to $PROXMOX ..."
|
||||
rsync -a "$REPO_DIR/" "$PROXMOX:/tmp/emmc-provisioning-deploy/" --exclude='.git' --exclude='scripts/deploy-to-proxmox.sh' --exclude='scripts/deploy-*.log'
|
||||
|
||||
log "[4/5] Running remote install (host + LXC) ..."
|
||||
|
||||
# Pass optional LXC SSH vars (base64) and selected storage
|
||||
ssh "$PROXMOX" "ROOTFS_STORAGE='$ROOTFS_STORAGE' CM4_BACKUPS_HOST_PATH='${CM4_BACKUPS_HOST_PATH:-}' DEPLOY_SSH_KEY_B64='${DEPLOY_SSH_KEY_B64:-}' DEPLOY_LXC_PWD_B64='${DEPLOY_LXC_PWD_B64:-}'" bash -s << 'REMOTE'
|
||||
set -e
|
||||
DEPLOY=/tmp/emmc-provisioning-deploy
|
||||
ROOTFS_STORAGE="${ROOTFS_STORAGE:?ROOTFS_STORAGE not set}"
|
||||
BACKUPS_HOST_PATH="${CM4_BACKUPS_HOST_PATH:-}"
|
||||
LXC_HOSTNAME="cm4-provisioning"
|
||||
log() { echo "[$(date -Iseconds)] $*"; }
|
||||
|
||||
# Storage already chosen interactively; validate it exists on host (match by name + active, robust to column alignment)
|
||||
if ! pvesm status 2>/dev/null | grep -w "$ROOTFS_STORAGE" | grep -q active; then
|
||||
log "Error: storage $ROOTFS_STORAGE not found or not valid on host"
|
||||
exit 1
|
||||
fi
|
||||
log "Using storage: $ROOTFS_STORAGE"
|
||||
|
||||
# --- Find existing LXC by hostname or use next available ID ---
|
||||
CTID=""
|
||||
for id in $(pct list 2>/dev/null | awk 'NR>1 {print $1}'); do
|
||||
h=$(pct config "$id" 2>/dev/null | sed -n 's/^hostname: *//p')
|
||||
if [[ "$h" == "$LXC_HOSTNAME" ]]; then
|
||||
CTID="$id"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ -n "$CTID" ]]; then
|
||||
log "Found existing LXC $CTID (hostname: $LXC_HOSTNAME)."
|
||||
else
|
||||
MAX_ID=$(pct list 2>/dev/null | awk 'NR>1 {print $1}' | sort -n | tail -1)
|
||||
[[ -z "$MAX_ID" ]] && MAX_ID=0
|
||||
CTID=$((MAX_ID + 1))
|
||||
log "Creating LXC $CTID ($LXC_HOSTNAME) (rootfs on ${ROOTFS_STORAGE})..."
|
||||
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
|
||||
[[ -z "$DEBIAN12_TMPL" ]] && { log "Error: no Debian 12 template found"; exit 1; }
|
||||
TMPL_NAME=$(basename "$DEBIAN12_TMPL")
|
||||
# Optional: add eth1 for network-boot LAN (DHCP+TFTP). Set DEPLOY_LXC_NET1 e.g. "name=eth1,bridge=vmbr1,ip=10.20.50.1/24"
|
||||
NET1_OPT=""
|
||||
if [[ -n "${DEPLOY_LXC_NET1:-}" ]]; then
|
||||
NET1_OPT="--net1 $DEPLOY_LXC_NET1"
|
||||
fi
|
||||
pct create "$CTID" "local:vztmpl/${TMPL_NAME}" \
|
||||
--hostname "$LXC_HOSTNAME" --memory 1024 --swap 0 --cores 1 \
|
||||
--rootfs "${ROOTFS_STORAGE}:8" --net0 name=eth0,bridge=vmbr0,ip=dhcp $NET1_OPT \
|
||||
--unprivileged 0 --features nesting=1 -tag cm4-provisioning
|
||||
mkdir -p /var/lib/cm4-provisioning
|
||||
pct set "$CTID" -mp0 /var/lib/cm4-provisioning,mp=/var/lib/cm4-provisioning
|
||||
log "LXC $CTID created and mount configured."
|
||||
fi
|
||||
|
||||
# Optional: bind-mount host directory for backup images (skip if already mounted with same path)
|
||||
if [[ -n "$BACKUPS_HOST_PATH" ]]; then
|
||||
BACKUPS_PATH_NORM="${BACKUPS_HOST_PATH%/}"
|
||||
mkdir -p "$BACKUPS_HOST_PATH"
|
||||
CURRENT_MP1=$(pct config "$CTID" 2>/dev/null | sed -n 's/^mp1: *//p')
|
||||
NEED_MOUNT=1
|
||||
if [[ -n "$CURRENT_MP1" ]]; then
|
||||
if [[ "$CURRENT_MP1" == *"mp=/var/lib/cm4-provisioning/backups"* ]] && { [[ "$CURRENT_MP1" == *"$BACKUPS_PATH_NORM"* ]] || [[ "$CURRENT_MP1" == *"$BACKUPS_HOST_PATH"* ]]; }; then
|
||||
NEED_MOUNT=0
|
||||
log "Backups mount already configured (host $BACKUPS_PATH_NORM), skipping."
|
||||
fi
|
||||
fi
|
||||
if [[ "$NEED_MOUNT" -eq 1 ]]; then
|
||||
pct stop "$CTID" 2>/dev/null || true
|
||||
pct set "$CTID" -mp1 "$BACKUPS_HOST_PATH",mp=/var/lib/cm4-provisioning/backups
|
||||
pct start "$CTID" 2>/dev/null || true
|
||||
log "Backups mount: host $BACKUPS_HOST_PATH -> LXC $CTID /var/lib/cm4-provisioning/backups"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Host: scripts, systemd, udev (always update so changes are applied) ---
|
||||
HOST_PROV_EXISTS=0
|
||||
[[ -f /opt/cm4-provisioning/flash-emmc-on-connect.sh ]] && HOST_PROV_EXISTS=1
|
||||
if [[ "$HOST_PROV_EXISTS" -eq 1 ]]; then
|
||||
log "Host: updating scripts and systemd units (already configured) ..."
|
||||
else
|
||||
log "Host: installing scripts and systemd units ..."
|
||||
fi
|
||||
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/run-shrink-on-host.sh" /opt/cm4-provisioning/
|
||||
chmod +x /opt/cm4-provisioning/run-shrink-on-host.sh
|
||||
cp "$DEPLOY/scripts/fix-gadget-bootcode-on-host.sh" /opt/cm4-provisioning/ 2>/dev/null && chmod +x /opt/cm4-provisioning/fix-gadget-bootcode-on-host.sh || true
|
||||
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/
|
||||
cp "$DEPLOY/host/cm4-shrink.path" /etc/systemd/system/
|
||||
cp "$DEPLOY/host/cm4-shrink.service" /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now cm4-build-cloudinit.path 2>/dev/null || true
|
||||
systemctl enable --now cm4-shrink.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 2>/dev/null || true
|
||||
|
||||
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 /var/lib/cm4-provisioning/cloudinit-images /var/lib/cm4-provisioning/portal-files /var/lib/cm4-provisioning/download-cache
|
||||
[[ -n "$BACKUPS_HOST_PATH" ]] && mkdir -p "$BACKUPS_HOST_PATH"
|
||||
grep -q "CLOUDINIT_IMAGES_DIR" /opt/cm4-provisioning/env || echo "CLOUDINIT_IMAGES_DIR=/var/lib/cm4-provisioning/cloudinit-images" >> /opt/cm4-provisioning/env
|
||||
grep -q "CM4_DOWNLOAD_CACHE_DIR" /opt/cm4-provisioning/env || echo "CM4_DOWNLOAD_CACHE_DIR=/var/lib/cm4-provisioning/download-cache" >> /opt/cm4-provisioning/env
|
||||
|
||||
# --- Host: ensure xz-utils (and file) for cloud-init image build (decompress .img.xz) ---
|
||||
if command -v xz >/dev/null 2>&1; then
|
||||
log "Host: xz-utils already present, skipping."
|
||||
else
|
||||
log "Host: installing xz-utils and file (required for cloud-init image decompress)..."
|
||||
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq xz-utils file 2>/dev/null || log "Warning: could not install xz-utils (no internet?). Cloud-init build will fail at decompress until you run: apt install -y xz-utils file"
|
||||
fi
|
||||
|
||||
# --- Host: install usbboot (rpiboot) only if not already present ---
|
||||
if [[ -x /opt/usbboot/rpiboot ]] || [[ -f /opt/usbboot/rpiboot ]]; then
|
||||
log "Host: usbboot already installed at /opt/usbboot/rpiboot, skipping."
|
||||
else
|
||||
log "Host: installing usbboot (rpiboot)..."
|
||||
if bash "$DEPLOY/scripts/install-usbboot-on-host.sh" 2>&1; then
|
||||
log "Host: usbboot installed at /opt/usbboot/rpiboot"
|
||||
else
|
||||
log "Warning: usbboot install failed (e.g. no internet). USB flash/backup will not work until you run: bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Host: install PiShrink only if not already present ---
|
||||
if [[ -x /usr/local/bin/pishrink.sh ]] || [[ -f /usr/local/bin/pishrink.sh ]]; then
|
||||
log "Host: PiShrink already installed, skipping."
|
||||
grep -q "SHRINK_BACKUP" /opt/cm4-provisioning/env || echo "SHRINK_BACKUP=1" >> /opt/cm4-provisioning/env
|
||||
grep -q "PISHRINK_COMPRESS" /opt/cm4-provisioning/env || echo "PISHRINK_COMPRESS=xz" >> /opt/cm4-provisioning/env
|
||||
else
|
||||
log "Host: installing PiShrink..."
|
||||
if bash "$DEPLOY/scripts/install-pishrink-on-host.sh" 2>&1; then
|
||||
log "Host: PiShrink installed"
|
||||
grep -q "SHRINK_BACKUP" /opt/cm4-provisioning/env || echo "SHRINK_BACKUP=1" >> /opt/cm4-provisioning/env
|
||||
grep -q "PISHRINK_COMPRESS" /opt/cm4-provisioning/env || echo "PISHRINK_COMPRESS=xz" >> /opt/cm4-provisioning/env
|
||||
else
|
||||
log "Warning: PiShrink install failed (e.g. no internet). Dashboard Shrink/Compress will report 'PiShrink not installed' until you run: bash /tmp/emmc-provisioning-deploy/scripts/install-pishrink-on-host.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Start LXC if stopped ---
|
||||
log "Starting LXC $CTID if stopped ..."
|
||||
pct start "$CTID" 2>/dev/null || true
|
||||
|
||||
# --- LXC: flash scripts (for reference; actual flash runs on host) ---
|
||||
log "LXC: installing flash scripts ..."
|
||||
pct exec "$CTID" -- mkdir -p /opt/cm4-provisioning /etc/cm4-provisioning
|
||||
pct push "$CTID" "$DEPLOY/host/flash-emmc-on-connect.sh" /opt/cm4-provisioning/flash-emmc-on-connect.sh
|
||||
pct exec "$CTID" -- chmod +x /opt/cm4-provisioning/flash-emmc-on-connect.sh
|
||||
pct push "$CTID" "$DEPLOY/host/cm4-flash-trigger.sh" /usr/local/bin/cm4-flash-trigger.sh
|
||||
pct exec "$CTID" -- chmod +x /usr/local/bin/cm4-flash-trigger.sh
|
||||
pct exec "$CTID" -- 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: dashboard (all files) ---
|
||||
log "LXC: installing dashboard ..."
|
||||
pct exec "$CTID" -- mkdir -p /opt/cm4-provisioning/dashboard/templates
|
||||
pct push "$CTID" "$DEPLOY/dashboard/app.py" /opt/cm4-provisioning/dashboard/app.py
|
||||
pct push "$CTID" "$DEPLOY/dashboard/templates/home.html" /opt/cm4-provisioning/dashboard/templates/home.html
|
||||
pct push "$CTID" "$DEPLOY/dashboard/templates/login.html" /opt/cm4-provisioning/dashboard/templates/login.html
|
||||
pct push "$CTID" "$DEPLOY/dashboard/templates/admin.html" /opt/cm4-provisioning/dashboard/templates/admin.html
|
||||
pct push "$CTID" "$DEPLOY/dashboard/cm4-dashboard.service" /opt/cm4-provisioning/dashboard/cm4-dashboard.service
|
||||
# Dashboard secret for sessions (create once so logins persist across restarts)
|
||||
pct exec "$CTID" -- bash -c '[[ -f /opt/cm4-provisioning/dashboard.env ]] || echo "CM4_DASHBOARD_SECRET_KEY=$(openssl rand -hex 24 2>/dev/null || head -c 24 /dev/urandom | xxd -p)" > /opt/cm4-provisioning/dashboard.env'
|
||||
|
||||
# --- LXC: Flask and systemd (skip apt install if flask already present) ---
|
||||
if pct exec "$CTID" -- dpkg -l python3-flask 2>/dev/null | grep -q '^ii'; then
|
||||
log "LXC: python3-flask already installed, skipping apt install."
|
||||
else
|
||||
log "LXC: installing python3-flask ..."
|
||||
pct exec "$CTID" -- bash -c 'apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3-flask python3-werkzeug'
|
||||
fi
|
||||
pct exec "$CTID" -- cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/
|
||||
pct exec "$CTID" -- systemctl daemon-reload
|
||||
pct exec "$CTID" -- systemctl enable --now cm4-dashboard
|
||||
pct exec "$CTID" -- systemctl restart cm4-dashboard
|
||||
log "LXC: cm4-dashboard enabled and restarted (new code loaded)."
|
||||
|
||||
# --- LXC: optional SSH (root password + SSH key from deploy env) ---
|
||||
if [[ -n "${DEPLOY_SSH_KEY_B64:-}" ]] || [[ -n "${DEPLOY_LXC_PWD_B64:-}" ]]; then
|
||||
log "LXC: configuring SSH (root login, password, authorized_keys)..."
|
||||
if pct exec "$CTID" -- dpkg -l openssh-server 2>/dev/null | grep -q '^ii'; then
|
||||
log "LXC: openssh-server already installed, skipping apt install."
|
||||
else
|
||||
pct exec "$CTID" -- bash -c 'apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openssh-server 2>/dev/null' || true
|
||||
fi
|
||||
pct exec "$CTID" -- bash -c 'systemctl enable ssh 2>/dev/null; systemctl start ssh 2>/dev/null' || true
|
||||
pct exec "$CTID" -- bash -c 'sed -i "s/^#*PermitRootLogin.*/PermitRootLogin yes/" /etc/ssh/sshd_config 2>/dev/null; grep -q "^PermitRootLogin" /etc/ssh/sshd_config || echo "PermitRootLogin yes" >> /etc/ssh/sshd_config; systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null' || true
|
||||
if [[ -n "${DEPLOY_LXC_PWD_B64:-}" ]]; then
|
||||
PWD_RAW=$(echo "$DEPLOY_LXC_PWD_B64" | base64 -d 2>/dev/null)
|
||||
echo "root:$PWD_RAW" | pct exec "$CTID" -- chpasswd 2>/dev/null && log "LXC: root password set." || true
|
||||
fi
|
||||
if [[ -n "${DEPLOY_SSH_KEY_B64:-}" ]]; then
|
||||
echo "$DEPLOY_SSH_KEY_B64" | base64 -d 2>/dev/null | pct exec "$CTID" -- bash -c "mkdir -p /root/.ssh; chmod 700 /root/.ssh; cat >> /root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys" 2>/dev/null && log "LXC: SSH key added to /root/.ssh/authorized_keys." || true
|
||||
fi
|
||||
LXC_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}')
|
||||
[[ -n "$LXC_IP" ]] && log "LXC SSH: ssh root@$LXC_IP"
|
||||
fi
|
||||
# Always capture LXC IP for final summary (write so local script can read it)
|
||||
LXC_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}')
|
||||
echo "${LXC_IP:-}" > "$DEPLOY/lxc_ip.txt"
|
||||
|
||||
log "Deploy done on remote. LXC ID: $CTID"
|
||||
# Heredoc terminator (must be at column 1, no leading space/tab)
|
||||
REMOTE
|
||||
|
||||
# Read LXC IP written by remote (container hostname -I)
|
||||
LXC_IP=$(ssh "$PROXMOX" "cat /tmp/emmc-provisioning-deploy/lxc_ip.txt 2>/dev/null" | tr -d '\n\r')
|
||||
|
||||
log "[5/5] Deploy finished."
|
||||
echo ""
|
||||
echo "=== Deploy complete ==="
|
||||
echo "Host and LXC are fully set up: usbboot (rpiboot), PiShrink, dashboard, systemd, udev."
|
||||
[[ -n "$LXC_IP" ]] && echo " LXC IP: $LXC_IP"
|
||||
echo ""
|
||||
echo "--- Only remaining step (manual) ---"
|
||||
echo " Add a golden image for Deploy (writing image to device):"
|
||||
echo " • Dashboard: open http://${LXC_IP:-<LXC-IP>}:5000 → Build cloud-init image → then Set as golden"
|
||||
echo " • Or copy your image: scp your-image.img $PROXMOX:/var/lib/cm4-provisioning/golden.img"
|
||||
echo " Backup (read from device) works without golden.img."
|
||||
echo ""
|
||||
echo "--- You have ---"
|
||||
echo " - Dashboard: http://${LXC_IP:-<LXC-IP>}:5000"
|
||||
[[ -n "${DEPLOY_LXC_ROOT_PASSWORD:-}" || -n "${DEPLOY_SSH_KEY_B64:-}" ]] && [[ -n "$LXC_IP" ]] && echo " - LXC SSH: ssh root@$LXC_IP (password and/or key were set)"
|
||||
[[ -n "${DEPLOY_LXC_ROOT_PASSWORD:-}" || -n "${DEPLOY_SSH_KEY_B64:-}" ]] && [[ -z "$LXC_IP" ]] && echo " - LXC SSH: ssh root@<LXC-IP> (password and/or key were set)"
|
||||
[[ -n "${CM4_BACKUPS_HOST_PATH:-}" ]] && echo " - Backups on host: $CM4_BACKUPS_HOST_PATH"
|
||||
if [[ -n "$LOG_FILE" ]]; then
|
||||
echo " - Log: $LOG_FILE"
|
||||
fi
|
||||
Reference in New Issue
Block a user