Repository navigation
dev2: fleet kit to move Railway sites onto dev2 and deploy them on merge - #103
Merged
Merged
Conversation
dev2-site reads the truth from Railway (services, domains, volumes, database variables), renders the box files from templates, provisions ~/www/<site> over ssh, copies Postgres through Railway's ssh endpoint into the shared cluster, issues the certificate over Porkbun DNS-01 before DNS moves, flips Porkbun, stops and disconnects the Railway service, and merges the per-repo deploy-dev2.yml. First site through it: bg0ne.com. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…show deploy stderr Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… cutover) + proxied gateway hosts Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
With dozens of compose networks Docker moves to 192.168.x/20 pools, which an allowlist of 172.16.0.0/12 alone drops (CONNECT_TIMEOUT to :5432 from the app). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…apps Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ify db url Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…heckouts Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… and node-postgres accept Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…austed) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…uire otherwise) Bun.SQL forwards unknown URL parameters to the server as GUCs, so uselibpqcompat=true was FATAL there while the health check stayed green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ode 22 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ing it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ale embedded DNS) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…o resolve Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…services only; opensocial.chat override Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… nodejs_18, --regen Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…PACKS_* command variables Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…clone/build); openaccess + openmcp overrides Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… commands Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ate order Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| pw = cluster_pg_password() | ||
| # The app connects as `postgres` (the only role pg_hba lets in from another compose | ||
| # network); isolation is one database per app, same as nichedb and rssamplifier. | ||
| exists = pg_admin(f"select count(*) from pg_database where datname='{db}'").strip() |
ThreatCrush Security Scan25 finding(s) HIGH/CRITICAL: 4 | MEDIUM: 12 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
…s re-pointed once a database exists Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| the app's Postgres schema is applied by the app or by `libsql-pg convert-schema`).""" | ||
| s = site(args.site); st = load_state(s["site"]) | ||
| db = db_name_for(s); pw = cluster_pg_password() | ||
| if pg_admin(f"select count(*) from pg_database where datname='{db}'").strip() == "0": |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rops long streams) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The fleet kit wrote the values it re-points straight into
`sites.d/<site>.json`, so this pull request carried threatcrush.com's
Supabase service_role key, its anon key and its database password, plus
tipoffwatch.com's retired Railway Postgres URL -- in a public repository.
ThreatCrush was right to fail the branch.
`env_overrides` now takes `secret:<KEY>`, resolved at render time from
~/.config/cli-tools/credentials.json (0600, outside every checkout) under
`<site>.<KEY>`, falling back to a bare `<KEY>` for a value shared across
sites. A reference with nothing behind it stops provision and names the
key, rather than deploying a site whose environment contains the literal
string `secret:...`.
`supabase-cutover` was the thing writing them, so it now writes the
reference and puts the value in credentials.json. It marks what is secret
by provenance -- the state keys it substituted -- with a key-name pattern
as the backstop, because a wrong guess there costs one extra entry in
credentials.json and the opposite costs a published key.
Also:
- the four values above moved into credentials.json on dev1; provision
renders exactly what it rendered before (verified by resolving each
reference back to the value this commit removes)
- `porkbun_keys` and the Supabase SMTP lookup hand-rolled this same
read twice; both now call `cred()`
- `db_name_for` validates the identifier at the one place it is
derived: `db_name` in sites.d reaches `create database` and a DSN
unquoted
- drop the committed `__pycache__/*.pyc` and ignore it
The keys this branch published still need rotating; removing them here
does not unpublish them.
…SE when Railway set none Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…is merged Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ralyodio
added a commit
to profullstack/threatcrush
that referenced
this pull request
Sep 25, 2026
Third false positive in the same family as #203: a pattern matching the shape of a dangerous call without asking whether the danger is reachable. py-ssrf-outbound-request fires on `urlopen(req)` for any variable `req`, so a Python tool that talks to exactly two fixed APIs was reported twice at high severity: req = urllib.request.Request("https://backboard.railway.com/graphql/v2", data=body) req = urllib.request.Request(f"https://api.supabase.com/v1/{path}") SSRF is control of the destination, not of the path. Neither of those can be steered to the metadata endpoint or to localhost for any input, and the first has no interpolation in it at all. `constantRequestHostGuard` resolves the variable to its assignments in the file and exonerates only when every one of them names a literal host. An interpolated authority (`f"https://{host}/v1"`), a bare variable (`Request(url)`), or a name with no assignment in sight all leave the finding standing, and a name assigned in two functions is exonerated only if both destinations are fixed. Measured on profullstack/cli-tools#103 with the language resolved the way the CLI resolves it -- by shebang, since the file is extensionless: 4 findings -> 2, and the two that go are exactly the two GitHub reported at dev2/dev2-site:136 and :1132. The two that remain are the real interpolated SQL statements.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he Turso second pass Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… default Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <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.
dev2/dev2-sitemoves any Railway-hosted site onto dev2 in one resumable command and leaves the repo deploying there on merge: registry from Railway, scaffold PR (deploy-dev2.yml, nixpacks Dockerfile when needed), Postgres copy into the shared cluster, provisioning over ssh, certificate over Porkbun DNS-01 before DNS moves, nginx vhost, Porkbun flip, Railway stop + repo disconnect, merge, public verify. Second passes: per-site self-hosted Supabase (stack, pull, load, storage, cutover). Image-only services and companion services are supported throughsites.d/.63 of 79 sites went through it on 2026-09-25.
dev2/README.mdhas the runbook and the traps.🤖 Generated with Claude Code