Terraform

Create virtual machine environment on public cloud with Terraform

Terraform is a popular “Infrastructure as Code” tool that you can use to create virtual machines on public clouds with one click.

Pigsty currently provides example Terraform templates for Alibaba Cloud, AWS (global and China), Azure, GCP, Tencent Cloud, Hetzner, Vultr, DigitalOcean, and Linode. The aliyun-s3.tf template also creates a private OSS bucket and dedicated RAM read/write credentials for S3/pgBackRest scenarios.


Quick Start

Install Terraform

On macOS, you can use Homebrew to install Terraform:

brew install terraform

For other platforms, refer to the Terraform Official Installation Guide.

Initialize and Apply

Enter the Terraform directory, select a template, initialize provider plugins, and apply the configuration:

cd ~/pigsty/terraform
cp spec/aliyun.tf terraform.tf         # Select template
terraform init                         # Install cloud provider plugins (first use)
terraform apply                        # Generate execution plan and create resources

After running the apply command, type yes to confirm when prompted. Terraform will create VMs and related cloud resources for you.

Get IP Address

After creation, print the public IP address of the admin node:

terraform output -raw meta_ip

Configure SSH Access

Global-cloud templates usually also provide an executable ssh_command output:

terraform output -raw ssh_command

The repository’s ./ssh script is a compatibility tool for legacy templates whose outputs are all IP addresses and whose root password is PigstyDemo4. It iterates over every Terraform output, treats it as an IP address, writes it to ~/.ssh/pigsty_config, and distributes keys with sshpass. It is suitable for compatibility templates such as aliyun.tf, aliyun-full.tf, aliyun-oss.tf, and aliyun-pro.tf. Do not run it against modern templates that output ssh_command, private IPs, or access keys.

When using a compatible template:

./ssh       # Write SSH config and distribute keys
ssh meta    # Login using hostname instead of IP

Destroy Resources

After testing, you can destroy all created cloud resources with one click:

terraform destroy

Template Specs

Pigsty provides multiple predefined cloud resource templates in the terraform/spec/ directory:

Template FileCloud ProviderDescription
aliyun.tfAlibaba CloudSingle-node meta template, supports all distributions and AMD/ARM (default)
aliyun-s3.tfAlibaba CloudSingle node + private OSS bucket and RAM read/write credentials for S3/pgBackRest
aliyun-full.tfAlibaba CloudFour-node sandbox, supports all distributions and AMD/ARM
aliyun-oss.tfAlibaba CloudSix-node build template, supports all distributions and AMD/ARM
aliyun-pro.tfAlibaba CloudSeven-node multi-distribution test template
aws.tfAWSGlobal AWS single node, Debian 12/13, AMD/ARM
aws-cn.tfAWSLegacy single-node environment for AWS China
azure.tfAzureSingle node, Debian 12/13, AMD/ARM
gcp.tfGCPSingle node, Debian 12/13, AMD/ARM
qcloud.tfTencent CloudTencent Cloud single-node environment
hetzner.tfHetznerSingle node, Debian 12/13, AMD/ARM
vultr.tfVultrSingle node, Debian 12/13, currently AMD only
digitalocean.tfDigitalOceanSingle node, Debian 12/13, currently AMD only
linode.tfLinodeSingle node, Debian 12/13, currently AMD only

When using a template, copy the template file to terraform.tf:

cd ~/pigsty/terraform
cp spec/aliyun-full.tf terraform.tf   # Use Alibaba Cloud 4-node sandbox template
terraform init && terraform apply

Variable Configuration

Variables differ between templates. Alibaba Cloud templates support the full multi-distribution matrix and default to u26. Global AWS, Azure, GCP, Tencent Cloud, and Hetzner support Debian 12/13 with AMD/ARM selection and generally default to d12/amd64. Vultr, DigitalOcean, and Linode currently expose AMD instance choices only.

Architecture and Distribution

variable "architecture" {
  description = "Architecture type (amd64 or arm64)"
  type        = string
  default     = "amd64"    # Comment this line to use arm64
  #default     = "arm64"   # Uncomment to use arm64
}

variable "distro" {
  description = "Distribution code (the exact set depends on the template)"
  type        = string
  default     = "d12"       # Global-cloud templates usually default to Debian 12; Alibaba Cloud defaults to u26
}

Resource Configuration

Alibaba Cloud templates expose the following resource parameters in a locals block. Other cloud templates use provider-specific instance, disk, and network variables or local values; consult the selected .tf file.

locals {
  bandwidth        = 100                    # Public bandwidth (Mbps)
  disk_size        = 40                     # System disk size (GB)
  spot_policy      = "SpotWithPriceLimit"   # Spot policy: NoSpot, SpotWithPriceLimit, SpotAsPriceGo
  spot_price_limit = 5                      # Max spot price (only effective with SpotWithPriceLimit)
}

Alibaba Cloud Configuration

Credential Setup

Add your Alibaba Cloud credentials to environment variables, for example in ~/.bash_profile or ~/.zshrc:

export ALICLOUD_ACCESS_KEY="<your_access_key>"
export ALICLOUD_SECRET_KEY="<your_secret_key>"
export ALICLOUD_REGION="cn-shanghai"

Supported Images

The following are commonly used ECS Public OS Image prefixes in Alibaba Cloud:

DistroCodex86_64 Image Prefixaarch64 Image Prefix
CentOS 7.9el7centos_7_9_x64-
Rocky 8.10el8rockylinux_8_10_x64rockylinux_8_10_arm64
Rocky 9.7el9rockylinux_9_7_x64rockylinux_9_7_arm64
Rocky 10.1el10rockylinux_10_1_x64rockylinux_10_1_arm64
Debian 11.11d11debian_11_11_x64-
Debian 12.14d12debian_12_14_x64debian_12_14_arm64
Debian 13.5d13debian_13_5_x64debian_13_5_arm64
Ubuntu 22.04.5 LTSu22ubuntu_22_04_x64_20Gubuntu_22_04_arm64_20G
Ubuntu 24.04.4 LTSu24ubuntu_24_04_x64_20Gubuntu_24_04_arm64_20G
Ubuntu 26.04.0 LTSu26ubuntu_26_04_x64_20Gubuntu_26_04_arm64_20G
Anolis 8.10an8anolisos_8_10_x64anolisos_8_10_arm64
Alibaba Cloud Linux 3al3aliyun_3_x64_20G_alibase_[0-9]+aliyun_3_arm64_20G_alibase_[0-9]+

OSS Storage Configuration

The aliyun-s3.tf template additionally creates an OSS bucket and related permissions for PostgreSQL PITR backup:

  • OSS Bucket: Creates a private bucket named pigsty-oss
  • RAM User: Creates a dedicated pigsty-oss-user user
  • Access Key: Generates AccessKey and saves to ~/pigsty.sk
  • RAM Policy: Grants the user oss:* permissions on the bucket and its objects for read/write use

AWS Configuration

Credential Setup

Both global and China-region templates can read standard AWS environment variables or credential files:

export AWS_ACCESS_KEY_ID="<your_access_key>"
export AWS_SECRET_ACCESS_KEY="<your_secret_key>"
export AWS_REGION="us-west-2"

# ~/.aws/config
[default]
region = us-west-2

# ~/.aws/credentials
[default]
aws_access_key_id = <YOUR_AWS_ACCESS_KEY>
aws_secret_access_key = <AWS_ACCESS_SECRET>

aws.tf reads ~/.ssh/id_rsa.pub by default. The legacy China-region aws-cn.tf instead reads this dedicated public key:

~/.aws/pigsty-key.pub

Tencent Cloud Configuration

Credential Setup

Add Tencent Cloud credentials to environment variables:

export TENCENTCLOUD_SECRET_ID="<your_secret_id>"
export TENCENTCLOUD_SECRET_KEY="<your_secret_key>"
export TENCENTCLOUD_REGION="ap-beijing"

Other Cloud Credentials

# Azure: az login is recommended; for a service principal, use all four
export ARM_CLIENT_ID="<client_id>"
export ARM_CLIENT_SECRET="<client_secret>"
export ARM_SUBSCRIPTION_ID="<subscription_id>"
export ARM_TENANT_ID="<tenant_id>"

# GCP: gcloud auth application-default login is also supported
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

# Hetzner / Vultr / DigitalOcean / Linode
export HCLOUD_TOKEN="<api_token>"
export VULTR_API_KEY="<api_key>"
export DIGITALOCEAN_TOKEN="<api_token>"
export LINODE_TOKEN="<api_token>"

The GCP template also requires a project variable, for example terraform apply -var="project=my-project". Except for AWS China, current key-based templates read ~/.ssh/id_rsa.pub by default; edit the selected template to use another public-key path.


Shortcut Commands

Pigsty provides some Makefile shortcuts for Terraform operations:

cd ~/pigsty/terraform

make u          # terraform apply -auto-approve + run legacy ./ssh (compatible templates only)
make d          # terraform destroy -auto-approve
make apply      # terraform apply (interactive confirmation)
make destroy    # terraform destroy (interactive confirmation)
make out        # terraform output
make ssh        # Run ssh script to configure SSH access
make r          # Reset terraform.tf to repository state

For modern templates with ssh_command, private-IP, or other non-IP outputs, run terraform apply directly; do not use make u, which invokes the legacy ./ssh script afterward.


Notes


Last Modified: 2026-08-05: update extension count (6da764c)