<message>Delete the existing bootstrap.sh script used for cloud-init first boot, as it is no longer needed. Update the bootstrap.sh.example script to provide clearer instructions for users on how to customize and deploy their own bootstrap script, ensuring better guidance for cloud-init integration. These changes streamline the provisioning process and enhance user experience.
136 lines
6.2 KiB
Bash
Executable File
136 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Revision: 4
|
|
# Sync portal (file server) content from the repo to the LXC.
|
|
#
|
|
# All files that first-boot.sh downloads live in cloud-init/fileserver/.
|
|
# This script rsyncs that folder to the LXC's portal-files directory so
|
|
# the dashboard /files/ endpoint serves them.
|
|
#
|
|
# Expected layout on the LXC after sync:
|
|
# /var/lib/cm4-provisioning/portal-files/
|
|
# ├── first-boot.sh ← cloud-init runcmd downloads this
|
|
# ├── first-boot.conf ← cloud-init runcmd downloads this (required)
|
|
# ├── first-boot.conf.example ← reference
|
|
# ├── bootstrap.sh ← user-data.bootstrap downloads this (main path)
|
|
# └── first-boot/ ← FILE_SERVER points here
|
|
# ├── steps/
|
|
# │ ├── 01-hostname.sh … 13-reboot.sh
|
|
# ├── start-chromium.sh
|
|
# ├── splash.png
|
|
# └── ...
|
|
#
|
|
# Usage: ./sync-portal-files-to-lxc.sh [user@lxc_ip]
|
|
# Example: ./sync-portal-files-to-lxc.sh root@10.130.60.141
|
|
|
|
set -e
|
|
LXC="${1:-root@10.130.60.141}"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
|
CLOUDINIT_DIR="$REPO_DIR/cloud-init"
|
|
FILESERVER_DIR="$CLOUDINIT_DIR/fileserver"
|
|
REMOTE_PORTAL="/var/lib/cm4-provisioning/portal-files"
|
|
REMOTE_FIRST_BOOT="${REMOTE_PORTAL}/first-boot"
|
|
|
|
# Files we sync to the portal root (outside first-boot/)
|
|
PORTAL_ROOT_FILES=(first-boot.sh first-boot.conf first-boot.conf.example bootstrap.sh)
|
|
|
|
# ── Validate local files ────────────────────────────────────────────────
|
|
if [[ ! -d "$FILESERVER_DIR" ]]; then
|
|
echo "Error: fileserver dir not found: $FILESERVER_DIR"
|
|
exit 1
|
|
fi
|
|
if [[ ! -f "$CLOUDINIT_DIR/first-boot.sh" ]]; then
|
|
echo "Error: first-boot.sh not found in $CLOUDINIT_DIR"
|
|
exit 1
|
|
fi
|
|
if [[ ! -f "$CLOUDINIT_DIR/first-boot.conf" ]]; then
|
|
echo "Warning: first-boot.conf not found — first-boot.sh requires it!"
|
|
fi
|
|
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ Sync portal files → $LXC"
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
|
|
# ── Ensure rsync on LXC ────────────────────────────────────────────────
|
|
ssh "$LXC" "command -v rsync >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y rsync)"
|
|
ssh "$LXC" "mkdir -p $REMOTE_FIRST_BOOT"
|
|
|
|
# ── Dry-run: show what will change ──────────────────────────────────────
|
|
echo "── Preview (dry-run) ──────────────────────────────────────────"
|
|
echo ""
|
|
echo "Portal root ($REMOTE_PORTAL/):"
|
|
for f in "${PORTAL_ROOT_FILES[@]}"; do
|
|
if [[ -f "$CLOUDINIT_DIR/$f" ]]; then
|
|
echo " ✓ $f"
|
|
else
|
|
echo " ✗ $f (not found locally, will skip)"
|
|
fi
|
|
done
|
|
echo ""
|
|
echo "first-boot/ assets ($REMOTE_FIRST_BOOT/):"
|
|
CHANGES=$(rsync -avzn --delete "$FILESERVER_DIR/" "$LXC:$REMOTE_FIRST_BOOT/" 2>&1 | grep -v '^\(sending\|sent\|total\|$\|building\|\.d\.\.\.\.\.\.\.\.\.\)' | head -40)
|
|
if [[ -z "$CHANGES" ]]; then
|
|
echo " (no changes)"
|
|
else
|
|
echo "$CHANGES" | sed 's/^/ /'
|
|
fi
|
|
echo ""
|
|
|
|
read -rp "Proceed with sync? [Y/n] " CONFIRM
|
|
CONFIRM="${CONFIRM:-Y}"
|
|
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
|
|
echo "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
# ── Sync portal root files ──────────────────────────────────────────────
|
|
echo ""
|
|
echo "── Syncing portal root files ──────────────────────────────────"
|
|
for f in "${PORTAL_ROOT_FILES[@]}"; do
|
|
if [[ -f "$CLOUDINIT_DIR/$f" ]]; then
|
|
rsync -avz "$CLOUDINIT_DIR/$f" "$LXC:$REMOTE_PORTAL/"
|
|
fi
|
|
done
|
|
|
|
# ── Sync fileserver/ → first-boot/ (with --delete) ──────────────────────
|
|
echo ""
|
|
echo "── Syncing fileserver/ → first-boot/ ──────────────────────────"
|
|
rsync -avz --delete "$FILESERVER_DIR/" "$LXC:$REMOTE_FIRST_BOOT/"
|
|
|
|
# ── Check for extra files in portal root ────────────────────────────────
|
|
echo ""
|
|
echo "── Checking for extra files in portal root ────────────────────"
|
|
|
|
REMOTE_FILES=$(ssh "$LXC" "find $REMOTE_PORTAL -maxdepth 1 -not -path $REMOTE_PORTAL -printf '%f\n' 2>/dev/null" | sort)
|
|
EXPECTED_FILES=$(printf '%s\n' "${PORTAL_ROOT_FILES[@]}" "first-boot" | sort -u)
|
|
EXTRA_FILES=$(comm -23 <(echo "$REMOTE_FILES") <(echo "$EXPECTED_FILES"))
|
|
|
|
if [[ -z "$EXTRA_FILES" ]]; then
|
|
echo " No extra files found. Portal root is clean."
|
|
else
|
|
echo " Extra files/folders found in $REMOTE_PORTAL/:"
|
|
echo "$EXTRA_FILES" | while read -r f; do
|
|
SIZE=$(ssh "$LXC" "du -sh '$REMOTE_PORTAL/$f' 2>/dev/null | cut -f1" 2>/dev/null || echo "?")
|
|
TYPE="file"
|
|
ssh "$LXC" "[ -d '$REMOTE_PORTAL/$f' ]" 2>/dev/null && TYPE="dir"
|
|
echo " $f ($TYPE, $SIZE)"
|
|
done
|
|
echo ""
|
|
read -rp " Remove extra files? [y/N] " REMOVE
|
|
if [[ "$REMOVE" =~ ^[Yy]$ ]]; then
|
|
echo "$EXTRA_FILES" | while read -r f; do
|
|
echo " Removing: $f"
|
|
ssh "$LXC" "rm -rf '$REMOTE_PORTAL/$f'"
|
|
done
|
|
echo " Done."
|
|
else
|
|
echo " Kept extra files."
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "══════════════════════════════════════════════════════════════"
|
|
echo "Done. Portal files at http://$(echo "$LXC" | cut -d@ -f2):5000/files/"
|
|
echo "══════════════════════════════════════════════════════════════"
|