koborin.ai

Technical proving ground for exploring AI, cloud architecture, and continuous learning.
Astro (
) runs on Cloud Run behind a global HTTPS load balancer, and the entire stack (app + infra) lives in this monorepo with Pulumi (Go).
Architecture
Dev/Prod share the same HTTPS load balancer and Artifact Registry; only Cloud Run scaling/access policies differ.
---
title: "Google Cloud Project"
---
flowchart LR
subgraph PULUMI_STATE["Pulumi Backend State - GCS"]
STATE_SHARED["shared"]
STATE_DEV["dev"]
STATE_PROD["prod"]
end
subgraph SHARED["Shared Resources"]
APIS["APIs"]
ARTIFACT["Artifact Registry"]
WIF["Workload Identity<br/>Pool/Provider"]
end
subgraph DNS["Cloudflare DNS (manual)"]
DEV_DOMAIN["dev.koborin.ai<br/>A record"]
PROD_DOMAIN["koborin.ai<br/>A record"]
end
subgraph LB["Unified HTTPS LB - shared"]
STATIC_IP["Static IP<br/>PREMIUM tier"]
SSL_CERT["Managed SSL Cert<br/>multi-domain"]
URL_MAP["URL Map<br/>host routing"]
HTTPS_PROXY["HTTPS Proxy"]
end
subgraph DEV_BACKEND["Dev Backend"]
DEV_IAP["IAP<br/>+ X-Robots-Tag"]
DEV_NEG["Serverless NEG"]
DEV_CR["Cloud Run<br/>koborin-ai-web-dev (Astro)<br/>(LB-only ingress)"]
end
subgraph PROD_BACKEND["Prod Backend"]
PROD_NEG["Serverless NEG"]
PROD_CR["Cloud Run<br/>koborin-ai-web-prod (Astro)<br/>(LB-only ingress)"]
end
subgraph CICD["GitHub Actions"]
GH_WIF["Workload Identity<br/>Federation"]
PULUMI_SA["Pulumi SA"]
end
STATE_SHARED -.-> SHARED
STATE_SHARED -.-> LB
STATE_DEV -.-> DEV_BACKEND
STATE_PROD -.-> PROD_BACKEND
ARTIFACT -.->|"Container Image"| DEV_CR
ARTIFACT -.->|"Container Image"| PROD_CR
DEV_DOMAIN --> STATIC_IP
PROD_DOMAIN --> STATIC_IP
STATIC_IP --> SSL_CERT
SSL_CERT --> HTTPS_PROXY
HTTPS_PROXY --> URL_MAP
URL_MAP -->|"dev host"| DEV_IAP
URL_MAP -->|"prod host"| PROD_NEG
DEV_IAP --> DEV_NEG
DEV_NEG --> DEV_CR
PROD_NEG --> PROD_CR
GH_WIF -.->|"Authenticate"| WIF
WIF -.->|"Impersonate"| PULUMI_SA
PULUMI_SA -.->|"Preview/Up"| PULUMI_STATE
style PULUMI_STATE fill:#E8E8E8,color:#000,stroke:#666,stroke-width:2px
style STATE_SHARED fill:#F5F5F5,color:#000
style STATE_DEV fill:#F5F5F5,color:#000
style STATE_PROD fill:#F5F5F5,color:#000
style APIS fill:#9E9E9E,color:#fff
style ARTIFACT fill:#9E9E9E,color:#fff
style WIF fill:#9E9E9E,color:#fff
style STATIC_IP fill:#00B6AC,color:#fff
style SSL_CERT fill:#00B6AC,color:#fff
style URL_MAP fill:#00B6AC,color:#fff
style HTTPS_PROXY fill:#00B6AC,color:#fff
style DEV_IAP fill:#F76560,color:#fff
style DEV_CR fill:#4A90E2,color:#fff
style PROD_CR fill:#4A90E2,color:#fff
style GH_WIF fill:#FFB74D,color:#000
style PULUMI_SA fill:#FFB74D,color:#000
DNS is hosted in Cloudflare. Pulumi does not manage DNS records; add/update koborin.ai / dev.koborin.ai A records manually whenever the load balancer IP changes.
Environment matrix
| Layer | Dev (dev.koborin.ai) | Prod (koborin.ai) |
|---|
| Runtime | Cloud Run (koborin-ai-web-dev) | Cloud Run (koborin-ai-web-prod) |
| Access | IAP allow list + X-Robots-Tag: noindex | Public (no IAP) |
| Ingress | INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER | INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER |
| Scaling | Min: 0, Max: 1 | Min: 0, Max: 10 |
| Env Vars | NODE_ENV=development, NEXT_PUBLIC_ENV=dev | NODE_ENV=production, NEXT_PUBLIC_ENV=prod |
| Content | Same MDX content (no env-specific filtering) | Same MDX content (no env-specific filtering) |
| Analytics | GA4 (debug view) + optional server events | GA4 + server events + Cloud Monitoring |
CI/CD
Infrastructure and application deploys are each handled by dedicated GitHub Actions workflows using Workload Identity Federation.
flowchart LR
subgraph GitHub Actions
planInfra[plan-infra.yml]
releaseInfra[release-infra.yml]
appCI[app-ci.yml]
appRelease[app-release.yml]
end
subgraph Cloud Build
buildApp[Docker Build\n+ Artifact Registry]
end
subgraph Pulumi
sharedStack[Shared Stack]
envStacks[Dev/Prod Stacks]
end
planInfra --> sharedStack
releaseInfra --> sharedStack
releaseInfra --> envStacks
appCI -->|PR validation| GitHub
appRelease --> buildApp --> envStacks