# Manage Gyro Containers with the API, gyro CLI and Terraform

https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-api-cli-terraform

- **What you will learn**: The API, `gyro container` command and Terraform equivalent of every container action you take in the panel, with examples for creating, publishing, scaling, rolling back, domains, secrets and the registry.
- **Time**: 12 minutes
- **Who this is for**: Developers automating deployment.
- **What you need**: An API key ([First steps with the Gyro API](https://www.gyrohosting.com/en/knowledgebase/article/gyro-api-ilk-adim)); `gyro` 1.10 or later ([installation](https://www.gyrohosting.com/en/knowledgebase/article/gyro-cli-kurulum)); for Terraform provider 0.9 or later ([Terraform guide](https://www.gyrohosting.com/en/knowledgebase/article/terraform-ile-gyro-bulut)).

## 1. First: identity and environment number

When creating the API key tick the permissions: **services read** (`services_read`) and **services write** (`services_write`); for spending data **billing read** (`billing_read`). For safety restrict the key to your CI server's IP.

The `{id}` / `12345` in commands is **the service number of your container environment**. To find it:

```
gyro configure                  # once: stores the key
gyro service list               # all your services; find the container environment's number
```

## 2. Command summary

| Action | Command |
| --- | --- |
| List services / details | `gyro container service list ID` · `gyro container service get ID NAME` |
| Create a service | `gyro container service create ID --name NAME --image IMAGE --port 8080 --public` |
| Publish a new revision | `gyro container service update ID NAME --image IMAGE --reason "note"` |
| Scale | `gyro container service scale ID NAME --replicas N` |
| Restart | `gyro container service restart ID NAME` |
| Revisions / roll back | `gyro container service revisions ID NAME` · `gyro container service rollback ID NAME [--revision N]` |
| Delete a service | `gyro container service delete ID NAME` |
| Environment variables | `gyro container env set ID NAME --data '{"set":{"K":"V"}}'` · `--unset K` · `--replace 1` |
| Secrets | `gyro container secret set ID NAME --data @-` · `gyro container secret delete ID NAME --keys K` |
| Domains | `gyro container domain add\|list\|verify\|remove` |
| Logs / graphs / events | `gyro container logs ID NAME` · `gyro container metrics ID NAME` · `gyro container events ID` |
| Node pool | `gyro container nodes ID` |
| Gyro image registry | `gyro container registry get\|images\|credentials\|rotate\|policy\|image-delete ID` |
| External private registry | `gyro container external-registry set\|delete ID` |

Destructive actions (delete, rollback, password rotation) ask for confirmation; use `--yes` in scripts. Use `-o json` for output and `--query` for a single field.

## 3. gyro CLI examples

```
# Create a service
gyro container service create 12345 --name api \
  --image registry.ist.gyrohosting.com/<your-code>/api:1.0 --port 8080 \
  --replicas 2 --cpu-m 250 --memory-mi 256 --health-path /healthz --public

# A secret (via stdin, so it is not written to the shell history)
echo '{"set":{"DB_PASSWORD":"very-secret"}}' | gyro container secret set 12345 api --data @-

# A new revision, then a rollback
gyro container service update 12345 api --image registry.ist.gyrohosting.com/<your-code>/api:1.1 --reason "release 1.1"
gyro container service rollback 12345 api --yes

# Connect a domain
gyro container domain add 12345 api --domain api.example.com
gyro container domain verify 12345 api

# Logs and spending
gyro container logs 12345 api --since-minutes 30
gyro billing balance get
```

## 4. REST API examples

The base address is `https://www.gyrohosting.com/api/v1/client`; identity is `Authorization: Bearer $GYRO_TOKEN`.

```
B=https://www.gyrohosting.com/api/v1/client
H=(-H "Authorization: Bearer $GYRO_TOKEN" -H "Content-Type: application/json")

# List services
curl -s "$B/cloud/containers/12345/services" "${H[@]}"

# Create a service
curl -s -X POST "$B/cloud/containers/12345/services" "${H[@]}" -d '{
  "name":"api","image":"registry.ist.gyrohosting.com/<your-code>/api:1.0","port":8080,
  "replicas":2,"cpu_m":250,"memory_mi":256,"health_path":"/healthz","public":true}'

# New revision
curl -s -X PATCH "$B/cloud/containers/12345/services/api" "${H[@]}" \
  -d '{"image":"registry.ist.gyrohosting.com/<your-code>/api:1.1","reason":"release 1.1"}'

# Scale
curl -s -X POST "$B/cloud/containers/12345/services/api/scale" "${H[@]}" -d '{"replicas":3}'

# Roll back (needs confirmation)
curl -s -X POST "$B/cloud/containers/12345/services/api/rollback" "${H[@]}" -d '{"confirm":true}'

# A secret
curl -s -X PUT "$B/cloud/containers/12345/services/api/secrets" "${H[@]}" -d '{"set":{"DB_PASSWORD":"very-secret"}}'
```

All endpoints are in the API reference on the `/developers` page (`/cloud/containers/{id}/…`: `services`, `env`, `secrets`, `domains`, `logs`, `metrics`, `nodes`, `events`, `registry`, `external-registry`).

## 5. With Terraform

```
variable "db_password" {
  type      = string
  sensitive = true
}

resource "gyro_container_service" "web" {
  service_id  = 12345                  # service number of your container environment
  name        = "web"
  image       = "registry.ist.gyrohosting.com/<your-code>/web:1.4"
  port        = 8080
  replicas    = 2
  cpu_m       = 500
  memory_mi   = 512
  public      = true
  health_path = "/healthz"

  env     = { MODE = "prod" }
  secrets = { DB_PASSWORD = var.db_password }   # write-only, never read back

  # First write a CNAME from your domain to gyro_container_service.web.host.
  domains = ["app.example.com"]
}

output "web_url" {
  value = gyro_container_service.web.url
}
```

- Every change (except the replica count) creates a new revision and is rolled out without downtime.
- Secrets are write-only; if one is removed outside Terraform the next plan shows a difference.
- Import: `terraform import gyro_container_service.web 12345/web`. (After an import, a difference for secrets in the first plan is expected.)

## 6. Automation tips

- Use **a separate API key** and a separate **registry password** for CI/CD; store both as secret variables.
- Give the image with a **version tag or commit id** when releasing (not `latest`); write the commit id to the revision history with `--reason`.
- A full example: [Deploy with GitHub Actions](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-github-actions).

## 7. Frequently asked questions

**Where do I find the environment number?**

It is the number in the service page address in the client area, or the container environment's number in the `gyro service list` output.

**I get a quota_exceeded error; what should I do?**

You are exceeding your pool capacity: reduce the replica count or size, or move to a higher package.

**How do I know a rollout has finished?**

When the status in `gyro container service get ID NAME` is `running` and the ready replica count equals the desired count.

**Terraform shows a difference on every plan; what should I do?**

Usually secrets or changes made outside Terraform; reflect fields you changed in the panel in the Terraform file too.

## Next step

- [Deploy with GitHub Actions](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-github-actions)
- [The Spending page](https://www.gyrohosting.com/en/knowledgebase/article/spending-page-hour-by-hour-ledger)
