Skip to main content

Deploy Retool on AWS with Terraform

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 AWS infrastructure and Retool services.

These components support the deployment but don't run Retool containers directly.

ComponentPurpose
VPC (Virtual Private Cloud) with NAT (Network Address Translation) gateways across 3 AZs (Availability Zones)Isolates the cluster and database, and provides outbound connectivity for private subnets.
ALB (Application Load Balancer)Handles traffic ingress and routing to the cluster.
Route 53 hosted zoneHosts the DNS records for your domain.
ACM certificateProvides the TLS certificate for https://your-domain.
Secrets Manager secretsStores database credentials and other sensitive values used by the Helm release.
IAM rolesGrants the cluster and its services the AWS permissions they need.

Before you start

Install the required tools and collect the account details and access you need.

Your AWS CLI profile needs permissions to create and manage VPCs, EKS clusters, RDS instances, S3 buckets, IAM roles, ACM certificates, and Route 53 hosted zones.

Prepare the AWS account for deployment

If you don't already have an AWS CLI profile with sufficient permissions, run aws configure --profile your-profile-name and provide your access key, secret key, and default region. Then confirm it's authenticated:

Verify AWS CLI authentication
aws sts get-caller-identity --profile your-profile-name

Confirm your account has a payment method on file and isn't limited to the AWS Free Tier, which blocks RDS instance creation.

Next, check the account's vCPU quota for on-demand standard instances. Many new or personal AWS accounts default to a 32-vCPU quota for this instance family, which can exactly match this blueprint's baseline node usage, leaving no headroom for Karpenter to launch new nodes during routine scaling or rolling updates:

Check on-demand standard instance vCPU quota
aws service-quotas get-service-quota --region your-region \
--service-code ec2 --quota-code L-1216C47A \
--query 'Quota.{Name:QuotaName,Value:Value}'

If the available headroom is small relative to your expected node 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 aws_all_inclusive example's files to a local working directory.

mkdir my-retool-deployment
cd my-retool-deployment
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/aws_all_inclusive/main.tf --output-dir . -O
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/aws_all_inclusive/provider.example.tf --output-dir . -O
curl -f https://raw.githubusercontent.com/tryretool/terraform-retool-self-hosted-blueprints/refs/heads/main/examples/aws_all_inclusive/versions.tf --output-dir . -O
note

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 deployment information.

locals
locals {
prefix = "your-retool-org" # The prefix for all AWS resource names. Must be globally unique.
aws_profile = "your-aws-profile" # AWS CLI profile with sufficient permissions.
region = "us-east-1" # The region in which to deploy.
tags = {}
domain_name = "retool.example.com" # The fully qualified domain name to use for the deployment.

# Start with HTTP. You enable HTTPS in a later step, after DNS is delegated.
enable_user_ingress_https = false
}

prefix also names the S3 bucket used for app storage, workflow artifacts, and agent sandbox snapshots (retool-<prefix>-rr). S3 bucket names are unique across every AWS account, 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.

db-main

db-main provisions the RDS PostgreSQL instance. Override the engine version, since the default doesn't exist in every region, and, for new accounts, disable backup retention:

db-main
module "db-main" {
# ...
engine_version = "16.9" # the default (16.8) doesn't exist in every region
backup_retention_period = 0 # set higher once you need automated backups
}

retool-services

retool-services contains Retool-specific deployment information, such as the license key and services to enable.

retool-services
module "retool-services" {
# ...
license_key = "your-license-key"
enable_agent_sandbox = true # required for Retool AI agents
enable_rr_s3 = 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. The blueprint's default Helm chart version and image tag are both outdated, so update both explicitly. 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:

retool
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.7-stable" # current recommended stable release; never the "latest" tag
}
})]
}
Warning

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.

Caution

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 an S3 backend for production deployments.

The S3 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. Set use_lockfile = true for native S3 state locking rather than a separate DynamoDB table:

providers.tf
terraform {
backend "s3" {
bucket = "your-terraform-state-bucket"
key = "retool/terraform.tfstate"
region = "us-east-1"
use_lockfile = true
encrypt = true
}
}

3. Apply the configuration

Run terraform apply -auto-approve to apply the template that provisions infrastructure. Provisioning occurs automatically in the following order:

  1. VPC.
  2. EKS.
  3. RDS.
  4. Retool services.
  5. Helm release.
  6. Load balancer.

Provisioning time varies depending on your account and region, with EKS cluster creation and RDS instance provisioning typically taking the longest amount of time.

note

The blueprint uses Karpenter to autoscale worker nodes. Karpenter's controller pods must be Running before workload pods can schedule. If pods are stuck Pending, check the Karpenter controller logs:

kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter
Resolve a tainted EKS cluster after an interrupted apply

If the apply is interrupted and EKS is tainted on resume, untaint it and re-apply:

Untaint and re-apply EKS
terraform untaint 'module.eks.module.eks.aws_eks_cluster.this[0]'
terraform apply -auto-approve

4. Configure DNS

Once the apply completes, delegate your domain to the Route 53 hosted zone that the blueprint created.

Retrieve the hosted zone nameservers:

terraform output -json modules | jq -r '.["user-ingress"].zone_name_servers[]'

Update the NS record for your domain at your registrar or parent DNS provider to point to these nameservers.

Retrieve the load balancer DNS name to verify before full cutover:

terraform output -json modules | jq -r '.["user-ingress"].alb_dns_name'

Once DNS propagates, your domain resolves to the load balancer. You can verify before delegating the primary domain using a temporary CNAME in your DNS provider:

blueprints.retool.example.com  →  <alb-dns-name>

This subdomain is created automatically by the blueprints.

5. Enable HTTPS

After DNS is delegated and propagated, enable HTTPS:

  1. In main.tf, set enable_user_ingress_https = true.
  2. Run terraform apply -auto-approve again. This provisions the HTTPS listener, updates the load balancer configuration, and updates the Helm release to use secure cookies.

The re-apply is generally much faster than the initial apply, though it can take longer if ACM validation is slow to complete.

note

The blueprint provisions a wildcard ACM certificate (*.yourdomain.com) in addition to the apex certificate. ACM validates both automatically against the Route 53 hosted zone the blueprint already manages, so no manual CNAME records are required. Terraform may pause during this re-apply while validation completes.

6. 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 '.["eks"].cluster.name')
REGION=$(awk -F'"' '/region[[:space:]]*=/{print $2; exit}' main.tf)
aws eks update-kubeconfig --name "$CLUSTER_NAME" --region "$REGION"

Use kubectl to verify all pods are running:

kubectl get pods -n default

Expect pods for:

  • retool
  • retool-r2-agent-worker
  • retool-workflow-backend
  • retool-workflow-worker
  • retool-agent-sandbox-controller
  • retool-agent-sandbox-proxy
  • retool-code-executor
  • retool-js-executor

7. 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.

Recommended

Retool hosts and manages a Temporal Cloud cluster for you. No Helm configuration is required.

  1. Go to SettingsWorkflows and click Enroll now.
  2. 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.

After updating your configuration for Temporal, re-apply the changes:

terraform apply -auto-approve

8. 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.

note

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.

note

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.

FeatureDescription
Retool AI AccessMain control for all AI features. Must be enabled before any other feature below.
Updated App BuilderRequired to build and edit apps in the new app builder. Disabling this setting restricts users to the classic app builder.
AI ActionsUse AI to power workflows and apps, from summarization and classification to query generation, within the classic app builder. See AI Actions.
AI AgentsBuild and deploy autonomous Agents that can reason over data, docs, and actions.
Assist TabEnable app generation, editing, and explanation through natural language prompts from within the classic app builder.
Vector StorageStore text embeddings in a Retool-managed vector store to provide context to AI models.
Ask AIEnable prompt-based code assistance in the query editor to generate, edit, or troubleshoot queries.
Agent SharingAllow users to share public chat threads with an AI Agent.
Function Generation for AgentsFunction generation within AI agents.
note

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.