USB
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
# Build output
|
||||||
|
output/
|
||||||
|
data/
|
||||||
|
|
||||||
|
# Nebula certificates and keys (user-provided secrets)
|
||||||
|
nebula/*.crt
|
||||||
|
nebula/*.key
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
FROM alpine:3.22
|
||||||
|
|
||||||
|
# Base tools
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
bash \
|
||||||
|
coreutils \
|
||||||
|
util-linux \
|
||||||
|
tar \
|
||||||
|
gzip \
|
||||||
|
xz \
|
||||||
|
cpio \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
ca-certificates \
|
||||||
|
rsync \
|
||||||
|
file \
|
||||||
|
grep \
|
||||||
|
gawk \
|
||||||
|
sed \
|
||||||
|
vim
|
||||||
|
|
||||||
|
# Filesystem + disk tools (needed by chroot-setup.sh and for Alpine install)
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
dosfstools \
|
||||||
|
e2fsprogs \
|
||||||
|
xfsprogs \
|
||||||
|
btrfs-progs \
|
||||||
|
parted \
|
||||||
|
sfdisk \
|
||||||
|
blkid \
|
||||||
|
lsblk \
|
||||||
|
wipefs \
|
||||||
|
util-linux-misc \
|
||||||
|
findmnt
|
||||||
|
|
||||||
|
# ISO + boot tools
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
xorriso \
|
||||||
|
syslinux \
|
||||||
|
mtools \
|
||||||
|
squashfs-tools \
|
||||||
|
libarchive-tools \
|
||||||
|
busybox-static
|
||||||
|
|
||||||
|
# GRUB (BIOS + EFI) — available if needed for alternative builds
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
grub \
|
||||||
|
grub-bios \
|
||||||
|
grub-efi \
|
||||||
|
efibootmgr
|
||||||
|
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
|
CMD ["/bin/bash"]
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
# Alpine Linux USB Rescue ISO
|
||||||
|
|
||||||
|
A bootable hybrid ISO that:
|
||||||
|
|
||||||
|
- Gets an IP via **DHCP on `eth0`**
|
||||||
|
- Automatically opens a **Nebula overlay tunnel**
|
||||||
|
- Runs **OpenSSH** (login: `root` / `alpine`)
|
||||||
|
- Carries all tools needed to **install Alpine onto the host machine** (`setup-alpine`, `setup-disk`, `parted`, …)
|
||||||
|
|
||||||
|
The ISO is a hybrid image — it can be written to a USB stick with `dd` *or* burned to a CD/DVD.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker + Docker Compose
|
||||||
|
- A Nebula certificate set for this node (see below)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Place Nebula certificates
|
||||||
|
|
||||||
|
Put the following files in `nebula/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
nebula/
|
||||||
|
nebula ← binary (already included)
|
||||||
|
config.yml ← already included, edit as needed
|
||||||
|
ca.crt ← your Nebula CA certificate ← YOU PROVIDE
|
||||||
|
host.crt ← this node's certificate ← YOU PROVIDE
|
||||||
|
host.key ← this node's private key ← YOU PROVIDE
|
||||||
|
```
|
||||||
|
|
||||||
|
`ca.crt`, `host.crt`, and `host.key` are gitignored.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Build the ISO
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose run --rm alpine bash /scripts/create.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The ISO is written to `output/rescue-alpine.iso`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Write to USB
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dd if=output/rescue-alpine.iso of=/dev/sdX bs=4M status=progress && sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `/dev/sdX` with your USB device (check with `lsblk`). **All data on the device will be erased.**
|
||||||
|
|
||||||
|
Or burn to CD/DVD:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cdrecord dev=/dev/sr0 output/rescue-alpine.iso
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Boot and connect
|
||||||
|
|
||||||
|
1. Insert USB and boot the target machine from it.
|
||||||
|
2. The system comes up fully in RAM — no writes to the host disk.
|
||||||
|
3. On boot, `eth0` gets an IP via DHCP, then the Nebula tunnel comes up automatically.
|
||||||
|
4. SSH in via the Nebula overlay IP (see `nebula/config.yml`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh root@<nebula-ip>
|
||||||
|
# password: alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Install Alpine onto the host machine
|
||||||
|
|
||||||
|
Once SSH'd in (or at the local console):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive guided installer — partitions disk, installs Alpine
|
||||||
|
setup-alpine
|
||||||
|
|
||||||
|
# Or use setup-disk for more control
|
||||||
|
setup-disk -m sys /dev/sda
|
||||||
|
```
|
||||||
|
|
||||||
|
All required tools (`parted`, `e2fsprogs`, `dosfstools`, `btrfs-progs`, `alpine-conf`, …) are pre-installed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Default credentials
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|----------|----------|
|
||||||
|
| Username | `root` |
|
||||||
|
| Password | `alpine` |
|
||||||
|
|
||||||
|
Change this in `scripts/chroot-setup.sh` before building if needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
ISO (hybrid — bootable on USB or CD)
|
||||||
|
└── isolinux (BIOS boot)
|
||||||
|
├── vmlinuz-lts
|
||||||
|
└── initramfs.gz ← entire Alpine system packed as cpio+gzip
|
||||||
|
├── eth0 DHCP (openrc networking)
|
||||||
|
├── nebula → /usr/local/bin/nebula
|
||||||
|
├── /etc/nebula/ (config + certs)
|
||||||
|
├── OpenSSH (sshd)
|
||||||
|
└── Alpine install tools
|
||||||
|
```
|
||||||
|
|
||||||
|
The system runs **entirely in RAM** — the host disk is never touched until you explicitly run the installer.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
docker compose run --rm alpine bash /scripts/create.sh
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
services:
|
||||||
|
alpine:
|
||||||
|
build: .
|
||||||
|
devices:
|
||||||
|
- /dev/loop-control:/dev/loop-control
|
||||||
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- ./data:/work
|
||||||
|
- ./scripts:/scripts:ro
|
||||||
|
- ./nebula:/nebula:ro
|
||||||
|
- ./output:/output
|
||||||
|
- /dev:/dev
|
||||||
|
working_dir: /work
|
||||||
|
tty: true
|
||||||
|
stdin_open: true
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
pki:
|
||||||
|
ca: /etc/nebula/ca.crt
|
||||||
|
cert: /etc/nebula/host.crt
|
||||||
|
key: /etc/nebula/host.key
|
||||||
|
static_host_map:
|
||||||
|
"192.168.9.1": ["167.71.79.60:4242"]
|
||||||
|
lighthouse:
|
||||||
|
am_lighthouse: false
|
||||||
|
interval: 60
|
||||||
|
hosts:
|
||||||
|
- "192.168.9.1"
|
||||||
|
listen:
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 4242
|
||||||
|
punchy:
|
||||||
|
punch: true
|
||||||
|
|
||||||
|
relay:
|
||||||
|
am_relay: false
|
||||||
|
use_relays: true
|
||||||
|
|
||||||
|
tun:
|
||||||
|
disabled: false
|
||||||
|
dev: nebula2
|
||||||
|
drop_local_broadcast: false
|
||||||
|
drop_multicast: false
|
||||||
|
tx_queue: 500
|
||||||
|
mtu: 1300
|
||||||
|
routes:
|
||||||
|
#- mtu: 8800
|
||||||
|
# route: 10.0.0.0/16
|
||||||
|
|
||||||
|
unsafe_routes:
|
||||||
|
logging:
|
||||||
|
level: info
|
||||||
|
format: text
|
||||||
|
firewall:
|
||||||
|
outbound_action: drop
|
||||||
|
inbound_action: drop
|
||||||
|
|
||||||
|
conntrack:
|
||||||
|
tcp_timeout: 12m
|
||||||
|
udp_timeout: 3m
|
||||||
|
default_timeout: 10m
|
||||||
|
|
||||||
|
outbound:
|
||||||
|
- port: any
|
||||||
|
proto: any
|
||||||
|
host: any
|
||||||
|
|
||||||
|
inbound:
|
||||||
|
- port: any #ping
|
||||||
|
proto: icmp
|
||||||
|
groups:
|
||||||
|
- admin
|
||||||
|
|
||||||
|
|
||||||
|
- port: 22 #GIT
|
||||||
|
proto: tcp
|
||||||
|
groups:
|
||||||
|
- admin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
BIN
Binary file not shown.
Executable
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# chroot-setup.sh — Runs inside the Alpine chroot to configure the system
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. APK repositories
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Configuring APK repositories"
|
||||||
|
cat > /etc/apk/repositories <<'EOF'
|
||||||
|
https://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
||||||
|
https://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
||||||
|
EOF
|
||||||
|
|
||||||
|
apk update
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Install packages
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Installing packages"
|
||||||
|
apk add --no-cache \
|
||||||
|
linux-lts \
|
||||||
|
mkinitfs \
|
||||||
|
openrc \
|
||||||
|
busybox \
|
||||||
|
musl \
|
||||||
|
libc-utils \
|
||||||
|
util-linux \
|
||||||
|
e2fsprogs \
|
||||||
|
dosfstools \
|
||||||
|
btrfs-progs \
|
||||||
|
parted \
|
||||||
|
sfdisk \
|
||||||
|
openssh \
|
||||||
|
dhcpcd \
|
||||||
|
iproute2 \
|
||||||
|
iputils \
|
||||||
|
net-tools \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
ca-certificates \
|
||||||
|
vim \
|
||||||
|
mc \
|
||||||
|
bind-tools \
|
||||||
|
nmap \
|
||||||
|
rsync \
|
||||||
|
alpine-conf
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3. Generate initramfs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Generating initramfs with mkinitfs"
|
||||||
|
mkinitfs $(ls /lib/modules/ | tail -1)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 4. Network configuration
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Configuring network interfaces"
|
||||||
|
mkdir -p /etc/network
|
||||||
|
cat > /etc/network/interfaces <<'EOF'
|
||||||
|
auto lo
|
||||||
|
iface lo inet loopback
|
||||||
|
|
||||||
|
auto eth0
|
||||||
|
iface eth0 inet dhcp
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 5. SSH configuration
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Configuring sshd"
|
||||||
|
sed -i \
|
||||||
|
-e 's/^#*\s*PermitRootLogin.*/PermitRootLogin yes/' \
|
||||||
|
-e 's/^#*\s*PasswordAuthentication.*/PasswordAuthentication yes/' \
|
||||||
|
/etc/ssh/sshd_config
|
||||||
|
|
||||||
|
# Ensure the directives exist if sed found nothing to replace
|
||||||
|
grep -q '^PermitRootLogin' /etc/ssh/sshd_config || echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
|
||||||
|
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
|
||||||
|
|
||||||
|
echo "==> Generating SSH host keys"
|
||||||
|
ssh-keygen -A
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 6. Root password
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Setting root password"
|
||||||
|
echo "root:alpine" | chpasswd
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 7. Nebula OpenRC service
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Creating /etc/init.d/nebula"
|
||||||
|
cat > /etc/init.d/nebula <<'EOF'
|
||||||
|
#!/sbin/openrc-run
|
||||||
|
description="Nebula overlay network"
|
||||||
|
command="/usr/local/bin/nebula"
|
||||||
|
command_args="-config /etc/nebula/config.yml"
|
||||||
|
command_background=true
|
||||||
|
pidfile="/run/nebula.pid"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need net
|
||||||
|
after networking
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
checkpath -f -m 0600 -o root:root /run/nebula.pid
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
chmod +x /etc/init.d/nebula
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 8. OpenRC service enablement
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Enabling services"
|
||||||
|
rc-update add sshd default
|
||||||
|
rc-update add networking default
|
||||||
|
rc-update add nebula default
|
||||||
|
|
||||||
|
# Also ensure basic boot services are present
|
||||||
|
rc-update add devfs sysinit || true
|
||||||
|
rc-update add dmesg sysinit || true
|
||||||
|
rc-update add mdev sysinit || true
|
||||||
|
rc-update add hwdrivers sysinit || true
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 9. Hostname
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Setting hostname to 'rescue'"
|
||||||
|
echo "rescue" > /etc/hostname
|
||||||
|
|
||||||
|
echo "==> chroot-setup.sh complete"
|
||||||
Executable
+211
@@ -0,0 +1,211 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# create.sh — Build a bootable Alpine Linux rescue ISO
|
||||||
|
#
|
||||||
|
# Run inside the Docker build container:
|
||||||
|
# docker compose run --rm alpine bash /scripts/create.sh
|
||||||
|
#
|
||||||
|
# The resulting ISO is a hybrid image: it can be burned to a CD/DVD or
|
||||||
|
# written directly to a USB stick with dd.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ALPINE_MIRROR="https://dl-cdn.alpinelinux.org/alpine"
|
||||||
|
ALPINE_BRANCH="latest-stable"
|
||||||
|
ALPINE_ARCH="x86_64"
|
||||||
|
MINIROOTFS_BASE="${ALPINE_MIRROR}/${ALPINE_BRANCH}/releases/${ALPINE_ARCH}"
|
||||||
|
|
||||||
|
ISO="/output/rescue-alpine.iso"
|
||||||
|
CHROOT="/mnt/alpine-chroot"
|
||||||
|
ISOROOT="/tmp/isoroot"
|
||||||
|
|
||||||
|
mkdir -p /output "$CHROOT" "$ISOROOT"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. Fetch latest Alpine minirootfs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Fetching latest Alpine minirootfs index"
|
||||||
|
TARBALL=$(curl -fsSL "${MINIROOTFS_BASE}/" \
|
||||||
|
| grep -oP 'alpine-minirootfs-[0-9.]+-x86_64\.tar\.gz' \
|
||||||
|
| sort -V | tail -1)
|
||||||
|
|
||||||
|
[[ -z "$TARBALL" ]] && { echo "ERROR: could not determine minirootfs tarball" >&2; exit 1; }
|
||||||
|
|
||||||
|
TARBALL_LOCAL="/tmp/${TARBALL}"
|
||||||
|
if [[ ! -f "$TARBALL_LOCAL" ]]; then
|
||||||
|
echo "==> Downloading ${MINIROOTFS_BASE}/${TARBALL}"
|
||||||
|
curl -fsSL -o "$TARBALL_LOCAL" "${MINIROOTFS_BASE}/${TARBALL}"
|
||||||
|
else
|
||||||
|
echo "==> Using cached ${TARBALL_LOCAL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Extract minirootfs into chroot
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Extracting minirootfs into ${CHROOT}"
|
||||||
|
tar -xzf "$TARBALL_LOCAL" -C "$CHROOT"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3. Copy Nebula binary and config into chroot
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Installing Nebula binary"
|
||||||
|
mkdir -p "${CHROOT}/usr/local/bin"
|
||||||
|
cp /nebula/nebula "${CHROOT}/usr/local/bin/nebula"
|
||||||
|
chmod +x "${CHROOT}/usr/local/bin/nebula"
|
||||||
|
|
||||||
|
echo "==> Installing Nebula config and certificates"
|
||||||
|
mkdir -p "${CHROOT}/etc/nebula"
|
||||||
|
cp /nebula/config.yml "${CHROOT}/etc/nebula/config.yml"
|
||||||
|
for f in /nebula/*.crt /nebula/*.key; do
|
||||||
|
[[ -f "$f" ]] && cp "$f" "${CHROOT}/etc/nebula/"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 4. Bind-mount virtual filesystems for chroot
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Bind-mounting virtual filesystems"
|
||||||
|
mount --bind /dev "${CHROOT}/dev"
|
||||||
|
mount --bind /proc "${CHROOT}/proc"
|
||||||
|
mount --bind /sys "${CHROOT}/sys"
|
||||||
|
mkdir -p "${CHROOT}/run"
|
||||||
|
mount --bind /run "${CHROOT}/run"
|
||||||
|
cp /etc/resolv.conf "${CHROOT}/etc/resolv.conf"
|
||||||
|
|
||||||
|
# Make scripts available inside chroot
|
||||||
|
mkdir -p "${CHROOT}/scripts"
|
||||||
|
mount --bind /scripts "${CHROOT}/scripts"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 5. Run in-chroot configuration
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Running chroot-setup.sh inside chroot"
|
||||||
|
chroot "$CHROOT" /bin/sh /scripts/chroot-setup.sh
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 6. Unmount virtual filesystems
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Unmounting virtual filesystems"
|
||||||
|
umount "${CHROOT}/scripts" || true
|
||||||
|
umount "${CHROOT}/run" || true
|
||||||
|
umount "${CHROOT}/sys" || true
|
||||||
|
umount "${CHROOT}/proc" || true
|
||||||
|
umount "${CHROOT}/dev" || true
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 7. Pack the full system as a squashfs (xz compressed)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Creating squashfs from chroot (xz — this may take a while)"
|
||||||
|
mksquashfs "$CHROOT" "${ISOROOT}/rootfs.squashfs" \
|
||||||
|
-comp xz -Xdict-size 100% -noappend \
|
||||||
|
-e boot/initramfs-lts 2>/dev/null || \
|
||||||
|
mksquashfs "$CHROOT" "${ISOROOT}/rootfs.squashfs" \
|
||||||
|
-comp xz -noappend
|
||||||
|
echo " squashfs size: $(du -sh "${ISOROOT}/rootfs.squashfs" | cut -f1)"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 8. Copy kernel into ISO root
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Copying kernel"
|
||||||
|
cp "${CHROOT}/boot/vmlinuz-lts" "${ISOROOT}/vmlinuz"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 9. Build tiny initramfs: busybox + init script that mounts the squashfs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Building tiny initramfs"
|
||||||
|
INITRD="/tmp/initrd"
|
||||||
|
rm -rf "$INITRD"
|
||||||
|
mkdir -p "${INITRD}"/{bin,dev,proc,sys,mnt/boot,mnt/squash,mnt/upper,mnt/work,mnt/newroot}
|
||||||
|
|
||||||
|
# Static busybox — no external library deps
|
||||||
|
BBOX=$(find /bin /usr/bin /usr/sbin -name 'busybox.static' -o -name 'busybox' 2>/dev/null \
|
||||||
|
| xargs -r file 2>/dev/null | grep -i 'statically linked' | cut -d: -f1 | head -1)
|
||||||
|
[[ -z "$BBOX" ]] && { echo "ERROR: cannot find a statically linked busybox" >&2; exit 1; }
|
||||||
|
echo " using static busybox: $BBOX"
|
||||||
|
cp "$BBOX" "${INITRD}/bin/busybox"
|
||||||
|
chmod +x "${INITRD}/bin/busybox"
|
||||||
|
for cmd in sh mount umount mkdir mknod switch_root mdev sleep; do
|
||||||
|
ln -sf busybox "${INITRD}/bin/${cmd}"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat > "${INITRD}/init" <<'INIT_EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
mount -t proc none /proc
|
||||||
|
mount -t sysfs none /sys
|
||||||
|
mount -t devtmpfs none /dev 2>/dev/null || mdev -s
|
||||||
|
|
||||||
|
# Scan block devices for the ISO containing rootfs.squashfs
|
||||||
|
found=0
|
||||||
|
for try in 1 2 3 4 5; do
|
||||||
|
for dev in /dev/sr0 /dev/sda /dev/sda1 /dev/sdb /dev/sdb1 /dev/sdc /dev/sdc1; do
|
||||||
|
[ -b "$dev" ] || continue
|
||||||
|
mount -t iso9660 -o ro "$dev" /mnt/boot 2>/dev/null || \
|
||||||
|
mount -o ro "$dev" /mnt/boot 2>/dev/null || continue
|
||||||
|
if [ -f /mnt/boot/rootfs.squashfs ]; then
|
||||||
|
found=1
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
umount /mnt/boot 2>/dev/null
|
||||||
|
done
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$found" != "1" ]; then
|
||||||
|
echo "ERROR: rootfs.squashfs not found — dropping to shell"
|
||||||
|
exec sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
mount -t squashfs -o ro /mnt/boot/rootfs.squashfs /mnt/squash
|
||||||
|
|
||||||
|
mount -t tmpfs tmpfs /mnt/upper
|
||||||
|
mkdir -p /mnt/upper/rw /mnt/upper/work
|
||||||
|
mount -t overlay overlay \
|
||||||
|
-o lowerdir=/mnt/squash,upperdir=/mnt/upper/rw,workdir=/mnt/upper/work \
|
||||||
|
/mnt/newroot
|
||||||
|
|
||||||
|
exec switch_root /mnt/newroot /sbin/init
|
||||||
|
INIT_EOF
|
||||||
|
chmod +x "${INITRD}/init"
|
||||||
|
|
||||||
|
( cd "$INITRD" && find . | cpio --quiet -oH newc | gzip -9 ) > "${ISOROOT}/initramfs.gz"
|
||||||
|
echo " initramfs size: $(du -sh "${ISOROOT}/initramfs.gz" | cut -f1)"
|
||||||
|
echo " initramfs contents:"
|
||||||
|
zcat "${ISOROOT}/initramfs.gz" | cpio -t 2>/dev/null
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 10. Build ISO with grub-mkrescue (BIOS + UEFI hybrid)
|
||||||
|
# grub-mkrescue uses its own file loader — no BIOS INT 13h size limits.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "==> Writing GRUB config"
|
||||||
|
mkdir -p "${ISOROOT}/boot/grub"
|
||||||
|
cat > "${ISOROOT}/boot/grub/grub.cfg" <<'EOF'
|
||||||
|
set timeout=5
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "Alpine Linux USB Rescue" {
|
||||||
|
linux /vmlinuz quiet init=/sbin/init
|
||||||
|
initrd /initramfs.gz
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "==> Building hybrid ISO with grub-mkrescue: ${ISO}"
|
||||||
|
grub-mkrescue -o "$ISO" "$ISOROOT" -- -V ALPINE_RESCUE
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Done
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
ISO_SIZE=$(du -sh "$ISO" | cut -f1)
|
||||||
|
echo ""
|
||||||
|
echo "================================================================"
|
||||||
|
echo " Build complete!"
|
||||||
|
echo " ISO : ${ISO} (${ISO_SIZE})"
|
||||||
|
echo ""
|
||||||
|
echo " Burn to USB:"
|
||||||
|
echo " dd if=${ISO} of=/dev/sdX bs=4M status=progress && sync"
|
||||||
|
echo ""
|
||||||
|
echo " Burn to CD/DVD:"
|
||||||
|
echo " cdrecord dev=/dev/sr0 ${ISO}"
|
||||||
|
echo ""
|
||||||
|
echo " Default login : root / alpine"
|
||||||
|
echo " Nebula tunnel : auto-starts on boot (needs certs in nebula/)"
|
||||||
|
echo "================================================================"
|
||||||
Reference in New Issue
Block a user