Deploying LangFuse on Azure with Terraform
Deploying LangFuse on Azure with Terraform
Problem: You need to deploy a self-hosted LangFuse instance on Azure infrastructure for your organization’s AI observability needs.
Solution: Use the official LangFuse Terraform module to deploy a production-ready LangFuse instance on Azure Kubernetes Service (AKS) with Application Gateway, PostgreSQL, and proper DNS configuration.
Prerequisites
Before starting, ensure you have:
Required Tools
- Azure CLI installed and configured
- Terraform installed (version 1.0+)
- kubectl for Kubernetes management
Azure Requirements
- Valid Azure subscription with appropriate permissions
- Domain name you want to use for LangFuse (e.g.,
<YOUR_DOMAIN_URL>
)
Required Azure Permissions
- Contributor role on the subscription or resource group
- User Access Administrator (for role assignments)
- Key Vault Contributor (for Key Vault operations)
Pre-Deployment Setup
1. Azure Authentication
# Login to Azure
az login
# Set your subscription
az account set --subscription "your-subscription-id"
# Verify current subscription
az account show
Terraform Configuration
1. Create Your Main Configuration
Create a main.tf
file with your deployment configuration:
main.tf
provider "azurerm" {
features {
resource_group {= false
prevent_deletion_if_contains_resources
}
}= "your-subscription-id"
subscription_id
}
module "langfuse" {
source = "github.com/langfuse/langfuse-terraform-azure?ref=0.1.2"
# REQUIRED: Domain configuration
= "<YOUR_DOMAIN_URL>" # Your domain
domain = "<INSERT_SHORT_NAME>" # Short name for your deployment
name = "westeurope"
location
# OPTIONAL: Network configuration
= "10.224.0.0/12"
virtual_network_address_prefix = "10.224.0.0/16"
aks_subnet_address_prefix = "10.225.0.0/16"
app_gateway_subnet_address_prefix
# OPTIONAL: Kubernetes configuration
= "1.32"
kubernetes_version = "Standard_D8s_v6"
node_pool_vm_size = 2
node_pool_min_count = 10
node_pool_max_count
# OPTIONAL: Database configuration
= 2
postgres_instance_count = "SameZone"
postgres_ha_mode = "GP_Standard_D2s_v3"
postgres_sku_name
# OPTIONAL: Security features
= true
use_ddos_protection
}
# Provider configurations for Kubernetes and Helm
provider "kubernetes" {
= module.langfuse.cluster_host
host = base64decode(module.langfuse.cluster_client_certificate)
client_certificate = base64decode(module.langfuse.cluster_client_key)
client_key = base64decode(module.langfuse.cluster_ca_certificate)
cluster_ca_certificate
}
provider "helm" {
= {
kubernetes = module.langfuse.cluster_host
host = base64decode(module.langfuse.cluster_client_certificate)
client_certificate = base64decode(module.langfuse.cluster_client_key)
client_key = base64decode(module.langfuse.cluster_ca_certificate)
cluster_ca_certificate
} }
Version Check: Always use the latest stable version from LangFuse Terraform releases.
2. Initialize and Validate
# Initialize Terraform
terraform init
# Validate configuration
terraform validate
# Check the deployment plan
terraform plan
Deployment Process
Option A: Single Deployment (Recommended for Simple Cases)
terraform apply -auto-approve
Option B: Phased Deployment (Recommended for Complex Deployments)
For large deployments or when you encounter permission issues:
# Phase 1: Core infrastructure
terraform apply -target="module.langfuse.azurerm_resource_group.this" -auto-approve
terraform apply -target="module.langfuse.azurerm_virtual_network.this" -auto-approve
# Phase 2: Security resources
terraform apply -target="module.langfuse.azurerm_key_vault.this" -auto-approve
terraform apply -target="module.langfuse.azurerm_key_vault_access_policy.this" -auto-approve
# Wait for Azure propagation
sleep 60
# Phase 3: Application resources
terraform apply -auto-approve
Permission Propagation: If you encounter permission errors, wait 30-60 seconds and retry. Azure permissions take time to propagate.
DNS Configuration
1. Get Your Deployment IP Address
# List all public IPs in your resource group
az network public-ip list --resource-group <YOUR_RESOURCE_GROUP> --output table
# Get the specific Application Gateway IP
az network public-ip show --resource-group <YOUR_RESOURCE_GROUP> --name <YOUR_DEPLOYMENT_NAME>-appgw --query "ipAddress" -o tsv
2. DNS Delegation Setup
Your deployment creates an Azure DNS zone that requires proper delegation from your parent domain.
Why NS Records Are Required:
- SSL Certificate Validation: Let’s Encrypt uses DNS-01 challenges requiring TXT record creation
- Automatic Certificate Renewal: cert-manager needs DNS authority to manage records
- Full DNS Control: Azure DNS needs authority over the entire subdomain
3. Configure DNS Delegation
Step 1: Get Azure DNS Nameservers
az network dns zone show --resource-group <YOUR_RESOURCE_GROUP> --name <YOUR_DOMAIN_URL> --query "nameServers" -o table
Step 2: Configure Parent Domain
For MoJ justice.gov.uk domains:
- DNS Repository: https://github.com/ministryofjustice/dns
- Follow the README instructions for making DNS changes
- Open a Pull Request with your NS records:
<YOUR SUBDOMAIN>:
ttl: 3600
type: NS
value:
- ns1-xx.azure-dns.com.
- ns2-xx.azure-dns.net.
- ns3-xx.azure-dns.org.
- ns4-xx.azure-dns.info.
For other domains: Add NS records in your domain management system:
<YOUR_SUBDOMAIN>.<YOUR_DOMAIN>.com. IN NS ns1-xx.azure-dns.com.
<YOUR_SUBDOMAIN>.<YOUR_DOMAIN>.com. IN NS ns2-xx.azure-dns.net.
<YOUR_SUBDOMAIN>.<YOUR_DOMAIN>.com. IN NS ns3-xx.azure-dns.org.
<YOUR_SUBDOMAIN>.<YOUR_DOMAIN>.com. IN NS ns4-xx.azure-dns.info.
Example:
langfuse-ai:
ttl: 3600
type: NS
value:
- ns1-06.azure-dns.com.
- ns2-06.azure-dns.net.
- ns3-06.azure-dns.org.
- ns4-06.azure-dns.info.
Note that the DNS repo has certain standards for domain names that you will need to comply with. You will also need to ensure that the records and record attributes are in strict alphabetical order. Failing to do this will likely result in your PR being closed by the cloud operations team.
4. Test DNS Delegation
# Test NS delegation is working
nslookup -type=NS <YOUR_DOMAIN_URL>
# Test DNS propagation (may take 5-30 minutes)
nslookup <YOUR_DOMAIN_URL>
# Should show the Azure Application Gateway IP
What Happens After NS Delegation:
- ✅ A record created automatically by Terraform in Azure DNS
- ✅ Automatic certificate renewal forever
- ✅ Full DNS control for any future DNS records
Initial Validation
1. Verify Kubernetes Deployment
# Get AKS credentials
az aks get-credentials --resource-group <YOUR_RESOURCE_GROUP> --name aks-<YOUR_DEPLOYMENT_NAME> --overwrite-existing
# Check LangFuse pods
kubectl get pods -n langfuse
# Check services
kubectl get services -n langfuse
# Check ingress
kubectl get ingress -n langfuse
2. Test Access
# Test HTTP access (before SSL setup)
curl -I http://<YOUR_DOMAIN_URL>
# Expected: Should show Application Gateway response
SSL Required: The deployment creates self-signed certificates by default. You’ll need to configure proper SSL certificates before production use. See the SSL Configuration Guide for next steps.
Next Steps
Your LangFuse infrastructure is now deployed! To make it production-ready:
- Configure SSL Certificates - Set up Let’s Encrypt for trusted SSL
- Set Up Email Notifications - Enable user invitations and notifications
- Deployment Troubleshooting - Common issues and solutions
Common Issues During Deployment
Permission Errors: Wait 30-60 seconds and retry
sleep 30
terraform apply -auto-approve
Key Vault Naming Conflicts: Use shorter names or different domains
DNS Propagation: Allow 5-30 minutes for DNS changes to propagate globally
🚀 You now have LangFuse deployed on Azure! Continue with SSL configuration to make it production-ready.