fix(security): bind fleetcrown to localhost only, not every interface - #437
Merged
Conversation
launch.sh's own comment claimed `unset HOSTNAME` makes the standalone Next server "reachable at 127.0.0.1 / localhost" — it does the opposite. Next's standalone server reads HOSTNAME as the bind address; unsetting it does not default to localhost, it falls back to Next's own default of 0.0.0.0 (every interface). Found 2026-08-29 while auditing why two unrelated services (revampit, aoz-demo) were listening on all interfaces — fleetcrown itself turned out to be one too. Not an active incident: ufw's default-deny only allows 22/80/443, so port 4002 was never actually internet-reachable. But relying on the firewall to cover a bind-address mistake is exactly the kind of thing that breaks quietly the day the firewall config changes for an unrelated reason. Every other app in the fleet already gets this right — sync-infra.sh sets `HOSTNAME=127.0.0.1` for every site it provisions. fleetcrown launches itself outside that shared script and never picked up the same convention. Fixed to match: export HOSTNAME=127.0.0.1 instead of unsetting it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y9rKLxddothnXEtY6KDziN
github-actions Bot
pushed a commit
to bitbaum/orangecat
that referenced
this pull request
Aug 29, 2026
…830) launch.sh did `unset HOSTNAME` before starting the standalone server. That does not default to localhost — Next's standalone server reads HOSTNAME as the bind address, and unsetting it falls back to Next's own default, 0.0.0.0 (every interface). Confirmed against the actual bind on the box: orangecat-app was listening on 0.0.0.0:4003, not 127.0.0.1:4003 like every other app in the fleet. Not an active incident — ufw's default-deny only allows 22/80/443, so the port was never actually internet-reachable — but relying on the firewall alone to cover a bind-address mistake is exactly the kind of thing that breaks quietly the day firewall config changes for an unrelated reason. Already applied directly to the running box (this file is vendored TO the box, not FROM it on regular deploys — deploy-selfhost.sh preserves whatever launch.sh is already there rather than overwriting it from the repo, per its own comment). This commit is the repo catching up to what's already live, so the next full box provision starts from the correct file instead of reintroducing the bug. Same fix shipped for fleetcrown (bitbaum/fleetcrown#437) — this repo had the identical bug, independently. Claude-Session: https://claude.ai/code/session_01Y9rKLxddothnXEtY6KDziN Co-authored-by: Georgy Butaev <41178744+g-but@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
launch.sh's own comment claimedunset HOSTNAMEmakes the standalone server "reachable at 127.0.0.1 / localhost" — verified against the actual build artifact (.next/standalone/server.js: const hostname = process.env.HOSTNAME || '0.0.0.0') that it does the opposite: unsetting falls back to Next's own default,0.0.0.0(every interface).Found while auditing why two unrelated services were listening on all interfaces — fleetcrown itself turned out to be one too.
Not an active incident: ufw's default-deny only allows 22/80/443, so port 4002 was never actually internet-reachable. But relying on the firewall alone to cover a bind-address mistake is exactly the kind of thing that breaks quietly the day firewall config changes for an unrelated reason.
Every other app in the fleet already gets this right —
sync-infra.shsetsHOSTNAME=127.0.0.1for every site it provisions. fleetcrown launches itself outside that shared script and never picked up the convention. Fixed to match.Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Y9rKLxddothnXEtY6KDziN