Deploy Retool on GCP with Terraform
Deploy a production-ready self-hosted Retool instance on Google Cloud using Retool's Terraform blueprints.
Self-hosted Retool must be deployed on a Kubernetes cluster with Helm. Retool provides an officially maintained Terraform blueprint that provisions all the required infrastructure and deploys Retool using the official Helm chart.
Budget roughly 1-3 hours from your first terraform apply to a working login page, though actual time varies depending on your cloud environment and account configuration. Infrastructure provisioning, DNS propagation, and certificate issuance can each take longer than expected.
Deployment architecture
This tutorial provisions the following GCP infrastructure and Retool services.
- Network and infrastructure
- Retool
These components support the deployment but don't run Retool containers directly.
| Component | Purpose |
|---|---|
| VPC (Virtual Private Cloud) with private service access | Isolates the cluster and database, and gives the cluster private connectivity to Cloud SQL. |
| External HTTPS Load Balancer (via GKE Gateway) | Handles traffic ingress and routing to the cluster. |
| Cloud DNS managed zone | Hosts the DNS records for your domain. |
| Certificate Manager certificate | Provides the TLS certificate for https://your-domain. |
| Secret Manager secrets | Stores database credentials and other sensitive values used by the Helm release. |
Retool is deployed on a GKE cluster as a set of containers and services, including workflow services and the agent sandbox.
| Component | Purpose | Container or service |
|---|---|---|
| Cloud SQL (PostgreSQL) | Stores Retool's application data. | postgres |
| Cloud Storage bucket | Stores app storage, workflow artifacts, and agent sandbox snapshots. | Blob storage |
Before you start
Install the required tools and collect the account details and access you need.
You can create a new project with the gcloud CLI tool using gcloud projects create and then link it to your billing account with gcloud billing projects link.
Prepare the GCP project for deployment
You can prepare the GCP project using the gcloud CLI tool. First, use gcloud to sign in to GCP. Your account must have the necessary permissions to create and manage VPC networks, GKE clusters, Cloud SQL instances, service accounts, Secret Manager secrets, and Cloud DNS zones.
gcloud auth application-default login
Once authenticated, enable the required APIs on the project.
gcloud services enable \
compute.googleapis.com \
servicenetworking.googleapis.com \
sqladmin.googleapis.com \
container.googleapis.com \
secretmanager.googleapis.com \
dns.googleapis.com \
certificatemanager.googleapis.com \
--project your-project-id
Configuring the required APIs before starting the deployment will avoid API-propagation races that might occur.
Next, check the project's regional SSD quota. GCP's default SSD_TOTAL_GB regional quota (500GB on many new projects) can exactly match this blueprint's default node pool footprint (5 nodes, 100GB each), leaving no headroom for the cluster autoscaler or for GKE's routine surge-based node pool operations, such as version upgrades. Check your project's current quota and usage in your target region:
gcloud compute regions describe your-region --project your-project-id \
--format="table(quotas.metric,quotas.limit,quotas.usage)" | grep SSD_TOTAL_GB
If the available headroom is less than double your expected node pool's total disk usage, request a quota increase before deploying.
1. Configure the template
Use the following steps to configure the template.
Start from an example
Copy the gcp_all_inclusive example's files to a local working directory.
- curl
- git clone
mkdir my-retool-deployment
cd my-retool-deployment
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/gcp_all_inclusive/main.tf --output-dir . -O
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/gcp_all_inclusive/provider.example.tf --output-dir . -O
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/gcp_all_inclusive/versions.tf --output-dir . -O
git clone https://github.com/tryretool/terraform-retool-self-hosted-blueprints.git
ls terraform-retool-self-hosted-blueprints/examples/
cp -r terraform-retool-self-hosted-blueprints/examples/gcp_all_inclusive my-retool-deployment
cd my-retool-deployment
Example directory names may change between releases. If a command above fails, check the current names in the blueprints repository and adjust the path accordingly.
Rename the provider template
mv provider.example.tf providers.tf
Update the root template
Open main.tf and update each of the following sections with the required values.
locals
locals contains the core GCP project information.
locals {
prefix = "your-retool-org" # The prefix for all GCP resource names. Must be globally unique.
project_id = "your-project-id" # Your GCP project ID.
region = "us-east1" # The region in which to deploy.
domain_name = "retool.example.com" # The fully qualified domain name to use for the deployment.
}
prefix also names the GCS bucket used for app storage, workflow artifacts, and agent sandbox snapshots (retool-<prefix>-rr). GCS bucket names are unique across every GCP project, so a generic value like retool-prod can collide with a bucket another customer already created. Choose a prefix specific to your organization to avoid this.
vpc
vpc provisions your VPC network, including the GKE subnet ranges and the private service access range used for Cloud SQL. Set private_service_access_ip_range to a range that can scale for production Cloud SQL usage, such as a /16:
module "vpc" {
# ...
private_service_access_ip_range = "10.3.0.0/16"
}
retool-services
retool-services contains Retool-specific deployment information, such as the license key and services to enable.
module "retool-services" {
# ...
license_key = "your-license-key"
enable_agent_sandbox = true # required for Retool AI agents
enable_rr_gcs = true # required for app storage, workflow artifacts, and sandbox snapshots
}
retool
retool specifies the Helm chart version and Retool image tag to use. Retool's new app builder requires self-hosted Retool 4.0 or later. Getting the chart version right matters since the chart and image tag need to be compatible with each other. Check the current version on Artifact Hub or the retool-helm releases page, and pin to it explicitly rather than leaving it unset.
module "retool" {
# ...
retool_helm_chart_version = "6.11.10" # check retool-helm releases for the latest
retool_helm_extra_values = [yamlencode({
image = {
tag = "4.0.9-stable" # current recommended stable release; never the "latest" tag
}
})]
}
All services must run the same tag. Tag mismatches can cause the deployment to run incorrectly.
2. Initialize Terraform
Run terraform init to trigger the download of provider plugins and module sources.
Configure a remote backend to store Terraform state before running terraform apply. The default local backend stores state in a file on disk. If that file is lost or corrupted, you lose the ability to manage your infrastructure with Terraform. Use a GCS bucket backend for production deployments.
The GCS bucket used for the backend must already exist before you run terraform init, since Terraform can't provision the backend that stores its own state. Create it first, then add a backend block to providers.tf:
terraform {
backend "gcs" {
bucket = "your-terraform-state-bucket"
prefix = "retool"
}
}
3. Apply the configuration
Run terraform apply -auto-approve to apply the template that provisions infrastructure. Provisioning occurs automatically in the following order:
- VPC.
- GKE.
- Cloud SQL.
- Retool services.
- Ingress.
- Helm release.
Provisioning time varies depending on your project and region, with Cloud SQL typically taking the longest amount of time.
Resolve timeouts caused by Cloud SQL
If the apply provisioning times out on Cloud SQL but the instance shows as RUNNABLE in the Cloud SQL console, you can import it and re-apply rather than recreating it.
terraform import module.db-main.module.pg.google_sql_database_instance.default your-project/instance-name
terraform apply -auto-approve
If the instance is in a FAILED state from a previous bad apply, delete it manually before re-applying:
gcloud sql instances delete instance-name --project=your-project-id --quiet
terraform apply -auto-approve
4. Configure DNS
Once the apply outputs nameservers, delegate your domain to them as soon as possible. Certificate Manager begins ACME validation immediately, and delaying delegation adds time to certificate issuance.
You can retrieve the Cloud DNS managed zone nameservers from the terraform output:
terraform output -json modules | jq -r '.["user-ingress"].zone_name_servers[]'
Configure an NS record for each nameserver that points to your chosen FQDN. The following example represents NS records configured for a retool subdomain:
NS retool ns-cloud-e1.googledomains.com.
NS retool ns-cloud-e2.googledomains.com.
NS retool ns-cloud-e3.googledomains.com.
NS retool ns-cloud-e4.googledomains.com.
Once configured, use dig to confirm the changes have propagated:
dig +short NS retool.example.com
The gcp-user-ingress module manages the A record (via external-dns) pointing at the reserved static IP, and the Certificate Manager DNS authorization validates automatically once delegation completes. Certificate issuance time varies and can occasionally take an hour or more, even after NS propagation completes. Once active, your deployment automatically becomes available at the FQDN you specified (e.g., https://retool.example.com).
5. Verify deployment infrastructure
Before you begin setting up Retool, confirm that the deployment infrastructure is healthy. Retrieve the cluster details from the Terraform output and then update your kubeconfig:
CLUSTER_NAME=$(terraform output -json modules | jq -r '.["gke"].cluster.name')
CLUSTER_REGION=$(terraform output -json modules | jq -r '.["gke"].cluster.location')
gcloud container clusters get-credentials "$CLUSTER_NAME" --region "$CLUSTER_REGION" --project your-project-id
Use kubectl to verify all pods are running:
kubectl get pods -n default
6. Enable Temporal
Retool's new app builder, Workflows, and Agents all require Temporal to orchestrate agent sandbox provisioning, workflow execution, and agent run execution. Choose how you'll use Temporal and then update main.tf with one of the following configurations accordingly. In most cases, a Retool-managed cluster is the lowest-friction, lowest-cost, and most reliable option, and is recommended unless you have a specific reason to self-manage.
- Retool-managed cluster
- Self-managed cluster
- Local cluster
Recommended
Retool hosts and manages a Temporal Cloud cluster for you. No Helm configuration is required.
- Go to Settings → Workflows and click Enroll now.
- Once your namespace initializes, return to the page and click Complete setup.
Your deployment needs outbound egress on ports 443 and 7233 to *.retool.com, *.tryretool.com, *.temporal.io, and *.tmprl.cloud.
Use an existing Temporal cluster, either on Temporal Cloud or in your own infrastructure. Add the temporal block to retool_helm_extra_values in main.tf:
retool_helm_extra_values = [yamlencode({
image = { tag = "4.0.9-stable" }
temporal = {
enabled = true
host = "your-temporal-frontend-host"
port = 7233
namespace = "your-temporal-namespace"
sslEnabled = true
sslCert = "base64-encoded-client-cert"
sslKey = "base64-encoded-client-key"
}
})]
temporal.enabled is incompatible with the retool-temporal-services-helm subchart. Enable only one.
If your cluster runs on Temporal Cloud, your deployment also needs outbound egress on ports 443 and 7233 to *.temporal.io and *.tmprl.cloud.
Spin up a new Temporal cluster alongside your deployment, using the bundled retool-temporal-services-helm subchart. Pre-create the Temporal databases in Cloud SQL first, since Cloud SQL is only reachable from inside the VPC:
CLOUD_SQL_IP=$(terraform output -json modules | jq -r '.["db-main"].address')
DB_PASSWORD=$(gcloud secrets versions access latest --secret=your-prefix-main-db-password --project=your-project-id)
kubectl run psql-tmp --image=postgres:16 --restart=Never --rm -i -n default \
--env="PGPASSWORD=$DB_PASSWORD" \
-- psql -h $CLOUD_SQL_IP -U retool -d retool \
-c "CREATE DATABASE temporal;" \
-c "CREATE DATABASE temporal_visibility;"
Enable the subchart in retool_helm_extra_values:
retool_helm_extra_values = [yamlencode({
image = { tag = "4.0.9-stable" }
"retool-temporal-services-helm" = {
enabled = true
server = {
config = {
persistence = {
default = {
sql = {
host = "your-cloud-sql-private-ip"
port = 5432
database = "temporal"
user = "retool"
password = "your-db-password"
tls = {
enabled = true
enableHostVerification = false
}
}
}
visibility = {
sql = {
host = "your-cloud-sql-private-ip"
port = 5432
database = "temporal_visibility"
user = "retool"
password = "your-db-password"
tls = {
enabled = true
enableHostVerification = false
}
}
}
}
}
}
}
})]
The temporal-frontend, temporal-history, temporal-matching, and temporal-worker pods should reach Running within a few minutes.
After updating your configuration for Temporal, re-apply the changes:
terraform apply -auto-approve
7. Complete setup in Retool
Once the deployment is healthy, navigate to the Signup and create your user account. The first user account of the organization is automatically the default admin.
After you sign up, the deployment performs some one-time setup steps in the background. If a feature doesn't seem to work right away, wait a few minutes before troubleshooting further.
Configure and enable AI functionality
Retool's AI features are not enabled by default. You must first create an AI resource using an API key from your AI provider, then enable the features to use.
Create an AI resource
You must create an AI resource using a bring-your-own-key (BYOK) credential to make use of any AI features in Retool. Navigate to the Resources page and create an AI resource using a supported AI provider.
Assist for classic apps supports OpenAI and Anthropic AI resources only. If you plan to use this feature, you must provide an OpenAI or Anthropic API key regardless of whether you use another AI provider, such as Google Gemini.
Enable features
Retool's AI features are not enabled by default. Navigate to the AI settings page and enable the features you plan to use. Retool AI Access is the main control for all AI features and must be enabled first.
| Feature | Description |
|---|---|
| Retool AI Access | Main control for all AI features. Must be enabled before any other feature below. |
| Updated App Builder | Required to build and edit apps in the new app builder. Disabling this setting restricts users to the classic app builder. |
| AI Actions | Use AI to power workflows and apps, from summarization and classification to query generation, within the classic app builder. See AI Actions. |
| AI Agents | Build and deploy autonomous Agents that can reason over data, docs, and actions. |
| Assist Tab | Enable app generation, editing, and explanation through natural language prompts from within the classic app builder. |
| Vector Storage | Store text embeddings in a Retool-managed vector store to provide context to AI models. |
| Ask AI | Enable prompt-based code assistance in the query editor to generate, edit, or troubleshoot queries. |
| Agent Sharing | Allow users to share public chat threads with an AI Agent. |
| Function Generation for Agents | Function generation within AI agents. |
After enabling Updated App Builder, do a hard refresh of your browser (for example, Cmd/Ctrl+Shift+R). Without it, you may see permission errors when trying to create or open apps in the new app builder.
Verify your setup
After completing the configuration in Retool, confirm everything functions correctly end to end.