Moves the production deploy from AWS to the Frostmoln production cluster (namespace `sites`).
- `deploy-prod` (AWS) has failed since CI left AWS: the runners have no `k8s.unbound.se` context, so the site on AWS still runs an older image. It's replaced by `deploy-prod-frostmoln`, the same pattern as Shiny's `deploy-frostmoln-staging`: `FROSTMOLN_PRODUCTION_DEPLOY_KEY` + `FROSTMOLN_PRODUCTION_CLUSTER_ID` (org), `BUILDTOOLS_FROSTMOLN_PRODUCTION` (org, target `prod-frostmoln`), `deploy prod-frostmoln -n sites`.
- Frostmoln enforces restricted Pod Security: the served image is `nginxinc/nginx-unprivileged` (uid 101, port 8080), with a matching securityContext; the Service is ClusterIP.
- `ingress-prod.yaml` (ALB) → `ingress-prod-frostmoln.yaml` (Traefik, Let's Encrypt).
Checked locally: the image serves `/health` and `/` (200) as uid 101 with all capabilities dropped.
**Merge after** infra's `feat/frostmoln-production-sites` is applied (namespace + org secret). The hostnames keep pointing at AWS until the Route 53 switch, a separate step; the certificate is issued after that.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Ma8eHhW59hLAJuLzBnLvUu
Reviewed-on: #243
## Summary
`k8s/deploy.yaml` takes the image from build-tools: `image: ${IMAGE}` instead of the hard-coded `oci.unbound.se/unboundsoftware/unbound-site:${COMMIT}`.
`deploy` substitutes `${IMAGE}` with `<registry>/<owner>/<name>:<tag>`, where the registry comes from the build-tools config and the tag is the value `${COMMIT}` gets today. The rendered reference is unchanged. Moving off `oci.unbound.se` later becomes one change in infra.
Validated on shiny/time-service#864: merged and deployed to AWS staging and Frostmoln staging with the same image. Prerequisites, all merged:
- unboundsoftware/infra#1808: registry in `BUILDTOOLS_FROSTMOLN_STAGING`
- shiny/acctest#952: acctest pins build-tools to the Gitea registry
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: #241
Remove cpu from resource limits while keeping memory limits and all
requests intact. CPU limits cause unnecessary throttling and
overcommit alerts when actual usage is far below limits.
Change label keys from "app" to "app.kubernetes.io/name"
to standardize the label format across the deployment,
service, and pod specifications. This improves clarity and
ensures alignment with Kubernetes best practices for
labeling and facilitates better management and
selection of resources.
Adjust the CPU and memory requests for the container from 10m and
10Mi to 5m and 5Mi, respectively, to optimize resource usage in
the Kubernetes deployment. This change aims to allocate fewer
resources while maintaining application performance.