Bring Your Own Cloud (BYOC): Create a Data Plane
Introduction
Private DDN BYOC allows you to deploy the Data Plane component in your own cloud environment. This approach is useful if you have specific requirements or constraints which prevent you from using the dedicated Data Plane on Hasura's cloud.
BYOC is currently supported on AWS, GCP and Azure.
If you would like access to Private DDN BYOC, please contact sales.
📌 Onboarding Process
To get started with BYOC, customers are required to have one of the following:
- A dedicated AWS Account
- A dedicated project on Google Cloud
- A dedicated Resource Group on Microsoft Azure
Instructions
AWS
The setup involves creating an IAM role in your AWS account that establishes a trust relationship with Hasura's AWS automation role (PulumiDDNCli). This role will be used to deploy and manage workloads necessary for Hasura DDN.
Pre-requisites
- Dedicated AWS Account with administrative access
- AWS CLI installed and configured
AWS_REGION
environment variable set to your desired region (e.g.,export AWS_REGION=us-east-1
)- Ensure the AWS region where you plan to deploy is enabled in your account
aws account get-regions --region-opt-status-contains ENABLED --query 'Regions[*].RegionName'
Setup Instructions
- Copy the following template and save it as
cloudformation.yaml
cloudformation.yaml
Parameters:
ExternalId:
Type: String
Default: hasura-cloud
Description: External ID for the trust relationship with Hasura Cloud
MinLength: 2
MaxLength: 1224
AllowedPattern: "[A-Za-z0-9+=,.@:\\/-]*"
Resources:
BootstrapRole:
Type: AWS::IAM::Role
Properties:
RoleName: HasuraCloudBYOC
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::760537944023:role/PulumiDDNCli
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Ref ExternalId
BootstrapPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: HasuraCloudBYOC
Roles:
- !Ref BootstrapRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ec2:DescribeAddresses
- ec2:DescribeAddressesAttribute
- ec2:DescribeAvailabilityZones
- ec2:DescribeInternetGateways
- ec2:DescribeNatGateways
- ec2:DescribeNetworkInterfaces
- ec2:DescribeRegions
- ec2:DescribeRouteTables
- ec2:DescribeSecurityGroupRules
- ec2:DescribeSecurityGroups
- ec2:DescribeSubnets
- ec2:DescribeTags
- ec2:DescribeVpcAttribute
- ec2:DescribeVpcs
- ec2:DescribeVpcEndpointServices
- ec2:DescribeVpcEndpoints
- eks:DeleteAddon
- eks:DescribeAddon
- eks:DescribeCluster
- eks:DescribeNodegroup
- eks:ListClusters
- iam:GetRole
- iam:GetServiceLinkedRoleDeletionStatus
- sqs:GetQueueAttributes
- rds:DescribeDBInstances
- rds:DescribeOrderableDBInstanceOptions
Resource: '*'
- Effect: Allow
Action:
- ec2:AllocateAddress
- ec2:AssociateAddress
- ec2:AssociateRouteTable
- ec2:CreateInternetGateway
- ec2:CreateNatGateway
- ec2:CreateRoute
- ec2:CreateRouteTable
- ec2:CreateSubnet
- ec2:CreateTags
- ec2:CreateVpc
- ec2:CreateSecurityGroup
- ec2:AuthorizeSecurityGroupIngress
- ec2:CreateVpcEndpoint
- eks:CreateCluster
- eks:CreateNodegroup
- globalaccelerator:CreateAccelerator
- globalaccelerator:CreateEndpointGroup
- globalaccelerator:CreateListener
- globalaccelerator:TagResource
- sqs:CreateQueue
- sqs:TagQueue
- acm:RequestCertificate
- events:PutRule
- events:TagResource
- iam:CreateOpenIDConnectProvider
- iam:TagOpenIDConnectProvider
- rds:CreateDBSubnetGroup
- rds:CreateDBInstance
Resource: '*'
Condition:
StringEquals:
aws:RequestTag/Created-By: HasuraCloud
- Effect: Allow
Action:
- ec2:CreateTags
Resource:
- !Sub arn:aws:ec2:*:${AWS::AccountId}:security-group/*
Condition:
StringEquals:
aws:RequestTag/karpenter.sh/discovery: dataplane
- Effect: Allow
Action:
- ec2:DeleteTags
Resource:
- !Sub arn:aws:ec2:*:${AWS::AccountId}:security-group/*
Condition:
StringEquals:
aws:ResourceTag/karpenter.sh/discovery: dataplane
- Effect: Allow
Action:
- eks:AssociateAccessPolicy
- eks:DisassociateAccessPolicy
Resource:
- !Sub arn:aws:eks:*:${AWS::AccountId}:access-entry/dataplane/*
- Effect: Allow
Action:
- iam:AttachRolePolicy
- iam:CreateInstanceProfile
- iam:CreatePolicy
- iam:CreateRole
- iam:CreatePolicyVersion
- iam:DeleteInstanceProfile
- iam:DeleteOpenIDConnectProvider
- iam:DeletePolicy
- iam:DeleteRole
- iam:DeleteServiceLinkedRole
- iam:DetachRolePolicy
- iam:UpdateAssumeRolePolicy
- iam:UpdateOpenIDConnectProviderThumbprint
- iam:GetInstanceProfile
- iam:GetOpenIDConnectProvider
- iam:GetPolicy
- iam:GetPolicyVersion
- iam:GetRolePolicy
- iam:ListAttachedRolePolicies
- iam:ListInstanceProfilesForRole
- iam:ListOpenIDConnectProviderTags
- iam:ListPolicyVersions
- iam:ListRolePolicies
- iam:PassRole
- iam:PutRolePolicy
- iam:RemoveRoleFromInstanceProfile
- iam:TagInstanceProfile
- iam:TagOpenIDConnectProvider
- iam:TagPolicy
- iam:TagRole
Resource:
# Roles
- !Sub arn:aws:iam::${AWS::AccountId}:role/KarpenterNodeRole
- !Sub arn:aws:iam::${AWS::AccountId}:role/eksClusterRole-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/lb-controller-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/autoscaler-controller-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/global-accelerator-operator-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/karpenter-controller-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/HasuraWorkloadAutomationRole-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/vpc-cni-*
- !Sub arn:aws:iam::${AWS::AccountId}:role/ebsCsiDriverRole-*
# Instance Profiles
- !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/dataplane_*
# Policies
- !Sub arn:aws:iam::${AWS::AccountId}:policy/lb-controller-*
- !Sub arn:aws:iam::${AWS::AccountId}:policy/autoscaler-controller-*
- !Sub arn:aws:iam::${AWS::AccountId}:policy/global-accelerator-operator-*
- !Sub arn:aws:iam::${AWS::AccountId}:policy/karpenter-controller-*
# OIDC Providers
- !Sub arn:aws:iam::${AWS::AccountId}:oidc-provider/oidc.eks.*
# Service Roles
- !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot
- Effect: Allow
Action:
- iam:CreateServiceLinkedRole
Resource: '*'
Condition:
StringEquals:
iam:AWSServiceName:
- spot.amazonaws.com
- globalaccelerator.amazonaws.com
- eks.amazonaws.com
- eks-nodegroup.amazonaws.com
- rds.amazonaws.com
- Effect: Allow
Action:
- eks:*
- globalaccelerator:*
- sqs:*
- acm:*
- events:*
- rds:*
Resource: '*'
Condition:
StringEquals:
aws:ResourceTag/Created-By: HasuraCloud
- Effect: Allow
Action:
- ec2:*
Resource: '*'
Condition:
StringEquals:
ec2:ResourceTag/Created-By: HasuraCloud
Outputs:
RoleArn:
Description: "ARN of the HasuraCloudBYOC IAM Role"
Value: !GetAtt BootstrapRole.Arn
-
Deploy the CloudFormation stack:
First, check if the stack already exists:
aws cloudformation describe-stacks --stack-name hasura-cloud-byoc
Then, based on the result:
-
If you see an error "Stack with id hasura-cloud-byoc does not exist":
# Create new stack
aws cloudformation create-stack \
--stack-name hasura-cloud-byoc \
--template-body file://cloudformation.yaml \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ParameterKey=ExternalId,ParameterValue=hasura-cloud
# Wait for creation to complete
aws cloudformation wait stack-create-complete \
--stack-name hasura-cloud-byoc -
If the stack exists:
# Update existing stack
aws cloudformation update-stack \
--stack-name hasura-cloud-byoc \
--template-body file://cloudformation.yaml \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ParameterKey=ExternalId,ParameterValue=hasura-cloud
# Wait for update to complete
aws cloudformation wait stack-update-complete \
--stack-name hasura-cloud-byoc
-
-
Monitor stack status:
aws cloudformation describe-stacks \
--stack-name hasura-cloud-byoc \
--query 'Stacks[0].StackStatus' -
Once complete, retrieve the Role ARN:
aws cloudformation describe-stacks \
--stack-name hasura-cloud-byoc \
--query 'Stacks[0].Outputs[?OutputKey==`RoleArn`].OutputValue' \
--output text
Required Information
Share the following with the Hasura team:
- (Required) Role ARN (From output above)
- (Required) AWS Region
- (Optional) External ID
- The external ID used in the trust relationship between your AWS account and Hasura's AWS account
- This is the value you specified for the
ExternalId
parameter in the CloudFormation template - If not specified, the default value "hasura-cloud" will be used
- Must have a minimum of 2 characters and a maximum of 1,224 characters
- Must be alphanumeric without white space, but can include the following symbols: plus (+), equal (=), comma (,), period (.), at (@), colon (:), forward slash (/), and hyphen (-)
- Important: Make sure to provide this value to the Hasura team if you've customized it
- (Optional) Preferred Availability Zones
- Use AZ IDs (e.g., use1-az1, use1-az2) instead of AZ names (us-east-1a, us-east-1b)
- You can get the AZ IDs by running:
aws ec2 describe-availability-zones \
--region <region> \
--output table \
--query "AvailabilityZones[?State=='available'] | [].{ZoneName: ZoneName, ZoneId: ZoneId}" - If you have specific zones which you'd like to use, please pass it along. Otherwise, Hasura will assign accordingly.
- (Optional) VPC CIDR (/16-/19 CIDR)
- If you have a specific CIDR in mind for the VPC setup, please pass it along. If not specified, Hasura will assign 10.0.0.0/16.
- Note: If you are planning to use VPC Peering, this CIDR should not conflict with any networks on your side.
- (Optional) Kubernetes Service CIDR (/16-20 CIDR)
- A /16-/20 CIDR block used for Kubernetes service cluster IP addresses in your Data Plane. If not specified, Hasura will assign 172.20.0.0/16.
- Note: If you are planning to use VPC Peering, this CIDR should not conflict with any networks on your side.
GCP
The setup involves enabling APIs & creating IAM policy bindings; The IAM policy bindings establish a trust relationship with Hasura’s GCP service account which will be used to deploy and manage workloads necessary for Hasura DDN.
Pre-requisites
- Dedicated GCP Project
Setup instructions
- Enable APIs within GCP project:
gcloud services enable \
compute.googleapis.com \
dns.googleapis.com \
gkehub.googleapis.com \
multiclusterservicediscovery.googleapis.com \
trafficdirector.googleapis.com \
multiclusteringress.googleapis.com \
sqladmin.googleapis.com \
servicenetworking.googleapis.com \
container.googleapis.com \
certificatemanager.googleapis.com --project ${GCP_PROJECT_ID}
- Create following IAM Policy bindings for Hasura's
ddn-automation
service account:
IAM Policy bindings
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/compute.networkAdmin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/dns.admin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/gkehub.editor
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/logging.configWriter
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/container.clusterAdmin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/monitoring.metricsScopesAdmin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/certificatemanager.editor
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member='serviceAccount:[email protected]' \
--role='roles/resourcemanager.projectIamAdmin' \
--condition='^:^title=Restrict IAM Granting for ddn-automation:description=Restrict ddn-automation to granting specific roles to specific members:expression=api.getAttribute("iam.googleapis.com/modifiedGrantsByRole", []).hasOnly(["roles/container.defaultNodeServiceAccount"]) || api.getAttribute("iam.googleapis.com/modifiedGrantsByRole", []).hasOnly(["roles/container.admin"]) || api.getAttribute("iam.googleapis.com/modifiedGrantsByRole", []).hasOnly(["roles/compute.networkViewer"])'
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/container.admin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/iam.serviceAccountAdmin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/cloudsql.admin
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member "serviceAccount:[email protected]" \
--role roles/iam.workloadIdentityPoolAdmin
Provide Required Information
Share the following with the Hasura team:
- (Required) Project ID
- (Required) GCP Region
- (Optional) Preferred Availability Zones
- If you have specific zones which you'd like to use, please pass it along. Otherwise, Hasura will assign accordingly.
- (Optional) VPC CIDR (/16-/19 CIDR)
- If you have a specific CIDR in mind for the VPC setup, please pass it along. If not specified, Hasura will assign 10.0.0.0/16.
- Note: If you are planning to use VPC Peering, this CIDR should not conflict with any networks on your side.
Azure
The setup involves creating service principal registrations and role assignments that establish a trust relationship with Hasura's Azure automation service principals. These will be used to deploy and manage workloads necessary for Hasura DDN.
Prerequisites
- Azure Account with administrative access
- Dedicated Azure Subscription where Hasura Cloud will provision BYOC infrastructure
- Permissions to register Enterprise applications in your Azure AD tenant
- Permissions to assign roles at the subscription level
Provisioning Access
Step 1: Register Hasura Cloud Service Principals
You need to register the Hasura Cloud service principal in your Azure AD tenant:
For Infrastructure Provisioning (PrivateDdnInfra):
- Log in with an account that has permissions to register Enterprise applications
- Open a browser tab and navigate to the following URL, replacing
<TENANT_ID>
with your Azure Tenant ID:https://login.microsoftonline.com/<TENANT_ID>/oauth2/authorize?client_id=4f7f1f59-f0b0-4adb-8603-2afacc50552b&response_type=code&redirect_uri=https://hasura.io/docs/3.0/private-ddn/creating-a-data-plane/byoc
- Verify the service principal details match exactly:
- Client ID:
4f7f1f59-f0b0-4adb-8603-2afacc50552b
- Name:
Hasura Cloud Infrastructure Manager
- Client ID:
- Select "Consent on behalf of your organization" and click "Accept"
- You will be redirected back to this documentation page, confirming the registration was completed
Step 2: Verify Service Principal Registration
After completing the registration process, you can verify that the service principal was created successfully:
- Go to the Azure Portal
- Navigate to Azure Active Directory → Enterprise applications
- Search for "Hasura Cloud Infrastructure Manager" to confirm it appears in your tenant
Step 3: Deploy Role Assignments Using Azure Bicep
Use the provided Azure Bicep template to automatically set up the required roles and permissions:
- Copy the following ARM template and save it as
role.json
:
role.json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.37.4.10188",
"templateHash": "2560153094460201751"
}
},
"parameters": {
"resourceGroupNames": {
"type": "array",
"metadata": {
"description": "An array of resource group names to assign the role in."
}
},
"principalId": {
"type": "string",
"metadata": {
"description": "The principal (service principal) ID to assign the role to."
}
},
"principalType": {
"type": "string",
"defaultValue": "ServicePrincipal",
"allowedValues": [
"User",
"Group",
"ServicePrincipal"
],
"metadata": {
"description": "The type of principal (User, Group, or ServicePrincipal)."
}
}
},
"resources": [
{
"type": "Microsoft.Authorization/roleDefinitions",
"apiVersion": "2022-04-01",
"name": "[guid(subscription().id, 'HasuraCloudBYOCRole')]",
"properties": {
"roleName": "HasuraCloudBYOC",
"description": "Role for Hasura Cloud BYOC",
"type": "CustomRole",
"assignableScopes": [
"[subscription().id]"
],
"permissions": [
{
"actions": [
"Microsoft.DBforPostgreSQL/flexibleServers/*"
]
}
]
}
},
{
"copy": {
"name": "roleAssignments",
"count": "[length(parameters('resourceGroupNames'))]"
},
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"name": "[format('roleAssignment-{0}', parameters('resourceGroupNames')[copyIndex()])]",
"resourceGroup": "[parameters('resourceGroupNames')[copyIndex()]]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"customRoleDefinitionId": {
"value": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', guid(subscription().id, 'HasuraCloudBYOCRole'))]"
},
"principalId": {
"value": "[parameters('principalId')]"
},
"principalType": {
"value": "[parameters('principalType')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.37.4.10188",
"templateHash": "3705801931007012674"
}
},
"parameters": {
"customRoleDefinitionId": {
"type": "string",
"metadata": {
"description": "The custom role definition ID to assign."
}
},
"principalId": {
"type": "string",
"metadata": {
"description": "The principal (user, group, service principal) object ID to assign the role to."
}
},
"principalType": {
"type": "string",
"defaultValue": "ServicePrincipal",
"allowedValues": [
"User",
"Group",
"ServicePrincipal"
],
"metadata": {
"description": "The type of principal (User, Group, or ServicePrincipal)."
}
}
},
"variables": {
"networkContributorRoleId": "4d97b98b-1d4f-4787-a291-c67834d212e7",
"managedIdentityContributorRoleId": "e40ec5ca-96e0-45a2-b4ff-59039f2c2b59",
"managedIdentityOperatorRoleId": "f1a07417-d97a-45cb-824c-7a7467783830",
"aksContributorRoleId": "ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8",
"rbacAdministratorRoleId": "f58310d9-a9f6-439a-9e8d-f62e7b41a168",
"rbacCondition": "!(ActionMatches{'Microsoft.Authorization/roleAssignments/write'} OR ActionMatches{'Microsoft.Authorization/roleAssignments/delete'}) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {4d97b98b-1d4f-4787-a291-c67834d212e7, acdd72a7-3385-48ef-bd42-f606fba81ae7, b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b} AND @Request[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEqualsIgnoreCase {'ServicePrincipal', 'MSI'})"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, parameters('customRoleDefinitionId'), parameters('principalId'), 'custom')]",
"properties": {
"roleDefinitionId": "[parameters('customRoleDefinitionId')]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]"
}
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, variables('networkContributorRoleId'), parameters('principalId'), 'network')]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('networkContributorRoleId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]"
}
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, variables('managedIdentityContributorRoleId'), parameters('principalId'), 'identity')]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('managedIdentityContributorRoleId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]"
}
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, variables('managedIdentityOperatorRoleId'), parameters('principalId'), 'operator')]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('managedIdentityOperatorRoleId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]"
}
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, variables('aksContributorRoleId'), parameters('principalId'), 'aks')]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('aksContributorRoleId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]"
}
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id, variables('rbacAdministratorRoleId'), parameters('principalId'), 'rbac')]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('rbacAdministratorRoleId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "[parameters('principalType')]",
"condition": "[variables('rbacCondition')]",
"conditionVersion": "2.0"
}
}
]
}
},
"dependsOn": [
"[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', guid(subscription().id, 'HasuraCloudBYOCRole'))]"
]
}
]
}
-
Deploy the template using Azure CLI:
# Set your subscription
az account set --subscription "your-subscription-id"
# Get the Object ID of the Hasura Cloud Infrastructure Manager service principal
PRINCIPAL_ID=$(az ad sp list --filter "appId eq '4f7f1f59-f0b0-4adb-8603-2afacc50552b'" --query "[0].id" --output tsv)
# Deploy the template
az deployment sub create \
--name "hasura-cloud-byoc" \
--location "East US" \
--template-file role.json \
--parameters \
resourceGroupNames='["your-resource-group-name"]' \
principalId="$PRINCIPAL_ID" \
principalType="ServicePrincipal"Replace the following values:
your-subscription-id
: Your Azure subscription IDyour-resource-group-name
: The resource group where Hasura will operate (you can specify multiple resource groups:'["rg1","rg2","rg3"]'
)"East US"
: Your preferred Azure region
-
Monitor the deployment:
az deployment sub show --name hasura-cloud-byoc --query 'properties.provisioningState'
Additional Requirements
Feature Flag Registration
Register the required Azure feature flag for API server VNet integration:
az feature register --namespace "Microsoft.ContainerService" --name "EnableAPIServerVnetIntegrationPreview"
You can check the registration status with:
az feature show --namespace "Microsoft.ContainerService" --name "EnableAPIServerVnetIntegrationPreview"
Required Information
Gather the following information from your Azure Portal and provide it to the Hasura team:
Required:
- Subscription ID: The target subscription where BYOC infrastructure will be deployed
- Tenant ID: Your Azure AD tenant identifier
- Resource Group Name(s): The resource group(s) where Hasura will operate
- Azure Region: The target region for deployment (e.g., "East US", "West Europe")
Optional:
- Preferred Availability Zones: Specific logical zone IDs within your chosen region
- If not specified, Hasura will select zones automatically
- Use logical zone IDs (e.g., "1", "2", "3") which map to physical zones
- You can get the zone mappings by running:
Replace
az rest --method get \
--uri '/subscriptions/{subscriptionId}/locations?api-version=2022-12-01' \
--query 'value[?name==`eastus` && availabilityZoneMappings != `null`].{displayName: displayName, name: name, availabilityZoneMappings: availabilityZoneMappings}'eastus
with your desired region name and{subscriptionId}
with your subscription ID - Example: ["1", "2", "3"] for logical zones 1, 2, and 3
- VNet CIDR: Custom CIDR block for the virtual network (/16-/19 range)
- Default: 10.0.0.0/16 if not specified
- Important: Ensure this doesn't conflict with existing networks if using VNet peering