{% extends "base.html" %} {% block title %}iPXE Boot Files - PXE Server Manager{% endblock %} {% macro sig_badge(info, chain_ok=none) -%} {% if info.kind == 'microsoft-2011' %}Microsoft UEFI CA 2011 only {% elif info.kind == 'microsoft-2023' %}Microsoft UEFI CA 2023 {% elif info.kind == 'microsoft' %}Microsoft (other CA) {% elif info.kind == 'ipxe' %}iPXE Secure Boot CA {% elif info.kind == 'bios' %}Legacy BIOS, unsigned {% elif info.kind == 'unsigned' %}Unsigned {% elif info.kind == 'error' %}Not checked {% else %}Other signer{% endif %} {% if chain_ok == false %}Shim will refuse{% endif %} {%- endmacro %} {% macro chain(info) -%} {% if info.signers %}
Signer chain ({{ info.signers | length }}) {% for subject, issuer in info.signers %}
{{ subject }} issued by {{ issuer }}
{% endfor %}
{% endif %} {% if info.trusts %}
Starts second stages signed by {{ info.trusts }}
{% endif %} {% if info.sbat %}
SBAT: {{ info.sbat }}
{% endif %} {%- endmacro %} {% block content %}

The Secure Boot chain that dnsmasq hands out over TFTP: the Microsoft-signed shim (ipxe-shim.efi) starts ipxe.efi, which is signed by the iPXE Secure Boot CA. Updates come from the upstream iPXE release tarball on GitHub; its sha256 is checked against GitHub's published digest and each file's signer chain is read with sbverify before it can be installed. ipxe-bcm.efi, dnsmasq.conf and the Blancco files are never changed here.

{# ---- Upstream ------------------------------------------------------------ #}
Upstream release
{% if latest %}
{{ latest.tag }} {% if latest.name and latest.name != latest.tag %}{{ latest.name }}{% endif %} {% if status == 'update' %}newer than installed {% elif status == 'current' %}installed {% elif status == 'newer' %}installed build is newer {% else %}installed version unknown{% endif %}
Published {{ latest.published | local_dt }} | checked {{ latest.checked | local_dt }} {% if latest.size %}| {{ "%.1f"|format(latest.size / 1048576) }} MB{% endif %} | release page
sha256 {{ latest.sha256 or 'not published' }}
{% else %}

Not checked yet. Check for updates asks the GitHub API for the latest release (a few seconds).

{% endif %}
Speed cap applies to every download on the Updates pages (Dell and iPXE); 0 means no cap.
{% if job.state %}
{% if job.state in ('queued', 'running') %}
{{ 'Starting' if job.state == 'queued' else (job.step | capitalize) }} {{ job.tag }}...
{% elif job.state == 'error' %}
Download of {{ job.tag }} failed: {{ job.error }}
{% elif job.state == 'interrupted' %}
The download of {{ job.tag }} stopped without finishing (server restart?). Start it again; it resumes the partial file.
{% elif job.state == 'done' and job.failed %}
{{ job.tag }} downloaded, but {{ job.failed | join(', ') }} failed verification; see below.
{% endif %}
{% endif %}
{# ---- Installed ----------------------------------------------------------- #}
Installed on the TFTP root
{% for r in rows %} {% set i = r.info %} {% if i %} {% else %} {% endif %} {% endfor %}
FileVersionSizeModifiedsha256Signature
{{ r.name }} {% if not r.managed %}
read-only here
{% endif %}
{{ i.version or '-' }}{% if i.release %}
from {{ i.release }}
{% endif %}
{{ "{:,}".format(i.size) }} B {{ i.modified | timestamp_fmt }} {{ i.sha256[:12] }} {{ sig_badge(i, i.chain_ok if i.chain_ok is defined else none) }}{{ chain(i) }}Not present
{# ---- Staged -------------------------------------------------------------- #} {% if staged %}
Downloaded and verified
{% for s in staged %}
{{ s.tag }} verified {{ s.staged | local_dt }} | tarball sha256 {{ (s.tarball_sha256 or '')[:12] }} matches GitHub
{% for name, f in s.files.items() %} {% endfor %}
FileFrom tarballVersionsha256Check
{% if name not in default_install %}
optional
{% endif %}
{{ f.source or '-' }} {{ f.version or '-' }} {{ (f.sha256 or '')[:12] }} {% if f.sha256 and f.sha256 == installed_sha[name] %}
same as installed
{% endif %}
{% if f.ok %}OK {% if f.kind %}{{ sig_badge(f) }}{% endif %} {% else %}Failed
{{ f.error }}
{% endif %} {% if f.signers is defined %}{{ chain(f) }}{% endif %}
ipxe-shim.efi is only installed together with ipxe.efi from the same release. ipxe.pxe is for legacy BIOS clients.
{% endfor %}
{% endif %} {# ---- dnsmasq routing ----------------------------------------------------- #}
Who gets which file (dnsmasq, read-only)
{% if routing.boots %}
{% for b in routing.boots %} {% endfor %}
Boot fileRequires tagUnless taggedClients
{{ b.file }} {% if b.managed %}updated here{% elif b.read_only %}never touched {% elif b.other_copy %}other copy, not updated here{% endif %} {{ b.need | join(', ') or '-' }} {{ b.exclude | join(', ') or '-' }} {% if b.macs %}{{ b.macs | join(', ') }} {% elif b.need %}clients matching {{ b.need | join(' and ') }} {% else %}every client not excluded{% endif %}
Relevant dnsmasq lines ({{ routing.lines | length }})
{% for l in routing.lines %}{{ l }}
{% endfor %}
{% else %}

No dhcp-boot lines found in the dnsmasq configuration.

{% endif %}
{# ---- Backups ------------------------------------------------------------- #}
Backups
{% if backups %}
{% for b in backups %} {% endfor %}
BackupReasonFiles
{{ b.id }} {{ b.reason or '-' }} {% for f in b.files %}
{{ f }} {{ b.versions[f] or '' }}
{% endfor %} {% if not b.files %}empty{% endif %}
{% if b.files %} {# The id is a folder name (hand-made backups too): keep it out of the JS source. #}
{% endif %}
{% else %}

No backups yet. One is made automatically before every install and rollback.

{% endif %}
{# ---- How-to -------------------------------------------------------------- #}
How to find and install the latest signed build by hand

Use this when the buttons above cannot reach GitHub, or to check what they do. All commands run on the PXE server as root.

  1. Find the release. The latest release is at {{ releases_page }}. The signed boot files are the asset ipxeboot.tar.gz; GitHub shows its sha256 next to the asset (or ask the API: curl -s https://api.github.com/repos/ipxe/ipxe/releases/latest | grep -B2 -A2 '"digest"').
  2. Download and check the sha256. It must equal the digest on the release page.
    cd /tmp
    curl -fLO {{ tarball_url }}
    sha256sum ipxeboot.tar.gz
    GitHub goes through Zscaler. A certificate error from curl means the Zscaler root CA is missing from /usr/local/share/ca-certificates/ (the playbook installs it).
  3. Unpack. The Secure Boot files are in ipxeboot/x86_64-sb/: shimx64.efi (the shim), ipxe.efi and snponly.efi. ipxe-shim.efi and snponly-shim.efi there are only symlinks to shimx64.efi. The legacy BIOS build is ipxeboot/x86_64/ipxe.pxe.
    tar xzf ipxeboot.tar.gz
    ls -l ipxeboot/x86_64-sb/
  4. Check the signatures.
    sbverify --list ipxeboot/x86_64-sb/shimx64.efi
    sbverify --list ipxeboot/x86_64-sb/ipxe.efi
    The shim must be issued by CN=Microsoft Corporation UEFI CA 2011 or, on a newer build, CN=Microsoft UEFI CA 2023 (prefer a 2023-signed shim when upstream ships one). ipxe.efi must show CN=iPXE Secure Boot Intermediate ... issued by CN=iPXE Secure Boot CA. The shim's warning: data remaining ... gaps between PE/COFF sections? is normal. Do not rely on sbverify --cert: it reports OK even for the wrong certificate.
  5. Back up the current files. A backup made in this folder also shows in the Backups list above, with Rollback.
    B=/var/lib/pxe-webapp/updates/ipxe/backups/$(date +%Y%m%d-%H%M%S)
    mkdir -p "$B" && cp -p /srv/tftp/ipxe-shim.efi /srv/tftp/ipxe.efi "$B"/
  6. Install both files, from the same release. The shim only starts an ipxe.efi signed under the CA it carries, and it always loads ipxe.efi from the TFTP root, so the name must stay ipxe.efi. Copy to a temporary name and rename, so a client that is booting never reads half a file:
    install -m 0644 ipxeboot/x86_64-sb/ipxe.efi    /srv/tftp/.ipxe.efi.new      && mv -f /srv/tftp/.ipxe.efi.new      /srv/tftp/ipxe.efi
    install -m 0644 ipxeboot/x86_64-sb/shimx64.efi /srv/tftp/.ipxe-shim.efi.new && mv -f /srv/tftp/.ipxe-shim.efi.new /srv/tftp/ipxe-shim.efi
    No dnsmasq restart is needed. Never replace ipxe-bcm.efi; it serves every other UEFI client.
  7. Who gets it. dnsmasq decides, in /etc/dnsmasq.conf: clients listed as dhcp-host=<mac>,set:ipxe2 get the shim through dhcp-boot=tag:ipxe2,tag:!ipxe,tag:!bios,ipxe-shim.efi; every other UEFI client gets ipxe-bcm.efi through dhcp-boot=tag:!bios,tag:!ipxe2,ipxe-bcm.efi. The table above shows the live lines. Test on one tagged machine before tagging more.
  8. Roll back. Use Rollback above, or copy the backed-up files back the same way (temporary name, then mv -f).
  9. Normal log noise. While booting, the shim asks TFTP for optional files such as revocations_*.efi and shim_certificate_0.efi. The "not found" lines for them in the dnsmasq log are expected and harmless.
{% if job.state in ('queued', 'running') %} {% endif %} {% endblock %}