ops: take Redis off the internet, put 5432 behind an allowlist - #300
Merged
Merged
Conversation
Anthony: "we shouldn't need remote access to redis i don't think if supabase/redis/app are all n teh same server" — right, and measured: 12 of 14 Redis connections were containers on this box and the app reaches it by service name. The only remote consumer was the prober. So Redis is no longer published at all. The prober reaches it through an ssh tunnel whose key is restricted to exactly one forward (restrict,port-forwarding,permitopen="127.0.0.1:6379",command="/bin/false"), so it can neither get a shell nor reach another port. That is strictly tighter than what it had: its old URL was plaintext redis:// over Railway's PUBLIC tcp proxy, not the rediss:// the workflow comment claims. The tunnel binds 6380 locally because the prober droplet already runs its own redis-server on 6379 — using 6379 would have pointed it at the wrong Redis without erroring. 5432 stays published (the kit's design, and the nichedb stack sharing this cluster needs it) but is now an allowlist in DOCKER-USER: dev box, loopback and 172.16.0.0/12. That last entry matters — other apps on the box run in their own compose projects on their own bridges and arrive from a different docker subnet, so a narrower list cuts them off. ufw cannot do this job: Docker inserts its rules ahead of ufw's chains. pg_hba is untouched: TLS required, postgres role only, scram. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan48 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 31 | LOW: 15
Snippets are redacted; ThreatCrush never prints matched credential material. |
ThreatCrush flags any credential-shaped connection string in the docs, and it is right to: a runbook that spells out user:password@host teaches people to paste one somewhere it will be kept. Same fix as the cloud DB URL earlier - say which fields to use and where the password lives, and build the URL where the secret is set. Co-Authored-By: Claude Opus 5 (1M context) <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.
Follow-up to #296/#297, closing the two data ports that were still reachable from the internet.
Anthony's call, and it checked out when measured: 12 of 14 Redis connections were containers on dev2 and the app reaches Redis by service name, so nothing on the box needs remote access. The only remote consumer was the prober on scan.crawlproof.com.
Redis: no longer published at all
The prober reaches it through an ssh tunnel instead. Its key on dev2 is
restrict,port-forwarding,permitopen="127.0.0.1:6379",command="/bin/false"— no shell, no other port. That is tighter than what it had: the prober's old URL was plaintextredis://over Railway's public tcp proxy, despite the workflow comment claimingrediss://.Two traps encoded in the scripts:
bind 0.0.0.0+protected-mode noand was internet-reachable (password-protected, but needlessly open). Now loopback.5432: allowlist, not closed
It stays published because the kit designs for it and the nichedb stack sharing this cluster needs it, but it is now
DOCKER-USER: dev box, loopback, and172.16.0.0/12.That last entry is load-bearing — other apps on the box run in their own compose projects on their own bridges and arrive from a different docker subnet, so a narrower list cuts them off the moment they start. Coordinated with the nichedb session, who confirmed it covers them.
ufw cannot do this job: Docker inserts its rules ahead of ufw's chains, so a ufw rule for a published container port is decoration.
pg_hbais untouched — TLS required,postgresrole only, scram.Verified after the change
active, connected through the tunnel