# Deployment This repository owns the app-side deployment assets for `unrip`: - application source - Docker build inputs - Kubernetes manifests under `deploy/k8s/base/` - the Forgejo workflow under `.forgejo/workflows/deploy.yml` The shared platform bootstrap lives in the separate infra/platform repository. In the current local split, that repo is available as `../unrip3`. ## Ownership split Platform repo responsibilities: - Hetzner/OpenTofu provisioning - cloud-init and k3s bootstrap - shared registry - Forgejo and the Forgejo runner - cert-manager, Traefik, observability, and other cluster services This repo responsibilities: - app image build context - app namespace manifests - app runtime secret names - app deployment workflow ## Deployment model The intended production path is: 1. bootstrap the shared platform from the platform repo 2. create the `unrip` app secrets in the cluster 3. push this repo to Forgejo 4. let `.forgejo/workflows/deploy.yml` build and roll the app in-cluster The image build happens inside Kubernetes via Kaniko. The operator pushes Git, not Docker images. ## Platform prerequisite Before deploying this repo, the platform repo should already have completed its Hetzner bootstrap flow. From the current local split, the relevant operator docs live in: - `../unrip3/deploy/hetzner/README.md` - `../unrip3/deploy/k8s/README.md` - `../unrip3/docs/hetzner-self-hosted-ci-runbook.md` After platform bootstrap, you should have: - a reachable Forgejo instance - a reachable shared registry - a running Forgejo runner in the cluster - `../unrip3/.state/hetzner/kubeconfig.yaml` - `../unrip3/.state/hetzner/kubeconfig.incluster.yaml` ## One-time app namespace setup Apply the namespace first: ```bash kubectl apply -f deploy/k8s/base/namespace.yaml ``` Create the app runtime secret required by `near-intents-ingest`: ```bash kubectl -n unrip create secret generic unrip-secrets \ --from-literal=NEAR_INTENTS_API_KEY=replace_me ``` Create the registry auth secret used both for image pulls and the in-cluster Kaniko build job: ```bash kubectl -n unrip create secret docker-registry unrip-registry-creds \ --docker-server=registry. \ --docker-username="$REGISTRY_USERNAME" \ --docker-password="$REGISTRY_PASSWORD" ``` Then apply the app manifests: ```bash kubectl apply -k deploy/k8s/base ``` Notes: - `deploy/k8s/base/unrip.yaml` references `unrip-secrets` and `unrip-registry-creds`; they are not created by this repo. - the checked-in image `ghcr.io/example/unrip:bootstrap` is only a placeholder. The first real image tag is set by the Forgejo workflow or by a manual `kubectl set image`. ## Required Forgejo repo settings Required repo secret: - `KUBECONFIG_B64` Required repo variable: - `REGISTRY_HOST` Recommended repo variables when you do not want to rely on workflow defaults: - `PROJECT_NAME` - `PROJECT_NAMESPACE` - `PROJECT_DEPLOYMENTS` - `PROJECT_REGISTRY_SECRET_NAME` Recommended values for this repo: - `REGISTRY_HOST=registry.` - `PROJECT_NAME=unrip` - `PROJECT_NAMESPACE=unrip` - `PROJECT_DEPLOYMENTS=near-intents-ingest,dummy-reactor,dummy-executor,dummy-consumer` - `PROJECT_REGISTRY_SECRET_NAME=unrip-registry-creds` `KUBECONFIG_B64` should be the base64-encoded contents of the in-cluster kubeconfig produced by the platform repo, not the public workstation kubeconfig: ```bash base64 -w0 ../unrip3/.state/hetzner/kubeconfig.incluster.yaml ``` The current workflow does not read `REGISTRY_USERNAME` or `REGISTRY_PASSWORD` from Forgejo directly. Those values are still needed on the operator side when creating the `unrip-registry-creds` Kubernetes secret. ## Seed the repo into Forgejo Create the repository in Forgejo, add a `forgejo` remote for this repo, and push `main`. For example: ```bash git remote add forgejo https://git.//$(basename "$PWD").git git push forgejo HEAD:refs/heads/main ``` ## Routine deploy flow Once the repo exists in Forgejo and the repo settings above are configured: ```bash git push forgejo main ``` On push to `main`, `.forgejo/workflows/deploy.yml` does the following: 1. loads kubeconfig from `KUBECONFIG_B64` 2. applies `deploy/k8s/base` 3. creates an in-cluster Kaniko Job in the `unrip` namespace 4. builds and pushes `REGISTRY_HOST/unrip:` 5. updates the four app deployments and waits for rollout ## Observe rollout ```bash kubectl -n unrip get deploy,pods,pvc,job kubectl -n unrip rollout status deploy/near-intents-ingest kubectl -n unrip rollout status deploy/dummy-reactor kubectl -n unrip rollout status deploy/dummy-executor kubectl -n unrip rollout status deploy/dummy-consumer ``` Useful logs: ```bash kubectl -n unrip logs deploy/near-intents-ingest -f kubectl -n unrip logs deploy/dummy-reactor -f kubectl -n unrip logs deploy/dummy-executor -f kubectl -n unrip logs deploy/dummy-consumer -f kubectl -n unrip logs job/redpanda-topic-bootstrap ``` ## Local development Local iteration remains separate from the production path: ```bash cp .env.example .env docker compose up -d --build ``` That path is for local testing. Production rollout is Forgejo + Kubernetes.