10 changed files with 423 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||||
|
config.yaml |
||||
|
auth.json |
||||
@ -0,0 +1,21 @@ |
|||||
|
# Bind on enp1s0 |
||||
|
bind-dynamic |
||||
|
interface=enp1s0 |
||||
|
|
||||
|
# Disable DHCP |
||||
|
no-dhcpv4-interface=enp1s0 |
||||
|
no-dhcpv6-interface=enp1s0 |
||||
|
dhcp-alternate-port |
||||
|
|
||||
|
# Disable DNS |
||||
|
port=0 |
||||
|
|
||||
|
# Enable TFTP |
||||
|
enable-tftp=enp1s0 |
||||
|
tftp-root=/var/lib/tftpboot |
||||
|
tftp-secure |
||||
|
tftp-lowercase |
||||
|
|
||||
|
# Just to be safe... |
||||
|
log-dhcp |
||||
|
log-queries |
||||
@ -0,0 +1,34 @@ |
|||||
|
user nginx; |
||||
|
worker_processes auto; |
||||
|
error_log /var/log/nginx/error.log notice; |
||||
|
pid /run/nginx.pid; |
||||
|
|
||||
|
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. |
||||
|
include /usr/share/nginx/modules/*.conf; |
||||
|
|
||||
|
events { |
||||
|
worker_connections 1024; |
||||
|
} |
||||
|
|
||||
|
http { |
||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' |
||||
|
'$status $body_bytes_sent "$http_referer" ' |
||||
|
'"$http_user_agent" "$http_x_forwarded_for"'; |
||||
|
|
||||
|
access_log /var/log/nginx/access.log main; |
||||
|
|
||||
|
sendfile on; |
||||
|
tcp_nopush on; |
||||
|
keepalive_timeout 65; |
||||
|
types_hash_max_size 4096; |
||||
|
|
||||
|
include /etc/nginx/mime.types; |
||||
|
default_type application/octet-stream; |
||||
|
|
||||
|
server { |
||||
|
listen 127.0.0.1:8080; |
||||
|
server_name _; |
||||
|
root /var/www; |
||||
|
access_log /var/log/nginx/access.log; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,100 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
if [[ "$UID" -ne 0 ]]; then |
||||
|
echo "This command must be run as root!" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Get the directory of this script |
||||
|
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" |
||||
|
|
||||
|
# This function iterates over all files contained in the directory passed as the first argument |
||||
|
# and install them to the directory passed as the second argument, using the install command. |
||||
|
# It preserves the directory structure of the source directory. |
||||
|
# The remaining arguments are passed to the install command. |
||||
|
function install_files() { |
||||
|
local src_dir="$1" |
||||
|
local dest_dir="$2" |
||||
|
shift 2 |
||||
|
|
||||
|
find "$src_dir" -type f | while read -r file; do |
||||
|
local relative_path="${file#$src_dir/}" |
||||
|
local dest_path="$dest_dir/$relative_path" |
||||
|
|
||||
|
install "$@" "$file" "$dest_path" |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
# Same but for directories |
||||
|
function install_directories() { |
||||
|
local src_dir="$1" |
||||
|
local dest_dir="$2" |
||||
|
shift 2 |
||||
|
|
||||
|
find "$src_dir" -type d | while read -r dir; do |
||||
|
local relative_path="${dir#$src_dir}" |
||||
|
relative_path="${relative_path#/}" # Remove leading slash if present |
||||
|
local dest_path="$dest_dir/$relative_path" |
||||
|
|
||||
|
install "$@" -d "$dest_path" |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
# This function templates a kickstart file by replacing placeholders with actual values. |
||||
|
# The templates are located in the www/ks directory. |
||||
|
# The output files are written to /var/www/ks. |
||||
|
# The placeholders are in the format expected by envsubst. |
||||
|
# For each template file, seven versions are created: base + scenario{1,2,3,4,5,6}. |
||||
|
# The output files are named as /var/www/ks/<template>/<scenario>.ks. |
||||
|
function template_kickstart_files() { |
||||
|
local templates_dir="${SCRIPT_DIR}/www/ks" |
||||
|
local output_dir="/var/www/ks" |
||||
|
local scenarios=("base" "scenario1" "scenario2" "scenario3" "scenario4" "scenario5" "scenario6") |
||||
|
|
||||
|
for template in "$templates_dir"/*.ks; do |
||||
|
local template_name="$(basename "$template" .ks)" |
||||
|
|
||||
|
for scenario in "${scenarios[@]}"; do |
||||
|
install -d -m 0755 -o root -g root -Z "$output_dir/${template_name}" |
||||
|
local output_file="$output_dir/${template_name}/${scenario}.ks" |
||||
|
echo "Templating $template_name to $output_file" |
||||
|
( |
||||
|
export SCENARIO_NAME="$scenario" |
||||
|
if [ -f "auth.json" ]; then |
||||
|
export AUTH_JSON_CONTENT="$(cat auth.json)" |
||||
|
fi |
||||
|
if [ -f "config.yaml" ]; then |
||||
|
export FLIGHTCTL_CONFIG_CONTENT="$(cat config.yaml)" |
||||
|
fi |
||||
|
envsubst < "$template" > "/tmp/tmp.$$.ks" |
||||
|
) |
||||
|
install -m 0644 -o root -g root "/tmp/tmp.$$.ks" "$output_file" |
||||
|
done |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
echo "Installing PXE boot files..." |
||||
|
rm -rf "/var/lib/tftpboot" |
||||
|
install_directories "${SCRIPT_DIR}/tftpboot" "/var/lib/tftpboot" -m 755 -o dnsmasq -g dnsmasq -Z |
||||
|
install_files "${SCRIPT_DIR}/tftpboot" "/var/lib/tftpboot" -m 644 -o dnsmasq -g dnsmasq -Z |
||||
|
install -m 0644 -o dnsmasq -g dnsmasq /usr/share/ipxe/{undionly.kpxe,ipxe-snponly-x86_64.efi} /var/lib/tftpboot/ |
||||
|
install -m 0644 -o dnsmasq -g dnsmasq /usr/share/ipxe/arm64-efi/snponly.efi /var/lib/tftpboot/ipxe-snponly-arm64.efi |
||||
|
restorecon -RF "/var/lib/tftpboot" |
||||
|
|
||||
|
echo "Installing nginx files..." |
||||
|
rm -rf "/var/www/ks" |
||||
|
install -d -m 0755 -o root -g root /var/www/repo/rhel{9,10}/{x86_64,arm64}/ /var/www/ks/ |
||||
|
template_kickstart_files |
||||
|
restorecon -RF "/var/www" |
||||
|
|
||||
|
echo "Configuring dnsmasq..." |
||||
|
install -m 0644 -o root -g root -Z "${SCRIPT_DIR}/config/dnsmasq/dnsmasq.conf" /etc/dnsmasq.d/tftp.conf |
||||
|
systemctl enable dnsmasq.service |
||||
|
systemctl restart dnsmasq.service |
||||
|
|
||||
|
echo "Configuring nginx..." |
||||
|
install -m 0644 -o root -g root -Z "${SCRIPT_DIR}/config/nginx/nginx.conf" /etc/nginx/nginx.conf |
||||
|
systemctl enable nginx.service |
||||
|
systemctl restart nginx.service |
||||
@ -0,0 +1,7 @@ |
|||||
|
#!ipxe |
||||
|
|
||||
|
set base_url http://192.168.2.41 |
||||
|
set rhel9_url http://192.168.2.41/repo/rhel9/${buildarch} |
||||
|
set rhel10_url http://192.168.2.41/repo/rhel10/${buildarch} |
||||
|
set rhde_options inst.text |
||||
|
set kickstart_url ${base_url}/ks/mac-${mac:hexraw} |
||||
@ -0,0 +1,30 @@ |
|||||
|
#!ipxe |
||||
|
|
||||
|
# Load global variables |
||||
|
chain --autofree boot.cfg || |
||||
|
|
||||
|
# Boot config/buildarch-<arch>.ipxe |
||||
|
# if buildarch DHCP variable is set and script is present |
||||
|
isset ${buildarch} && chain --autofree config/buildarch-${buildarch}.ipxe || |
||||
|
|
||||
|
# Boot config/hostname-<hostname>.ipxe |
||||
|
# if hostname DHCP variable is set and script is present |
||||
|
isset ${hostname} && chain --autofree config/hostname-${hostname}.ipxe || |
||||
|
|
||||
|
# Boot config/uuid-<UUID>.ipxe |
||||
|
# if SMBIOS UUID variable is set and script is present |
||||
|
isset ${uuid} && chain --autofree config/uuid-${uuid}.ipxe || |
||||
|
|
||||
|
# Boot config/mac-010203040506.ipxe if script is present |
||||
|
chain --autofree config/mac-${mac:hexraw}.ipxe || |
||||
|
|
||||
|
# Boot config/pci-8086100e.ipxe if one type of |
||||
|
# PCI Intel adapter is present and script is present |
||||
|
chain --autofree config/pci-${pci/${busloc}.0.2}${pci/${busloc}.2.2}.ipxe || |
||||
|
|
||||
|
# Boot config/chip-82541pi.ipxe if one type of |
||||
|
# PCI Intel adapter is present and script is present |
||||
|
chain --autofree config/chip-${chip}.ipxe || |
||||
|
|
||||
|
# Boot menu.ipxe script if all other options have been exhausted |
||||
|
chain --replace --autofree menu.ipxe || |
||||
@ -0,0 +1,59 @@ |
|||||
|
#!ipxe |
||||
|
|
||||
|
isset ${menu_default} || set menu_default rhde |
||||
|
isset ${menu_timeout} || set menu_timeout 30000 |
||||
|
|
||||
|
menu iPXE Menu |
||||
|
item --key 0 rhde [0] Install Red Hat Device Edge - Base |
||||
|
item --key 1 rhde-scenario1 [1] Install Red Hat Device Edge - Scenario 1 |
||||
|
item --key 2 rhde-scenario2 [2] Install Red Hat Device Edge - Scenario 2 |
||||
|
item --key 3 rhde-scenario3 [3] Install Red Hat Device Edge - Scenario 3 |
||||
|
item --key 4 rhde-scenario4 [4] Install Red Hat Device Edge - Scenario 4 |
||||
|
item --key 5 rhde-scenario5 [5] Install Red Hat Device Edge - Scenario 5 |
||||
|
item --key 6 rhde-scenario6 [6] Install Red Hat Device Edge - Scenario 6 |
||||
|
item |
||||
|
item --key r reboot [R] Reboot computer |
||||
|
item --key x exit [X] Exit iPXE and continue BIOS boot |
||||
|
choose --timeout ${menu_timeout} --default ${menu_default} selected |
||||
|
goto ${selected} |
||||
|
|
||||
|
:reboot |
||||
|
reboot |
||||
|
|
||||
|
:exit |
||||
|
exit |
||||
|
|
||||
|
:rhde |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/base.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario1 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario1.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario2 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario2.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario3 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario3.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario4 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario4.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario5 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario5.ks ${rhde_options} |
||||
|
boot |
||||
|
|
||||
|
:rhde-scenario6 |
||||
|
initrd ${rhel9_url}/images/pxeboot/initrd.img |
||||
|
kernel ${rhel9_url}/images/pxeboot/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${rhel9_url} inst.ks=${kickstart_url}/scenario6.ks ${rhde_options} |
||||
|
boot |
||||
@ -0,0 +1,85 @@ |
|||||
|
## |
||||
|
## Environment setup |
||||
|
## |
||||
|
|
||||
|
# Install mode: text (interactive installs) or cmdline (unattended installs) |
||||
|
text |
||||
|
|
||||
|
# French keyboard layout |
||||
|
keyboard --vckeymap=fr --xlayouts='fr' |
||||
|
|
||||
|
# English i18n |
||||
|
lang en_US.UTF-8 --addsupport fr_FR.UTF-8 |
||||
|
|
||||
|
# Accept the EULA |
||||
|
eula --agreed |
||||
|
|
||||
|
# Which action to perform after install: poweroff or reboot |
||||
|
reboot |
||||
|
|
||||
|
# Timezone is GMT |
||||
|
timezone Etc/GMT --utc |
||||
|
|
||||
|
## |
||||
|
## network configuration |
||||
|
## |
||||
|
|
||||
|
# No network configuration here since Anaconda does it automatically. |
||||
|
|
||||
|
## |
||||
|
## partitioning |
||||
|
## |
||||
|
|
||||
|
# Install on /dev/sda |
||||
|
ignoredisk --only-use=sda |
||||
|
|
||||
|
# Clear the target disk |
||||
|
zerombr |
||||
|
|
||||
|
# Remove existing partitions |
||||
|
clearpart --all --initlabel |
||||
|
|
||||
|
# Automatically create partitions required by hardware platform |
||||
|
reqpart --add-boot |
||||
|
|
||||
|
# Create a root and a /var partition |
||||
|
part / --fstype xfs --size=1 --grow --asprimary --label=root |
||||
|
|
||||
|
## |
||||
|
## Pre-installation |
||||
|
## |
||||
|
|
||||
|
%pre --log=/tmp/pre-install.log --erroronfail |
||||
|
cat > /etc/ostree/auth.json << 'EOF' |
||||
|
${AUTH_JSON_CONTENT} |
||||
|
EOF |
||||
|
chmod 0600 /etc/ostree/auth.json |
||||
|
%end |
||||
|
|
||||
|
## |
||||
|
## Installation |
||||
|
## |
||||
|
|
||||
|
rootpw --lock |
||||
|
ostreecontainer --url="edge-registry.itix.fr/demo-edge-retail/${SCENARIO_NAME}:latest" --transport=registry --no-signature-verification |
||||
|
|
||||
|
## |
||||
|
## Post-installation |
||||
|
## |
||||
|
|
||||
|
%post --log=/var/log/anaconda/post-install.log --erroronfail |
||||
|
|
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
# Inject flightctl initial configuration |
||||
|
cat > /etc/flightctl/config.yaml << 'EOF' |
||||
|
${FLIGHTCTL_CONFIG_CONTENT} |
||||
|
EOF |
||||
|
chmod 600 /etc/flightctl/config.yaml |
||||
|
|
||||
|
cat > /etc/ostree/auth.json << 'EOF' |
||||
|
${AUTH_JSON_CONTENT} |
||||
|
EOF |
||||
|
chmod 0600 /etc/ostree/auth.json |
||||
|
|
||||
|
%end |
||||
@ -0,0 +1,85 @@ |
|||||
|
## |
||||
|
## Environment setup |
||||
|
## |
||||
|
|
||||
|
# Install mode: text (interactive installs) or cmdline (unattended installs) |
||||
|
text |
||||
|
|
||||
|
# French keyboard layout |
||||
|
keyboard --vckeymap=fr --xlayouts='fr' |
||||
|
|
||||
|
# English i18n |
||||
|
lang en_US.UTF-8 --addsupport fr_FR.UTF-8 |
||||
|
|
||||
|
# Accept the EULA |
||||
|
eula --agreed |
||||
|
|
||||
|
# Which action to perform after install: poweroff or reboot |
||||
|
reboot |
||||
|
|
||||
|
# Timezone is GMT |
||||
|
timezone Etc/GMT --utc |
||||
|
|
||||
|
## |
||||
|
## network configuration |
||||
|
## |
||||
|
|
||||
|
# No network configuration here since Anaconda does it automatically. |
||||
|
|
||||
|
## |
||||
|
## partitioning |
||||
|
## |
||||
|
|
||||
|
# Install on /dev/nvme0n1 |
||||
|
ignoredisk --only-use=nvme0n1 |
||||
|
|
||||
|
# Clear the target disk |
||||
|
zerombr |
||||
|
|
||||
|
# Remove existing partitions |
||||
|
clearpart --all --initlabel |
||||
|
|
||||
|
# Automatically create partitions required by hardware platform |
||||
|
reqpart --add-boot |
||||
|
|
||||
|
# Create a root and a /var partition |
||||
|
part / --fstype xfs --size=1 --grow --asprimary --label=root |
||||
|
|
||||
|
## |
||||
|
## Pre-installation |
||||
|
## |
||||
|
|
||||
|
%pre --log=/tmp/pre-install.log --erroronfail |
||||
|
cat > /etc/ostree/auth.json << 'EOF' |
||||
|
${AUTH_JSON_CONTENT} |
||||
|
EOF |
||||
|
chmod 0600 /etc/ostree/auth.json |
||||
|
%end |
||||
|
|
||||
|
## |
||||
|
## Installation |
||||
|
## |
||||
|
|
||||
|
rootpw --lock |
||||
|
ostreecontainer --url="edge-registry.itix.fr/demo-edge-retail/${SCENARIO_NAME}:latest" --transport=registry --no-signature-verification |
||||
|
|
||||
|
## |
||||
|
## Post-installation |
||||
|
## |
||||
|
|
||||
|
%post --log=/var/log/anaconda/post-install.log --erroronfail |
||||
|
|
||||
|
set -Eeuo pipefail |
||||
|
|
||||
|
# Inject flightctl initial configuration |
||||
|
cat > /etc/flightctl/config.yaml << 'EOF' |
||||
|
${FLIGHTCTL_CONFIG_CONTENT} |
||||
|
EOF |
||||
|
chmod 600 /etc/flightctl/config.yaml |
||||
|
|
||||
|
cat > /etc/ostree/auth.json << 'EOF' |
||||
|
${AUTH_JSON_CONTENT} |
||||
|
EOF |
||||
|
chmod 0600 /etc/ostree/auth.json |
||||
|
|
||||
|
%end |
||||
Loading…
Reference in new issue