Terraform Provider
The GPCN™ (Global Private Cloud Network™) Terraform provider lets you describe your infrastructure in code and build it with terraform apply. This guide takes you from an empty folder to a running virtual machine (VM) you can sign in to over SSH, then shows how to organize what you build and tear it down.
By the end you'll have a VPC in one data center, a security group that lets SSH in from your own address, a subnet, an SSH key, and a VM with an elastic IP. Everything is defined in one file you can version, review, and rebuild.
Prerequisites
- Terraform 1.5 or later. Check with
terraform version. - An API key. Create one in the portal under Identity & Access → Credentials → API Keys — see API Keys. The key acts with your roles, so it can only create what you could create in the portal.
- A role that can create resources. Tenant Operator, Tenant Manager, or Tenant Administrator. An organization-wide role creates in your Default resource group; to create in another group, you need a role scoped to that group — see Roles & Permissions.
- An SSH key pair on your machine. This guide uses
~/.ssh/id_ed25519.pub. - Your public IP address, so the security group can allow SSH from it and nothing else.
Install and authenticate
Create a new folder and a file named main.tf. Start it with the provider requirement:
terraform {
required_providers {
gpcn = {
source = "Global-Private-Cloud-Network/gpcn"
version = "~> 1.5"
}
}
}
provider "gpcn" {}
The provider block can stay empty. The provider reads its connection from two environment variables:
export GPCN_HOST="https://api.gpcn.com"
export GPCN_API_KEY="<your API key>"
Then install the provider:
terraform init
terraform init downloads the provider from the Terraform Registry. You can also set host and api_key inside the provider block, but keep the key out of anything you commit.
The provider checks your API key when it starts. A revoked or expired key stops the plan with a clear message, and a key that expires within seven days shows a warning — rotate it before it lapses.
Build the infrastructure
Add each block below to main.tf, in order. Together they make one working configuration.
1. Pick a data center, an image, and a size
Data sources look up IDs so you don't have to copy them from the portal. This example uses the Chicago 1 data center, the Alma Linux 8.x image, and a general-purpose size with at least two CPUs:
data "gpcn_datacenters" "chicago" {
name = "Chicago 1"
vpc_capable = true
}
locals {
datacenter_id = data.gpcn_datacenters.chicago.datacenters[0].id
}
data "gpcn_virtualmachine_images" "alma" {
datacenter_id = local.datacenter_id
image_name = "Alma Linux 8.x"
}
data "gpcn_virtualmachine_sizes" "small" {
datacenter_id = local.datacenter_id
category = "general-purpose"
min_cpu = 2
}
To build somewhere else, swap in a data center and image your organization uses. Use the names the portal shows when you create a VM:
namematches any part of a data center's name or its code, without regard to case."Chicago 1"and"CHI-1"find the same data center. Keep the value specific enough to match only the one you want, because the example takes the first match.vpc_capable = truekeeps only data centers that offer VPCs. If the plan reports no matching data center, check the name, then check that the data center offers VPCs.image_namematches any part of an image's name, without regard to case. The image must be offered in the data center you picked.
gpcn_datacenters also filters by country_name, region_name, and gpu_enabled. Sizes come in two categories, general-purpose and memory-optimized.
2. Create a VPC
A VPC is your private network in one data center. Its range must be a private (RFC 1918) block between /16 and /24:
resource "gpcn_vpc" "main" {
name = "getting-started"
datacenter_id = local.datacenter_id
cidr = "10.20.0.0/16"
}
3. Add a security group
The security group is the VPC's packet filter. The rule blocks you declare are the group's complete rule set: they replace its rules, they don't add to them. So list everything the group should allow.
This group allows three things:
- SSH from your address. Replace
203.0.113.10/32with your own public address. - All traffic from the subnet you'll create in the next step (
10.20.1.0/24). Without this rule, the VM can't answer your connection. - All outbound traffic.
resource "gpcn_vpc_nsg" "ssh" {
vpc_id = gpcn_vpc.main.id
name = "ssh"
rule {
direction = "ingress"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_cidr = "203.0.113.10/32"
description = "SSH from my address"
}
rule {
direction = "ingress"
protocol = "all"
remote_cidr = "10.20.1.0/24"
description = "All traffic from the app subnet"
}
rule {
direction = "egress"
protocol = "all"
remote_cidr = "0.0.0.0/0"
description = "All outbound traffic"
}
}
If you change the subnet's range in step 4, change this rule to match.
4. Add a subnet
A subnet is an address range inside the VPC. Binding the security group here applies it to every machine on the subnet:
resource "gpcn_vpc_subnet" "app" {
vpc_id = gpcn_vpc.main.id
name = "app"
cidr = "10.20.1.0/24"
nsg_id = gpcn_vpc_nsg.ssh.id
}
5. Register your SSH key
resource "gpcn_ssh_key" "me" {
name = "getting-started"
public_key = file("~/.ssh/id_ed25519.pub")
}
6. Create the VM
resource "gpcn_virtualmachine" "web" {
name = "web-1"
datacenter_id = local.datacenter_id
size_id = data.gpcn_virtualmachine_sizes.small.sizes[0].id
image_id = data.gpcn_virtualmachine_images.alma.images[0].id
subnet_id = gpcn_vpc_subnet.app.id
allocate_public_ip = true
initial_auth = {
ssh_key_id = gpcn_ssh_key.me.id
username = "almalinux"
}
}
output "web_public_ip" {
value = gpcn_virtualmachine.web.public_ip
}
allocate_public_ip = true acquires an elastic IP for the VM so you can reach it over SSH. initial_auth takes an SSH key or a password, plus a username, and only applies when the VM is created.
Plan and apply
Preview what Terraform will create:
terraform plan
The plan lists five resources to add: the VPC, the security group, the subnet, the SSH key, and the VM. Apply it:
terraform apply
Creating a VM, GPU VM, volume, VPC, or L2 segment runs as a job on the platform, and the provider waits for each one to finish. When the apply completes, Terraform prints web_public_ip. Sign in with:
ssh almalinux@<web_public_ip>
Organize with resource groups
Every resource belongs to a resource group. gpcn_virtualmachine, gpcn_gpu, gpcn_volume, gpcn_vpc, and gpcn_l2_segment each take a resource_group_id:
- Leave it out and the resource joins your organization's Default group. The attribute then reports the Default group's ID.
- Set it to place the resource in another group. Your role must reach that group.
- Change it to move the resource in place, without replacing it. Moving a VPC takes its subnets, security groups, and elastic IPs along.
- Remove it from the configuration and nothing moves; the resource stays where it is.
If your API key's roles don't reach the Default group, set resource_group_id on every resource you create. Otherwise the platform refuses the create.
The gpcn_resource_groups data source finds a group by its exact name and gives you default_resource_group_id. Use gpcn_resource_group to create a group in code.
Terraform can't delete the Default group or a group that still holds resources. If one apply moves resources out of a group and also deletes it, Terraform tries the delete first and it fails. Apply the moves on their own (for example with -target), then apply again to delete the group. For how groups and roles work, see Resource Groups.
What changes in place and what replaces
Read the plan before you apply. Where a change can't be made to the existing resource, the plan says must be replaced, and Terraform destroys the resource and creates a new one.
- VM size (
size_id): changes in place when the new size is an upgrade the platform offers for that VM; otherwise the VM is replaced. - VM image or subnet (
image_id,subnet_id): always replaces the VM. initial_auth: only used at creation. Changing it later updates Terraform's state, not the VM.- Resource group (
resource_group_id): changes in place.
Elastic IPs and other building blocks
There are two ways to give a VM a public address, and you can't combine them:
allocate_public_ip = trueacquires an elastic IP for the VM. Destroying the VM releases it.public_ip_idattaches an elastic IP your organization already holds (gpcn_vpc_public_ip). That address outlives the VM, and it keeps billing until you release it.
Other resources you'll use as you grow:
gpcn_gpufor GPU VMs, with thegpcn_gpu_inventorydata source to see what's available.gpcn_volumeandgpcn_volume_attachmentfor storage. Attaching or detaching a volume doesn't stop the VM.gpcn_l2_segmentfor a flat layer-2 network. A VM takes up to four segments throughl2_segment_ids; changing them stops the VM unless its image supports network hotplug.gpcn_vpc_public_ip_attachmentto attach a held elastic IP separately from the VM.
gpcn_network, the legacy L3 network resource, is deprecated, and creating one is refused. Build new networking with VPCs.
Provider settings
Three optional settings tune how the provider talks to the platform:
| Setting | Default | What it controls |
|---|---|---|
polling_timeout |
600 seconds | How long the provider waits for a job to finish |
request_timeout |
60 seconds | How long a single request can take |
max_retries |
3 | How many times a request that fails for a temporary reason is retried |
State and teams
The provider has no state backend of its own; any standard Terraform backend works. When several people manage the same infrastructure, use a remote backend with state locking so two applies can't run at once.
Clean up
When you're done, destroy what you built so it stops billing:
terraform destroy
Destroying the VM releases the elastic IP it acquired with allocate_public_ip. An elastic IP you hold separately stays, and keeps billing, until you release it.
Next Steps
- Terraform provider documentation — every resource, data source, and argument, plus migration and upgrade guides
- VPC Overview — how VPCs, subnets, security groups, and elastic IPs fit together
- Resource Groups — organizing resources and who can act on them
- API Keys — create and rotate the key Terraform uses
.png)