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.
terraform {required_providers {simplicloud = {source = "simplicloud/simplicloud"version = "~> 1.0"}}}provider "simplicloud" {org = "korafoods"project = "production"# token = var.simplicloud_token # or set SIMPLICLOUD_TOKEN}
2. Resources
| Resource | Creates | Key arguments |
|---|---|---|
simplicloud_ssh_key | An SSH key | name, public_key |
simplicloud_server | A server | name, plan, image, ssh_key_ids, backups |
simplicloud_volume | A volume | name, size_gb, server_id |
simplicloud_app | An app from GitHub | name, repo, branch, plan, env, domains |
simplicloud_database | A managed database | name, engine, version, plan |
simplicloud_bucket | A Spaces bucket | name, acl |
simplicloud_dns_record | A DNS record | domain, 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:
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 = 50server_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.uriS3_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
export SIMPLICLOUD_TOKEN="sc_live_…"terraform initterraform planterraform applyApply complete! Resources: 7 added, 0 changed, 0 destroyed.
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.
terraform import simplicloud_server.worker worker-1terraform import simplicloud_database.orders orders-dbterraform import simplicloud_dns_record.www korafoods.ng/CNAME/www
6. Keep state in Spaces
Spaces speaks S3, so the standard s3 backend works:
terraform {backend "s3" {bucket = "korafoods-tfstate"key = "production/terraform.tfstate"region = "us-east-1"endpoints = { s3 = "https://spaces.simplicloud.ai" }skip_credentials_validation = trueskip_region_validation = trueskip_requesting_account_id = trueuse_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.