iPXE Server
This commit is contained in:
246
Containerfile
Normal file
246
Containerfile
Normal 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"
|
||||
48
README.md
Normal file
48
README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# IPXE Boot server
|
||||
|
||||
Boot from ipxe.nuc.lan:8080
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|-------------------------|-------------------------------------------------|
|
||||
| `ipxe-server.container` | Quadlet unit joining `internal_caddy` network |
|
||||
| `Containerfile` | Alpine + nginx serving boot assets on port 8080 |
|
||||
| `snippets/ipxe` | Caddy snippet with reusable proxy directives |
|
||||
| `caddy/ipxe.caddyfile` | Site block for `ipxe.nuc.lan` (HTTP + HTTPS) |
|
||||
| `setup.sh` | Automated deployment script |
|
||||
|
||||
**Integration with existing Caddyfile:**
|
||||
|
||||
1. Copy `snippets/ipxe` to your snippets directory
|
||||
2. Add to top of your Caddyfile:
|
||||
|
||||
```
|
||||
import snippets/ipxe
|
||||
```
|
||||
|
||||
3. Add the `ipxe.nuc.lan` block (or paste the content from `ipxe.caddyfile`)
|
||||
|
||||
|
||||
**Or** since you have `*.nuc.lan` already, add this matcher to your wildcard block:
|
||||
|
||||
```caddy
|
||||
@ipxe host ipxe.nuc.lan
|
||||
handle @ipxe {
|
||||
reverse_proxy ipxe-server:8080
|
||||
}
|
||||
```
|
||||
|
||||
**Quick deploy:**
|
||||
|
||||
```bash
|
||||
./setup.sh install # Creates dirs, builds image, installs Quadlet
|
||||
./setup.sh start # Starts via systemd
|
||||
|
||||
# Add boot files
|
||||
cp vmlinuz initrd.img ~/ipxe/boot/
|
||||
cp squashfs.img ~/ipxe/images/fedora-42/
|
||||
```
|
||||
|
||||
**Note:** HTTP is intentionally kept open for `ipxe.nuc.lan:80` because most PXE ROMs chainload via HTTP before the full iPXE stack with HTTPS support is loaded. The local network restriction handles security.
|
||||
|
||||
114
ipxe.caddyfile
Normal file
114
ipxe.caddyfile
Normal file
@@ -0,0 +1,114 @@
|
||||
# === iPXE BOOT SERVER ===
|
||||
# Add this to your main Caddyfile or include via import
|
||||
# Requires: import snippets/ipxe at the top of Caddyfile
|
||||
|
||||
# HTTPS endpoint for iPXE (local network)
|
||||
ipxe.nuc.lan {
|
||||
tls /etc/caddy/tls/wildcard.nuc.lan.crt /etc/caddy/tls/wildcard.nuc.lan.key {
|
||||
protocols tls1.2 tls1.3
|
||||
}
|
||||
|
||||
# Only allow local network access
|
||||
@local_network {
|
||||
remote_ip 192.168.1.0/24 10.89.0.0/24 10.10.5.0/24
|
||||
}
|
||||
|
||||
# Boot menus - no caching
|
||||
@menus {
|
||||
path /menus/* /menu
|
||||
}
|
||||
handle @menus {
|
||||
import ipxe-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Boot files (kernels, initramfs) - cache aggressively
|
||||
@boot {
|
||||
path /boot/*
|
||||
}
|
||||
handle @boot {
|
||||
import ipxe-boot-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Images (ISO, squashfs) - moderate caching, range support
|
||||
@images {
|
||||
path /images/*
|
||||
}
|
||||
handle @images {
|
||||
import ipxe-image-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Health/status endpoints
|
||||
@health {
|
||||
path /health /status
|
||||
}
|
||||
handle @health {
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Default handler for local network
|
||||
handle @local_network {
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Block external access
|
||||
handle {
|
||||
respond "Access denied" 403
|
||||
}
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/ipxe.log {
|
||||
roll_size 10MB
|
||||
roll_keep 3
|
||||
}
|
||||
format json
|
||||
}
|
||||
}
|
||||
|
||||
# HTTP endpoint for iPXE (required for legacy/chainloading)
|
||||
# iPXE firmware often starts with HTTP before HTTPS
|
||||
ipxe.nuc.lan:80 {
|
||||
# Allow HTTP for initial iPXE chainload (most PXE ROMs don't support HTTPS)
|
||||
@local_network {
|
||||
remote_ip 192.168.1.0/24 10.89.0.0/24 10.10.5.0/24
|
||||
}
|
||||
|
||||
# Menus via HTTP (for initial boot)
|
||||
@menus {
|
||||
path /menus/* /menu
|
||||
}
|
||||
handle @menus {
|
||||
import ipxe-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Boot files via HTTP
|
||||
@boot {
|
||||
path /boot/*
|
||||
}
|
||||
handle @boot {
|
||||
import ipxe-boot-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Images via HTTP (for clients that don't support HTTPS)
|
||||
@images {
|
||||
path /images/*
|
||||
}
|
||||
handle @images {
|
||||
import ipxe-image-headers
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
# Health endpoint
|
||||
handle @local_network {
|
||||
import ipxe-upstream
|
||||
}
|
||||
|
||||
handle {
|
||||
respond "Access denied" 403
|
||||
}
|
||||
}
|
||||
|
||||
51
ipxe.snippet
Normal file
51
ipxe.snippet
Normal file
@@ -0,0 +1,51 @@
|
||||
# snippets/ipxe
|
||||
# iPXE Boot Server reverse proxy configuration
|
||||
# Import in Caddyfile with: import snippets/ipxe
|
||||
|
||||
(ipxe-headers) {
|
||||
header {
|
||||
# Disable caching for menus (dynamic content)
|
||||
Cache-Control "no-cache, no-store, must-revalidate"
|
||||
Pragma "no-cache"
|
||||
-Server
|
||||
}
|
||||
}
|
||||
|
||||
(ipxe-boot-headers) {
|
||||
header {
|
||||
# Cache boot files aggressively (kernels, initramfs rarely change)
|
||||
Cache-Control "public, max-age=86400"
|
||||
-Server
|
||||
}
|
||||
}
|
||||
|
||||
(ipxe-image-headers) {
|
||||
header {
|
||||
# Moderate caching for images
|
||||
Cache-Control "public, max-age=3600"
|
||||
# Support range requests for large files
|
||||
Accept-Ranges "bytes"
|
||||
-Server
|
||||
}
|
||||
}
|
||||
|
||||
(ipxe-upstream) {
|
||||
# Reverse proxy to iPXE container
|
||||
reverse_proxy ipxe-server:8080 {
|
||||
# Timeouts for large file transfers
|
||||
transport http {
|
||||
response_header_timeout 30s
|
||||
read_timeout 300s
|
||||
write_timeout 300s
|
||||
}
|
||||
|
||||
# Health check
|
||||
health_uri /health
|
||||
health_interval 30s
|
||||
health_timeout 5s
|
||||
|
||||
# Fail fast if unhealthy
|
||||
fail_duration 30s
|
||||
}
|
||||
}
|
||||
|
||||
50
quadlet
Normal file
50
quadlet
Normal file
@@ -0,0 +1,50 @@
|
||||
# ipxe-server.container
|
||||
# Quadlet unit for iPXE boot server
|
||||
# Place in: ~/.config/containers/systemd/ (rootless) or /etc/containers/systemd/ (root)
|
||||
|
||||
[Unit]
|
||||
Description=iPXE Boot Server
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
Requires=caddy.service
|
||||
After=caddy.service
|
||||
|
||||
[Container]
|
||||
Image=localhost/ipxe-server:latest
|
||||
ContainerName=ipxe-server
|
||||
|
||||
# Join caddy network for reverse proxy
|
||||
Network=internal_caddy
|
||||
|
||||
# Mount points for boot assets and configuration
|
||||
Volume=%h/ipxe/boot:/srv/boot:ro,Z
|
||||
Volume=%h/ipxe/menus:/srv/menus:ro,Z
|
||||
Volume=%h/ipxe/config:/etc/ipxe:ro,Z
|
||||
|
||||
# Optional: mount ISO storage for serving live images
|
||||
Volume=%h/ipxe/images:/srv/images:ro,Z
|
||||
|
||||
# Environment
|
||||
Environment=IPXE_LOG_LEVEL=info
|
||||
Environment=TZ=Europe/Oslo
|
||||
|
||||
# Resource limits
|
||||
PodmanArgs=--memory=256m --cpus=0.5
|
||||
|
||||
# Labels for Caddy/Traefik discovery (optional)
|
||||
Label=ipxe.server=true
|
||||
|
||||
# Health check
|
||||
HealthCmd=/usr/local/bin/healthcheck.sh
|
||||
HealthInterval=30s
|
||||
HealthTimeout=5s
|
||||
HealthRetries=3
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
TimeoutStartSec=90
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
||||
234
setup.sh
Executable file
234
setup.sh
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/bin/bash
|
||||
# Setup script for iPXE boot server
|
||||
# Creates directory structure and deploys Quadlet
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[0;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { printf "${BLUE}[INFO]${NC} %s\n" "$1"; }
|
||||
log_ok() { printf "${GREEN}[OK]${NC} %s\n" "$1"; }
|
||||
log_warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$1"; }
|
||||
log_err() { printf "${RED}[ERROR]${NC} %s\n" "$1"; }
|
||||
|
||||
# Configuration
|
||||
IPXE_BASE="${IPXE_BASE:-$HOME/ipxe}"
|
||||
QUADLET_DIR="${QUADLET_DIR:-$HOME/.config/containers/systemd}"
|
||||
CADDY_SNIPPETS="${CADDY_SNIPPETS:-$HOME/Caddy/snippets}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
iPXE Boot Server Setup
|
||||
|
||||
Usage: $0 [command]
|
||||
|
||||
Commands:
|
||||
install Install Quadlet and create directories
|
||||
build Build the container image
|
||||
start Start the iPXE server
|
||||
stop Stop the iPXE server
|
||||
status Show server status
|
||||
logs Show server logs
|
||||
uninstall Remove Quadlet unit
|
||||
|
||||
Options:
|
||||
--rootless Install for rootless Podman (default)
|
||||
--root Install system-wide (requires sudo)
|
||||
EOF
|
||||
}
|
||||
|
||||
create_directories() {
|
||||
log_info "Creating directory structure..."
|
||||
|
||||
mkdir -p "$IPXE_BASE"/{boot,menus,images,config}
|
||||
mkdir -p "$QUADLET_DIR"
|
||||
mkdir -p "$CADDY_SNIPPETS"
|
||||
|
||||
log_ok "Directories created at $IPXE_BASE"
|
||||
}
|
||||
|
||||
install_quadlet() {
|
||||
log_info "Installing Quadlet unit..."
|
||||
|
||||
# Copy Quadlet file
|
||||
cp "$SCRIPT_DIR/ipxe-server.container" "$QUADLET_DIR/"
|
||||
|
||||
# Update paths in Quadlet to use actual home directory
|
||||
sed -i "s|%h/ipxe|$IPXE_BASE|g" "$QUADLET_DIR/ipxe-server.container"
|
||||
|
||||
log_ok "Quadlet installed to $QUADLET_DIR/ipxe-server.container"
|
||||
}
|
||||
|
||||
install_caddy_snippet() {
|
||||
log_info "Installing Caddy snippet..."
|
||||
|
||||
cp "$SCRIPT_DIR/snippets/ipxe" "$CADDY_SNIPPETS/"
|
||||
|
||||
log_ok "Caddy snippet installed to $CADDY_SNIPPETS/ipxe"
|
||||
log_warn "Don't forget to:"
|
||||
log_warn " 1. Add 'import snippets/ipxe' to your Caddyfile"
|
||||
log_warn " 2. Add the ipxe.nuc.lan site block from caddy/ipxe.caddyfile"
|
||||
log_warn " 3. Reload Caddy: podman exec caddy caddy reload --config /etc/caddy/Caddyfile"
|
||||
}
|
||||
|
||||
copy_default_menu() {
|
||||
log_info "Copying default boot menu..."
|
||||
|
||||
if [[ ! -f "$IPXE_BASE/menus/boot.ipxe" ]]; then
|
||||
# Extract default menu from Containerfile or use embedded one
|
||||
cat > "$IPXE_BASE/menus/boot.ipxe" << 'EOF'
|
||||
#!ipxe
|
||||
# iPXE Boot Menu - NUC Home Server
|
||||
|
||||
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 --gap -- -------- Utilities --------
|
||||
item shell iPXE Shell
|
||||
item reboot Reboot
|
||||
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...
|
||||
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 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
|
||||
|
||||
:shell
|
||||
shell
|
||||
|
||||
:reboot
|
||||
reboot
|
||||
EOF
|
||||
log_ok "Default boot menu created"
|
||||
else
|
||||
log_warn "Boot menu already exists, skipping"
|
||||
fi
|
||||
}
|
||||
|
||||
build_image() {
|
||||
log_info "Building iPXE server container image..."
|
||||
|
||||
podman build -t localhost/ipxe-server:latest -f "$SCRIPT_DIR/Containerfile" "$SCRIPT_DIR"
|
||||
|
||||
log_ok "Image built: localhost/ipxe-server:latest"
|
||||
}
|
||||
|
||||
reload_systemd() {
|
||||
log_info "Reloading systemd user units..."
|
||||
systemctl --user daemon-reload
|
||||
log_ok "Systemd reloaded"
|
||||
}
|
||||
|
||||
start_server() {
|
||||
log_info "Starting iPXE server..."
|
||||
systemctl --user start ipxe-server
|
||||
log_ok "iPXE server started"
|
||||
}
|
||||
|
||||
stop_server() {
|
||||
log_info "Stopping iPXE server..."
|
||||
systemctl --user stop ipxe-server
|
||||
log_ok "iPXE server stopped"
|
||||
}
|
||||
|
||||
show_status() {
|
||||
systemctl --user status ipxe-server
|
||||
}
|
||||
|
||||
show_logs() {
|
||||
journalctl --user -u ipxe-server -f
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
log_info "Uninstalling iPXE server..."
|
||||
|
||||
systemctl --user stop ipxe-server 2>/dev/null || true
|
||||
rm -f "$QUADLET_DIR/ipxe-server.container"
|
||||
systemctl --user daemon-reload
|
||||
|
||||
log_ok "Quadlet removed"
|
||||
log_warn "Data in $IPXE_BASE preserved. Remove manually if needed."
|
||||
}
|
||||
|
||||
do_install() {
|
||||
create_directories
|
||||
install_quadlet
|
||||
install_caddy_snippet
|
||||
copy_default_menu
|
||||
build_image
|
||||
reload_systemd
|
||||
|
||||
echo ""
|
||||
log_ok "Installation complete!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Add boot files to: $IPXE_BASE/boot/"
|
||||
echo " 2. Add images to: $IPXE_BASE/images/"
|
||||
echo " 3. Edit boot menu: $IPXE_BASE/menus/boot.ipxe"
|
||||
echo " 4. Update Caddy config (see caddy/ipxe.caddyfile)"
|
||||
echo " 5. Start server: $0 start"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main
|
||||
case "${1:-}" in
|
||||
install)
|
||||
do_install
|
||||
;;
|
||||
build)
|
||||
build_image
|
||||
;;
|
||||
start)
|
||||
start_server
|
||||
;;
|
||||
stop)
|
||||
stop_server
|
||||
;;
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
logs)
|
||||
show_logs
|
||||
;;
|
||||
uninstall)
|
||||
uninstall
|
||||
;;
|
||||
-h|--help|help|"")
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
log_err "Unknown command: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user