247 lines
6.8 KiB
Docker
247 lines
6.8 KiB
Docker
# ------------------------------------------------------------------
|
|
# ██╗██████╗ ██╗ ██╗███████╗ Lightweight HTTP server
|
|
# ██║██╔══██╗╚██╗██╔╝██╔════╝ for network booting.
|
|
# ██║██████╔╝ ╚███╔╝ █████╗
|
|
# ██║██╔═══╝ ██╔██╗ ██╔══╝ Serves boot menus, kernels, and images
|
|
# ██║██║ ██╔╝ ██╗███████╗
|
|
# ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ Version 1.0.0
|
|
# ███████╗███████╗██████╗ ██╗ ██╗███████╗██████╗
|
|
# ██╔════╝██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗
|
|
# ███████╗█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝
|
|
# ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██╔══╝ ██╔══██╗
|
|
# ███████║███████╗██║ ██║ ╚████╔╝ ███████╗██║ ██║
|
|
# ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝
|
|
# Author: Kevin [+ Claude]
|
|
# Created: 2025-02-02
|
|
# ------------------------------------------------------------------
|
|
|
|
FROM docker.io/library/alpine:3.21 AS base
|
|
|
|
# Install runtime dependencies
|
|
RUN apk add --no-cache \
|
|
nginx \
|
|
curl \
|
|
tzdata \
|
|
tini \
|
|
&& rm -rf /var/cache/apk/*
|
|
|
|
# Create ipxe user
|
|
RUN addgroup -g 1000 ipxe && \
|
|
adduser -D -s /sbin/nologin -u 1000 -G ipxe ipxe
|
|
|
|
# Create directory structure
|
|
RUN mkdir -p \
|
|
/srv/boot \
|
|
/srv/menus \
|
|
/srv/images \
|
|
/srv/scripts \
|
|
/etc/ipxe \
|
|
/var/log/nginx \
|
|
/var/lib/nginx \
|
|
/run/nginx && \
|
|
chown -R ipxe:ipxe /srv /var/log/nginx /var/lib/nginx /run/nginx
|
|
|
|
# nginx configuration for iPXE
|
|
RUN cat > /etc/nginx/nginx.conf << 'EOF'
|
|
worker_processes auto;
|
|
error_log /var/log/nginx/error.log warn;
|
|
pid /run/nginx/nginx.pid;
|
|
|
|
events {
|
|
worker_connections 256;
|
|
use epoll;
|
|
}
|
|
|
|
http {
|
|
include /etc/nginx/mime.types;
|
|
default_type application/octet-stream;
|
|
|
|
# Custom MIME types for iPXE
|
|
types {
|
|
application/octet-stream ipxe efi;
|
|
text/plain ipxe menu;
|
|
}
|
|
|
|
log_format ipxe '$remote_addr - [$time_local] "$request" $status $body_bytes_sent '
|
|
'"$http_user_agent" rt=$request_time';
|
|
|
|
access_log /var/log/nginx/access.log ipxe;
|
|
|
|
sendfile on;
|
|
tcp_nopush on;
|
|
tcp_nodelay on;
|
|
keepalive_timeout 65;
|
|
|
|
# Disable buffering for faster boot file delivery
|
|
proxy_buffering off;
|
|
|
|
server {
|
|
listen 8080;
|
|
server_name _;
|
|
|
|
root /srv;
|
|
|
|
# Boot files (kernels, initramfs, iPXE binaries)
|
|
location /boot/ {
|
|
alias /srv/boot/;
|
|
autoindex on;
|
|
autoindex_exact_size off;
|
|
autoindex_localtime on;
|
|
}
|
|
|
|
# iPXE menus and scripts
|
|
location /menus/ {
|
|
alias /srv/menus/;
|
|
autoindex on;
|
|
default_type text/plain;
|
|
}
|
|
|
|
# ISO/squashfs images
|
|
location /images/ {
|
|
alias /srv/images/;
|
|
autoindex on;
|
|
autoindex_exact_size on;
|
|
|
|
# Support range requests for large files
|
|
add_header Accept-Ranges bytes;
|
|
}
|
|
|
|
# Dynamic menu endpoint (can be extended with scripts)
|
|
location /menu {
|
|
alias /srv/menus/boot.ipxe;
|
|
default_type text/plain;
|
|
}
|
|
|
|
# Health check endpoint
|
|
location /health {
|
|
access_log off;
|
|
return 200 'OK\n';
|
|
add_header Content-Type text/plain;
|
|
}
|
|
|
|
# Status page
|
|
location /status {
|
|
stub_status on;
|
|
access_log off;
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Health check script
|
|
RUN cat > /usr/local/bin/healthcheck.sh << 'EOF'
|
|
#!/bin/sh
|
|
set -e
|
|
curl -sf http://localhost:8080/health > /dev/null || exit 1
|
|
echo "iPXE server healthy"
|
|
EOF
|
|
RUN chmod +x /usr/local/bin/healthcheck.sh
|
|
|
|
# Entrypoint script
|
|
RUN cat > /usr/local/bin/entrypoint.sh << 'EOF'
|
|
#!/bin/sh
|
|
set -e
|
|
|
|
echo "=== iPXE Boot Server ==="
|
|
echo "Boot files: /srv/boot"
|
|
echo "Menus: /srv/menus"
|
|
echo "Images: /srv/images"
|
|
echo ""
|
|
|
|
# List available boot assets
|
|
echo "Available boot files:"
|
|
ls -la /srv/boot/ 2>/dev/null || echo " (none)"
|
|
echo ""
|
|
echo "Available menus:"
|
|
ls -la /srv/menus/ 2>/dev/null || echo " (none)"
|
|
echo ""
|
|
|
|
# Validate nginx config
|
|
nginx -t
|
|
|
|
# Start nginx in foreground
|
|
exec nginx -g 'daemon off;'
|
|
EOF
|
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
|
|
|
# Default boot menu template
|
|
RUN cat > /srv/menus/boot.ipxe << 'EOF'
|
|
#!ipxe
|
|
# iPXE Boot Menu - NUC Home Server
|
|
# Served via Caddy reverse proxy
|
|
|
|
set menu-timeout 30000
|
|
set menu-default local
|
|
|
|
:start
|
|
menu iPXE Boot Menu - nuc.lan
|
|
item --gap -- -------- Boot Options --------
|
|
item local Boot from local disk
|
|
item --gap -- -------- Network Boot --------
|
|
item fedora-live Fedora 42 Live (Minimal)
|
|
item fedora-kiosk Fedora 42 Kiosk/PoS
|
|
item fedora-rescue Fedora 42 Rescue
|
|
item --gap -- -------- Utilities --------
|
|
item memtest Memtest86+
|
|
item shell iPXE Shell
|
|
item reboot Reboot
|
|
item exit Exit to BIOS
|
|
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
|
|
goto ${selected}
|
|
|
|
:cancel
|
|
echo Boot cancelled
|
|
goto start
|
|
|
|
:local
|
|
sanboot --no-describe --drive 0x80 || goto start
|
|
|
|
:fedora-live
|
|
echo Booting Fedora 42 Live (Minimal)...
|
|
set base-url http://ipxe.nuc.lan/images/fedora-42
|
|
kernel ${base-url}/vmlinuz initrd=initrd.img root=live:${base-url}/squashfs.img rd.live.image rd.live.overlay.overlayfs=1 quiet
|
|
initrd ${base-url}/initrd.img
|
|
boot || goto start
|
|
|
|
:fedora-kiosk
|
|
echo Booting Fedora 42 Kiosk...
|
|
set base-url http://ipxe.nuc.lan/images/fedora-42-kiosk
|
|
kernel ${base-url}/vmlinuz initrd=initrd.img root=live:${base-url}/squashfs.img rd.live.image quiet
|
|
initrd ${base-url}/initrd.img
|
|
boot || goto start
|
|
|
|
:fedora-rescue
|
|
echo Booting Fedora 42 Rescue...
|
|
set base-url http://ipxe.nuc.lan/images/fedora-42
|
|
kernel ${base-url}/vmlinuz initrd=initrd.img rescue quiet
|
|
initrd ${base-url}/initrd.img
|
|
boot || goto start
|
|
|
|
:memtest
|
|
echo Loading Memtest86+...
|
|
kernel http://ipxe.nuc.lan/boot/memtest86+.bin
|
|
boot || goto start
|
|
|
|
:shell
|
|
echo Dropping to iPXE shell...
|
|
shell
|
|
|
|
:reboot
|
|
reboot
|
|
|
|
:exit
|
|
exit
|
|
EOF
|
|
|
|
EXPOSE 8080
|
|
|
|
USER ipxe
|
|
WORKDIR /srv
|
|
|
|
ENTRYPOINT ["/sbin/tini", "--"]
|
|
CMD ["/usr/local/bin/entrypoint.sh"]
|
|
|
|
LABEL maintainer="Kevin" \
|
|
version="1.0.0" \
|
|
description="iPXE boot server for network booting"
|