Pilot pricing in Lagos: servers from ₦10 an hour, Spaces from ₦6,750 a month →
Docs menu

Docs / Reference

Terraform

10 minute read

Declare servers, apps, databases, buckets and DNS records as code with the simplicloud provider. State stays wherever you keep it.

1. Configure the provider

Add the provider to your configuration and run terraform init. The provider reads the API key from SIMPLICLOUD_TOKEN if you don't set token.

main.tf
terraform {
required_providers {
simplicloud = {
source = "simplicloud/simplicloud"
version = "~> 1.0"
}
}
}
provider "simplicloud" {
org = "korafoods"
project = "production"
# token = var.simplicloud_token # or set SIMPLICLOUD_TOKEN
}
Use a Developer key with an expiry for Terraform. Changes made by it show up in the audit log under the key's name.

2. Resources

ResourceCreatesKey arguments
simplicloud_ssh_keyAn SSH keyname, public_key
simplicloud_serverA servername, plan, image, ssh_key_ids, backups
simplicloud_volumeA volumename, size_gb, server_id
simplicloud_appAn app from GitHubname, repo, branch, plan, env, domains
simplicloud_databaseA managed databasename, engine, version, plan
simplicloud_bucketA Spaces bucketname, acl
simplicloud_dns_recordA DNS recorddomain, type, name, value, ttl

Plans use the same slugs as the API: s1–s4 for servers, basic, professional, pro-plus for apps, starter, standard, business for databases.

3. A full example

A server with a volume, a PostgreSQL database, an app that uses it, a bucket for images and a domain pointing at the app:

main.tf
resource "simplicloud_ssh_key" "laptop" {
name = "laptop"
public_key = file("~/.ssh/id_ed25519.pub")
}
resource "simplicloud_server" "worker" {
name = "worker-1"
plan = "s2"
image = "ubuntu-24.04"
ssh_key_ids = [simplicloud_ssh_key.laptop.id]
backups = true
}
resource "simplicloud_volume" "data" {
name = "worker-data"
size_gb = 50
server_id = simplicloud_server.worker.id
}
resource "simplicloud_database" "orders" {
name = "orders-db"
engine = "postgresql"
version = "16"
plan = "standard"
}
resource "simplicloud_app" "storefront" {
name = "storefront"
repo = "kora/storefront"
branch = "main"
plan = "professional"
domains = ["www.korafoods.ng"]
env = {
NODE_ENV = "production"
DATABASE_URL = simplicloud_database.orders.uri
S3_BUCKET = simplicloud_bucket.images.name
}
}
resource "simplicloud_bucket" "images" {
name = "korafoods-images"
acl = "public-read"
}
resource "simplicloud_dns_record" "www" {
domain = "korafoods.ng"
type = "CNAME"
name = "www"
value = "${simplicloud_app.storefront.name}.apps.simplicloud.ai"
ttl = 3600
}
output "ssh" {
value = "ssh -p ${simplicloud_server.worker.ssh_port} [email protected]"
}

4. Plan and apply

Terminal
export SIMPLICLOUD_TOKEN="sc_live_…"
terraform init
terraform plan
terraform apply
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
State contains database passwords and connection strings. Keep it in an encrypted backend, such as a private Spaces bucket, never in git.

5. Bring in existing resources

Import things you created in the console so Terraform manages them from now on. Use the name shown in the console as the ID.

Terminal
terraform import simplicloud_server.worker worker-1
terraform import simplicloud_database.orders orders-db
terraform import simplicloud_dns_record.www korafoods.ng/CNAME/www

6. Keep state in Spaces

Spaces speaks S3, so the standard s3 backend works:

backend.tf
terraform {
backend "s3" {
bucket = "korafoods-tfstate"
key = "production/terraform.tfstate"
region = "us-east-1"
endpoints = { s3 = "https://spaces.simplicloud.ai" }
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
use_path_style = true
}
}

Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to a Spaces access key. The region value is required by the backend but ignored by Spaces.

Was this page helpful?

Related guides

Terraform · Docs · SimpliCloud