main
1#!/usr/bin/env bash
2# Deploy an Alpine appliance image to a host.
3# Usage: ./alpine/deploy.sh <hostname> [update|flash]
4set -euo pipefail
5
6SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7HOST="${1:?Usage: $0 <hostname> [update|flash]}"
8ACTION="${2:-update}"
9IMAGE_DIR="$SCRIPT_DIR/images/$HOST"
10
11if [ ! -d "$IMAGE_DIR" ]; then
12 echo "Error: no image found for $HOST. Run build.sh first."
13 exit 1
14fi
15
16case "$ACTION" in
17 update)
18 echo "==> Deploying to $HOST via rsync"
19 echo "WARNING: This will update the boot partition. The host will need a reboot."
20 read -p "Continue? [y/N] " -n 1 -r
21 echo
22 [[ $REPLY =~ ^[Yy]$ ]] || exit 0
23
24 # Mount boot partition (diskless Alpine doesn't mount it by default)
25 ssh "root@${HOST}.vpn" "mkdir -p /boot && mount /dev/mmcblk0p1 /boot 2>/dev/null || true"
26
27 # Backup current files (A/B rollback)
28 ssh "root@${HOST}.vpn" "cp /boot/initramfs /boot/initramfs.prev 2>/dev/null || true"
29 ssh "root@${HOST}.vpn" "cp /boot/vmlinuz-rpi /boot/vmlinuz-rpi.prev 2>/dev/null || true"
30
31 # Deploy new files
32 rsync -Pv "$IMAGE_DIR/initramfs" "root@${HOST}.vpn:/boot/initramfs"
33 rsync -Pv "$IMAGE_DIR/vmlinuz-rpi" "root@${HOST}.vpn:/boot/vmlinuz-rpi" 2>/dev/null || true
34
35 # Unmount boot partition
36 ssh "root@${HOST}.vpn" "umount /boot"
37
38 echo "==> Deployed. Reboot $HOST to activate:"
39 echo " ssh root@${HOST}.vpn reboot"
40 echo ""
41 echo " To rollback: ssh root@${HOST}.vpn"
42 echo " mount -o remount,rw /boot"
43 echo " mv /boot/initramfs.prev /boot/initramfs"
44 echo " reboot"
45 ;;
46 flash)
47 echo "==> SD card flashing"
48 echo "Manual steps:"
49 echo " 1. Partition SD: 256MB FAT32 (boot, label=ALPINE) + 512MB ext4 (label=persist)"
50 echo " 2. Copy boot files from $IMAGE_DIR/ to FAT32 partition"
51 echo " 3. Copy SSH host key to persist: persist/ssh/ssh_host_ed25519_key"
52 echo " 4. Copy WireGuard key to persist: persist/wireguard/private.key"
53 ;;
54 *)
55 echo "Unknown action: $ACTION"
56 echo "Usage: $0 <hostname> [update|flash]"
57 exit 1
58 ;;
59esac