Skip to content

Rewrite the inbound-SSH section: it described a state that no longer exists - #104

Merged
aterga merged 2 commits into
mainfrom
claude/readme-ssh-section
Jul 29, 2026
Merged

Rewrite the inbound-SSH section: it described a state that no longer exists#104
aterga merged 2 commits into
mainfrom
claude/readme-ssh-section

Conversation

@aterga

@aterga aterga commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

deploy/native/README.md's "Narrowing inbound SSH" section had two load-bearing claims that are now false. With the repo heading for public visibility, a reader would be misled on both.

"It still does" need 22/tcp open to the world. Not true as of today. Internet-facing SSH is closed on both hosts: each has a public-facing interface and a private one, security groups attach per-interface, and the public one now carries a group permitting 80/443 only. Verified from outside the VPN — 22 times out where it previously reached sshd.

"Do not try to solve this with a narrower CIDR — there isn't one." The evidence for this was a single observed public source address, and it turned out to be an artifact. Staging's DEPLOY_HOST named the public FQDN, so its deploys left over the internet rather than the VPN and presented a public source. With both hosts on private addresses, both present sources inside the private range. The section spent four paragraphs arguing a conclusion that had already collapsed.

Related issues

Part of #101 (publication scrub — the section now carries no internal addresses or resource identifiers). Supersedes the analysis in #91, which is being updated separately.

Changes

Rewritten to state what is true now and what is left to do:

  • Internet-facing SSH is closed, and how — the per-interface security group split.
  • DEPLOY_HOST must be the host's private address, with the failure mode spelled out. This is the same requirement Stop documenting a decommissioned host address as the DEPLOY_HOST example #102 adds to the secret's own description.
  • The residual: 22 still open on the private interface, so the VPN and on-prem estate still reach SSH. Recorded as accepted rather than left implicit.
  • The remaining step: narrow to the private range, delete the world-facing rule — after confirming the source across both runner clusters, and adding our own rule rather than depending on another team's, which can change without reference to this deployment.
  • The Calico reasoning is kept, demoted from "this is impossible" to "verify rather than assume". That is what it actually supports, and it is the reason not to act on two readings.
  • SSM is kept as considered and declined, with its reasoning intact and an explicit note to revisit if the judgement changes. It is the stronger end state; it was judged over-engineering for the residual once internet SSH was closed.
  • The earlier failed attempt is recorded with its real cause, so nobody concludes the rule itself is untouchable.
  • The ::/0 note and the $SSH_CLIENT / journalctl observation guidance are kept — both still correct and still useful.

Testing

  • git grep over the whole tree finds no internal IPs, VPC/subnet/security-group/ENI/instance identifiers, or IPv6 addresses.
  • Section boundaries preserved — the ship_runs_on and /version-assertion paragraphs that follow belong to the parent section and are untouched.
  • Not run: cargo / npm — documentation only.

Checklist

  • I have read the Contributing guidelines.
  • Docs (README / comments) updated for any user-visible change — this PR is the doc change.
  • No secrets, credentials, or internal-only information are included — it removes internal detail rather than adding it.

Sequencing

Best merged after #102. One sentence here says the requirement is stated in deploy-native.yml's secret description, which is what #102 adds. Harmless if merged first, briefly forward-looking.


Generated by Claude Code

…exists

Two of the section's load-bearing claims were false, and the repo is heading for
public visibility, so a reader would have been misled on both counts.

"It still does" need 22/tcp open to the world — no longer true. Internet-facing
SSH is closed on both hosts: each has a public-facing interface and a private
one, security groups attach per-interface, and the public one now carries a group
permitting 80/443 only. Verified from outside the VPN.

"Do not try to solve this with a narrower CIDR — there isn't one" — the evidence
for that was one observed public source address, which turned out to be an
artifact. Staging's DEPLOY_HOST named the public FQDN, so its deploys were
leaving over the internet rather than the VPN and presenting a public source.
Both hosts on private addresses present sources inside the private range. The
section spent four paragraphs arguing a conclusion that had already collapsed.

Rewritten to say what is now true and what is left: narrow the rule to the
private range and delete the world-facing one, after confirming the source
across both runner clusters, and add our own rule rather than depending on
another team's. The Calico reasoning is kept, demoted from "this is impossible"
to "verify rather than assume", which is what it actually supports. SSM is kept
as considered-and-declined with its reasoning intact, since the judgement could
change.

Also removes every internal address and resource identifier from the section, so
it is publication-safe (part of #101). Details that need them live on #91.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8ZshwKmjD5fZ4Hs9dS6zh

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the native deployment documentation to reflect the current network/security posture for deploy-host SSH access, removing now-incorrect claims and clarifying the remaining hardening work.

Changes:

  • Rewrites “Narrowing inbound SSH” to state that internet-facing SSH is closed via per-interface security groups and to explain the DEPLOY_HOST private-address requirement.
  • Reframes the CIDR-narrowing guidance as “verify then act” (Calico/SNAT variability) and records the prior failure mode accurately.
  • Keeps SSM Session Manager as an explicitly considered (but currently declined) alternative end state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deploy/native/README.md Outdated
The rewritten section referred to it as bare `deploy-native.yml` while lines
168-169 and 180 use a relative link. Matches them now.

Scoped to the .yml files deliberately: `deploy.sh` appears bare in nine other
places here and stays that way, so this follows the existing convention rather
than inventing a new one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8ZshwKmjD5fZ4Hs9dS6zh
@aterga
aterga marked this pull request as ready for review July 29, 2026 16:46
@aterga
aterga requested review from a team and Copilot July 29, 2026 16:46
@aterga
aterga merged commit c0cd6f3 into main Jul 29, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

deploy/native/README.md:222

  • This sentence claims the DEPLOY_HOST secret description in deploy-native.yml “now says so”, but in the current workflow it still uses the old example (ec2-user@10.118.0.61) and doesn’t state the private-address requirement. If this PR can land before #102, make this wording non-time-dependent (or reference #102 explicitly) so the README stays accurate.
configured, unnoticed, until that change made it fail. The secret's description in
[`deploy-native.yml`](../../.github/workflows/deploy-native.yml) now says so.

aterga added a commit that referenced this pull request Jul 29, 2026
…exists (#104)

* Rewrite the inbound-SSH section: it described a state that no longer exists

Two of the section's load-bearing claims were false, and the repo is heading for
public visibility, so a reader would have been misled on both counts.

"It still does" need 22/tcp open to the world — no longer true. Internet-facing
SSH is closed on both hosts: each has a public-facing interface and a private
one, security groups attach per-interface, and the public one now carries a group
permitting 80/443 only. Verified from outside the VPN.

"Do not try to solve this with a narrower CIDR — there isn't one" — the evidence
for that was one observed public source address, which turned out to be an
artifact. Staging's DEPLOY_HOST named the public FQDN, so its deploys were
leaving over the internet rather than the VPN and presenting a public source.
Both hosts on private addresses present sources inside the private range. The
section spent four paragraphs arguing a conclusion that had already collapsed.

Rewritten to say what is now true and what is left: narrow the rule to the
private range and delete the world-facing one, after confirming the source
across both runner clusters, and add our own rule rather than depending on
another team's. The Calico reasoning is kept, demoted from "this is impossible"
to "verify rather than assume", which is what it actually supports. SSM is kept
as considered-and-declined with its reasoning intact, since the judgement could
change.

Also removes every internal address and resource identifier from the section, so
it is publication-safe (part of #101). Details that need them live on #91.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8ZshwKmjD5fZ4Hs9dS6zh

* Link deploy-native.yml the way the rest of this README does

The rewritten section referred to it as bare `deploy-native.yml` while lines
168-169 and 180 use a relative link. Matches them now.

Scoped to the .yml files deliberately: `deploy.sh` appears bare in nine other
places here and stays that way, so this follows the existing convention rather
than inventing a new one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8ZshwKmjD5fZ4Hs9dS6zh

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

4 participants