Remove obsolete eMMC provisioning scripts and documentation for reTerminal DM4, including udev rules, flash trigger scripts, and related guides.

This commit is contained in:
nearxos
2026-02-18 10:27:23 +02:00
parent d6b09cdd6f
commit 21fc0e8fd2
15 changed files with 337 additions and 38 deletions

View File

@@ -1,17 +1,44 @@
# reTerminal DM4 eMMC auto-provisioning
# reTerminal DM4 eMMC provisioning
Automatically flash a **golden image** to the CM4 eMMC when the reTerminal is connected in **boot mode** (eMMC disable jumper). Optional **backup** mode saves the current eMMC to a timestamped image file instead. Uses **cloud-init** for first-boot configuration.
Automatically **deploy** or **backup** the CM4 eMMC when the reTerminal is connected in **USB boot mode** or when it **boots over the network**. Uses **cloud-init** for first-boot configuration.
| File | Purpose |
|------|--------|
| **EMMC-PROVISIONING-GUIDE.md** | Full setup and usage guide read this first. |
| **flash-emmc-on-connect.sh** | Script that runs `rpiboot` then either flashes the golden image to eMMC or backs up eMMC to a file (mode set via dashboard or `mode` file). |
| **cm4-flash-trigger.sh** | Called by udev when CM4 in boot mode is connected; starts the flash job. |
| **90-cm4-boot-mode.rules** | udev rule: when USB device 2b8e is added, run the trigger script. |
| **cloud-init/** | Example NoCloud files (`user-data`, `meta-data`, `network-config`) for the golden image. |
| **dashboard/** | Flask web UI: auto-detect device (USB or network), prompt **Backup or Deploy**, show status and connection steps. See **dashboard/README.md**. |
| **network-client/** | Script for network-booted devices: register with the dashboard and perform Deploy (pull image, write eMMC) or Backup (upload eMMC). See **network-client/README.md**. |
---
Quick start: see **EMMC-PROVISIONING-GUIDE.md**.
## Project layout
**Proxmox:** LXC 201 + host setup is documented in **PROXMOX-LXC-DEPLOYMENT.md**. Use **scripts/deploy-to-proxmox.sh** to deploy to a Proxmox host; flash runs on the host, golden image is in a bind-mounted dir shared with the LXC.
```
emmc-provisioning/
├── README.md ← You are here
├── docs/ Documentation
│ ├── EMMC-PROVISIONING-GUIDE.md Full setup and usage
│ ├── PROXMOX-LXC-DEPLOYMENT.md Proxmox LXC + host setup
│ └── PORTAL_STYLING_GUIDE.md Dashboard UI styling reference
├── host/ Scripts that run on the provisioning host (Proxmox host)
│ ├── flash-emmc-on-connect.sh rpiboot + wait for Backup/Deploy choice, then dd
│ ├── cm4-flash-trigger.sh Called by udev; starts the flash job
│ └── 90-cm4-boot-mode.rules udev rule (USB vendor 2b8e)
├── scripts/ Deployment and one-off scripts
│ ├── deploy-to-proxmox.sh Deploy to Proxmox host + LXC 201
│ └── install-usbboot-on-host.sh Build and install rpiboot on the host
├── dashboard/ Flask web UI (runs in LXC or standalone)
│ ├── app.py
│ ├── templates/
│ ├── cm4-dashboard.service
│ └── README.md
├── cloud-init/ Example NoCloud files for the golden image
│ ├── user-data
│ ├── meta-data
│ └── network-config
└── network-client/ For network-booted devices
├── provisioning-client.sh Register + poll, then Deploy or Backup
└── README.md
```
---
## Quick start
1. **Read** [docs/EMMC-PROVISIONING-GUIDE.md](docs/EMMC-PROVISIONING-GUIDE.md) for setup and usage.
2. **Proxmox:** Use [scripts/deploy-to-proxmox.sh](scripts/deploy-to-proxmox.sh) to deploy to a Proxmox host; see [docs/PROXMOX-LXC-DEPLOYMENT.md](docs/PROXMOX-LXC-DEPLOYMENT.md).
3. **Manual host:** Copy scripts from `host/` to the host and install the udev rule (see the guide).
4. Put **golden.img** in `/var/lib/cm4-provisioning/` (or your configured path). When a device is detected (USB or network), the **dashboard** asks **Backup** or **Deploy**.

View File

@@ -48,8 +48,8 @@ sudo cp rpiboot /opt/usbboot/
#### 3. Install the auto-flash script and trigger
```bash
# From this repo (chromium-setup/emmc-provisioning/)
SCRIPT_DIR="$(pwd)"
# From this repo (chromium-setup/emmc-provisioning/host/)
cd chromium-setup/emmc-provisioning/host
sudo mkdir -p /opt/cm4-provisioning
sudo cp flash-emmc-on-connect.sh /opt/cm4-provisioning/
@@ -69,6 +69,7 @@ If your golden image path or rpiboot path is different, set `GOLDEN_IMAGE`, `RPI
#### 4. Install udev rule
```bash
# From emmc-provisioning/host/
sudo cp 90-cm4-boot-mode.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

View File

@@ -57,7 +57,27 @@ bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh
This installs dependencies, clones usbboot, builds it, and copies `rpiboot` to `/opt/usbboot/`.
### 2. Put the golden image on the host (or in the LXC)
### 2. Enable root SSH and add your SSH key to LXC 201
No root password is set by default. To log in as root over SSH:
- **Option A Use the setup script (recommended):** From your machine (with SSH key and optional password):
```bash
# Add your default SSH key (~/.ssh/id_ed25519.pub or id_rsa.pub) and enable root SSH
./chromium-setup/emmc-provisioning/scripts/setup-lxc-ssh.sh root@10.130.60.224
# Or specify key file and set root password
ROOT_PASSWORD='YourPassword' ./chromium-setup/emmc-provisioning/scripts/setup-lxc-ssh.sh root@10.130.60.224 ~/.ssh/id_ed25519.pub
```
Then connect with `ssh root@<LXC-IP>` (script prints the IP). Get the IP anytime with:
`ssh root@10.130.60.224 "pct exec 201 -- hostname -I"`
- **Option B Manual:**
`ssh root@10.130.60.224` then `pct exec 201 -- bash` to get a shell in the container. Run `apt-get install -y openssh-server`, edit `/etc/ssh/sshd_config` to set `PermitRootLogin yes`, run `passwd` to set root password, add your key to `/root/.ssh/authorized_keys`, and restart `ssh`.
### 3. Put the golden image on the host (or in the LXC)
The image must be at **`/var/lib/cm4-provisioning/golden.img`** on the **host**. Because that directory is bind-mounted into the LXC, you can use either:
@@ -72,7 +92,7 @@ The image must be at **`/var/lib/cm4-provisioning/golden.img`** on the **host**.
# Copy to that path inside the container; it's the same as the host path.
```
### 3. Run the provisioning dashboard (optional)
### 4. Run the provisioning dashboard (optional)
The dashboard shows **connection steps** and **live deployment status** (idle / connecting / flashing / done / error) and a recent flash log. It reads the same `status.json` and `flash.log` that the hosts flash script writes (via the bind-mounted `/var/lib/cm4-provisioning`).
@@ -96,7 +116,7 @@ systemctl enable --now cm4-dashboard
Then open **http://&lt;LXC-201-IP&gt;:5000** (get the IP with `pct exec 201 -- hostname -I`). If the LXC is on a private network, set up port forwarding on the Proxmox host or use a reverse proxy so you can reach the dashboard from your browser.
### 4. Optional: disable or enable auto-flash
### 5. Optional: disable or enable auto-flash
- **Disable:**
`ssh root@10.130.60.224 "rm /etc/cm4-provisioning/enabled"`

View File

@@ -0,0 +1,11 @@
# Host-side provisioning scripts
These files run on the **provisioning host** (e.g. the Proxmox host where the reTerminal is connected via USB).
| File | Purpose |
|------|--------|
| **flash-emmc-on-connect.sh** | Runs `rpiboot`, detects eMMC, waits for dashboard choice (Backup/Deploy), then runs `dd`. Install to `/opt/cm4-provisioning/`. |
| **cm4-flash-trigger.sh** | Started by udev when USB device 2b8e is added. Launches the flash script via `systemd-run`. Install to `/usr/local/bin/`. |
| **90-cm4-boot-mode.rules** | udev rule: on USB add (vendor 2b8e), run the trigger. Install to `/etc/udev/rules.d/`. |
See [../docs/EMMC-PROVISIONING-GUIDE.md](../docs/EMMC-PROVISIONING-GUIDE.md) for full setup. The [deploy script](../scripts/deploy-to-proxmox.sh) copies these into place on the Proxmox host and LXC.

View File

@@ -55,9 +55,22 @@ if [[ ! -f "$GOLDEN_IMAGE" ]]; then
fi
RPIBOOT_BIN="$RPIBOOT_DIR/rpiboot"
# Gadget dir for CM4 (64-bit); fallback to mass-storage-gadget
RPIBOOT_GADGET=""
for d in "$RPIBOOT_DIR/mass-storage-gadget64" "$RPIBOOT_DIR/mass-storage-gadget"; do
if [[ -d "$d" ]]; then
RPIBOOT_GADGET="$d"
break
fi
done
if [[ ! -x "$RPIBOOT_BIN" ]]; then
log "rpiboot not found: $RPIBOOT_BIN (build usbboot and set RPIBOOT_DIR)"
write_status "error" "rpiboot not installed" "null" "rpiboot not found. Run install-usbboot-on-host.sh on the host."
write_status "error" "rpiboot not installed" "null" "rpiboot not found. Run install-usbboot-on-host.sh on the host or build-and-deploy-usbboot-to-host.sh from your machine."
exit 1
fi
if [[ -z "$RPIBOOT_GADGET" ]]; then
log "rpiboot gadget dir not found under $RPIBOOT_DIR (need mass-storage-gadget64 or mass-storage-gadget)"
write_status "error" "rpiboot gadget missing" "null" "Copy mass-storage-gadget(64) to $RPIBOOT_DIR"
exit 1
fi
@@ -69,7 +82,7 @@ write_status "rpiboot" "Connecting to CM4 in boot mode…" "0"
before_devs=$(lsblk -nd -o NAME 2>/dev/null | sort)
log "Starting rpiboot to expose CM4 eMMC as mass storage..."
if ! "$RPIBOOT_BIN"; then
if ! "$RPIBOOT_BIN" -d "$RPIBOOT_GADGET"; then
log "rpiboot failed or no device connected"
write_status "error" "rpiboot failed" "null" "rpiboot failed or no device connected"
exit 1

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Build usbboot (rpiboot) on THIS machine (e.g. Fedora) and deploy to the Proxmox host.
# Use this when the host has no internet. Requires: dnf (Fedora) or apt (Debian/Ubuntu), git, ssh to host.
# Usage: ./build-and-deploy-usbboot-to-host.sh [proxmox_host]
# Example: ./build-and-deploy-usbboot-to-host.sh root@10.130.60.224
set -e
PROXMOX="${1:-root@10.130.60.224}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="/tmp/usbboot-build-$$"
cleanup() { rm -rf "$BUILD_DIR"; }
trap cleanup EXIT
echo "[$(date -Iseconds)] Building usbboot for host $PROXMOX ..."
# Install build deps (Fedora or Debian/Ubuntu)
if command -v dnf &>/dev/null; then
echo "Installing build deps (dnf)..."
sudo dnf install -y git libusb1-devel pkg-config glibc-devel gcc gcc-c++ make
elif command -v apt-get &>/dev/null; then
echo "Installing build deps (apt)..."
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y git libusb-1.0-0-dev pkg-config build-essential
else
echo "Error: need dnf or apt-get to install dependencies."
exit 1
fi
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
echo "Cloning usbboot (with submodules)..."
git clone --recurse-submodules --shallow-submodules --depth=1 https://github.com/raspberrypi/usbboot
cd usbboot
echo "Building..."
make
# Deploy: binary + gadget dir(s) to host /opt/usbboot
echo "[$(date -Iseconds)] Deploying to $PROXMOX:/opt/usbboot ..."
ssh "$PROXMOX" "mkdir -p /opt/usbboot"
rsync -a "$BUILD_DIR/usbboot/rpiboot" "$PROXMOX:/opt/usbboot/"
# CM4 needs mass-storage-gadget (64-bit); copy whichever exists
for dir in mass-storage-gadget64 mass-storage-gadget; do
if [[ -d "$BUILD_DIR/usbboot/$dir" ]]; then
rsync -a "$BUILD_DIR/usbboot/$dir" "$PROXMOX:/opt/usbboot/"
echo " Copied $dir/"
fi
done
ssh "$PROXMOX" "chmod +x /opt/usbboot/rpiboot"
echo "[$(date -Iseconds)] usbboot deployed to $PROXMOX:/opt/usbboot"
echo "Ensure the host flash script runs rpiboot with: -d /opt/usbboot/mass-storage-gadget64 (or mass-storage-gadget)."

View File

@@ -0,0 +1,24 @@
[2026-02-18T09:57:49+02:00] Logging to /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-095749.log
[2026-02-18T09:57:49+02:00] Deploying to root@10.130.60.224 ...
[2026-02-18T09:57:49+02:00] [1/4] Cleaning remote staging dir ...
[2026-02-18T09:57:50+02:00] [2/4] Rsync repo to root@10.130.60.224 ...
[2026-02-18T09:57:50+02:00] [3/4] Running remote install (host + LXC) ...
[2026-02-18T08:01:21+00:00] LXC 201 already exists.
[2026-02-18T08:01:21+00:00] Host: installing scripts and udev ...
[2026-02-18T08:01:22+00:00] Host: env and dirs ...
[2026-02-18T08:01:22+00:00] Starting LXC 201 if stopped ...
[2026-02-18T08:01:25+00:00] LXC: installing flash scripts ...
failed to create file: /opt/cm4-provisioning/: Is a directory
[2026-02-18T08:01:45+00:00] LXC: installing dashboard ...
failed to create file: /opt/cm4-provisioning/dashboard/: Is a directory
failed to create file: /opt/cm4-provisioning/dashboard/templates/: Is a directory
[2026-02-18T08:01:59+00:00] Deploy done (remote).
Next: Install usbboot on host when online: ssh <host> 'bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh'
Next: Enable dashboard in LXC 201: pct exec 201 -- bash -c 'apt-get install -y python3-flask; cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/; systemctl daemon-reload; systemctl enable --now cm4-dashboard'
failed to create file: /opt/cm4-provisioning/dashboard/: Is a directory
[2026-02-18T09:58:31+02:00] [4/4] Deploy finished.
Done. Put golden.img in /var/lib/cm4-provisioning/ on the host (or scp to LXC 201 at /var/lib/cm4-provisioning/).
When the host has internet, run on the host: bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh
Dashboard: install flask in LXC 201 and enable cm4-dashboard.service (see docs/PROXMOX-LXC-DEPLOYMENT.md).
Log written to: /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-095749.log

View File

@@ -0,0 +1,20 @@
[2026-02-18T09:58:59+02:00] Logging to /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-095859.log
[2026-02-18T09:58:59+02:00] Deploying to root@10.130.60.224 ...
[2026-02-18T09:58:59+02:00] [1/4] Cleaning remote staging dir ...
[2026-02-18T09:59:00+02:00] [2/4] Rsync repo to root@10.130.60.224 ...
[2026-02-18T09:59:00+02:00] [3/4] Running remote install (host + LXC) ...
[2026-02-18T08:02:32+00:00] LXC 201 already exists.
[2026-02-18T08:02:32+00:00] Host: installing scripts and udev ...
[2026-02-18T08:02:32+00:00] Host: env and dirs ...
[2026-02-18T08:02:32+00:00] Starting LXC 201 if stopped ...
[2026-02-18T08:02:35+00:00] LXC: installing flash scripts ...
[2026-02-18T08:02:55+00:00] LXC: installing dashboard ...
[2026-02-18T08:03:09+00:00] Deploy done (remote).
Next: Install usbboot on host when online: ssh <host> 'bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh'
Next: Enable dashboard in LXC 201: pct exec 201 -- bash -c 'apt-get install -y python3-flask; cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/; systemctl daemon-reload; systemctl enable --now cm4-dashboard'
[2026-02-18T09:59:41+02:00] [4/4] Deploy finished.
Done. Put golden.img in /var/lib/cm4-provisioning/ on the host (or scp to LXC 201 at /var/lib/cm4-provisioning/).
When the host has internet, run on the host: bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh
Dashboard: install flask in LXC 201 and enable cm4-dashboard.service (see docs/PROXMOX-LXC-DEPLOYMENT.md).
Log written to: /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-095859.log

View File

@@ -0,0 +1,20 @@
[2026-02-18T10:11:19+02:00] Logging to /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-101119.log
[2026-02-18T10:11:19+02:00] Deploying to root@10.130.60.224 ...
[2026-02-18T10:11:19+02:00] [1/4] Cleaning remote staging dir ...
[2026-02-18T10:11:20+02:00] [2/4] Rsync repo to root@10.130.60.224 ...
[2026-02-18T10:11:21+02:00] [3/4] Running remote install (host + LXC) ...
[2026-02-18T08:14:52+00:00] LXC 201 already exists.
[2026-02-18T08:14:52+00:00] Host: installing scripts and udev ...
[2026-02-18T08:14:52+00:00] Host: env and dirs ...
[2026-02-18T08:14:52+00:00] Starting LXC 201 if stopped ...
[2026-02-18T08:14:56+00:00] LXC: installing flash scripts ...
[2026-02-18T08:15:16+00:00] LXC: installing dashboard ...
[2026-02-18T08:15:30+00:00] Deploy done (remote).
Next: Install usbboot on host when online: ssh <host> 'bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh'
Next: Enable dashboard in LXC 201: pct exec 201 -- bash -c 'apt-get install -y python3-flask; cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/; systemctl daemon-reload; systemctl enable --now cm4-dashboard'
[2026-02-18T10:12:02+02:00] [4/4] Deploy finished.
Done. Put golden.img in /var/lib/cm4-provisioning/ on the host (or scp to LXC 201 at /var/lib/cm4-provisioning/).
When the host has internet, run on the host: bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh
Dashboard: install flask in LXC 201 and enable cm4-dashboard.service (see docs/PROXMOX-LXC-DEPLOYMENT.md).
Log written to: /home/nearxos/Projects/reTerminal DM4/chromium-setup/emmc-provisioning/scripts/deploy-20260218-101119.log

View File

@@ -3,39 +3,58 @@
# Usage: ./deploy-to-proxmox.sh [proxmox_host]
# Example: ./deploy-to-proxmox.sh root@10.130.60.224
# 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}"
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
echo "Deploying to $PROXMOX ..."
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" bash -s << 'REMOTE'
set -e
DEPLOY=/tmp/emmc-provisioning-deploy
log() { echo "[$(date -Iseconds)] $*"; }
# Ensure LXC 201 exists (create if not)
if ! pct status 201 &>/dev/null; then
echo "Creating LXC 201 (cm4-provisioning)..."
log "Creating LXC 201 (cm4-provisioning)..."
pct create 201 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
--hostname cm4-provisioning --memory 1024 --swap 0 --cores 1 \
--rootfs local-zfs: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
# Host: install scripts and udev
# Host: install scripts and udev (from host/)
log "Host: installing scripts and udev ..."
mkdir -p /opt/cm4-provisioning /etc/cm4-provisioning
cp "$DEPLOY/flash-emmc-on-connect.sh" /opt/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/cm4-flash-trigger.sh" /usr/local/bin/
cp "$DEPLOY/host/cm4-flash-trigger.sh" /usr/local/bin/
chmod +x /usr/local/bin/cm4-flash-trigger.sh
cp "$DEPLOY/90-cm4-boot-mode.rules" /etc/udev/rules.d/
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
@@ -45,26 +64,42 @@ touch /etc/cm4-provisioning/enabled
mkdir -p /var/lib/cm4-provisioning/backups
# Start LXC if stopped
log "Starting LXC 201 if stopped ..."
pct start 201 2>/dev/null || true
# LXC: install scripts
# 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/flash-emmc-on-connect.sh" /opt/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/cm4-flash-trigger.sh" /usr/local/bin/cm4-flash-trigger.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/
pct push 201 "$DEPLOY/dashboard/templates/index.html" /opt/cm4-provisioning/dashboard/templates/
pct push 201 "$DEPLOY/dashboard/cm4-dashboard.service" /opt/cm4-provisioning/dashboard/
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
echo "Deploy done. Install usbboot on host when online: ssh $PROXMOX 'bash /tmp/emmc-provisioning-deploy/scripts/install-usbboot-on-host.sh'"
echo "To enable the dashboard in LXC 201: pct exec 201 -- bash -c 'apt-get install -y python3-flask; cp /opt/cm4-provisioning/dashboard/cm4-dashboard.service /etc/systemd/system/; systemctl daemon-reload; systemctl enable --now cm4-dashboard'"
# 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/)."
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 PROXMOX-LXC-DEPLOYMENT.md)."
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

View File

@@ -1,15 +1,20 @@
#!/usr/bin/env bash
# Run on the Proxmox HOST (root) when the host has internet.
# Builds usbboot (rpiboot) and installs to /opt/usbboot so the auto-flash can run.
# If the host has no internet, run build-and-deploy-usbboot-to-host.sh from your Fedora machine instead.
set -e
apt-get update
apt-get install -y libusb-1.0-0-dev git
apt-get install -y libusb-1.0-0-dev git pkg-config build-essential
cd /tmp
rm -rf usbboot
git clone --depth=1 https://github.com/raspberrypi/usbboot
git clone --recurse-submodules --shallow-submodules --depth=1 https://github.com/raspberrypi/usbboot
cd usbboot
make
mkdir -p /opt/usbboot
cp rpiboot /opt/usbboot/
# Copy gadget dir(s) so rpiboot -d works
for dir in mass-storage-gadget64 mass-storage-gadget; do
[[ -d "$dir" ]] && cp -a "$dir" /opt/usbboot/
done
echo "usbboot installed at /opt/usbboot/rpiboot"

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# Enable root SSH login on LXC 201 (cm4-provisioning) and add your SSH key.
# Usage:
# ./setup-lxc-ssh.sh [proxmox_host] [ssh_public_key_file]
# ROOT_PASSWORD='yourpassword' ./setup-lxc-ssh.sh [proxmox_host] [ssh_public_key_file]
#
# Examples:
# ./setup-lxc-ssh.sh root@10.130.60.224
# ./setup-lxc-ssh.sh root@10.130.60.224 ~/.ssh/id_ed25519.pub
# ROOT_PASSWORD='MySecurePass' ./setup-lxc-ssh.sh root@10.130.60.224
#
# If ssh_public_key_file is omitted, uses ~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub.
set -e
PROXMOX="${1:-root@10.130.60.224}"
KEY_FILE="${2:-}"
CTID="${CTID:-201}"
# Find public key
if [[ -z "$KEY_FILE" ]]; then
for f in ~/.ssh/id_ed25519.pub ~/.ssh/id_rsa.pub; do
if [[ -f "$f" ]]; then
KEY_FILE="$f"
break
fi
done
fi
if [[ -z "$KEY_FILE" || ! -f "$KEY_FILE" ]]; then
echo "No SSH public key found. Usage: $0 [proxmox_host] [ssh_public_key_file]"
exit 1
fi
KEY_CONTENT=$(cat "$KEY_FILE")
ROOT_PASSWORD="${ROOT_PASSWORD:-}"
echo "Using key from: $KEY_FILE"
echo "Configuring LXC $CTID on $PROXMOX (enable SSH, root login, add key)..."
ssh "$PROXMOX" bash -s << REMOTE
set -e
CTID="$CTID"
KEY_CONTENT='$(echo "$KEY_CONTENT" | sed "s/'/'\\\\''/g")'
ROOT_PASSWORD='$(echo "$ROOT_PASSWORD" | sed "s/'/'\\\\''/g")'
# Ensure container is running
pct start \$CTID 2>/dev/null || true
sleep 2
# Install openssh-server if missing, enable and start
pct exec \$CTID -- bash -c 'apt-get update -qq && apt-get install -y -qq openssh-server 2>/dev/null; systemctl enable ssh 2>/dev/null; systemctl start ssh 2>/dev/null' || true
# Enable root login via password and/or public key
pct exec \$CTID -- bash -c '
sed -i "s/^#*PermitRootLogin.*/PermitRootLogin yes/" /etc/ssh/sshd_config 2>/dev/null || true
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
'
# Set root password if provided (pass via stdin so no quoting in -c)
if [[ -n "\$ROOT_PASSWORD" ]]; then
echo "root:\$ROOT_PASSWORD" | pct exec \$CTID -- chpasswd
echo "Root password set."
fi
# Add SSH key to root (pass key via stdin to avoid quoting issues)
echo "\$KEY_CONTENT" | pct exec \$CTID -- bash -c "mkdir -p /root/.ssh; chmod 700 /root/.ssh; cat >> /root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys"
echo "SSH key added to /root/.ssh/authorized_keys"
# Show IP for convenience
IP=\$(pct exec \$CTID -- hostname -I 2>/dev/null | awk '{print \$1}')
echo "Done. Connect with: ssh root@\$IP"
REMOTE