I have written some salt files to:
- Check to make sure that
fedora-36-minimalis installed, and install it if it isn’t - Clone it into
sys-pxe-template(this is the bit I’m having trouble with) - Change
sys-pxe-templateinto a disposable VM template - Install the following packages into
sys-pxe-template:
nfs-servertftp-serverdhcp-serversyslinux
- Put the following config files into
sys-pxe-template:
-
/etc/dhcp/dhcpd.conf- Configure DHCP server with subnet of 192.168.100.0/24, and TFTP boot server
-
/var/lib/tftpboot/*- All the PXE files from
syslinux - The
pxelinux.cfgand customgrub2EFI files from Qubes OS/bootdirectory (needed to multiboot Xen)
- All the PXE files from
-
/usr/local/bin/download-and-verify-latest-qubes-iso- Bash script to download and verify the latest Qubes OS ISO
-
/etc/systemd/system/download-and-verify-latest-qubes-iso.service- Systemd service to automatically run
download-and-verify-latest-qubes-isowhen the Qube starts
- Systemd service to automatically run
-
/etc/systemd/network/20-all-interfaces.network- Set static IP address of
sys-pxeto 192.168.100.1 - Disable Qubes virtual NICs because they aren’t needed
- Set static IP address of
All of these config files are actually written in plain text in the *.sls files for transparency and to keep the install size down.
- Create a disposable VM called
sys-pxe, and base it onsys-pxe-template
- All the user has to do is open this DispVM, and their ethernet NIC automatically becomes a Qubes OS PXE Network Boot Server!
These are the salt files:
sys-pxe.top
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :
# Installs 'sys-pxe' Qubes OS ISO Network Boot Server Qube.
#
# Pillar data will also be merged if available within the ``qvm`` pillar key:
# ``qvm:sys-pxe``
#
# located in ``/srv/pillar/dom0/qvm/init.sls``
#
# Execute:
# qubesctl top.enable qvm.sys-pxe
# qubesctl --all state.highstate
{% if salt['pillar.get']('qvm:sys-pxe:name', 'sys-pxe') != salt['pillar.get']('qvm:sys-gui:name', 'sys-gui') %}
{% set vmname = salt['pillar.get']('qvm:sys-pxe:name', 'sys-pxe') %}
{% else %}
{% set vmname = salt['pillar.get']('qvm:sys-gui:name', 'sys-gui') %}
{% endif %}
base:
dom0:
- match: nodegroup
- qvm.sys-pxe
{{ salt['pillar.get']('qvm:sys-pxe:template', 'fedora-36-minimal') }}:
- qvm.sys-pxe-template
{{ vmname }}:
- qvm.sys-pxe-vm
sys-pxe-template.sls
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :
##
# qvm.sys-pxe-template
# ====================
##
fedora-36-minimal:
qvm.template_installed: []
#sys-pxe-template:
# qvm.template_installed: []
#dom0:
# cmd.run:
# - qvm-clone fedora-36-minimal sys-pxe-template
sys-pxe-template:
qvm.vm:
- present:
- label: black
- prefs:
- label: black
- dispvm-allowed: True
- features:
- enable:
- appmenus-dispvm
pkg.installed:
- pkgs:
- qubes-core-admin-client
- syslinux
- tftp-server
- nfs-server
- dhcp-server
- systemd-networkd
/var/lib/tftpboot/pxelinux.cfg/default:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
default vesamenu.c32
timeout 100
menu background splash.png
label Qubes-Manual
menu label ^Qubes OS 4.1.1 - Automated Install - Kickstart
kernel mboot.c32
append qubes/xen.gz console=none --- qubes/vmlinuz inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles ip=dhcp inst.ks=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/anaconda-ks.cfg i915.alpha_support=1 quiet rhgb --- qubes/initrd.img
label Qubes-Manual
menu label ^Qubes OS 4.1.1 - Manual Install - Regular ISO Boot
kernel mboot.c32
append qubes/xen.gz console=none --- qubes/vmlinuz inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles ip=dhcp i915.alpha_support=1 quiet rhgb --- qubes/initrd.img
label local
menu label Boot from ^Local Drive
localboot 0xffff
/var/lib/tftpboot/EFI/qubes/grub.cfg:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
function load_video {
insmod vga
insmod vbe
insmod efi_gop
insmod efi_vga
insmod ieee1275_fb
insmod video_bochs
insmod video_cirrus
insmod all_video
}
load_env
load_video
set gfxpayload=keep
insmod gzio
insmod gfxterm
insmod gfxtext
/etc/systemd/network/20-all-interfaces.network:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
# Match all ethernet NICs
[Match]
Type=ether
# For some reason, this network device exists and causes TFTP to fail if it's active...
Name=!enX0
# Set Ethernet NIC static IP address of 192.168.100.1
[Network]
Address=192.168.100.1/24
# May not be necessary, but including them just in case
Gateway=192.168.100.1
DNS=192.168.100.1
/etc/dhcp/dhcpd.conf:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
option arch code 93 = unsigned integer 16;
# If you are planning to PXE install Qubes OS on more than 253 machines at the same time, you are absolutely insane, and I love it!
# If you are, then you probably know how to edit this config file to expand the subnet...
subnet 192.168.100.0 netmask 255.255.255.0 {
authoritative;
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
option domain-name-servers 192.168.100.1;
option routers 192.168.100.1;
option broadcast-address 192.168.100.255;
option subnet-mask 255.255.255.0;
range 192.168.100.2 192.168.100.254;
if option arch = 00:07 {
# amd64 UEFI
filename "uefi/shimx64.efi";
next-server 192.168.100.1;
} else if option arch = 00:0b {
# aarch64 UEFI
filename "uefi/shimaa64.efi";
server-name 192.168.100.1;
} else {
filename "pxelinux.0";
next-server 192.168.100.1;
}
}
/var/lib/tftpboot/EFI/qubes/themes/qubes/theme.txt:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
# Copyright (C) 2016 Harald Sitter <sitter@kde.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of
# the License or any later version accepted by the membership of
# KDE e.V. (or its successor approved by the membership of KDE
# e.V.), which shall act as a proxy defined in Section 14 of
# version 3 of the license.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# paperwhite - #fcfcfc
# icongrey - #4d4d4d
# plasmablue - #3daee9
# black - #000000
# Global Property
# General settings
title-text: ""
title-font: "Unifont Regular 14"
message-font: "Unifont Regular 14"
message-color: "#7f8c8d"
message-bg-color: "#4d4d4d" # TODO: whatever is this for?
desktop-image: "qubes.png"
# title
# NOTE: can't put this in a vbox because GRUB is crap and item highlighting
# is broken if you put the boot_menu in a vbox...
# TODO: file bug report
+ label {
top = 50%-225 # (150+43+32) menu + height + spacer
left = 0%
width = 100%
text = "Qubes OS Installer - Network Boot"
align = "center"
font = "Unifont Regular 32"
color = "#ffffff"
}
# Show the boot menu
+ boot_menu {
left = 50%-200
width = 450
# NB: this is scooped upwards from the middle.
# effectively 50px are below and the remaining 150 above
top = 50%-150
height = 200
# Icon
icon_width = 4
icon_height = 0
# Item
item_height = 33
item_padding = 1
item_icon_space = 0
item_spacing = 1
item_font = "Unifont Regular 16"
item_color = "#4d4d4d"
selected_item_font = "Unifont Bold 16"
selected_item_color = "#ffffff"
}
+ vbox {
left = 50%-200 # same as menu
top = 50%+113 # (50+16+19+28) half menu + spacer + progress + spacer
width = 400 # same as menu
+ label { width = 400 align = "center" color = "#4d4d4d" font = "Unifont Regular 14" text = "[Enter] Boot the selected OS" }
+ label { width = 400 align = "center" color = "#4d4d4d" font = "Unifont Regular 14" text = "[Up and Down Key] navigation" }
+ label { width = 400 align = "center" color = "#4d4d4d" font = "Unifont Regular 14" text = "[E] Edit Selection" }
+ label { width = 400 align = "center" color = "#4d4d4d" font = "Unifont Regular 14" text = "[C] GRUB Command Line" }
}
# Show a styled horizontal progress bar
+ progress_bar {
id = "__timeout__"
left = 0
top = 100%-32
width = 100%
height = 32
show_text = false
bar_style = "progress_bar_*.png"
highlight_style = "progress_bar_hl_*.png"
}
# Show text progress bar
+ progress_bar {
id = "__timeout__"
left = 50%-200 # same as menu
top = 50%+66 # (50+16) half menu + spacer
width = 400 # same as menu
height = 19 # 14pt
show_text = true
font = "Unifont Regular 14"
text_color = "#4d4d4d"
align = "center"
text = "@TIMEOUT_NOTIFICATION_MIDDLE@"
bar_style = "progress_bar2_*.png"
}
/etc/exports:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
/var/lib/tftpboot/qubes/iso *(rw,no_root_squash)
cmd.run:
- name: systemctl enable tftp.service
- name: systemctl enable tftp.socket
- name: systemctl enable systemd-networkd
- name: exportfs -r
- name: systemctl enable nfs-server
- name: systemctl enable dhcpd
# TODO: Add more stuff to put the syslinux files in /var/lib/tftpboot
sys-pxe-vm.sls (needs a bit of work)
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :
##
# qvm.sys-pxe-vm
# ==============
##
# WIP: currently use default user 'user'
/var/lib/tftpboot/pxelinux.cfg/default:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
default vesamenu.c32
timeout 100
menu background splash.png
label Qubes-Manual
menu label ^Qubes OS 4.1.1 - Automated Install - Kickstart
kernel mboot.c32
append qubes/xen.gz console=none --- qubes/vmlinuz inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles ip=dhcp inst.ks=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/anaconda-ks.cfg i915.alpha_support=1 quiet rhgb --- qubes/initrd.img
label Qubes-Manual
menu label ^Qubes OS 4.1.1 - Manual Install - Regular ISO Boot
kernel mboot.c32
append qubes/xen.gz console=none --- qubes/vmlinuz inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles ip=dhcp i915.alpha_support=1 quiet rhgb --- qubes/initrd.img
label local
menu label Boot from ^Local Drive
localboot 0xffff
/var/lib/tftpboot/EFI/qubes/grub.cfg:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
function load_video {
insmod vga
insmod vbe
insmod efi_gop
insmod efi_vga
insmod ieee1275_fb
insmod video_bochs
insmod video_cirrus
insmod all_video
}
load_env
load_video
set gfxpayload=keep
insmod gzio
insmod gfxterm
insmod gfxtext
terminal_output gfxterm
insmod gfxmenu
loadfont $prefix/themes/qubes/unifont-bold-16.pf2
loadfont $prefix/themes/qubes/unifont-regular-14.pf2
loadfont $prefix/themes/qubes/unifont-regular-16.pf2
loadfont $prefix/themes/qubes/unifont-regular-32.pf2
insmod png
set theme=$prefix/themes/qubes/theme.txt
export theme
set timeout_style=menu
set timeout=10
menuentry 'Qubes OS 4.1.1 - Automated Install - Kickstart' --class fedora --class gnu-linux --class gnu --class os {
# echo "To make a tasty Qubes OS..."
# echo "We start with the Xen Hypervisor..."
echo "Loading Xen Hypervisor..."
multiboot2 qubes/xen.gz console=none
# echo "...add a whole raw Linux Kernel..."
echo "Loading Linux Kernel..."
module2 qubes/vmlinuz ip=dhcp inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles i915.alpha_support=1 quiet rhgb inst.ks=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/anaconda-ks.cfg
# echo "...infuse it with your Kickstart Config, for extra flavoury goodness..."
echo "Adding Kickstart File...l"
# echo "...and finally, sprinkle it with a robust Initramfs..."
echo "Loading Initramfs..."
module2 qubes/initrd.img
# echo "...and we have a delicious Qubes OS. Enjoy ;-)"
}
menuentry 'Qubes OS 4.1.1 - Manuak Install - Regular ISO Boot' --class fedora --class gnu-linux --class gnu --class os {
# echo "To make a tasty Qubes OS..."
# echo "We start with the Xen Hypervisor..."
echo "Loading Xen Hypervisor..."
multiboot2 qubes/xen.gz console=none
# echo "...add a whole raw Linux Kernel..."
echo "Loading Linux Kernel..."
module2 qubes/vmlinuz ip=dhcp inst.stage2=nfs:192.168.100.1:/var/lib/tftpboot/qubes/iso/Qubes.iso plymouth.ignore-serial-consoles i915.alpha_support=1 quiet rhgb
# echo "...and finally, sprinkle it with a robust Initramfs..."
echo "Loading Initramfs..."
module2 qubes/initrd.img
# echo "...and we have a delicious Qubes OS. Enjoy ;-)"
}
menuentry 'Exit this GRUB' {
exit
}
/var/lib/tftpboot/uefi/BOOTX64.CSV:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
shimx64.efi,Fedora,,This is the boot entry for Fedora
grubx64.efi,Qubes,,This is the boot entry for Qubes OS
/usr/local/bin/download-and-verify-latest-qubes-iso:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
#!/bin/bash
# Download the Qubes OS 4.1.1 ISO
gpg2 --import /etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
gpg2 --import /usr/share/qubes/qubes-master-ket.asc
wget https://ftp.qubes-os.org/iso/Qubes-R4.1.1-x86_64.iso.asc -O /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.asc &
wget https://ftp.qubes-os.org/iso/Qubes-R4.1.1-x86_64.iso -O /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso
wget https://ftp.qubes-os.org/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS -O /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS
md5sum -c /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS
sha1sum -c /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS
sha256sum -c /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS
sha512sum -c /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.DIGESTS
gpg2 -v --verify /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso.asc /var/lib/tftpboot/qubes/iso/Qubes-R4.1.1-x86_64.iso
/etc/systemd/system/download-and-verify-latest-qubes-iso:
file.managed:
- user: root
- mode: 644
- makedirs: True
- contents: |
[Unit]
Description=Download & Verify Latest Qubes OS ISO from ftp.qubes-os.org
[Service]
Type=oneshot
ExecStart=/usr/local/bin/download-and-verify-latest-qubes-iso
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sys-pxe.sls
# -*- coding: utf-8 -*-
# vim: set syntax=yaml ts=2 sw=2 sts=2 et :
##
# qvm.sys-pxe
# ===========
#
fedora-36-minimal:
qvm.template_installed: []
#sys-pxe-template:
# qvm.template_installed: []
{% from "qvm/template.jinja" import load -%}
{% if salt['pillar.get']('qvm:sys-pxe:name', 'sys-pxe') != salt['pillar.get']('qvm:sys-gui:name', 'sys-gui') %}
{% set vmname = salt['pillar.get']('qvm:sys-pxe:name', 'sys-pxe') %}
{% load_yaml as defaults -%}
name: sys-pxe
qvm.present:
- name: sys-pxe
- label: red
- mem: 400
prefs:
# Uncomment if you want additional repos via HTTP to be avaialble
# - netvm: "sys-firewall"
# Default - No access to the internet
- netvm: ""
- virt_mode: hvm
- autostart: true
- pci_strictreset: false
- pcidevs: {{ salt['grains.get']('pci_net_devs', [])|yaml }}
- class: DispVM
- template: sys-pxe-template
{%- endload %}
{{ load(defaults) }}
{% else %}
{% set vmname = salt['pillar.get']('qvm:sys-gui:name', 'sys-gui') %}
{{ vmname }}-pxe:
qvm.prefs:
- name: {{ vmname }}
- virt_mode: hvm
- pcidevs: {{ salt['grains.get']('pci_net_devs', [])|yaml }}
- pci_strictreset: false
{% endif %}
Is there any chance anyone could have a look at them and help me fix them?
Thank you so much in advance 