The single edge: Traefik + cert-manager + DNS
All inbound HTTPS enters through one door: Traefik, the
Ingress controller bundled with k3s. Nothing else listens on public 80/443.
cert-manager obtains and renews TLS. Run kubectl on the node, or locally
once set up — Access.
The request path
Section titled “The request path”flowchart LR B([Browser]) -->|DNS lookup| DNS[(public A record)] DNS -->|node public IP| N[node :443] N --> T[Traefik<br/>terminates TLS] T -->|by hostname| Svc[Service] Svc --> P[Pod]
A request to api.<domain> resolves to the node’s public IP, hits :443, and Traefik terminates TLS and routes by
hostname. Each Ingress declares its host, entrypoint, and the cert-manager issuer:
metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-prod traefik.ingress.kubernetes.io/router.entrypoints: websecurespec: ingressClassName: traefik tls: - hosts: [api.<domain>] secretName: <app>-tlsBackends serve plain HTTP behind Traefik — e.g. Keycloak runs httpEnabled: true and trusts X-Forwarded-*
(proxy.headers: xforwarded).
How certificates get issued
Section titled “How certificates get issued”cert-manager solves Let’s Encrypt’s HTTP-01 challenge through Traefik on port 80:
- The public DNS A record for the hostname points at the node’s public IP.
- Port 80 is reachable from the internet (cloud firewall / VCN).
Let’s Encrypt fetches http://<host>/.well-known/... and stores the cert in the Ingress Secret (<app>-tls,
keycloak-tls). cert-manager renews it automatically.
What is public vs private
Section titled “What is public vs private”flowchart TD H1[ingress hosts<br/>control / vault / auth / app APIs] -->|public IP| Edge[node :443 Traefik] H2[kubectl: node or local] --> API[kube API]
- Ingress hostnames → public IP. On this company domain:
control.webbies.dev(Argo),vault.webbies.dev(Infisical),uat.auth.webbies.dev/auth.webbies.dev(Keycloak), plus each app API host. An app’s web frontend may live off-cluster (e.g. Vercel). kubectl→ on the node, or locally over Tailscale (Access). Either way, you do not need 6443 open on the public firewall.