347 lines
12 KiB
Docker
347 lines
12 KiB
Docker
|
|
# EcoOS ISO Builder
|
||
|
|
# Build from eco_os directory:
|
||
|
|
# docker build -t ecoos-builder -f isobuild/Dockerfile .
|
||
|
|
# docker run --privileged -v $(pwd)/isobuild/output:/output ecoos-builder
|
||
|
|
|
||
|
|
FROM ubuntu:24.04
|
||
|
|
|
||
|
|
ENV DEBIAN_FRONTEND=noninteractive
|
||
|
|
|
||
|
|
# Install build dependencies
|
||
|
|
RUN apt-get update && apt-get install -y \
|
||
|
|
live-build \
|
||
|
|
debootstrap \
|
||
|
|
xorriso \
|
||
|
|
squashfs-tools \
|
||
|
|
grub-efi-amd64-bin \
|
||
|
|
grub-efi-amd64-signed \
|
||
|
|
grub-pc-bin \
|
||
|
|
shim-signed \
|
||
|
|
mtools \
|
||
|
|
dosfstools \
|
||
|
|
syslinux-utils \
|
||
|
|
syslinux \
|
||
|
|
syslinux-common \
|
||
|
|
isolinux \
|
||
|
|
curl \
|
||
|
|
unzip \
|
||
|
|
git \
|
||
|
|
&& rm -rf /var/lib/apt/lists/* \
|
||
|
|
&& ln -sf /usr/bin/isohybrid /usr/local/bin/isohybrid 2>/dev/null || true
|
||
|
|
|
||
|
|
# Install Deno
|
||
|
|
RUN curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh
|
||
|
|
|
||
|
|
# Create build directory
|
||
|
|
WORKDIR /build
|
||
|
|
|
||
|
|
# Copy isobuild configuration
|
||
|
|
COPY isobuild/config/ /build/config/
|
||
|
|
COPY isobuild/scripts/ /build/scripts/
|
||
|
|
|
||
|
|
# Copy hooks to enable services (already in config/, but put in separate dir for build script)
|
||
|
|
COPY isobuild/config/hooks/ /build/hooks/
|
||
|
|
|
||
|
|
# Copy daemon source (for bundling)
|
||
|
|
COPY ecoos_daemon/ /daemon/
|
||
|
|
|
||
|
|
# Bundle the daemon
|
||
|
|
RUN cd /daemon && deno compile --allow-all --output /build/daemon-bundle/eco-daemon mod.ts
|
||
|
|
|
||
|
|
# Download Chromium during Docker build (network works here, not in chroot hooks)
|
||
|
|
RUN echo "Downloading Chromium from official snapshots..." && \
|
||
|
|
cd /tmp && \
|
||
|
|
LATEST=$(curl -fsSL "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2FLAST_CHANGE?alt=media" 2>/dev/null || echo "1368529") && \
|
||
|
|
echo "Using Chromium build: $LATEST" && \
|
||
|
|
curl -fsSL "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2F${LATEST}%2Fchrome-linux.zip?alt=media" -o chromium.zip || \
|
||
|
|
curl -fsSL "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2F1368529%2Fchrome-linux.zip?alt=media" -o chromium.zip && \
|
||
|
|
mkdir -p /build/chromium && \
|
||
|
|
unzip -q chromium.zip -d /tmp && \
|
||
|
|
mv /tmp/chrome-linux/* /build/chromium/ && \
|
||
|
|
rm -rf chromium.zip /tmp/chrome-linux && \
|
||
|
|
chmod +x /build/chromium/chrome && \
|
||
|
|
echo "Chromium downloaded to /build/chromium/"
|
||
|
|
|
||
|
|
# Make scripts executable
|
||
|
|
RUN chmod +x /build/scripts/*.sh
|
||
|
|
|
||
|
|
# Create dummy isohybrid for UEFI-only builds (real isohybrid needs BIOS boot record)
|
||
|
|
RUN echo '#!/bin/sh' > /usr/local/bin/isohybrid && \
|
||
|
|
echo 'echo "Skipping isohybrid (UEFI-only build)"' >> /usr/local/bin/isohybrid && \
|
||
|
|
echo 'exit 0' >> /usr/local/bin/isohybrid && \
|
||
|
|
chmod +x /usr/local/bin/isohybrid
|
||
|
|
|
||
|
|
# Build script
|
||
|
|
COPY <<'EOF' /build/docker-build.sh
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
export PATH="/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH"
|
||
|
|
|
||
|
|
echo "=== EcoOS ISO Builder (Docker) ==="
|
||
|
|
|
||
|
|
cd /build
|
||
|
|
|
||
|
|
# Initialize live-build - UEFI only (no syslinux/BIOS)
|
||
|
|
# Using German mirror for faster/more stable downloads
|
||
|
|
lb config \
|
||
|
|
--architectures amd64 \
|
||
|
|
--distribution noble \
|
||
|
|
--archive-areas "main restricted universe multiverse" \
|
||
|
|
--mirror-bootstrap "http://ftp.halifax.rwth-aachen.de/ubuntu/" \
|
||
|
|
--mirror-chroot "http://ftp.halifax.rwth-aachen.de/ubuntu/" \
|
||
|
|
--mirror-chroot-security "http://ftp.halifax.rwth-aachen.de/ubuntu/" \
|
||
|
|
--mirror-binary "http://ftp.halifax.rwth-aachen.de/ubuntu/" \
|
||
|
|
--mirror-binary-security "http://ftp.halifax.rwth-aachen.de/ubuntu/" \
|
||
|
|
--binary-images iso-hybrid \
|
||
|
|
--debian-installer false \
|
||
|
|
--memtest none \
|
||
|
|
--bootloader grub-efi \
|
||
|
|
--iso-application "EcoOS" \
|
||
|
|
--iso-publisher "EcoBridge" \
|
||
|
|
--iso-volume "EcoOS"
|
||
|
|
|
||
|
|
# Copy package lists
|
||
|
|
cp /build/config/live-build/package-lists/*.list.chroot config/package-lists/
|
||
|
|
|
||
|
|
# Prepare includes.chroot
|
||
|
|
mkdir -p config/includes.chroot/opt/eco/bin
|
||
|
|
mkdir -p config/includes.chroot/opt/eco/daemon
|
||
|
|
mkdir -p config/includes.chroot/etc/systemd/system
|
||
|
|
|
||
|
|
# Copy daemon bundle
|
||
|
|
cp /build/daemon-bundle/eco-daemon config/includes.chroot/opt/eco/bin/
|
||
|
|
chmod +x config/includes.chroot/opt/eco/bin/eco-daemon
|
||
|
|
|
||
|
|
# Copy pre-downloaded Chromium
|
||
|
|
echo "Installing pre-downloaded Chromium into chroot..."
|
||
|
|
mkdir -p config/includes.chroot/opt/chromium
|
||
|
|
cp -r /build/chromium/* config/includes.chroot/opt/chromium/
|
||
|
|
chmod +x config/includes.chroot/opt/chromium/chrome
|
||
|
|
|
||
|
|
# Create symlinks for chromium-browser command
|
||
|
|
mkdir -p config/includes.chroot/usr/bin
|
||
|
|
cat > config/includes.chroot/usr/bin/chromium-browser << 'CHROMEWRAPPER'
|
||
|
|
#!/bin/sh
|
||
|
|
exec /opt/chromium/chrome "$@"
|
||
|
|
CHROMEWRAPPER
|
||
|
|
chmod +x config/includes.chroot/usr/bin/chromium-browser
|
||
|
|
ln -sf /opt/chromium/chrome config/includes.chroot/usr/bin/chromium
|
||
|
|
echo "Chromium installed to /opt/chromium/"
|
||
|
|
|
||
|
|
# Create dummy isohybrid in chroot (UEFI-only, no BIOS boot record)
|
||
|
|
mkdir -p config/includes.chroot/usr/bin
|
||
|
|
cat > config/includes.chroot/usr/bin/isohybrid << 'ISOHYBRID'
|
||
|
|
#!/bin/sh
|
||
|
|
echo "Skipping isohybrid (UEFI-only build)"
|
||
|
|
exit 0
|
||
|
|
ISOHYBRID
|
||
|
|
chmod +x config/includes.chroot/usr/bin/isohybrid
|
||
|
|
|
||
|
|
# Copy systemd services
|
||
|
|
cp /build/config/systemd/eco-daemon.service config/includes.chroot/etc/systemd/system/
|
||
|
|
|
||
|
|
# Copy installer (files are already in config/includes.chroot via COPY)
|
||
|
|
chmod +x config/includes.chroot/opt/eco/installer/install.sh 2>/dev/null || true
|
||
|
|
|
||
|
|
# Copy hooks to enable services
|
||
|
|
mkdir -p config/hooks/normal
|
||
|
|
cp /build/hooks/normal/*.hook.chroot config/hooks/normal/
|
||
|
|
chmod +x config/hooks/normal/*.hook.chroot
|
||
|
|
|
||
|
|
# Copy autoinstall config
|
||
|
|
mkdir -p config/includes.binary/autoinstall
|
||
|
|
cp /build/config/autoinstall/user-data config/includes.binary/autoinstall/
|
||
|
|
touch config/includes.binary/autoinstall/meta-data
|
||
|
|
|
||
|
|
# Prepare EFI boot files in includes.binary
|
||
|
|
echo "Preparing EFI boot structure..."
|
||
|
|
mkdir -p config/includes.binary/EFI/BOOT
|
||
|
|
mkdir -p config/includes.binary/boot/grub
|
||
|
|
|
||
|
|
# Copy signed EFI files from host (installed in Docker image)
|
||
|
|
cp /usr/lib/shim/shimx64.efi.signed.latest config/includes.binary/EFI/BOOT/BOOTX64.EFI || \
|
||
|
|
cp /usr/lib/shim/shimx64.efi.signed config/includes.binary/EFI/BOOT/BOOTX64.EFI || \
|
||
|
|
cp /usr/lib/shim/shimx64.efi config/includes.binary/EFI/BOOT/BOOTX64.EFI || true
|
||
|
|
|
||
|
|
cp /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed config/includes.binary/EFI/BOOT/grubx64.efi || \
|
||
|
|
cp /usr/lib/grub/x86_64-efi/grubx64.efi config/includes.binary/EFI/BOOT/grubx64.efi || true
|
||
|
|
|
||
|
|
# Also provide mmx64.efi for some UEFI implementations
|
||
|
|
if [ -f config/includes.binary/EFI/BOOT/grubx64.efi ]; then
|
||
|
|
cp config/includes.binary/EFI/BOOT/grubx64.efi config/includes.binary/EFI/BOOT/mmx64.efi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Create grub.cfg for live boot with installer option
|
||
|
|
cat > config/includes.binary/boot/grub/grub.cfg << 'GRUBCFG'
|
||
|
|
set default=0
|
||
|
|
set timeout=10
|
||
|
|
|
||
|
|
insmod part_gpt
|
||
|
|
insmod fat
|
||
|
|
insmod efi_gop
|
||
|
|
insmod efi_uga
|
||
|
|
|
||
|
|
menuentry "Install EcoOS (auto-selects in 10s)" {
|
||
|
|
linux /casper/vmlinuz boot=casper noprompt quiet splash ecoos_install=1 ---
|
||
|
|
initrd /casper/initrd
|
||
|
|
}
|
||
|
|
|
||
|
|
menuentry "EcoOS Live (Try without installing)" {
|
||
|
|
linux /casper/vmlinuz boot=casper noprompt quiet splash ---
|
||
|
|
initrd /casper/initrd
|
||
|
|
}
|
||
|
|
|
||
|
|
menuentry "EcoOS Live (Safe Mode)" {
|
||
|
|
linux /casper/vmlinuz boot=casper noprompt nomodeset ---
|
||
|
|
initrd /casper/initrd
|
||
|
|
}
|
||
|
|
GRUBCFG
|
||
|
|
|
||
|
|
# Also put grub.cfg in EFI/BOOT for fallback
|
||
|
|
cp config/includes.binary/boot/grub/grub.cfg config/includes.binary/EFI/BOOT/grub.cfg
|
||
|
|
|
||
|
|
# Build ISO - use individual lb stages to control the process
|
||
|
|
lb bootstrap
|
||
|
|
lb chroot
|
||
|
|
|
||
|
|
# Try lb binary, but continue even if isohybrid fails
|
||
|
|
lb binary || {
|
||
|
|
echo "lb binary had errors, checking if ISO was created anyway..."
|
||
|
|
if ls /build/*.iso 2>/dev/null; then
|
||
|
|
echo "ISO exists despite errors, continuing..."
|
||
|
|
else
|
||
|
|
echo "No ISO found, build truly failed"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if EFI was created properly
|
||
|
|
echo "Checking binary directory for EFI..."
|
||
|
|
ls -la binary/EFI/BOOT/ 2>/dev/null || echo "EFI/BOOT not found in binary dir"
|
||
|
|
|
||
|
|
# Find the ISO file
|
||
|
|
echo "Searching for ISO file..."
|
||
|
|
find /build -name "*.iso" -type f 2>/dev/null
|
||
|
|
ls -la /build/*.iso 2>/dev/null || true
|
||
|
|
|
||
|
|
ISO_FILE=$(find /build -name "*.iso" -type f 2>/dev/null | head -1)
|
||
|
|
if [ -z "$ISO_FILE" ]; then
|
||
|
|
echo "ERROR: No ISO file found in build directory"
|
||
|
|
echo "Listing /build contents:"
|
||
|
|
ls -la /build/
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Found ISO: $ISO_FILE"
|
||
|
|
|
||
|
|
# Always create proper EFI boot image and rebuild ISO
|
||
|
|
echo "Creating UEFI-bootable ISO..."
|
||
|
|
|
||
|
|
# Extract ISO contents
|
||
|
|
mkdir -p /tmp/iso_extract
|
||
|
|
xorriso -osirrox on -indev "$ISO_FILE" -extract / /tmp/iso_extract
|
||
|
|
|
||
|
|
# Find the actual kernel and initrd names
|
||
|
|
VMLINUZ=$(ls /tmp/iso_extract/casper/vmlinuz* 2>/dev/null | head -1 | xargs basename)
|
||
|
|
INITRD=$(ls /tmp/iso_extract/casper/initrd* 2>/dev/null | head -1 | xargs basename)
|
||
|
|
|
||
|
|
echo "Found kernel: $VMLINUZ, initrd: $INITRD"
|
||
|
|
|
||
|
|
# Ensure EFI structure exists with proper files
|
||
|
|
mkdir -p /tmp/iso_extract/EFI/BOOT
|
||
|
|
mkdir -p /tmp/iso_extract/boot/grub
|
||
|
|
|
||
|
|
# Copy EFI files from host
|
||
|
|
cp /usr/lib/shim/shimx64.efi.signed.latest /tmp/iso_extract/EFI/BOOT/BOOTX64.EFI 2>/dev/null || \
|
||
|
|
cp /usr/lib/shim/shimx64.efi.signed /tmp/iso_extract/EFI/BOOT/BOOTX64.EFI 2>/dev/null || \
|
||
|
|
cp /usr/lib/shim/shimx64.efi /tmp/iso_extract/EFI/BOOT/BOOTX64.EFI 2>/dev/null || true
|
||
|
|
|
||
|
|
cp /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed /tmp/iso_extract/EFI/BOOT/grubx64.efi 2>/dev/null || \
|
||
|
|
cp /usr/lib/grub/x86_64-efi/grubx64.efi /tmp/iso_extract/EFI/BOOT/grubx64.efi 2>/dev/null || true
|
||
|
|
|
||
|
|
# Copy mmx64.efi for secure boot compatibility
|
||
|
|
if [ -f /tmp/iso_extract/EFI/BOOT/grubx64.efi ]; then
|
||
|
|
cp /tmp/iso_extract/EFI/BOOT/grubx64.efi /tmp/iso_extract/EFI/BOOT/mmx64.efi
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Create grub.cfg with correct filenames and installer option
|
||
|
|
cat > /tmp/iso_extract/boot/grub/grub.cfg << GRUBCFG2
|
||
|
|
set default=0
|
||
|
|
set timeout=10
|
||
|
|
|
||
|
|
insmod part_gpt
|
||
|
|
insmod fat
|
||
|
|
insmod efi_gop
|
||
|
|
insmod efi_uga
|
||
|
|
|
||
|
|
menuentry "Install EcoOS (auto-selects in 10s)" {
|
||
|
|
linux /casper/${VMLINUZ} boot=casper noprompt quiet splash ecoos_install=1 ---
|
||
|
|
initrd /casper/${INITRD}
|
||
|
|
}
|
||
|
|
|
||
|
|
menuentry "EcoOS Live (Try without installing)" {
|
||
|
|
linux /casper/${VMLINUZ} boot=casper noprompt quiet splash ---
|
||
|
|
initrd /casper/${INITRD}
|
||
|
|
}
|
||
|
|
|
||
|
|
menuentry "EcoOS Live (Safe Mode)" {
|
||
|
|
linux /casper/${VMLINUZ} boot=casper noprompt nomodeset ---
|
||
|
|
initrd /casper/${INITRD}
|
||
|
|
}
|
||
|
|
GRUBCFG2
|
||
|
|
|
||
|
|
cp /tmp/iso_extract/boot/grub/grub.cfg /tmp/iso_extract/EFI/BOOT/grub.cfg
|
||
|
|
|
||
|
|
# Create EFI boot image (FAT filesystem for UEFI El Torito boot)
|
||
|
|
echo "Creating EFI boot image..."
|
||
|
|
dd if=/dev/zero of=/tmp/efi.img bs=1M count=10
|
||
|
|
mkfs.fat -F 12 /tmp/efi.img
|
||
|
|
mmd -i /tmp/efi.img ::/EFI
|
||
|
|
mmd -i /tmp/efi.img ::/EFI/BOOT
|
||
|
|
mcopy -i /tmp/efi.img /tmp/iso_extract/EFI/BOOT/BOOTX64.EFI ::/EFI/BOOT/
|
||
|
|
mcopy -i /tmp/efi.img /tmp/iso_extract/EFI/BOOT/grubx64.efi ::/EFI/BOOT/ 2>/dev/null || true
|
||
|
|
mcopy -i /tmp/efi.img /tmp/iso_extract/EFI/BOOT/mmx64.efi ::/EFI/BOOT/ 2>/dev/null || true
|
||
|
|
mcopy -i /tmp/efi.img /tmp/iso_extract/EFI/BOOT/grub.cfg ::/EFI/BOOT/
|
||
|
|
|
||
|
|
# Rebuild ISO with EFI boot support (UEFI-only, no BIOS boot)
|
||
|
|
echo "Rebuilding ISO with UEFI boot support..."
|
||
|
|
xorriso -as mkisofs \
|
||
|
|
-r -V "EcoOS" \
|
||
|
|
-o /tmp/ecoos-efi.iso \
|
||
|
|
-J -joliet-long \
|
||
|
|
-eltorito-alt-boot \
|
||
|
|
-e --interval:appended_partition_2:all:: \
|
||
|
|
-no-emul-boot -isohybrid-gpt-basdat \
|
||
|
|
-append_partition 2 0xef /tmp/efi.img \
|
||
|
|
/tmp/iso_extract
|
||
|
|
|
||
|
|
if [ -f /tmp/ecoos-efi.iso ]; then
|
||
|
|
ISO_FILE=/tmp/ecoos-efi.iso
|
||
|
|
echo "Created UEFI-bootable ISO: $ISO_FILE"
|
||
|
|
else
|
||
|
|
echo "ERROR: Failed to create EFI ISO"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
rm -rf /tmp/iso_extract
|
||
|
|
|
||
|
|
# Copy to output
|
||
|
|
mkdir -p /output
|
||
|
|
cp "$ISO_FILE" /output/ecoos.iso
|
||
|
|
|
||
|
|
# Final verification
|
||
|
|
echo ""
|
||
|
|
echo "=== Final ISO EFI check ==="
|
||
|
|
xorriso -indev /output/ecoos.iso -find / -maxdepth 2 -type d 2>/dev/null || true
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=== Build Complete ==="
|
||
|
|
echo "ISO: /output/ecoos.iso"
|
||
|
|
ls -lh /output/ecoos.iso
|
||
|
|
EOF
|
||
|
|
|
||
|
|
RUN chmod +x /build/docker-build.sh
|
||
|
|
|
||
|
|
CMD ["/build/docker-build.sh"]
|