Skip to main content
Zyra Zyra
Features Pricing Security FAQ Documentation
Sign In Sign up for free

Documentation › User Guides › Organizations › Stage 4 › Integrate Zyra with your CI/CD

Integrate Zyra with your CI/CD

Chapter 5 · about 20 minutes to read

Manual deploys are fine for the first month. After that, every change to your application should flow through CI. This chapter shows the patterns we see most often: spin a VS for an integration test, deploy from a release tag, and tear down everything when CI exits.

Time: about 20 minutes. Prerequisites: an API key from Chapter 1. At least one CI provider account.

The pattern

Three jobs in your pipeline:

  1. Build. Build and push your Docker image to a registry Zyra can pull from. Zyra's container registry (/api/v1/registry) is one option; Docker Hub, GHCR, ECR all work.
  2. Deploy. POST /api/v1/virtual-servers with the image. Poll status until running.
  3. Tear down (on failure or after tests). DELETE /api/v1/virtual-servers/{id} or POST .../stop for ephemeral runs.

GitHub Actions example

Save this as .github/workflows/deploy-zyra-vs.yml:

name: deploy-to-zyra
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      ZYRA_API_KEY: ${{ secrets.ZYRA_API_KEY }}
      ZYRA_BASE: https://app.getzyra.io/api/v1
      IMAGE: ghcr.io/${{ github.repository }}:${{ github.sha }}
    steps:
      - uses: actions/checkout@v4

      - name: Build and push image
        run: |
          echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker build -t "$IMAGE" .
          docker push "$IMAGE"

      - name: Deploy Virtual Server
        id: deploy
        run: |
          VS_ID=$(curl -fsS -X POST "$ZYRA_BASE/virtual-servers" \
            -H "Authorization: Bearer $ZYRA_API_KEY" \
            -H "Content-Type: application/json" \
            -d "{\"name\":\"prod-${{ github.sha }}\",\"docker_image\":\"$IMAGE\",\"vcpus\":2,\"memory_mb\":4096,\"disk_gb\":50}" \
            | jq -r '.data.id')
          echo "vs_id=$VS_ID" >> $GITHUB_OUTPUT

      - name: Wait for running
        run: |
          for i in {1..30}; do
            STATUS=$(curl -fsS "$ZYRA_BASE/virtual-servers/${{ steps.deploy.outputs.vs_id }}" \
              -H "Authorization: Bearer $ZYRA_API_KEY" | jq -r '.data.status')
            [ "$STATUS" = "running" ] && exit 0
            [ "$STATUS" = "error" ] && exit 1
            sleep 10
          done
          exit 1

      - name: Teardown on failure
        if: failure()
        run: |
          curl -fsS -X DELETE \
            "$ZYRA_BASE/virtual-servers/${{ steps.deploy.outputs.vs_id }}" \
            -H "Authorization: Bearer $ZYRA_API_KEY" || true

That's the minimal, honest version: build → deploy → poll for running → clean up on failure.

GitLab CI

Same shape, different syntax. Store ZYRA_API_KEY and IMAGE as protected CI variables and POST to $ZYRA_BASE/virtual-servers from a script: block, capturing the VS ID into a dotenv artifact for later jobs.

Jenkins (declarative pipeline)

pipeline {
  agent any
  environment {
    ZYRA_API_KEY = credentials('zyra-api-key')
    ZYRA_BASE    = 'https://app.getzyra.io/api/v1'
  }
  stages {
    stage('Deploy') {
      steps {
        sh 'curl -fsS -X POST "$ZYRA_BASE/virtual-servers" -H "Authorization: Bearer $ZYRA_API_KEY" -d "..."'
      }
    }
  }
}

Secrets — the only rule

Never hardcode ZYRA_API_KEY in a file that lives in your repo. Use the CI provider's secret store: GitHub Actions Secrets, GitLab CI variables, Jenkins Credentials Plugin, AWS Secrets Manager. Treat the key like a database password — it has full write access to your org. Rotate every 90 days.

Declarative deploys

For full Infrastructure-as-Code, two routes are wired today:

  • Terraform. POST /api/v1/terraform/... endpoints expose a state-aware deploy surface. A first-party provider is on the roadmap. [VERIFY: provider publication target]
  • GitOps. /api/v1/gitops routers connect a Git repository to your Zyra org, so a push to main triggers a deploy. Useful if you already run Argo CD or Flux.

For now, the curl recipes above are the recommended pattern.

What just happened

You wired a build → deploy → teardown loop with API-key auth, and you know where to keep secrets. Next chapter covers running dev / staging / prod side-by-side.

Troubleshooting

  • Polling hits a 404. The VS was likely auto-terminated by an SLA breach. Check audit log (Chapter 4).
  • docker_image pulls fail. Zyra's runtime needs registry credentials. Configure via POST /api/v1/registry/credentials.
  • Teardown leaks resources. Always wrap the deploy in if: failure() or a trap — orphaned VSs continue billing.

← Previous: Read and export the audit log

Next: Run dev / staging / prod environments →

Last reviewed: 2026-05-21

© 2026 Zyra. All rights reserved. | Privacy Policy | Terms of Service | Careers