fix: quote firewalld rich rules for the remote shell
Some checks failed
deploy / fetch (push) Successful in 17s
deploy / deploy-node (bob.hanzalova.internal, 0x134e73f06fa9bdb1dbfa909e149c563f5860ceb71a0e7307918f7033970edf59, benjy.hanzalova.internal) (push) Failing after 23s
deploy / deploy-miner (1, benjy.hanzalova.internal, bob.hanzalova.internal) (push) Has been skipped

run() is `ssh ... "$@"`, and ssh concatenates its argument vector with
spaces for the remote shell to re-split, so local quoting is lost. The
rich rule arrived as a dozen bare words:

  firewall-cmd: error: unrecognized arguments: family=ipv4 source
  address=10.6.0.146/32 service name=quantus-node-miner accept

Pass the three rich-rule invocations as one pre-quoted string each.
Verified against the real host as gitea_ci: the unquoted form reproduces
the CI error, the quoted form returns 'no' — so it parses and the scoped
sudoers rule matches it.

Every other command in the deploy survived only because no other
argument contains a space; CLAUDE.md now records the trap.
This commit is contained in:
Rob Thijssen
2026-08-31 18:14:07 +03:00
parent 4a9b09f442
commit 5b6fb431ff
2 changed files with 25 additions and 3 deletions

View File

@@ -247,11 +247,18 @@ jobs:
*) echo "refusing to open ${{ env.MINER_LINK_PORT }}/udp to non-mesh address '${miner_ip}' for ${m}" >&2; exit 1 ;;
esac
rich="rule family=ipv4 source address=${miner_ip}/32 service name=quantus-node-miner accept"
if run sudo firewall-cmd --zone="$zone" --query-rich-rule="$rich"; then
# Pass these as ONE pre-quoted string, not as separate run() args.
# `run()` is `ssh ... "$@"`, and ssh concatenates its argument vector
# with spaces for the REMOTE shell to re-split — so local quoting is
# lost and a rich rule arrives as a dozen bare words
# ("unrecognized arguments: family=ipv4 source address=..."). Every
# other command here survives only because no other argument
# contains a space. Keep the inner single quotes.
if run "sudo firewall-cmd --zone=$zone --query-rich-rule='$rich'"; then
echo "firewalld: rich rule for ${m} already present in ${zone}"
else
run sudo firewall-cmd --permanent --zone="$zone" --add-rich-rule="$rich"
run sudo firewall-cmd --zone="$zone" --add-rich-rule="$rich"
run "sudo firewall-cmd --permanent --zone=$zone --add-rich-rule='$rich'"
run "sudo firewall-cmd --zone=$zone --add-rich-rule='$rich'"
fi
done

View File

@@ -52,6 +52,21 @@ without re-measuring:
- Node Prometheus is on **9615**, not 9616. Upstream's `MINING.md` parameter
table is wrong about this; the running binary is the authority.
## ssh argument quoting
`run()` in the deploy is `ssh ... "$@"`. ssh joins its argument vector with
spaces and the REMOTE shell re-splits it, so any argument containing a space
must be passed as one pre-quoted string:
```sh
run "sudo firewall-cmd --zone=$zone --add-rich-rule='$rich'" # correct
run sudo firewall-cmd --zone="$zone" --add-rich-rule="$rich" # word-splits remotely
```
This bit the firewalld rich rules on run 1 and nothing else, because no other
argument in the deploy contains a space. Check this before adding any command
with a quoted multi-word argument.
## Working on the deploy
- The workflow is the source of infra truth (`deployment-gitea-actions.md`).