ghp: serve at ghp.unkin.net (gateway + cert + httproute + DNS) (#360)

## Why

Make `ghp.unkin.net` the primary URL that the ghp app responds to. Until now ghp has only been reachable at the internal admin name `ghp.k8s.syd1.au.unkin.net`; this promotes the apex `unkin.net` name to canonical (mirroring the gitea apex pattern) while keeping the k8s name as the admin/internal route.

## How

- **`apps/base/ghp/gateway.yaml`** — add `ghp.unkin.net` as the PRIMARY http/https listeners (`http-primary`/`https-primary`) and keep `ghp.k8s.syd1.au.unkin.net` as the admin route (`http-admin`/`https-admin`), mirroring gitea. Add the cert-manager gateway annotations (`cluster-issuer: vault-issuer`, `common-name: ghp.unkin.net`, `private-key-size: "4096"`) so cert-manager mints a NEW `ghp-gateway-tls` Secret with CN `ghp.unkin.net` + a SAN per TLS listener hostname (so it also covers the k8s host). Both https listeners' `certificateRefs` point at `ghp-gateway-tls`. This is a separate Secret from `ghp-tls` (ghp's own GitHub-impersonation cert), so cert-manager never fights over it. external-dns annotation stays scoped to the k8s host only — the apex is not published by external-dns.
- **`apps/base/ghp/httproute.yaml`** — add `ghp.unkin.net` to `hostnames`; update `parentRefs` to attach to the renamed `http-primary`/`http-admin`/`https-primary`/`https-admin` sections.
- **`apps/base/ghp/configmap.yaml`** — set `GHP_SERVER_MANAGEMENT_HOST: ghp.unkin.net` and `GHP_SERVER_BASE_URL: https://ghp.unkin.net`, so ghp serves its mgmt UI on that Host and OAuth callbacks use the new base.
- **`apps/base/bind-internal/authoritative/records.yaml`** — add a bind-operator `DNSRecord` `ghp-dns-internal` for `ghp.unkin.net` -> **A 198.18.200.4** (traefik-internal gateway VIP), mirroring the active `identity-dns-internal` record in the same file.

## ⚠️ NOTE — GitHub App OAuth callback must be updated on github.com

The GitHub App's OAuth callback URL must be changed on github.com to **`https://ghp.unkin.net/auth/github/callback`**. It was set to the k8s host in the runbook; OAuth login will break until this is updated.

## Note on DNS authority

The bind-operator apex `unkin.net` zone comments warn that some apex names may still be served by the puppet DNS master (records from PuppetDB), with the k8s bind cluster not yet confirmed as the live authority for `unkin.net`. This DNSRecord mirrors the already-active `identity`/`lb1` apex records in the same file, so it is consistent with them — but if the k8s bind cluster is not the live authority for `unkin.net`, `ghp.unkin.net` will not resolve from this Record alone and the puppet master record must be added instead.

## Validation

`kustomize build` of the ghp and bind-internal overlays render clean; kubeconform (strict) valid; yamllint + pre-commit clean. Not applied.

Reviewed-on: #360
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
This commit was merged in pull request #360.
This commit is contained in:
2026-08-13 22:48:23 +10:00
committed by BenVincent
parent 0130d538f5
commit 5e2eecda6b
4 changed files with 70 additions and 17 deletions
@@ -88,3 +88,17 @@ spec:
ttl: 600
values:
- 103.216.191.185
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: ghp-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: ghp
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the ghp Gateway serves ghp.unkin.net there.
- 198.18.200.4
+2 -2
View File
@@ -11,8 +11,8 @@ data:
GHP_SERVER_HTTP_LISTEN: ":8080"
GHP_METRICS_LISTEN: ":9136"
GHP_METRICS_ENABLED: "true"
GHP_SERVER_BASE_URL: https://ghp.k8s.syd1.au.unkin.net
GHP_SERVER_MANAGEMENT_HOST: ghp.k8s.syd1.au.unkin.net
GHP_SERVER_BASE_URL: https://ghp.unkin.net
GHP_SERVER_MANAGEMENT_HOST: ghp.unkin.net
# private_key key from the ghp-github-app Secret, mounted as a file.
GHP_GITHUB_PRIVATE_KEY_FILE: /etc/ghp/github-app/private_key
# cert-manager Certificate ghp-tls, mounted from the ghp-tls Secret.
+43 -13
View File
@@ -1,8 +1,12 @@
---
# Management UI ingress for ghp.k8s.syd1.au.unkin.net via the internal Traefik.
# TLS is terminated with the ghp-tls Secret produced by the cert-manager
# Certificate (which also carries the GitHub SANs); no cert-manager annotation
# here so the two never fight over the same Secret.
# HTTPS front for ghp, served on two names via the internal Traefik:
# ghp.unkin.net — canonical/primary (apex, bind-operator zone)
# ghp.k8s.syd1.au.unkin.net — admin/internal route (external-dns k8s.syd1 zone)
# The cert-manager annotations below make cert-manager mint the ghp-gateway-tls
# Secret with CN ghp.unkin.net and a DNS SAN for each TLS listener hostname
# automatically. This is a SEPARATE Secret from ghp-tls (certificate.yaml), which
# carries the GitHub impersonation SANs and is mounted by ghp itself — the two
# never share a Secret, so cert-manager does not fight over either.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
@@ -10,6 +14,12 @@ metadata:
traefik.io/instance: internal
annotations:
argocd.argoproj.io/sync-wave: "2"
cert-manager.io/cluster-issuer: vault-issuer
cert-manager.io/common-name: ghp.unkin.net
cert-manager.io/private-key-size: "4096"
# Only the k8s admin route is published by external-dns (it owns just the
# k8s.syd1.au.unkin.net zone). ghp.unkin.net lives in the apex zone and is
# served by the bind-operator DNSRecord — NOT managed here.
external-dns.alpha.kubernetes.io/hostname: ghp.k8s.syd1.au.unkin.net
external-dns.alpha.kubernetes.io/target: 198.18.200.4
name: ghp
@@ -17,23 +27,43 @@ metadata:
spec:
gatewayClassName: traefik-internal
listeners:
- allowedRoutes:
namespaces:
from: Same
hostname: ghp.k8s.syd1.au.unkin.net
name: http
- name: http-primary
port: 80
protocol: HTTP
- allowedRoutes:
hostname: ghp.unkin.net
allowedRoutes:
namespaces:
from: Same
hostname: ghp.k8s.syd1.au.unkin.net
name: https
- name: https-primary
port: 443
protocol: HTTPS
hostname: ghp.unkin.net
allowedRoutes:
namespaces:
from: Same
tls:
mode: Terminate
certificateRefs:
- group: ""
kind: Secret
name: ghp-tls
name: ghp-gateway-tls
- name: http-admin
port: 80
protocol: HTTP
hostname: ghp.k8s.syd1.au.unkin.net
allowedRoutes:
namespaces:
from: Same
- name: https-admin
port: 443
protocol: HTTPS
hostname: ghp.k8s.syd1.au.unkin.net
allowedRoutes:
namespaces:
from: Same
tls:
mode: Terminate
certificateRefs:
- group: ""
kind: Secret
name: ghp-gateway-tls
+11 -2
View File
@@ -8,16 +8,25 @@ metadata:
argocd.argoproj.io/sync-wave: "2"
spec:
hostnames:
- ghp.unkin.net
- ghp.k8s.syd1.au.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: ghp
sectionName: http
sectionName: http-primary
- group: gateway.networking.k8s.io
kind: Gateway
name: ghp
sectionName: https
sectionName: http-admin
- group: gateway.networking.k8s.io
kind: Gateway
name: ghp
sectionName: https-primary
- group: gateway.networking.k8s.io
kind: Gateway
name: ghp
sectionName: https-admin
rules:
- backendRefs:
- group: ""