Prerequisites
- A Git repository with your application code and a
docker-compose.yml - A Phala Cloud account with an API key
- A container registry account (Docker Hub, GHCR, or similar)
Secrets Management
Regardless of which CI platform you use, store your Phala Cloud API key as a secret. Never hardcode it in workflow files. GitHub: Go to Settings > Secrets and variables > Actions and add:
GitLab: Go to Settings > CI/CD > Variables and add the same values as masked variables.
GitHub Actions with the deploy action
If you only need to update a CVM fromphala.toml, use the Phala deploy action. It installs the CLI, waits for the update, and returns the result as outputs. See Deploy with the GitHub Action.
GitHub Actions with CLI
This is the simplest approach. The workflow builds your Docker image, pushes it to a registry, and deploys withphala deploy.
docker-compose.yml should reference the image variable:
--cvm-id names the CVM to update, so each push updates my-tee-app in place and --wait waits for the update to finish. The CLI does not look up an existing CVM by --name: phala deploy -n my-tee-app always creates a new CVM, and --wait has no effect on it. Create the CVM once before the first pipeline run, for example with phala deploy -n my-tee-app -c docker-compose.yml.
GitHub Actions with JS SDK
If you need more control over the deployment (conditional logic, custom error handling, multi-step provisioning), use the SDK directly in a Node.js script.GitLab CI
GitLab CI uses a similar pattern. Define a.gitlab-ci.yml in your repository root:
GitLab’s built-in container registry works well here. The
$CI_REGISTRY_* variables are available automatically in every pipeline.Terraform in CI
For infrastructure-as-code workflows, run Terraform in your pipeline. This is especially useful when you manage replicas, instance types, or environment variables declaratively.infra/main.tf would look something like this:
Store your Terraform state in a remote backend (S3, GCS, or Terraform Cloud) so that CI runs can access the same state file. Without remote state, each pipeline run would try to create a new CVM instead of updating the existing one.
Verify Deployment
After your pipeline completes, confirm the CVM is running:Troubleshooting
Authentication errors: Make surePHALA_CLOUD_API_KEY is set correctly in your CI secrets. Test locally with phala status to verify the key works.
Build failures: Ensure your Dockerfile builds locally with docker build . before pushing to CI.
Deploy timeouts: If --wait times out, the update may still be running. Check the dashboard or run phala cvms get my-tee-app to see the current status.
Image pull errors: Verify the image tag in your compose file matches what was pushed to the registry. For private registries, set DSTACK_DOCKER_USERNAME and DSTACK_DOCKER_PASSWORD as encrypted secrets on the CVM.
