Skip to main content

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 clone or git push through 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.com ingress 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.yaml keeps gitea.config.server.DISABLE_SSH: true.
  • The old SSH NodePort path is not part of the current Argo CD source set.
  • bootstrap/gitea/argocd.yaml no longer carries the reverted bootstrap/gitea/manifests direct-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

  1. Inspect the failing Git remote:

    git remote -v

    Any ssh://... or git@... remote is stale for the current Gitea path.

  2. Verify the current Gitea values:

    cd lumie-infra
    rg -n "DISABLE_SSH|ENABLE_REVERSE_PROXY_AUTHENTICATION|REVERSE_PROXY_AUTHENTICATION_USER" \
    bootstrap/gitea/helm-values.yaml
  3. 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
  4. 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_LIST aligned with the in-cluster receiver requirements instead of solving webhook failures by reopening SSH.

Prevention

  • Treat DISABLE_SSH: true as 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.

SurfaceCurrent expectationDrift symptom
Developer remotesHTTPS URL for the Teleport-backed host.git@... or ssh://... appears in git remote -v.
Server configDISABLE_SSH: true.Gitea advertises SSH clone URLs again.
Argo CD sourcesHelm values only for the current app shape.Old direct ingress manifests return.
Reverse proxy identityGitea 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

  1. Confirm whether the failing action is clone/push, webhook delivery, or UI access.
  2. For clone/push, convert the remote to HTTPS and retry before changing infrastructure.
  3. For automation, update CI variables, deploy keys, or credentials to the HTTPS contract.
  4. For webhook delivery, inspect webhook.ALLOWED_HOST_LIST and the receiver service path.
  5. 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: true is 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.