Last updated

Provisioning ibl.ai on Google Cloud (GCP)

Mirrored from iblai/infra-cli ยท docs/GCP.md. This page is generated โ€” edit it in the repository, not here.

This guide walks you through standing up a single-server ibl.ai deployment on GCP, start to finish. If you've used the AWS flow, this is the same experience โ€” just point it at a GCP project.

Scope: single-server only. Multi-server and call-server remain AWS-only for now. Storage note: GCP creates no object storage. The platform keeps using AWS S3 โ€” you supply AWS credentials at the setup step (details in Storage).


What you'll end up with

                 Internet
                    โ”‚
      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
      โ”‚  Global external HTTPS LB   โ”‚   โ† one static IP, Google-managed TLS cert
      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                    โ”‚ HTTP :80
      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
      โ”‚  1 VM (Ubuntu 22.04, Docker) โ”‚   โ† external IP for SSH (locked to your IP)
      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
   VPC ยท 1 subnet ยท 2 firewall rules ยท Cloud DNS A-records โ†’ the LB IP

1. Prerequisites (one-time)

#WhatHow
1A GCP project with billing onYou'll pass its project ID (e.g. my-proj-123456, not the display name).
2Local toolsterraform (โ‰ฅ1.0) and gcloud installed. Plus this CLI: uv sync (add --extra gcp โ€” see step 4).
3AuthenticationPick one:
โ€ข Local: gcloud auth application-default login
โ€ข CI / automation: a service-account key JSON file
4GCP Python librariesuv sync --extra gcp (installs the Google SDKs this CLI needs).
5IAM roles + APIsRun iblai infra permissions --provider gcp to print them. Short version below.
6A domain + Cloud DNS zone (for HTTPS)Either already have a Cloud DNS zone for your domain, or let the wizard create one and you delegate it (see DNS). Skip this only if you want HTTP-only.
7Three AWS S3 buckets + AWS keysThe platform stores media/static/backups on S3. See Storage.

Roles + APIs (what permissions prints):

# Grant to your user or service account:
#   roles/compute.admin   roles/dns.admin   roles/iam.serviceAccountUser

# Enable the APIs:
gcloud services enable compute.googleapis.com dns.googleapis.com --project <PROJECT_ID>

Authentication โ€” pick one

Option A โ€” your Google account (easiest for local use):

gcloud auth application-default login

gcloud auth login alone is not enough โ€” Terraform and the CLI read Application Default Credentials, which only the command above writes.

Option B โ€” service-account key (for CI, or when your Workspace org blocks Option A's browser flow with an "Access blocked / admin needs to review" page):

PROJECT=<your-project-id>
gcloud iam service-accounts create infra-cli --project=$PROJECT
for R in roles/compute.admin roles/dns.admin roles/iam.serviceAccountUser; do
  gcloud projects add-iam-policy-binding $PROJECT \
    --member="serviceAccount:infra-cli@$PROJECT.iam.gserviceaccount.com" --role=$R --condition=None
done
gcloud iam service-accounts keys create ~/infra-cli-key.json \
  --iam-account="infra-cli@$PROJECT.iam.gserviceaccount.com"

Use it by choosing "Service-account key file" in the wizard, or setting GCP_CREDENTIALS_FILE=~/infra-cli-key.json in your .env. Keep the key file out of git; delete the service account when you no longer need it.

Verify you're ready (works with either option):

iblai infra permissions --provider gcp --check --project <PROJECT_ID>

2. Provision โ€” the easy way (interactive)

iblai infra provision
  1. Choose cloud โ†’ select GCP.
  2. Authentication โ†’ project ID, region/zone, and ADC or a key file. (Validated on the spot.)
  3. Project & compute โ†’ a name, environment, machine type (default e2-standard-8), disk.
  4. Network & access โ†’ it auto-detects your public IP and locks SSH to it.
  5. Domain & certificates โ†’ pick your Cloud DNS zone (or create one), or skip HTTPS.
  6. Review โ†’ confirm, and it provisions.

When it finishes you'll see the VM IP, the app URL, and an SSH command.

AI heads-up: e2-standard-8 has 32 GB RAM. If you'll enable AI features at setup, choose a 64 GB machine (e2-standard-16 or n2-highmem-8).


3. Provision โ€” the automated way (non-interactive)

Best for CI or repeatable runs.

cp .env.provision.gcp.example .env
# edit .env โ€” set PROVIDER=gcp, GCP_PROJECT_ID, DOMAIN, etc.
iblai infra provision-env -f .env

Minimum .env:

PROVIDER=gcp
GCP_PROJECT_ID=my-proj-123456
# GCP_CREDENTIALS_FILE=/path/to/key.json   # omit to use `gcloud` ADC
PROJECT_NAME=mydeploy
DOMAIN=platform.example.com
VPN_IP=auto                                 # your current IP; or a literal IP
CERT_METHOD=auto                            # managed cert if a Cloud DNS zone matches, else HTTP-only
DNS_ZONE_NAME=my-zone                        # the zone's resource name (managed cert)

See .env.provision.gcp.example for every option (machine type, disk, upload certs, create-zone, etc.).


4. DNS & HTTPS

The certificate is a classic Google-managed SSL cert covering your base domain

  • 19 ibl.ai subdomains. Two things to know:
  1. It validates asynchronously. apply finishes while the cert is still PROVISIONING. HTTPS goes live 10โ€“60 minutes later, once DNS resolves to the load balancer. This is normal โ€” the CLI tells you so.
  2. Your domain must be delegated to Cloud DNS. If you let the CLI create the zone (CREATE_DNS_ZONE=true or the wizard's "create" option), it prints the nameservers โ€” set those at your registrar. The cert can't validate until delegation is live.

Check cert status any time:

gcloud compute ssl-certificates describe <project>-<env>-cert --global \
  --format="value(managed.status)"        # PROVISIONING โ†’ ACTIVE when ready

No domain yet? Choose CERT_METHOD=none (or "Skip HTTPS" in the wizard) to get an HTTP-only load balancer, and add TLS later.


5. Storage uses AWS S3

GCP provisions no buckets. Before (or during) setup, make sure you have three S3 buckets in an AWS account, named on the standard convention:

<project>-<environment>-<domain-with-dots-as-dashes>-backups
<project>-<environment>-<domain-with-dots-as-dashes>-dm-media
<project>-<environment>-<domain-with-dots-as-dashes>-dm-static   # public-read

Example, for PROJECT_NAME=mydeploy, ENVIRONMENT=prod, DOMAIN=platform.example.com:

mydeploy-prod-platform-example-com-backups
mydeploy-prod-platform-example-com-dm-media
mydeploy-prod-platform-example-com-dm-static   (public-read)

You provide the AWS access key + secret at the setup step (below); the app on the GCP box uses them to reach S3 โ€” exactly as the AWS deployment does today.


6. Set up the platform

Provisioning creates the infrastructure; setup installs and configures ibl.ai on the VM (over SSH, via Ansible):

iblai infra setup <PROJECT_NAME>

It reads the VM's IP and SSH key from the saved state and prompts for the AWS credentials (for S3), a GitHub token, and admin details. This step is identical to the AWS flow.


7. Inspect and tear down

iblai infra list                 # all environments (GCP rows are marked "gcp ยท single")
iblai infra status <PROJECT_NAME> # details for one
iblai infra destroy <PROJECT_NAME>

destroy removes everything this tool created (VM, LB, firewall, DNS records, cert). A Cloud DNS zone you created outside the tool is left alone; a zone the tool created is removed.


Troubleshooting

SymptomCause & fix
No Application Default Credentials foundRun gcloud auth application-default login (gcloud auth login alone is not enough), or set GCP_CREDENTIALS_FILE to a service-account key.
"Access blocked: โ€ฆ admin needs to review" during ADC loginYour Workspace org blocks the ADC browser flow. Use a service-account key instead โ€” Authentication, Option B.
API not enabled for this projectgcloud services enable compute.googleapis.com dns.googleapis.com --project <ID>.
HTTPS not working right after applyExpected โ€” the managed cert takes 10โ€“60 min. Confirm DNS is delegated and A-records resolve to the LB IP.
Cert stuck in PROVISIONING / FAILED_NOT_VISIBLEA domain isn't resolving to the LB. Check registrar delegation and that every A-record points at the LB IP.
503 "no healthy upstream"Expected before iblai infra setup completes โ€” the LB health check probes the LMS heartbeat (learn.<domain>/heartbeat on :80), which only exists once the platform is installed. The backend flips healthy ~1โ€“2 min after setup finishes. If it persists: SSH in and check curl -H "Host: learn.<domain>" http://localhost/heartbeat returns 200, then gcloud compute backend-services get-health <project>-<env>-backend --global.
apply fails assigning an external IP, or SSH keys ignoredYour project enforces an org policy (no external IPs, or OS Login). This build targets loose projects (external IP + metadata SSH). Tell the maintainers โ€” IAP + OS Login is a documented alternative.
Can't SSH to the VMSSH is locked to the IP you provided (VPN_IP). If your IP changed, re-provision or update the firewall rule.

How it maps to AWS (for reference)

AWSGCP
VPC + 2 AZ subnetsVPC + 1 regional subnet
Security groupsFirewall rules (by network tag)
EC2 + key pairCompute instance + metadata SSH key
Application Load BalancerGlobal external ALB (EXTERNAL_MANAGED)
Target groupUnmanaged instance group + backend service
ACM cert (Route53-validated)Google-managed cert (Cloud DNS, async)
Route53 A-alias recordsCloud DNS A-records โ†’ static LB IP
S3 buckets(none โ€” reuses AWS S3)

Deeper internals live in CLAUDE.md under GCP Provider (single-server).

Copyright ยฉ ibl.ai | support@iblai.zendesk.com