Provision a Cluster via Terraform
A focused, step-by-step tutorial for automating the provisioning of a MongoDB replicaset master node on 123cluster using Terraform with the Mastercard/restapi provider, demonstrating how to capture the REST API curl command from the UI, deconstruct its headers and payload, translate them into Terraform variables and resources, and integrate the process into a repeatable CI/CD workflow.
Step 1: Copy the curl Command from the UI
On the Create a new replicaset (Master) screen, click { REST API }. The following example is copied:
curl -v \
-H "Authorization: Bearer <YOUR_JWT_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"host": {
"name": "<HOST_NAME>",
"ssh_port": <SSH_PORT>,
"username": "<SSH_USERNAME>",
"password": "<SSH_PASSWORD>",
"private_key": "<OPTIONAL_PRIVATE_KEY_CONTENT>"
},
"cluster": {
"name": "<CLUSTER_NAME>"
},
"ex_params": {
"replicaset_name": "<REPLICASET_NAME>",
"repository": "<BACKUP_REPOSITORY>",
"ssl": <USE_SSL>
"service_name": "proxmox",
"proxmox": true,
"distributor": "<OS_DISTRIBUTOR>",
"release": "<OS_VERSION>"
},
"name": "<NODE_NAME>",
"auto_delete": false,
"version": "<DB_VERSION>",
"auto_delete_days": 1,
"port": <DB_PORT>,
"sizing": "<SIZING>",
"dir_123Cluster": "<DATA_DIRECTORY>",
"drop_inventories": false,
"database_user": "<DB_ADMIN_USER>",
"database_pwd": "<DB_ADMIN_PASSWORD>",
"rest_api": true
}' \
<API_BASE_URL><API_PATH>
Step 2: Parse the curl Command
- Authorization header: Extract your JWT token from Bearer <YOUR_JWT_TOKEN>.
- Content-Type & Accept: Preserve both application/json headers.
- Payload fields
- host.name / host.ssh_port / host.username / host.password / host.private_key
- cluster.name
- ex_params.replicaset_name / ex_params.repository / ex_params.ssl / ex_params.distributor / ex_params.release
- name (node identifier)
- auto_delete / auto_delete_days
- version / port / sizing / dir_123Cluster / drop_inventories
- database_user / database_pwd
- rest_api
- Endpoint
- Base URI: <API_BASE_URL>
Step 3: Translate into Terraform
Directory Structure
├── locals.tf
├── main.tf
├── outputs.tf
├── terraform.tfvars
└── variables.tf
Terraform Parameters
Replace fields in corner brackets <> in parameters file with values extracted from the URL.
File terraform.tfvars:
api_uri = "<API_BASE_URL>"
api_path = "<API_PATH>"
api_ssl_insecure = true
auth_key = "Bearer <YOUR_JWT_TOKEN>"
ssh_password = "<SSH_PASSWORD>"
ssh_private_key = "<OPTIONAL_PRIVATE_KEY_CONTENT>"
os_distro = "<OS_DISTRIBUTOR>"
os_release = <OS_VERSION>
database_user = "<DB_ADMIN_USER>"
database_pwd = "<DB_ADMIN_PASSWORD>"
cluster_name = "<CLUSTER_NAME>"
replicaset_name = "<REPLICASET_NAME>"
host_name = "<HOST_NAME>"
create_cluster_in_one_click = true
db_version = "<DB_VERSION>"
port = <DB_PORT>
Terraform Input Variables
Copy contents as is.
File variables.tf:
File variables.tf:
variable "api_uri" {
description = "REST API base URL"
type = string
}
variable "api_path" {
description = "REST API URI path for creating and object"
type = string
}
variable "api_ssl_insecure" {
description = "Skip SSL cert checks on API calls"
type = bool
default = false
}
variable "auth_key" {
description = "REST API Auth key"
type = string
sensitive = true
}
variable "ssh_port" {
description = "SSH port for initial host setup"
type = number
default = 22
}
variable "ssh_user" {
description = "SSH username"
type = string
default = "root"
}
variable "ssh_password" {
description = "SSH password"
type = string
sensitive = true
}
variable "ssh_private_key" {
description = "SSH private key"
type = string
sensitive = true
default = ""
}
variable "host_name" {
description = "Host name"
type = string
}
variable "cluster_name" {
description = "Name of the new DB cluster"
type = string
default = ""
}
variable "replicaset_name" {
description = "Internal replicaset identifier"
type = string
default = ""
}
variable "repository" {
description = "Backup repository location"
type = string
default = "network"
}
variable "use_ssl" {
description = "Configure SSL"
type = bool
default = false
}
variable "service_name" {
description = "Hosting service name"
type = string
default = "proxmox"
}
variable "is_proxmox" {
description = "Is Proxmox used"
type = bool
default = true
}
variable "os_distro" {
description = "OS Distributor name"
type = string
}
variable "os_release" {
description = "OS Release (version) name"
type = number
}
variable "db_version" {
description = "Desired DB server version"
type = string
}
variable "port" {
description = "DB service port"
type = number
}
variable "mongos_port" {
description = "MongoDB service port"
type = number
default = null
}
variable "data_directory" {
description = "Data directory for DB files"
type = string
default = "/123cluster/mongo/data1"
}
variable "database_user" {
description = "Database username"
type = string
}
variable "database_pwd" {
description = "Database password"
type = string
sensitive = true
}
variable "sizing" {
description = "Size of the deployment"
type = string
default = "SMALL"
}
variable "mysql_root_password" {
description = "MySQL root password"
type = string
sensitive = true
default = ""
}
variable "pg_password" {
description = "PostgreSQL administrator password"
type = string
sensitive = true
default = ""
}
variable "repmgr_pwd" {
description = "PostgreSQL replication manager password"
type = string
sensitive = true
default = ""
}
variable "certificate_authentication" {
description = "Use certificate authentication"
type = bool
default = null
}
variable "create_cluster_in_one_click" {
description = "Create cluster in one click"
type = bool
default = null
}
variable "auto_delete" {
description = "Delete server automatically"
type = bool
default = false
}
variable "auto_delete_days" {
description = "Delete server automatically after N days"
type = number
default = 1
}
variable "drop_inventories" {
description = "Delete all backups and exports if exist"
type = bool
default = false
}
Terraform Output Variables
Copy contents as is.
File outputs.tf:
/*
Output the full JSON response from the API call.
- Useful for logging, audit, or passing to downstream workflows.
*/
output "deploy_response" {
description = "Raw JSON response from API call"
value = restapi_object.deploy.data
sensitive = true
}
Terraform Local Variables
Copy contents as is.
File locals.tf:
locals {
call_params = merge(
{
host = {
ssh_port = var.ssh_port
username = var.ssh_user
password = var.ssh_password
private_key = var.ssh_private_key
name = var.host_name
}
cluster = {
name = var.cluster_name
}
ex_params = local.call_params_ex_params
name = "${var.host_name}:${var.port}"
auto_delete = var.auto_delete
version = var.db_version
auto_delete_days = var.auto_delete_days
port = var.port
sizing = var.sizing
dir_123Cluster = var.data_directory
drop_inventories = var.drop_inventories
database_user = var.database_user
database_pwd = var.database_pwd
rest_api = true
},
var.create_cluster_in_one_click != null ? {create_cluster_in_one_click = var.create_cluster_in_one_click} : {},
)
call_params_ex_params = merge(
{
repository = var.repository
ssl = var.use_ssl
service_name = var.service_name
proxmox = var.is_proxmox
distributor = var.os_distro
release = var.os_release
},
var.replicaset_name != "" ? {replicaset_name = var.replicaset_name} : {},
var.mongos_port != null ? {mongos_port = var.mongos_port} : {},
var.mysql_root_password != "" ? {mysql_root_password = var.mysql_root_password} : {},
var.pg_password != "" ? {pg_password = var.pg_password} : {},
var.repmgr_pwd != "" ? {repmgr_pwd = var.repmgr_pwd} : {},
var.certificate_authentication != null ? {certificate_authentication = var.certificate_authentication} : {},
)
ret_object_id = var.cluster_name
}
Terraform Main module
Copy contents as is.
File main.tf:
File main.tf:
terraform {
required_providers {
restapi = {
source = "Mastercard/restapi"
version = "1.19.1"
}
}
}
provider "restapi" {
uri = var.api_uri
insecure = var.api_ssl_insecure
write_returns_object = true
debug = true
headers = {
Authorization = var.auth_key
Content-Type = "application/json"
Accept = "application/json"
}
create_method = "POST"
update_method = "POST"
destroy_method = "POST"
}
resource "restapi_object" "deploy" {
path = var.api_path
data = jsonencode(local.call_params)
object_id = local.ret_object_id
}
Step 4: Deploy the Stack
Use Terraform to deploy the stack
# Download all dependencies
terraform init
# Validate the template
terraform validate
# Create the stack
terraform apply
# Retrieve outputs
terraform output deploy_response
Additional Guidance & Best Practices
Parameterization
All user-specific and environment-specific values are exposed as Terraform variables, making the template portable and reusable across multiple clusters, accounts.
Security
- Sensitive Parameters: Use sensitive = true for passwords and tokens to prevent them from appearing in console or API responses.
API Versioning
Always verify endpoint and payload requirements with the latest 123cluster API documentation to ensure compatibility. Update the Lambda function code as the API evolves.


