RedSwitches API Private beta Reference
Menu

Terraform

Manage RedSwitches servers, SSH keys and reverse DNS as code with the redswitches/redswitches Terraform provider.

Set up

terraform {
  required_providers {
    redswitches = {
      source = "redswitches/redswitches"
    }
  }
}

provider "redswitches" {
  # api_key = var.redswitches_api_key  # or set REDSWITCHES_API_KEY
}

The API key comes from the REDSWITCHES_API_KEY environment variable or the provider block. It is never written to the Terraform state. base_url (or REDSWITCHES_BASE_URL) changes the API root; leave it unset.

The key needs the permissions for what you manage: read always, ssh_keys for SSH keys, manage for labels and reverse DNS, order to create servers, power to change power_state, and cancel to destroy servers.

Data sources

Data sourceReadsAPI
redswitches_offersInstant servers in stock, with prices and OS choices. Optional filters: location (city or country code), country, max_price (monthly, before tax), in_stock, os (part of an OS name).GET /offers
redswitches_offerOne offer by id. Fails when it is not on offer now.GET /offers/{id}
redswitches_serversYour servers, every page. Optional filters: label_prefix, status.GET /servers
redswitches_serverOne server by id, with its IP addresses, OS, hardware and delivery state.GET /servers/{id}
redswitches_ssh_keysYour saved SSH keys.GET /ssh-keys
redswitches_accountAccount id, status, currency (and credit with read_billing).GET /account
data "redswitches_offers" "ams" {
  location  = "Amsterdam"
  max_price = 150
  in_stock  = true
}

locals {
  offer = data.redswitches_offers.ams.offers[0]
}

Resources

redswitches_ssh_key

resource "redswitches_ssh_key" "laptop" {
  name       = "laptop"
  public_key = file("~/.ssh/id_ed25519.pub")
}

Create adds the key (POST /ssh-keys); destroy removes it (DELETE /ssh-keys/{id}). Removing a saved key does not remove it from servers where it is already installed. Changing name or public_key replaces the resource. Import: terraform import redswitches_ssh_key.laptop sshkey_7.

redswitches_server

resource "redswitches_server" "web1" {
  offer_id       = "ofr_12"
  billing_cycle  = "monthly"
  os_id          = "os_31"
  ssh_key_id     = redswitches_ssh_key.laptop.id
  label          = "web-1"
  expected_total = { amount = "15480", currency = "USD" }
  power_state    = "on"

  timeouts {
    create = "60m"
  }
}

output "web1_ip" {
  value = redswitches_server.web1.primary_ip
}
  • Plan runs an order dry run (POST /orders?dry_run=true; nothing is ordered) for every server it would create. If the quoted total is not expected_total, the plan fails and shows the total to set. expected_total is in minor units: "15480" is 154.80 USD, setup and tax included. The dry run also catches a sold-out offer, missing credit and reached limits before you apply. A key without order cannot run it; the plan then only warns.
  • Create places an order paid from account credit (POST /orders) with expected_total, then waits until the server is ready (timeouts.create, default 60 minutes). If the price moved since the plan, apply fails with price_changed and nothing is ordered.
  • Read comes from GET /servers/{id}.
  • Update in place: label (POST /servers/{id}/label) and power_state, on or off (POST /servers/{id}/power, then the provider waits for the action). Changing ssh_key_id or expected_total later only updates the state: they belong to the order.
  • Replace: changing offer_id, os_id or billing_cycle cannot be done in place. Terraform orders a new server (paid now) and files a cancellation request for the old one, which keeps running and is billed until the end of its billing period. The plan warns when it does this.
  • Destroy files a cancellation request at the end of the billing period (POST /servers/{id}/cancel-request) and removes the server from the state. The server is not removed at once: it keeps running and is billed until its next due date, and it is still listed by GET /servers (and redswitches_servers) until then. GET /servers/{id}/cancel-request shows requested.
  • Import: terraform import redswitches_server.web1 srv_123. The API does not know the order attributes (offer_id, os_id, ssh_key_id, expected_total), so the values in your configuration are adopted without ordering a new server.

Creating a server spends money. Review every plan that adds or replaces a redswitches_server, and use lifecycle { prevent_destroy = true } on servers that must not be replaced or cancelled by accident. The root password never goes into the state; log in with the SSH key.

The API does not report power state, so a power change made in the client area is not seen by Terraform. Leave power_state unset to not manage power.

redswitches_rdns

resource "redswitches_rdns" "web1" {
  server_id = redswitches_server.web1.id
  ip        = redswitches_server.web1.primary_ip
  hostname  = "web-1.example.com"
}

Create and update file a reverse DNS request (POST /servers/{id}/rdns). Requests are applied shortly after, not at once; when the answer is an action, the provider waits for it. Destroy clears the name (hostname "", beta); where clearing is not available yet, destroy only removes it from the state, with a warning. Import: terraform import redswitches_rdns.web1 srv_123/203.0.113.10.

Idempotency and retries

Every write the provider makes carries an Idempotency-Key: a new one for each create, update or destroy, reused for every retry of that call. The provider retries only on network errors, 429 rate_limited, 503 and in_progress, with the same key, so a lost answer never orders a second server. Once an order is placed, the server is written to the state even if the wait for delivery is cut short (timeout or Ctrl-C), with a warning; the next apply does not order it again. If Terraform itself is killed while an order is being sent, list your orders (GET /orders) before you apply again. See Idempotency and retries.