End-to-End Example

DE-CIX PDM Team Updated by DE-CIX PDM Team

End-to-End Example: Deploying a Cloud ROUTER with Terraform

The live article is already quite good and close to the developer's MD file. I'll give you the complete optimized version ready to paste — with all improvements included.

This example demonstrates a complete Cloud ROUTER deployment using the IX-API Terraform provider. It is intended to show how a customer might attach multiple services to a single Cloud ROUTER and manage them consistently through Terraform.

The scenario includes:

  • 1 Cloud ROUTER (VRF)
  • 2 Cloud VC connections
  • 1 P2P VC connection
  • 1 Prefix List
  • 1 Routing Policy
  • 1 Static Route
  • Verification data sources

In this example:

  • Cloud VC 1 represents connectivity to a first cloud environment
  • Cloud VC 2 represents connectivity to a second cloud environment
  • P2P VC represents a private site-to-site or partner connection

The Cloud ROUTER acts as the central routing instance and terminates all three BGP sessions.

Prerequisites

  • Terraform v1.0 or later
  • Valid IX-API credentials
  • A Cloud ROUTER product offering ID
  • Existing network service IDs for 2 Cloud VCs and 1 P2P VC
  • A physical connection ID for the P2P VC
  • BGP passwords for all sessions

Step 1 – Define Variables

variable "account_id" {
description = "DE-CIX account ID"
type = string
}

variable "product_offering_id" {
description = "Cloud ROUTER product offering ID"
type = string
}

variable "p2p_vc_network_service_id" {
description = "Network service ID for the P2P VC"
type = string
}

variable "cloud_vc_network_service_id_1" {
description = "Network service ID for Cloud VC 1"
type = string
}

variable "cloud_vc_network_service_id_2" {
description = "Network service ID for Cloud VC 2"
type = string
}

variable "network_connection_id" {
description = "Physical connection ID for the P2P VC"
type = string
}

variable "bgp_password_p2p" {
description = "BGP password for the P2P VC session"
type = string
sensitive = true
}

variable "bgp_password_cloud_1" {
description = "BGP password for Cloud VC 1"
type = string
sensitive = true
}

variable "bgp_password_cloud_2" {
description = "BGP password for Cloud VC 2"
type = string
sensitive = true
}

Step 2 – Configure the Provider

terraform {
required_providers {
ixapi = {
source = "registry.terraform.io/ix-api-net/ixapi"
version = "~> 1.0"
}
}
}

provider "ixapi" {
api = "https://ixapi.de-cix.net/api/v2"
api_key = var.api_key
api_secret = var.api_secret
extension_de_cix_cloud_router_enabled = true
}

Step 3 – Create the Cloud ROUTER

resource "ixapi_de_cix_cloud_router" "main" {
managing_account = var.account_id
consuming_account = var.account_id
billing_account = var.account_id
product_offering = var.product_offering_id
asn = 65000
capacity = 1000
external_ref = "customer-cloud-router-prod"
}

Step 4 – Attach the P2P VC

This attachment can represent a private connection to a site, partner, or on-premises environment.

resource "ixapi_de_cix_cloud_router_network_service_config_p2p_vc" "site_a" {
managing_account = var.account_id
consuming_account = var.account_id
billing_account = var.account_id
cloud_router = ixapi_de_cix_cloud_router.main.id
network_service = var.p2p_vc_network_service_id
network_connection = var.network_connection_id
address = "10.0.1.1/30"
bgp_neighbor = "10.0.1.2"
bgp_neighbor_asn = 64512
bgp_password = var.bgp_password_p2p
admin_status = "enabled"
bfd_enabled = true
external_ref = "site-a-p2p"

vlan_config {
vlan_type = "dot1q"
vlan_id = 100
}
}

Step 5 – Attach Cloud VC 1

This attachment represents connectivity to a first cloud environment.

resource "ixapi_de_cix_cloud_router_network_service_config_cloud_vc" "cloud_1" {
managing_account = var.account_id
consuming_account = var.account_id
billing_account = var.account_id
cloud_router = ixapi_de_cix_cloud_router.main.id
network_service = var.cloud_vc_network_service_id_1
address = "10.0.2.1/30"
bgp_neighbor = "10.0.2.2"
bgp_neighbor_asn = 64513
bgp_password = var.bgp_password_cloud_1
admin_status = "enabled"
bfd_enabled = true
handover = 1
external_ref = "cloud-vc-1"
}

Step 6 – Attach Cloud VC 2

This attachment represents connectivity to a second cloud environment or a second cloud region.

resource "ixapi_de_cix_cloud_router_network_service_config_cloud_vc" "cloud_2" {
managing_account = var.account_id
consuming_account = var.account_id
billing_account = var.account_id
cloud_router = ixapi_de_cix_cloud_router.main.id
network_service = var.cloud_vc_network_service_id_2
address = "10.0.3.1/30"
bgp_neighbor = "10.0.3.2"
bgp_neighbor_asn = 64514
bgp_password = var.bgp_password_cloud_2
admin_status = "enabled"
bfd_enabled = true
handover = 2
external_ref = "cloud-vc-2"
}

Note on handover: Refers to cloud side diversity. For most cloud providers the value is always 1 (primary handover). For Azure, 2 can be used for a secondary handover point.

Step 7 – Create a Prefix List

This prefix list matches customer address space and can be referenced by routing policies.

resource "ixapi_de_cix_cloud_router_prefix_list" "customer_nets" {
name = "customer-networks"
managing_account = var.account_id
consuming_account = var.account_id

match_list {
prefix = "10.10.0.0/16"
min_length = 24
max_length = 28
}

match_list {
prefix = "172.20.0.0/16"
max_length = 24
}
}

Step 8 – Create a Routing Policy

This policy accepts matched customer prefixes and assigns a higher local preference. All other routes are rejected.

resource "ixapi_de_cix_cloud_router_policy" "inbound" {
name = "inbound-policy"
managing_account = var.account_id
consuming_account = var.account_id

entries {
sequence_number = 10
match_prefix_list = ixapi_de_cix_cloud_router_prefix_list.customer_nets.name

action {
filter = "accept"
local_preference = 200
}
}

entries {
sequence_number = 20

action {
filter = "reject"
}
}
}

Step 9 – Create a Static Route

This example creates an aggregate route and associates it with selected network service configurations.

resource "ixapi_de_cix_cloud_router_static_route" "internal_aggregate" {
name = "internal-aggregate"
prefix = "10.100.0.0/16"
next_hop = "aggregate"
network_service_configs = [
ixapi_de_cix_cloud_router_network_service_config_p2p_vc.site_a.id,
ixapi_de_cix_cloud_router_network_service_config_cloud_vc.cloud_1.id
]
}

Step 10 – Add Verification Data Sources

These data sources confirm that the Cloud ROUTER and attached sessions are operational after deployment.

data "ixapi_de_cix_cloud_router_routes" "main" {
vrf = ixapi_de_cix_cloud_router.main.id
}

data "ixapi_de_cix_cloud_router_bgp_state" "p2p" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_p2p_vc.site_a.id
}

data "ixapi_de_cix_cloud_router_bgp_state" "cloud_1" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_cloud_vc.cloud_1.id
}

data "ixapi_de_cix_cloud_router_bgp_state" "cloud_2" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_cloud_vc.cloud_2.id
}

data "ixapi_de_cix_cloud_router_bfd_state" "p2p" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_p2p_vc.site_a.id
}

data "ixapi_de_cix_cloud_router_bfd_state" "cloud_1" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_cloud_vc.cloud_1.id
}

data "ixapi_de_cix_cloud_router_bfd_state" "cloud_2" {
nsc_id = ixapi_de_cix_cloud_router_network_service_config_cloud_vc.cloud_2.id
}

Step 11 – Initialize, Review, and Apply

$ terraform init
$ terraform plan
$ terraform apply

Step 12 – Verify BGP Session State

After deployment, verify that the configured BGP sessions have reached the expected operational state. A healthy session is expected to reach the Established state.

You can check this directly via the API:

$ curl --request GET \
--url 'https://api.de-cix.net/api/v3/decix-vrf-v1/network-service-configs/<network_service_config_id>/bgp-state' \
--header 'Authorization: Bearer <token>'

Possible BGP states:

State

Description

Idle

Session not yet started

Connect

Attempting TCP connection

Active

TCP connection failed, retrying

Open Sent

TCP connected, BGP Open sent

Open Confirm

BGP Open received, waiting for Keepalive

Established

Session is fully operational ✓

Step 13 – Clean Up

To remove all resources managed by this example:

$ terraform destroy

Note: NSCs must be destroyed before the Cloud ROUTER. Terraform handles this automatically based on the resource dependency graph.

Notes

  • This example uses illustrative IP addressing and ASNs. Replace these values with the parameters required for your environment.
  • The exact network service IDs, handover values, and BGP settings depend on your provisioned services.
  • Cloud VC and P2P VC resources follow similar patterns, but their required attributes differ based on the service type.

How did we do?

State Management

Get in touch