Files
reterminal-dm4/emmc-provisioning/scripts/sync-portal-files-to-lxc.sh
nearxos 59f8ebe61d Remove obsolete bootstrap script and update example script for clarity</message>
<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.
2026-02-24 00:26:55 +02:00

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 "══════════════════════════════════════════════════════════════"