iPXE Server

This commit is contained in:
2026-02-02 21:50:03 +01:00
commit 96249d0c06
6 changed files with 743 additions and 0 deletions

246
Containerfile Normal file
View File

@@ -0,0 +1,246 @@
# ------------------------------------------------------------------
# ██╗██████╗ ██╗ ██╗███████╗ 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"