Skip to content

Fix config push on bind-mounted gateway.toml - #50

Merged
sashyo merged 1 commit into
mainfrom
fix/config-push-bind-mount
Aug 13, 2026
Merged

sashyo merged 1 commit into
mainfrom
fix/config-push-bind-mount

Conversation

@sashyo

@sashyo sashyo commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Found while working out how to update the containerised gateways.

The bug

write_toml wrote a temp file and renamed it over the target. That's the right way to avoid a truncated config on crash — but you cannot rename over a single-file bind mount. Docker returns EBUSY.

That's exactly the container setup DEPLOYMENT.md documents:

-v /etc/punchd-gateway/gateway.toml:/app/gateway.toml

So config push would have failed on every containerised gateway, with replace /app/gateway.toml: Device or resource busy. The gateways on tideorg/punchd-gateway are affected.

The fix

Try the atomic rename first, and fall back to writing through the mount when it's refused. If the fallback fails too, both errors are reported rather than just the second.

The fallback is less crash-safe by nature — that's inherent to bind mounts, since the only way to update the host file from inside the container is to write through it.

Also

Adds a test that constructs the signal server's real Router. The existing tests call handlers directly, so a malformed route path (axum 0.8 wants {id}, not :id) would panic at startup and no test would catch it — the binary would just never bind its port. Verified passing; this was ruled out as a cause during today's outage.

Testing

46 gateway tests (3 new) and 28 signal server tests (1 new) pass. The new write tests cover a fresh write that reads back, an overwrite leaving no .tmp behind, and the fallback firing when rename can't succeed.

The genuine bind-mount case needs Docker to reproduce; the test blocks the temp path with a directory to force the same code path.

The config write used a temp file and a rename, which cannot replace a
single-file bind mount — `-v host.toml:/app/gateway.toml`, the container
setup DEPLOYMENT.md documents. Docker returns EBUSY, so every push to a
containerised gateway would have failed.

Keeps the atomic path where it works and writes through the mount when the
rename is refused, reporting both errors if the fallback also fails.

Also adds a test that builds the signal server's real Router. The handler
tests call functions directly, so a malformed route path would have panicked
at startup with nothing catching it.
@sashyo
sashyo merged commit 8c7d9a6 into main Aug 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant