Skip to content

Commit 54e93d2

Browse files
committed
FIX: %s belongs in parameters: only, never in command:
Root cause of "Bootstrap netboot.xyz does nothing" (and the silent fetch_url failures): configd's base.py::_cmd_builder substitutes %s in the action's parameters: template, then returns command + " " + parameters. If command: ALSO has %s, that %s is concatenated literally and shows up as an extra argv element to the script. Our bootstrap action had: command:/usr/local/opnsense/scripts/netboot/bootstrap.sh %s parameters:%s so configctl netboot bootstrap netboot_xyz ran: bootstrap.sh %s 'netboot_xyz' $1 was the literal string '%s', which doesn't match the case statement (netboot_xyz | ipxe), so the script fell through to the unknown-preset arm, echoed an error to stderr, and exited 64. configd's script_output captures only stdout and returns empty on non-zero exit. Hence the GUI's "produced no output" path firing every time. How we caught it: the new diag endpoint showed direct-exec of bootstrap.sh from PHP produced 375 bytes of correct stdout AND downloaded both binaries, while the configd probe of the same script returned 0 bytes in 84ms. The 84ms was the giveaway -- a 1.5 MB download can't finish that fast; the script was completing instantly because it was bailing out on argv mismatch. Fix: drop %s from the command: line in both [bootstrap] and [fetch_url]. Add a sharp comment at the top of the actions block explaining the rule so it doesn't recur. The [bootstrap_netboot_xyz] alias was already correct (no %s anywhere) and worked fine via direct exec, but went through the same broken flow because it called the same script through configd. With this fix it works too.
1 parent b324b4d commit 54e93d2

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

src/opnsense/service/conf/actions.d/actions_netboot.conf

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,18 @@ parameters:
8282
type:script_output
8383
message:ensuring netboot runtime user and directories
8484

85+
# IMPORTANT: %s belongs ONLY in `parameters:`, NEVER in `command:`. configd's
86+
# base.py::_cmd_builder substitutes the user-supplied arguments into the
87+
# `parameters:` template and then returns `command + " " + parameters`. If
88+
# command also has %s, that %s is passed verbatim as an extra argv element
89+
# to the script -- which then mis-parses its real positional args. Symptom:
90+
# script falls through to the unknown-preset branch, prints an error to
91+
# stderr, exits non-zero, configd's script_output captures empty stdout
92+
# and returns 0 bytes. Hours of "Bootstrap does nothing" went into finding
93+
# this. See base.py:_cmd_builder upstream.
94+
8595
[fetch_url]
86-
command:/usr/local/opnsense/scripts/netboot/fetch_url.sh %s %s
96+
command:/usr/local/opnsense/scripts/netboot/fetch_url.sh
8797
parameters:%s %s
8898
type:script_output
8999
message:fetching url to netboot content root
@@ -94,7 +104,7 @@ message:fetching url to netboot content root
94104
# / etc. The script validates the preset name and refuses unknown values,
95105
# so this is safe to expose.
96106
[bootstrap]
97-
command:/usr/local/opnsense/scripts/netboot/bootstrap.sh %s
107+
command:/usr/local/opnsense/scripts/netboot/bootstrap.sh
98108
parameters:%s
99109
type:script_output
100110
message:fetching iPXE bootstrap binaries (BIOS + UEFI) for the selected preset

0 commit comments

Comments
 (0)