# Kubernetes deployment The site runs on the personal k3s cluster in the `personal-site` namespace and is served at https://jesseinit.dev (`www.` redirects to the apex). TLS comes from cert-manager (`letsencrypt-prod`). ## How deploys work `.github/workflows/deploy.yml` (run by Gitea Actions) on every push to `master`: 1. **Build site**: `npm ci && npm run build`, and renders the kustomization to catch manifest errors. 2. **Build and push image**: `tea.jesseinit.dev/jesseinit/personal-site:latest`. 3. **Deploy**: runs `kubectl apply -k k8s/`, then `kubectl rollout restart` so the pod pulls the new `:latest` (`imagePullPolicy: Always`), and waits for the rollout. There is no automatic rollback. Pull requests run step 1 only. Old images are cleaned up by the nightly `gitea-package-prune` cronjob. ### Required secrets (repo or `production` environment in Gitea) | Secret | Value | | ---------------- | ----------------------------------------------------- | | `REGISTRY_TOKEN` | Gitea token with `write:package` for `jesseinit` | | `KUBE_CONFIG` | base64-encoded kubeconfig for the personal cluster | ## Files - `namespace.yaml`: `personal-site` namespace - `deployment.yaml`: 1 replica, zero-downtime rolling updates, non-root, health checks - `service.yaml`: ClusterIP on port 80 → container port 3000 - `ingress.yaml`: nginx ingress + TLS for `jesseinit.dev` / `www.jesseinit.dev` - `configmap.yaml`: optional environment variables - `kustomization.yaml`: ties it together and sets the image ## Manual operations ```bash kubectl --context personal-cluster -n personal-site get pods,ingress,certificate kubectl --context personal-cluster -n personal-site logs -l app=jesseinit-portfolio -f # Deploy by hand (uses :latest) kubectl --context personal-cluster apply -k k8s/ kubectl --context personal-cluster -n personal-site rollout restart deployment/jesseinit-portfolio ```