Skip to main content

Terraform Provider (alpha release)

Hyperstack provides a Terraform provider that enables infrastructure-as-code management of your cloud resources. Similar to other major cloud providers, you can use familiar Terraform workflows to provision and manage your infrastructure on Hyperstack, including virtual machines, Kubernetes clusters, and network resources.

In this document, you will find step-by-step instructions to use the Terraform provider with Hyperstack. By following these guidelines, you will be able to automate your infrastructure deployment and management using industry-standard practices.

To view more examples and resources:

  • Check out our public GitHub repository here.
  • Check out our HashiCorp Terraform provider documentation here.
note

Hyperstack Terraform provider is currently in alpha. The provisioning of some resources may not be fully stable. Use caution when deploying production workloads.

In this article

  1. Getting Started with Terraform Provider

  2. Working with the Terraform provider

  3. Resource Lookup


Getting Started with the Terraform Provider

1. Prerequisites

Before you begin using the Hyperstack Terraform provider, ensure you have completed the following steps:

  1. Install Terraform by following the official HashiCorp documentation

  2. Create a new API key or copy your existing API key. For additional information on accessing your API key, click here.

  3. Set up your environment variables:

export HYPERSTACK_API_KEY=your-api-key-here

2. Provider Configuration

To use the Hyperstack Terraform provider, add the following configuration to your Terraform files:

terraform {
required_providers {
hyperstack = {
source = "NexGenCloud/hyperstack"
version = "0.2.2-alpha"
}
}
}

provider "hyperstack" {}

3. Create your first Terraform configuration

To create your first Terraform configuration, create a vm.tf extension and add the following code:

terraform {
required_providers {
hyperstack = {
source = "app.terraform.io/nexgencloud/hyperstack"
version = "0.2.2-alpha"
}
tls = {
source = "hashicorp/tls"
version = "4.0.5"
}
}
}
provider "hyperstack" {}
provider "tls" {}

# Create an environment
resource "hyperstack_core_environment" "canada" {
name = "terraform-environment"
region = "CANADA-1"
}

# Generate a keypair for SSH access
resource "tls_private_key" "ed25519" {
algorithm = "ED25519"
}

# Create a keypair resource
resource "hyperstack_core_keypair" "ed25519" {
name = "terraform-keypair"
environment = hyperstack_core_environment.canada.name
public_key = tls_private_key.ed25519.public_key_openssh
}

# Save the private key content
resource "local_sensitive_file" "ssh" {
filename = "./llm-inference-benchmarking-keypair.pem"
content = tls_private_key.ed25519.private_key_openssh
}

# Create a virtual machine
resource "hyperstack_core_virtual_machine" "example-vm" {
name = "terraform-example"
environment_name = hyperstack_core_environment.canada.name
key_name = hyperstack_core_keypair.ed25519.name
image_name = "Ubuntu Server 22.04 LTS R535 CUDA 12.2 with Docker"
flavor_name = "n1-cpu-small"
user_data = ""
assign_floating_ip = true
}

# Allow port 22 to SSH into this machine
resource "hyperstack_core_virtual_machine_sg_rule" "ssh_access" {
virtual_machine_id = hyperstack_core_virtual_machine.example-vm.id
direction = "ingress"
ethertype = "IPv4"
port_range_min = 22
port_range_max = 22
protocol = "tcp"
remote_ip_prefix = "0.0.0.0/0"
}

# Output
output "ssh_private_key" {
description = "SSH private key of the e2e test"
value = tls_private_key.ed25519.private_key_openssh
sensitive = true
}

output "ssh_public_key" {
description = "SSH public key of the e2e test"
value = tls_private_key.ed25519.public_key_openssh
}

output "vm_floating_ip" {
description = "The floating IP for the basic test VM"
value = hyperstack_core_virtual_machine.example-vm.floating_ip
}

4. Initialize and apply the Terraform configuration

After creating the Terraform configuration, initialize the working directory and apply the configuration:

terraform init
terraform apply

5. View the created resources

After applying the Terraform configuration, you can view the created resources in the Hyperstack console. Also, you can view the output of the Terraform configuration:

terraform refresh

This command will refresh the state of the resources and show the output of the Terraform configuration, for example:

Outputs:

ssh_private_key = <sensitive>
ssh_public_key = <<EOT
ssh-ed25519 ...

EOT
vm_floating_ip = "38.80.123.27"

6. Delete resources

To destroy the created resources, run the following command:

terraform destroy

Working with the Terraform provider

Below are some examples of how to use the Hyperstack Terraform provider to create virtual machines, Kubernetes clusters, and manage security groups.

For more examples, please check out our public GitHub repository here

Creating Virtual Machines

note

This assumes you already have an environment and keypair to re-use. If you want a clean set-up, check out our example above here.

To create a virtual machine with GPU support, use the following configuration:

# Setup the providers
terraform {

required_providers {
hyperstack = {
source = "NexGenCloud/hyperstack"
version = "0.2.2-alpha"
}
# TLS provider to generate keypairs
tls = {
source = "hashicorp/tls"
version = "4.0.5"
}
}
}

provider "hyperstack" {}
provider "tls" {}

# Create a VM with 1x RTX-A6000 GPU
resource "hyperstack_core_virtual_machine" "my_test_vm" {
name = "tf-my-test-vm"
environment_name = "<MY_ENV_NAME>"
key_name = "<MY_KEYPAIR_NAME>"
image_name = "Ubuntu Server 22.04 LTS R535 CUDA 12.2"
flavor_name = "n3-RTX-A6000x1"
user_data = ""
assign_floating_ip = true
}

# Allow port 22 to SSH into this machine
resource "hyperstack_core_virtual_machine_sg_rule" "ssh_access" {
virtual_machine_id = hyperstack_core_virtual_machine.my_test_vm.id

direction = "ingress"
ethertype = "IPv4"
port_range_min = 22
port_range_max = 22
protocol = "tcp"
remote_ip_prefix = "0.0.0.0/0"
}

# output the floating ip to ssh to
output "vm_floating_ip" {
value = hyperstack_core_virtual_machine.my_test_vm.floating_ip
}

Creating Kubernetes Clusters

note

Cluster creation is currently under active development, and provisioning via Terraform may not yet be fully stable. It is highly recommended to run this process within an established environment for more reliable results. For more info, check out our Kubernetes documentation here.

To create a Kubernetes cluster, use the following configuration:

# Setup the providers
terraform {

required_providers {
hyperstack = {
source = "NexGenCloud/hyperstack"
version = "0.2.2-alpha"
}
}
}

provider "hyperstack" {}

# Create a Kubernetes cluster from the existing environment
# and existing keypair, with two n3-H100x1 worker nodes
resource "hyperstack_core_cluster" "my_k8s" {
name = "my-k8s-demo1"
node_count = 2

environment_name = "<MY_ENV_NAME>"
keypair_name = "<MY_KEYPAIR_NAME>"

kubernetes_version = "1.27.8"
image_name = "Ubuntu Server 22.04 LTS R535 CUDA 12.2"
master_flavor_name = "n1-cpu-medium"
node_flavor_name = "n3-H100x1"
}

# Output the cluster kube_config
output "kube_config" {
value = base64decode(hyperstack_core_cluster.my_k8s.kube_config)
}

Managing Security Groups

Security group rules can be added to virtual machines to control network access:

# Allow HTTPS traffic
resource "hyperstack_core_virtual_machine_sg_rule" "https" {
virtual_machine_id = hyperstack_core_virtual_machine.example.id
direction = "ingress"
ethertype = "IPv4"
port_range_min = 443
port_range_max = 443
protocol = "tcp"
remote_ip_prefix = "0.0.0.0/0"
}

# Allow custom port range
resource "hyperstack_core_virtual_machine_sg_rule" "custom" {
virtual_machine_id = hyperstack_core_virtual_machine.example.id
direction = "ingress"
ethertype = "IPv4"
port_range_min = 8000
port_range_max = 8080
protocol = "tcp"
remote_ip_prefix = "10.0.0.0/8"
}

Remember to run terraform init to initialize your working directory before running terraform plan or terraform apply. For any changes to your infrastructure, always review the plan before applying it.

3. Resource Lookup

Before creating resources, you may need to look up available options such as regions, flavors, and images. You can use the following API endpoints:

List Available Regions

curl -H "api_key: ${HYPERSTACK_API_KEY}" "https://infrahub-api.nexgencloud.com/v1/core/regions"

List Available Flavors

# All flavors in CANADA-1
curl -H "api_key: ${HYPERSTACK_API_KEY}" \
-G \
-d "region=CANADA-1" \
"https://infrahub-api.nexgencloud.com/v1/core/flavors"

# H100 GPU flavors only
curl -H "api_key: ${HYPERSTACK_API_KEY}" \
-G \
-d "region=CANADA-1" \
"https://infrahub-api.nexgencloud.com/v1/core/flavors" \
| jq '.data[] | select(.gpu | startswith("H100") )'

List Available Images

# All images in CANADA-1
curl -H "api_key: ${HYPERSTACK_API_KEY}" \
-G \
-d "region=CANADA-1" \
"https://infrahub-api.nexgencloud.com/v1/core/images"

# Ubuntu images only
curl -H "api_key: ${HYPERSTACK_API_KEY}" \
-G \
-d "region=CANADA-1" \
"https://infrahub-api.nexgencloud.com/v1/core/images" \
| jq '.images[] | select(.type=="Ubuntu")'