Production-ready Terraform configurations for deploying secure Databricks workspaces on AWS with Private Link, Unity Catalog, and customer-managed encryption.
π Authentication Setup Guide β - Stuck on AWS/Databricks authentication? Start here!
awsdb4u/
βββ aws-pl-ws/ # Databricks Private Link workspace deployments
β βββ databricks-aws-production/ # β¨ Production-ready deployment (Recommended)
β β βββ modules/ # 7 modular Terraform modules
β β βββ docs/ # Visual-first documentation
β β βββ terraform.tfvars.example # Configuration template
β β βββ quick-destroy.sh # Safe cleanup script
β βββ modular-version/ # Legacy version (deprecated)
βββ README.md # This file
Production-ready, fully modularized Terraform deployment with comprehensive documentation and enterprise features.
Key Features:
Documentation:
Quick Deploy:
cd aws-pl-ws/databricks-aws-production
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your values
terraform init
terraform apply
Original modular version - deprecated in favor of databricks-aws-production.
Migration: Users of modular-version should migrate to databricks-aws-production for:
| Feature | databricks-aws-production | modular-version (legacy) |
|---|---|---|
| Status | β Active | β οΈ Deprecated |
| Documentation | Visual-first, comprehensive | Basic README |
| Quick Start | 5-minute guide | Manual configuration |
| Architecture Diagrams | β Mermaid diagrams | β None |
| Troubleshooting | β Detailed guide | β Limited |
| CMK Support | β Dual-layer (S3 + Workspace) | β Basic |
| BYOR Support | β Removed (CREATE only) | β N/A |
| Module Count | 7 modules | 7 modules |
| Configuration | .tfvars.example template |
Manual setup |
databricks-aws-production if you want:modular-version if you:Both deployments create a secure, production-ready Databricks workspace with:
graph TB
subgraph "AWS VPC (10.0.0.0/22)"
subgraph "Public Subnets (/26)"
NAT1[NAT Gateway 1<br/>10.0.0.0/26]
NAT2[NAT Gateway 2<br/>10.0.0.64/26]
IGW[Internet Gateway]
end
subgraph "Private Subnets (/24 - Databricks Clusters)"
PRIV1[Private Subnet 1<br/>10.0.1.0/24<br/>251 usable IPs]
PRIV2[Private Subnet 2<br/>10.0.2.0/24<br/>251 usable IPs]
end
subgraph "PrivateLink Subnets (/26 - VPC Endpoints)"
VPCE1[Workspace VPCE<br/>10.0.3.0/26]
VPCE2[Relay VPCE<br/>10.0.3.64/26]
STS[STS VPCE]
KINESIS[Kinesis VPCE]
end
subgraph "Storage"
S3[S3 Buckets<br/>DBFS + UC]
S3GW[S3 Gateway Endpoint]
end
end
subgraph "Databricks Control Plane"
CONTROL[Databricks Control Plane<br/>accounts.cloud.databricks.com]
end
PRIV1 -->|NAT| NAT1
PRIV2 -->|NAT| NAT2
NAT1 --> IGW
NAT2 --> IGW
PRIV1 -.->|Private Link| VPCE1
PRIV2 -.->|Private Link| VPCE2
VPCE1 -.->|Backend Private Link| CONTROL
VPCE2 -.->|Secure Cluster Connectivity| CONTROL
PRIV1 -->|S3 Access| S3GW
PRIV2 -->|S3 Access| S3GW
S3GW --> S3
style CONTROL fill:#FF3621
style S3 fill:#569A31
style VPCE1 fill:#FF9900
style VPCE2 fill:#FF9900
For detailed technical documentation, architecture, and configuration guides, see:
π databricks-aws-production Documentation
https://accounts.cloud.databricks.comclient_id (OAuth Client ID)client_secret (OAuth Secret)aws configure --profile your-profile-name
# OR
aws sso login --profile your-profile-name
workspace_admin_email variablecd aws-pl-ws/databricks-aws-production
# Copy example configuration
cp terraform.tfvars.example terraform.tfvars
# Edit with your values
nano terraform.tfvars
Add to ~/.zshrc or ~/.bashrc:
export TF_VAR_databricks_account_id="your-account-id"
export TF_VAR_databricks_client_id="your-service-principal-client-id"
export TF_VAR_databricks_client_secret="your-service-principal-secret"
terraform init
terraform plan
terraform apply
β±οΈ Deployment Time: ~15-20 minutes
Full Guide: Quick Start Documentation
| Document | Description |
|---|---|
| 00-PREREQUISITES | System setup & credentials |
| 01-ARCHITECTURE | Architecture & deployment flow |
| 02-IAM-SECURITY | IAM roles & policies |
| 03-NETWORK-ENCRYPTION | Network security & encryption |
| 04-QUICK-START | 5-minute deployment guide |
| 05-TROUBLESHOOTING | Common issues & solutions |
workspace_name = "my-databricks-workspace"
region = "us-west-1"
prefix = "dbx"
# S3 Buckets (globally unique)
root_storage_bucket_name = "mycompany-dbx-root-storage"
unity_catalog_bucket_name = "mycompany-dbx-uc-metastore"
unity_catalog_root_storage_bucket_name = "mycompany-dbx-uc-root-storage"
unity_catalog_external_bucket_name = "mycompany-dbx-uc-external"
# Security (defaults)
enable_private_link = true # Private Link enabled
enable_encryption = true # S3 KMS encryption
enable_workspace_cmk = false # Workspace CMK disabled
workspace_name = "my-secure-workspace"
region = "us-west-1"
# Full encryption
enable_private_link = true # Private Link
enable_encryption = true # S3 KMS encryption
enable_workspace_cmk = true # Workspace CMK (DBFS + EBS + Managed Services)
# Public access control
public_access_enabled = false # Block public internet access
# S3 Buckets
root_storage_bucket_name = "mycompany-dbx-root-storage"
unity_catalog_bucket_name = "mycompany-dbx-uc-metastore"
unity_catalog_root_storage_bucket_name = "mycompany-dbx-uc-root-storage"
unity_catalog_external_bucket_name = "mycompany-dbx-uc-external"
βββ VPC + 3 subnet tiers (public/private/privatelink)
βββ NAT Gateways (2 for HA)
βββ Internet Gateway
βββ Security Groups (2)
βββ VPC Endpoints (5):
β βββ Databricks Workspace (Interface)
β βββ Databricks Relay (Interface)
β βββ S3 (Gateway - FREE)
β βββ STS (Interface)
β βββ Kinesis (Interface)
βββ S3 Buckets (4):
β βββ DBFS root storage
β βββ Unity Catalog metastore
β βββ Unity Catalog root storage
β βββ Unity Catalog external
βββ IAM Roles (4):
β βββ Cross-account role
β βββ Instance profile role
β βββ UC metastore role
β βββ UC external role
βββ KMS Keys (2 - optional):
βββ S3 encryption key
βββ Workspace CMK
βββ Workspace (with Private Link)
βββ Unity Catalog Metastore
βββ Unity Catalog Assignment
βββ Storage Credentials
βββ External Locations
βββ Workspace Catalog (optional)
Traffic Flow:
Databricks Clusters (Private Subnets)
β (Private)
VPC Endpoints (PrivateLink Subnets)
β (AWS PrivateLink)
Databricks Control Plane
Benefits:
Layer 1: S3 Bucket Encryption (enable_encryption = true)
Layer 2: Workspace CMK (enable_workspace_cmk = true)
Note: Both layers can be enabled simultaneously for maximum security.
Data Governance:
Multi-Workspace Pattern:
Single Unity Catalog Metastore
βββ Workspace 1 (Production)
βββ Workspace 2 (Development)
βββ Workspace 3 (Staging)
# Skip metastore creation, use existing
metastore_id = "existing-metastore-id"
# Share PAS across multiple workspaces in same region
existing_private_access_settings_id = "existing-pas-id"
enable_workspace_cmk = true
existing_workspace_cmk_key_arn = "arn:aws:kms:us-west-1:123456789012:key/12345678-..."
existing_workspace_cmk_key_alias = "alias/databricks-workspace-cmk"
vpc_cidr = "10.0.0.0/22"
private_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
privatelink_subnet_cidrs = ["10.0.3.0/26", "10.0.3.64/26"]
public_subnet_cidrs = ["10.0.0.0/26", "10.0.0.64/26"]
# Manual AZ selection (or leave empty for auto-detect)
availability_zones = ["us-west-1a", "us-west-1c"]
cd aws-pl-ws/databricks-aws-production
terraform destroy
Issues? See Destroy Troubleshooting
Common issues and solutions:
| Issue | Quick Fix |
|---|---|
| Bucket already exists | Change bucket names in terraform.tfvars |
| AWS auth error | aws sso login --profile your-profile |
| Canβt access workspace | Wait 20 minutes after deployment |
| EIP limit exceeded | Release unused Elastic IPs |
| Provider errors | Run terraform init -upgrade |
Full Guide: Troubleshooting Documentation
export TF_LOG=DEBUG| Version | Status | Notes |
|---|---|---|
databricks-aws-production |
β Active | Production-ready, recommended |
modular-version |
β οΈ Deprecated | Legacy version, migrate to production |
Improvements and bug fixes are welcome:
This configuration is provided as-is for reference purposes.
Ready to Deploy? β Quick Start Guide β‘
provider "aws" {
region = "us-west-2"
profile = "your-aws-profile" # OR use default credentials
}
Authentication Options:
aws_profile variable)provider "databricks" {
alias = "account"
host = "https://accounts.cloud.databricks.com"
account_id = var.databricks_account_id
client_id = var.client_id
client_secret = var.client_secret
}
Used for:
provider "databricks" {
alias = "workspace"
host = module.databricks_workspace.workspace_url
client_id = var.client_id
client_secret = var.client_secret
}
Used for:
modules/networking)Creates a 3-tier VPC architecture:
VPC CIDR: 10.0.0.0/22 (1024 total IPs - optimized for single workspace)
βββ DNS Hostnames: Enabled
βββ DNS Support: Enabled
| Subnet Type | Purpose | CIDR | Usable IPs | Count |
|---|---|---|---|---|
| Public | NAT Gateways, Internet Gateway | 10.0.0.0/26, 10.0.0.64/26 |
59 each | 2 |
| Private | Databricks Clusters (compute) | 10.0.1.0/24, 10.0.2.0/24 |
251 each | 2 |
| PrivateLink | VPC Endpoints | 10.0.3.0/26, 10.0.3.64/26 |
59 each | 2 |
CIDR Allocation Strategy:
0.0.0.0/0 β Internet Gateway0.0.0.0/0 β NAT Gateway0.0.0.0/0 β NAT Gateway (for egress to Databricks control plane)Why Two NAT Gateways?
| Aspect | 2 NAT Gateways (HA) | 1 NAT Gateway (Cost) |
|---|---|---|
| Availability | β If one AZ fails, other continues | β Single point of failure |
| Cost | ~$64/month | ~$32/month (50% savings) |
| Cross-AZ Charges | β No extra cost | β $0.01/GB transfer fee |
| Production Ready | β Recommended | β Dev/test only |
π‘ Cost Optimization: For dev/test environments, you can use a single NAT gateway to save ~$32/month. Update nat_gateway_count = 1 in the networking module configuration. However, two NAT gateways are strongly recommended for production to ensure high availability.
modules/networking/vpc_endpoints.tf)| Endpoint | Type | Purpose | Port | Subnets |
|---|---|---|---|---|
| Workspace VPC Endpoint | Interface | REST API, UI access | 443, 8443-8451 | PrivateLink |
| Relay VPC Endpoint | Interface | Secure Cluster Connectivity | 6666 | PrivateLink |
Registration with Databricks:
resource "databricks_mws_vpc_endpoint" "workspace_vpce" {
account_id = var.databricks_account_id
aws_vpc_endpoint_id = aws_vpc_endpoint.workspace.id
vpc_endpoint_name = "${var.prefix}-workspace-vpce"
region = var.region
}
| Endpoint | Type | Purpose |
|---|---|---|
| S3 | Gateway | DBFS, logs, artifacts |
| STS | Interface | IAM role assumption |
| Kinesis | Interface | Logging and lineage |
Private DNS: All interface endpoints have private_dns_enabled = true for automatic DNS resolution.
modules/networking/security_groups.tf)Ingress Rules:
β
TCP 0-65535 from self (cluster-to-cluster communication)
β
UDP 0-65535 from self (cluster-to-cluster communication)
Egress Rules:
β
TCP 0-65535 to self (cluster-to-cluster)
β
UDP 0-65535 to self (cluster-to-cluster)
β
TCP 443 to VPC Endpoint SG (HTTPS to control plane via Private Link)
β
TCP 443 to 0.0.0.0/0 (library downloads, external APIs, S3 access)
β
TCP 3306 to 0.0.0.0/0 (external metastore - optional)
β
TCP 6666 to VPC Endpoint SG (Secure Cluster Connectivity)
β
TCP 8443-8451 to VPC Endpoint SG (Unity Catalog, control plane)
β
TCP/UDP 53 to 0.0.0.0/0 (DNS resolution)
Important Notes:
Ingress Rules:
β
TCP 443 from Workspace SG (HTTPS from clusters)
β
TCP 6666 from Workspace SG (SCC from clusters)
β
TCP 8443-8451 from Workspace SG (Unity Catalog, control plane)
Egress Rules:
β
ALL to 0.0.0.0/0 (to Databricks control plane)
modules/storage)Creates S3 buckets with encryption and versioning:
| Bucket | Purpose | Encryption | Versioning | Public Access |
|---|---|---|---|---|
| Root Storage | Workspace DBFS root | AES256 | Enabled | Blocked |
| UC Metastore | Unity Catalog metastore | AES256 | Enabled | Blocked |
| UC Root Storage | UC root storage location | AES256 | Enabled | Blocked |
| UC External | External data locations | AES256 | Enabled | Blocked |
Bucket Policy: Databricks-generated policy attached to root storage bucket for cross-account access.
modules/iam)Purpose: Allows Databricks control plane to manage workspace resources
Trust Policy: Databricks AWS account (414351767826)
Permissions: EC2, VPC, S3 (workspace management)
Generated by: databricks_aws_crossaccount_policy data source
Purpose: Grants Databricks clusters access to S3 and AWS services
Trust Policy: EC2 service
Permissions:
- S3 access to workspace buckets
- EC2 instance metadata access
- CloudWatch logs (optional)
Purpose: Grants Unity Catalog access to S3 data locations
Trust Policy: Databricks Unity Catalog AWS account
Permissions:
- S3 access to UC metastore bucket
- S3 access to UC data buckets
- KMS decrypt (if CMK enabled)
modules/kms)When enable_workspace_cmk = true:
Use Cases:
STORAGE - DBFS root and EBS volume encryptionMANAGED_SERVICES - Control plane notebook encryptionKey Policy:
Permissions:
β
Account root (key administration)
β
Databricks cross-account role (encrypt/decrypt)
β
EC2 service (EBS volume encryption via workspace VPCE)
Policy Conditions:
aws:PrincipalTag/DatabricksAccountId = Your Databricks Account IDaws:SourceVpce = Workspace VPC Endpoint ID (for EBS)modules/databricks_workspace)databricks_mws_credentials
βββ Role ARN: Cross-account role
βββ Purpose: AWS resource management
databricks_mws_storage_configurations
βββ Bucket: Root storage bucket
βββ Purpose: DBFS root storage
databricks_mws_networks
βββ VPC ID
βββ Subnet IDs: Private subnets
βββ Security Group: Workspace SG
βββ VPC Endpoints:
βββ rest_api: Workspace VPC Endpoint ID
βββ dataplane_relay: Relay VPC Endpoint ID
databricks_mws_private_access_settings
βββ Public Access: Configurable (default: enabled)
βββ Private Access Level: ENDPOINT or ACCOUNT
βββ Region: Workspace region
databricks_mws_workspaces
βββ Credentials ID
βββ Storage Configuration ID
βββ Network ID
βββ Private Access Settings ID
βββ CMK IDs (optional):
β βββ Managed Services CMK ID
β βββ Storage CMK ID
βββ Pricing Tier: ENTERPRISE
modules/unity_catalog)databricks_metastore
βββ Name: {prefix}-metastore
βββ Region: Workspace region
βββ Storage Root: s3://uc-metastore-bucket/metastore
βββ Owner: Metastore admin email
databricks_metastore_assignment
βββ Workspace ID
βββ Metastore ID
βββ Default Catalog: "main"
databricks_storage_credential (root_storage)
βββ IAM Role: UC root storage role ARN
βββ Purpose: Access to UC root storage bucket
databricks_storage_credential (external_storage)
βββ IAM Role: UC external storage role ARN
βββ Purpose: Access to external data buckets
databricks_external_location (root_storage)
βββ URL: s3://uc-root-storage-bucket/
βββ Credential: root_storage
databricks_external_location (external_location)
βββ URL: s3://uc-external-bucket/
βββ Credential: external_storage
databricks_catalog
βββ Name: {prefix}_catalog
βββ Storage Root: s3://uc-root-storage-bucket/catalog
βββ Grants: ALL_PRIVILEGES to workspace admin
modules/user_assignment)Assigns existing Databricks account user as workspace admin:
data "databricks_user" "workspace_access"
βββ Provider: databricks.account
βββ User Name: workspace_admin_email
databricks_mws_permission_assignment
βββ Workspace ID
βββ Principal ID: User ID
βββ Permissions: ["ADMIN"]
βββ Lifecycle: ignore_changes on principal_id
Prerequisites:
graph TD
A[AWS Infrastructure] --> B[Networking Module]
A --> C[Storage Module]
A --> D[IAM Module]
A --> E[KMS Module - Optional]
B --> F[VPC + Subnets]
B --> G[Security Groups]
B --> H[NAT Gateways]
B --> I[VPC Endpoints]
I --> J[Register with Databricks]
E --> K[Create KMS Key]
K --> L[Apply Key Policy]
J --> M[Databricks Workspace Module]
C --> M
D --> M
L --> M
M --> N[Private Access Settings]
M --> O[Credentials Config]
M --> P[Storage Config]
M --> Q[Network Config]
N --> R[Create Workspace]
O --> R
P --> R
Q --> R
R --> S[Unity Catalog Module]
C --> S
S --> T[Create Metastore]
T --> U[Assign to Workspace]
U --> V[Storage Credentials]
V --> W[External Locations]
W --> X[Workspace Catalog]
U --> Y[User Assignment Module]
style A fill:#f9f,stroke:#333
style M fill:#bbf,stroke:#333
style S fill:#bfb,stroke:#333
style Y fill:#fbb,stroke:#333
style R fill:#FF3621
sequenceDiagram
participant TF as Terraform
participant AWS as AWS
participant DB_ACC as Databricks Account
participant DB_WS as Databricks Workspace
Note over TF,AWS: Phase 1: AWS Infrastructure
TF->>AWS: Create VPC + Subnets
TF->>AWS: Create Security Groups
TF->>AWS: Create NAT Gateways
TF->>AWS: Create S3 Buckets
TF->>AWS: Create IAM Roles
TF->>AWS: Create VPC Endpoints
Note over TF,DB_ACC: Phase 2: Register Endpoints
TF->>DB_ACC: Register Workspace VPCE
TF->>DB_ACC: Register Relay VPCE
DB_ACC-->>TF: VPC Endpoint IDs
Note over TF,AWS: Phase 3: KMS (Optional)
TF->>AWS: Create KMS Key
TF->>AWS: Apply Key Policy
TF->>DB_ACC: Register CMK
Note over TF,DB_ACC: Phase 4: Workspace
TF->>DB_ACC: Create Private Access Settings
TF->>DB_ACC: Create Credentials Config
TF->>DB_ACC: Create Storage Config
TF->>DB_ACC: Create Network Config
TF->>DB_ACC: Create Workspace
DB_ACC-->>TF: Workspace ID + URL
Note over TF,DB_ACC: Phase 5: Unity Catalog
TF->>DB_ACC: Create UC Metastore
TF->>DB_ACC: Assign Metastore to Workspace
TF->>DB_WS: Create Storage Credentials
TF->>DB_WS: Create External Locations
TF->>DB_WS: Create Workspace Catalog
Note over TF,DB_ACC: Phase 6: User Assignment
TF->>DB_ACC: Lookup User
TF->>DB_ACC: Assign User as Admin
Note over DB_ACC: Wait 20 minutes for<br/>Backend Private Link
module "databricks_workspace" {
depends_on = [
module.networking, # VPC, subnets, VPC endpoints
module.storage, # S3 buckets
module.iam, # Cross-account role, instance profile
module.kms # KMS keys (if enabled)
]
}
module "unity_catalog" {
depends_on = [
module.databricks_workspace, # Workspace must exist
module.storage # UC buckets must exist
]
}
module "user_assignment" {
depends_on = [
module.unity_catalog.metastore_assignment_id # UC must be assigned first
]
}
Within Databricks Workspace Module:
VPC Endpoints Registration
β
Private Access Settings (depends on VPC endpoints)
β
Network Configuration (depends on VPC endpoints)
β
Workspace Creation (depends on all configurations)
Within Unity Catalog Module:
Metastore Creation
β
Metastore Assignment to Workspace
β
Storage Credentials (IAM roles must exist)
β
External Locations (credentials must exist)
β
Workspace Catalog (external locations must exist)
Create terraform.tfvars:
# AWS Configuration
region = "us-west-2"
aws_profile = "your-aws-profile" # Or use default credentials
# Databricks Account Configuration
databricks_account_id = "your-account-id"
client_id = "your-service-principal-client-id"
client_secret = "your-service-principal-secret"
# Workspace Configuration
workspace_name = "my-databricks-workspace"
workspace_admin_email = "admin@example.com"
# Metastore Configuration
metastore_admin_email = "admin@example.com"
# Network Configuration
vpc_cidr = "10.0.0.0/22"
private_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnet_cidrs = ["10.0.0.0/26", "10.0.0.64/26"]
privatelink_subnet_cidrs = ["10.0.3.0/26", "10.0.3.64/26"]
# VPC Endpoint Services (region-specific)
workspace_vpce_service = "com.amazonaws.vpce.us-west-2.vpce-svc-xxxxx"
relay_vpce_service = "com.amazonaws.vpce.us-west-2.vpce-svc-yyyyy"
# AWS Account
aws_account_id = "123456789012"
# Tags
tags = {
Environment = "dev"
Project = "databricks-privatelink"
ManagedBy = "terraform"
}
enable_workspace_cmk = true
cmk_admin_arn = "arn:aws:iam::123456789012:user/admin"
enable_ip_access_lists = true
allowed_ip_addresses = ["1.2.3.4/32", "5.6.7.8/32"]
create_workspace_catalog = true
public_access_enabled = false # Fully private workspace
private_access_level = "ACCOUNT" # or "ENDPOINT"
cd aws/modular-version
terraform init
terraform validate
terraform plan
terraform apply
Deployment Time: ~15-20 minutes
β οΈ IMPORTANT: Wait 20 minutes after workspace creation before creating clusters.
This allows the backend Private Link connection to fully stabilize.
Error:
Error: Provider type mismatch
The local name "databricks.account" in the root module represents provider
"hashicorp/databricks", but "databricks.account" in module represents
"databricks/databricks".
Solution:
rm -rf .terraform .terraform.lock.hcl
terraform init -upgrade
Cause: Terraform provider cache needs to be refreshed.
Warning:
Warning: Egress rules in the Security Group sg-xxxxx are not configured correctly.
See the requirements at https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html#security-groups.
Common Causes:
0.0.0.0/0 and S3 prefix list for port 443Solution:
Check for redundant rules:
# View all egress rules for the workspace security group
aws ec2 describe-security-groups \
--group-ids <WORKSPACE_SG_ID> \
--query 'SecurityGroups[0].IpPermissionsEgress[?FromPort==`443`]' \
--region <REGION>
If you see both 0.0.0.0/0 and a prefix list for port 443, remove the prefix list:
# Remove redundant S3 prefix list rule (change pl-xxxxx to your prefix list ID)
aws ec2 revoke-security-group-egress \
--group-id <WORKSPACE_SG_ID> \
--ip-permissions 'IpProtocol=tcp,FromPort=443,ToPort=443,PrefixListIds=[{PrefixListId=pl-xxxxx}]' \
--region <REGION>
Verify Terraform configuration matches AWS:
terraform plan # Should show no changes if in sync
Why this happens:
0.0.0.0/0 rule already covers all destinations including S3Cause: Drift between Terraform state and actual AWS configuration, or manual changes in AWS Console.
Error:
Error: creating EC2 VPC Endpoint: InvalidServiceName
Solution:
# Contact Databricks support for your region-specific service names
workspace_vpce_service = "com.amazonaws.vpce.REGION.vpce-svc-xxxxx"
relay_vpce_service = "com.amazonaws.vpce.REGION.vpce-svc-yyyyy"
Error:
Error: cannot create mws permission assignment: Permission assignment APIs are not available
Solution: This API requires:
Workaround:
# In terraform.tfvars, leave empty to skip:
workspace_admin_email = ""
# Then assign admin manually via Databricks UI
Error:
Error: Cycle: module.kms, module.iam
Solution: The KMS module constructs the cross-account role ARN internally:
locals {
cross_account_role_arn = "arn:aws:iam::${var.aws_account_id}:role/${var.prefix}-crossaccount"
}
Verify: Remove explicit depends_on = [module.iam] from KMS module call in root main.tf.
Error:
Error: Config: host=https://https://...
Solution: The workspace URL output should not include https:// prefix:
# Correct:
output "workspace_url" {
value = databricks_mws_workspaces.workspace.workspace_url
}
# Incorrect:
output "workspace_url" {
value = "https://${databricks_mws_workspaces.workspace.workspace_url}"
}
Error:
Cluster creation failed: Unable to connect to data plane
Solution:
aws ec2 describe-vpc-endpoints --vpc-endpoint-ids vpce-xxxxx
Error:
Error: Access Denied when accessing S3 bucket
Solution:
terraform state show 'module.iam.aws_iam_role.instance_profile_role'
terraform state show 'module.iam.aws_iam_role.unity_catalog_role'
aws s3api get-bucket-policy --bucket your-bucket-name
aws sts assume-role --role-arn arn:aws:iam::ACCOUNT:role/ROLE-NAME --role-session-name test
Error:
Error: cannot assign metastore to workspace
Solution:
terraform state show 'module.databricks_workspace.databricks_mws_workspaces.workspace'
terraform state show 'module.unity_catalog.databricks_metastore.this'
Error:
Error: cannot read storage credential: failed during request visitor
Solution: Use targeted destroy:
# Step 1: Remove Unity Catalog resources
terraform destroy -target=module.user_assignment
terraform destroy -target=module.unity_catalog
# Step 2: Remove workspace
terraform destroy -target=module.databricks_workspace
# Step 3: Remove remaining resources
terraform destroy
Alternative: Use the provided destroy script:
./scripts/pre-destroy.sh
terraform destroy
terraform state list
terraform state show 'module.name.resource.name'
terraform refresh
terraform output
terraform output -json | jq
export TF_LOG=DEBUG
export TF_LOG_PATH=terraform-debug.log
terraform apply
# Test VPC endpoint DNS resolution
nslookup workspace-endpoint-name.vpce-svc-xxxxx.us-west-2.vpce.amazonaws.com
# Check NAT Gateway status
aws ec2 describe-nat-gateways --region us-west-2
# Verify security group rules
aws ec2 describe-security-groups --group-ids sg-xxxxx
For issues or questions:
TF_LOG=DEBUG)This configuration is provided as-is for reference purposes.