Zero to first server in under ten lines.
IG1 is agentic-first: the machine surfaces — REST, the ig1 CLI, and the Terraform provider — are the first-class citizens, and they all speak the same contract. One one-time step, then pick your surface below. Every example targets the public endpoints under cloud.ig1.com exactly as they serve today.
1 · Nothing to install — the endpoints are publicly trusted
Since 2026-08-25 the customer-facing endpoints —
api, portal, docs, s3 and
zitadel under cloud.ig1.com — resolve on the public
internet and serve Let's Encrypt certificates. Stock
curl, boto3, the CLI and the Terraform provider verify them out
of the box. There is no CA to fetch and no --cacert to pass:
curl -s https://api.cloud.ig1.com/v1/whoami -H "Authorization: Bearer $IG1_PAT"
ig1-internal-ca-secret out of the cluster with
kubectl — which no customer has, and no longer needs. The internal CA
survives in exactly one place a customer meets it: the generated
*.10.57.8.75.nip.io hostnames on tenant edge exposures and
internet-facing load balancers. Those names resolve to a private address, so no public CA
can certify them — put your own domain on the exposure and it is publicly trusted too. The
full trust story is in the auth guide; the domain flow is in the
networking guide §6.1.
2 · Get an API key (once per machine or agent)
Portal → Security → API keys → Create: pick a label, choose
tier 1 (operate) so you can create a server, and set an expiry that
matches the machine's life (1–365 days; omitted means no expiry). The create response is
shown once and never kept by IG1 — it carries the
client_id + client_secret pair and a
pat, a paste-ready Bearer token that works as-is until the credential is
revoked or expires. Store all three now. The same flow works as
POST /v1/credentials or ig1 credential create — details in
auth and CLI.
3 · Export the environment
# the PAT is the whole auth story for curl — no mint, no refresh:
export IG1_PAT="<pat from step 2>"
# the pair drives the CLI login (and headless client_credentials mints —
# see the auth guide):
export IG1_CLIENT_ID="<client_id from step 2>"
export IG1_CLIENT_SECRET="<client_secret from step 2>"
# pick real ids for the server (any tier can read these):
# images GET /v1/openstack/image/v2/images
# flavors GET /v1/openstack/compute/v2.1/flavors/detail
# networks GET /v1/openstack/network/v2.0/networks
export IMG="<image id>" FLV="<flavor id>" NET="<network id>"
4 · Create the server — pick your surface
curl (REST)
the PAT is the Bearer — straight to the OpenStack proxy
curl -s -X POST \
https://api.cloud.ig1.com/v1/openstack/compute/v2.1/servers \
-H "Authorization: Bearer $IG1_PAT" -H "Content-Type: application/json" \
-d '{"server":{"name":"web-1","imageRef":"'$IMG'","flavorRef":"'$FLV'","networks":[{"uuid":"'$NET'"}]}}'
# prefer short-lived tokens? the pair mints one with client_credentials —
# the exact call is in the auth guide (§2, "Use")
ig1 CLI
one static binary — login, then one verb
ig1 config set-context lab \
--api https://api.cloud.ig1.com \
--issuer https://zitadel.cloud.ig1.com
ig1 config use-context lab
IG1_API_KEY="$IG1_CLIENT_ID:$IG1_CLIENT_SECRET" \
ig1 login --api-key
ig1 compute instance create --name web-1 \
--image "$IMG" --flavor "$FLV" \
--network "$NET" --yes
Terraform / OpenTofu
desired state over the same contract
provider "ig1" {
endpoint = "https://api.cloud.ig1.com"
api_key = var.ig1_client_id
api_secret = var.ig1_client_secret
}
resource "ig1_server" "web" {
name = "web-1"
image_id = var.image_id
flavor_id = var.flavor_id
networks = [var.network_id]
}
5 · See it
ig1 compute instance list
ig1 compute instance list -o json --query "[?name=='web-1']"
That is the whole loop. The same credential, tier rules, and project scoping apply on every surface — the API resolves them server-side from your credential, never from client-supplied headers.