{% extends "ui/_layout.html" %} {% block title %}Settings - bty-web{% endblock %} {% block subnav %} {# Settings is the one page with real sub-nav: in-page jump links to each card, separated by vertical rules. #} {% endblock %} {% block intro %} {% from "ui/_intro_box.html" import render as intro_box %} {% call intro_box() %} Where every bty magic value comes from. Most are read-only (set via environment variable or derived from the state directory); the Netboot release and Catalog cards are editable and persist in the database. The DHCP / Network boot cheatsheet below is the router-side config to point PXE / HTTP-Boot clients at this host. Operator authentication lives on the Account page. {% endcall %} {% endblock %} {% block content %} {# Both editable cards share the same POST handler (/ui/settings/upstream) but render as visually-distinct cards so the operator's mental model (netboot artifacts vs image catalog) maps onto the UI. The form element lives outside the row and is referenced by ``form= "upstream-form"`` on every input + button, which is the HTML5 way to associate fields with a non-ancestor form. Submitting from EITHER card saves all three fields in one round-trip. #}
{# Row 1: Catalog spans full width. The card carries an explanatory callout about the dual-flavour nosi catalog model plus the single URL input, so giving it full width keeps the call-out readable on wide screens. #}
The single URL that the Fetch catalog button
on the Images page GETs. Bytes
at that URL must parse as a catalog.toml;
the rows are imported into the local catalog table.
To point at a fork or a private catalog server, just
edit the URL.
The default URL pins to the nosi release this bty version was built against, so two operators on the same bty version see byte-identical catalog content; upgrading bty is what rolls the catalog forward. Three options if you want something else:
2026.W26), paste
/releases/download/<tag>/catalog.toml./releases/latest/download/catalog.toml;
each fetch is internally W-tag-pinned but the
URL roll-forwards with each new nosi release./releases/latest/download/catalog-latest.toml
(or /releases/download/<tag>/catalog-latest.toml);
image refs are :latest so bty flashes
whatever ghcr currently serves, every flash.{{ upstream.catalog_url }}{% if not upstream.catalog_url_override %}
(default; leave blank to keep){% endif %}.
The GitHub release that the Fetch artifacts
button on the Netboot page pulls
vmlinuz, initrd, and
squashfs from. Repo + tag are independent so
an operator can pin netboot to a known-good release while
the catalog rolls forward.
owner/repo. Effective:
{{ upstream.netboot_repo }}{% if not upstream.netboot_repo_override %}
(default; leave blank to keep){% endif %}.
latest or a tag like v0.23.0.
Effective:
{{ upstream.netboot_tag }}{% if not upstream.netboot_tag_override %}
(default; leave blank to keep){% endif %}.
{{ r.env }}{{ r.value }}bty.toml in the config search path.
Settings edits below have nowhere to persist. Set
$BTY_CONFIG_FILE to a writable path or create
<state_dir>/bty.toml.
Targets can net-boot two ways: PXE (legacy + UEFI, iPXE fetched over TFTP) and UEFI HTTP Boot (iPXE fetched over HTTP, no TFTP). bty serves the boot artifacts and per-MAC iPXE scripts over HTTP; TFTP is served by the tftp sidecar (container deploy) or a co-located dnsmasq (host install). The DHCP side stays with your LAN's router (or DHCP server); bty deliberately doesn't try to replace it. Point your router at this host with the settings below.
{% if missing_netboot_artifacts %}{{ boot_root }}:
{% for name in missing_netboot_artifacts %}
{{ name }}{% if not loop.last %}, {% endif %}
{% endfor %}.
PXE clients will chain into iPXE but get 404 on the
kernel fetch until these files are present.
| Interface | State | IPv4 |
|---|---|---|
{{ iface.name }} |
{{ iface.operstate }} |
{% if iface.ipv4 %}
{{ iface.ipv4 }}/{{ iface.prefix }}
{% else %}
(no address)
{% endif %}
|
| (no interfaces detected) | ||
Configure your LAN's DHCP server to tag PXE clients with the options below. For UniFi: Settings → Networks → [your LAN] → Advanced → DHCP → Network Boot. For pfSense / OpenWRT / dnsmasq: equivalent options on the DHCP service.
{# Shorthand for "this host's IP", reused across both tables. Prefer the configured advertised host (withcache URL host), falling back to the sniffed primary interface. #} {% set bty_ip = suggested_host if suggested_host else (primary.ipv4 if primary and primary.ipv4 else "Legacy BIOS and UEFI PXE. The firmware TFTPs the iPXE binary from this host, then iPXE chains on over HTTP.
| Option | Value | Notes |
|---|---|---|
option 60 |
PXEClient |
Vendor-class echo. Strict UEFI firmware filters offers without it. |
option 66 / Next-Server |
{{ bty_ip }} |
The TFTP server. Same box as bty-web. |
option 67 / Boot-Filename |
ipxe.efi |
For UEFI PXEClient (arch 6/7/9). Use undionly.kpxe for legacy BIOS (arch 0). |
option 67 for user-class=iPXE |
http://{{ bty_ip }}:8080/pxe-bootstrap.ipxe |
Stops iPXE chain-loop. Different bootfile when iPXE re-DHCPs. |
For firmware with UEFI HTTP Boot, the target fetches iPXE
directly over HTTP — no TFTP server in the path. Tag
HTTP-Boot clients (vendor-class HTTPClient) with
these instead of the PXE options above. Everything after iPXE
loads is identical to the PXE flow.
| Option | Value | Notes |
|---|---|---|
option 60 |
HTTPClient |
Vendor-class echo. UEFI HTTP-Boot firmware filters offers without it (the HTTP-Boot counterpart of PXEClient). |
option 66 / Next-Server |
{{ bty_ip }} |
Still required. bty's iPXE binary chains on to http://<next-server>:8080/pxe-bootstrap.ipxe, so this must point here even though the bootfile below is a full URL. |
option 67 / Boot-Filename |
http://{{ bty_ip }}:8080/boot/ipxe.efi |
Full URL. The firmware HTTP-downloads iPXE directly — no TFTP roundtrip. |
Both paths converge: once iPXE is running it fetches
http://{{ bty_ip }}:8080/pxe-bootstrap.ipxe and
then the per-MAC plan at /pxe/<mac>. The
only differences are the vendor class and how the iPXE binary
is delivered (TFTP vs HTTP).