Gitea SSH to HTTPS Migration
Use this guide when Gitea users or automation still try to clone, push, or configure remotes through SSH after the infrastructure moved to HTTPS-only Git access.
Symptom
git cloneorgit pushthrough an SSH remote fails.- A repository remote still points at an SSH-style URL instead of HTTPS.
- A workflow expects the old Gitea SSH NodePort or direct
git.lumie-infra.comingress to exist. - Webhooks work in Gitea itself, but the expected in-cluster receiver does not see events.
Current Contract
The current checked-in Gitea configuration is HTTPS-only:
lumie-infra/bootstrap/gitea/helm-values.yamlkeepsgitea.config.server.DISABLE_SSH: true.- The old SSH NodePort path is not part of the current Argo CD source set.
bootstrap/gitea/argocd.yamlno longer carries the revertedbootstrap/gitea/manifestsdirect-ingress source.- Runtime access is expected to flow through the Teleport-backed Gitea hostname, while Gitea trusts the
X-Teleport-*reverse-proxy identity headers.
Diagnostic Path
-
Inspect the failing Git remote:
git remote -vAny
ssh://...orgit@...remote is stale for the current Gitea path. -
Verify the current Gitea values:
cd lumie-infrarg -n "DISABLE_SSH|ENABLE_REVERSE_PROXY_AUTHENTICATION|REVERSE_PROXY_AUTHENTICATION_USER" \bootstrap/gitea/helm-values.yaml -
Confirm the removed direct-ingress source has not been reintroduced:
rg -n "bootstrap/gitea/manifests|git.lumie-infra.com" bootstrap/gitea/argocd.yaml bootstrap/gitea -
If webhooks are failing, check the webhook host allow-list:
rg -n "ALLOWED_HOST_LIST" bootstrap/gitea/helm-values.yaml
Fix
- Convert developer and automation remotes to the HTTPS Gitea URL that is valid for the current Teleport-backed access path.
- Do not re-add an SSH NodePort just to preserve an old remote. That would reopen an intentionally removed access surface.
- If a non-Teleport route is ever reintroduced, strip
X-Teleport-*headers at that boundary before traffic reaches Gitea. - Keep
webhook.ALLOWED_HOST_LISTaligned with the in-cluster receiver requirements instead of solving webhook failures by reopening SSH.
Prevention
- Treat
DISABLE_SSH: trueas the source-of-truth operating mode. - Keep repo setup instructions and CI secrets in HTTPS form.
- Audit for stale SSH remotes during onboarding or when a clone or push problem appears.
- For the broader hardening history, use the Gitea Bootstrap Hardening incident retrospective.
Operational Detail
The important operational boundary is that Git transport and user identity now flow through the HTTPS and Teleport path. Re-adding SSH would not just restore an old convenience path; it would create a second authentication and network surface that bypasses the current hardening assumptions.
| Surface | Current expectation | Drift symptom |
|---|---|---|
| Developer remotes | HTTPS URL for the Teleport-backed host. | git@... or ssh://... appears in git remote -v. |
| Server config | DISABLE_SSH: true. | Gitea advertises SSH clone URLs again. |
| Argo CD sources | Helm values only for the current app shape. | Old direct ingress manifests return. |
| Reverse proxy identity | Gitea trusts intended Teleport headers only at the protected boundary. | A non-Teleport path can spoof X-Teleport-*. |
Webhook failures should be separated from Git transport failures. A webhook receiver problem does not justify reopening SSH.
Recovery Playbook
- Confirm whether the failing action is clone/push, webhook delivery, or UI access.
- For clone/push, convert the remote to HTTPS and retry before changing infrastructure.
- For automation, update CI variables, deploy keys, or credentials to the HTTPS contract.
- For webhook delivery, inspect
webhook.ALLOWED_HOST_LISTand the receiver service path. - Search the infrastructure repo for old SSH NodePort or direct-ingress manifests before closing the issue.
Verification Evidence
The issue is resolved when:
- affected repositories show only HTTPS Gitea remotes,
DISABLE_SSH: trueis present in the checked-in Helm values and live config,- Gitea no longer advertises SSH clone instructions to users,
- CI or automation that previously used SSH can clone and push through HTTPS,
- webhook delivery succeeds without adding an SSH path.
Anti-Patterns
- Adding an SSH NodePort because one automation still has an old remote.
- Solving a webhook allow-list problem by changing Git transport.
- Trusting
X-Teleport-*headers on a route that is not actually protected by Teleport. - Keeping mixed SSH and HTTPS onboarding instructions after the migration.