Set up CI/CD for Nakama
Manually triggering builds and deployments works for early development, but it doesn’t scale with a team. CI/CD automates the path from code push to running deployment. Continuous Integration (CI) triggers Nakama builds automatically when code is pushed to your repository. Continuous Delivery (CD) deploys successful builds to target instances: automatically, on a schedule your pipeline controls, or with manual approval.
Building and deploying are separate operations with separate APIs, so opting into CI doesn’t commit you to CD. See Separate the build from the deploy if you want builds on every push but deploys on your own terms.
CI/CD workflows apply to Nakama only. LiveOps changes go through the Satori console. See Satori deployments.
Prerequisites #
- A Nakama Builder connected to your GitHub, GitLab, or Bitbucket repository. See Builders.
- A service user with Trigger permission on the relevant builder.
- Deploy permission on each target Nakama deployment, if the pipeline deploys as well as builds.
- Access to your repository’s CI/CD settings (for example, GitHub Actions secrets).
Part 1: Continuous integration #
The goal is to trigger a Heroic Cloud build automatically every time code is pushed to your repository.
Step 1: Create a service user #
- Create a service user in Heroic Cloud (for example, named “GitHub Actions CI”).
- Copy the service user’s secret token. Store it securely as it’s only shown once.
- Assign Trigger permission on the relevant builder, and add the service user to the relevant builder. For a build-only pipeline, that’s the only permission it needs. Add Deploy on individual deployments if the pipeline deploys as well. Follow the principle of least privilege.
See Access control for details on service user permissions.
Step 2: Store the token in your CI system #
For GitHub Actions:
- In your GitHub repository, go to Settings > Secrets and variables > Actions.
- Add the service user token as a repository secret (for example,
HEROIC_CLOUD_TOKEN).
For GitLab CI, add the token as a CI/CD variable in your project settings.
Step 3: Create the CI workflow #
Create a workflow file that calls the Heroic Cloud API on each push, authenticated with the service user token.
The flow:
- A developer pushes code to the repository.
- Your CI system triggers the workflow.
- The workflow calls the Heroic Cloud API to trigger a build.
- The builder compiles the code and produces a container image.
The following example triggers the Heroic Cloud builder and polls for the result. Add it to your repository at .github/workflows/heroic-cloud-build.yml, replacing the env values with your own.
| |
Key parameters:
| Parameter | Description | Example |
|---|---|---|
organization_name | Your Heroic Cloud organization slug. | my-studio |
builder_name | The name of the builder to trigger. | my-game-builder |
nakama_image | The Nakama on Heroic Cloud image version to build against. | heroiclabs/nakama-enterprise:3.24.0-r1 |
service_user_email | The service user email. Store as a GitHub secret. | ci-bot@my-studio.com |
service_user_secret | The service user secret token. Store as a GitHub secret. | mK9pLx2vNqRt5wYz |
retry_interval | Seconds to wait between polling attempts (default: 30). | 30 |
timeout_interval | Maximum seconds to wait before failing (default: 600). | 600 |
Store HEROIC_CLOUD_SERVICE_EMAIL and HEROIC_CLOUD_SERVICE_SECRET as encrypted secrets in your GitHub repository. Never commit credentials to your repository.
What happens if the build fails? #
A failed build doesn’t affect any running deployments. The failed image is never deployed anywhere. Your existing instances continue running the last successfully deployed image. Fix the issue in your code and push again.
Part 2: Continuous delivery #
Once builds trigger automatically, you need a strategy for getting those images onto your Nakama instances. Choose from three options: auto-deploy from the builder, manual deploys from the dashboard, and scripted deploys from the API.
Auto-deploy #
Auto-deploy connects a builder to one or more Nakama instances. When a build completes successfully, the resulting image deploys to the specified targets automatically, with no manual intervention.
Configure auto-deploy from the builder settings menu to target one or more instances.
Auto-deploy is a property of the builder, not of a branch or a workflow. Every successful build from that builder deploys to the configured targets, whoever triggered it and whatever branch it came from. A feature branch someone builds by hand from the dashboard reaches those same targets.
Auto-deploy limitations #
Auto-deploy is available for Nakama only. Satori doesn’t have auto-deploy.
Manual deployment #
Deploy any completed build manually from the builder page or from the Nakama deployment itself. Both methods use a rolling update, which avoids downtime on deployments running two or more Nakama nodes. Single-node deployments, including all development deployments, are briefly unreachable while the node restarts. See Deploy downtime.
Deploy with the API #
Deploying is its own API call, so your pipeline decides when a build reaches an instance and whether it reaches one at all. Change the image a Nakama deployment runs with a PUT to that deployment:
| |
Take <image> from the last_build.image field the builder returns once a build finishes. To deploy an older build instead, list the images the builder has produced with GET /v3/organization/<organization>/image and pick one.
The update is partial. Fields you leave out keep their current values, so a body containing only image changes the running image and nothing else. CPU, memory, database resources, runtime variables, and secret runtime variables all stay as they are. The same endpoint updates those settings too, so send only the fields you intend to change. See UpdateNakamaDeployment for the full body.
A 200 response means the update was accepted, not that the new image is serving traffic. Poll the deployment and read state.status, which uses the same OperationStatus values as builds:
| |
A status of 1 means the deploy is in progress, 2 that it completed, and 3 that it failed, with details in state.errors.
API deploys behave exactly like dashboard deploys, including the rolling update and the brief unavailability on single-node deployments. See Deploy downtime.
Grant the service user only the permissions a change needs on the deployments it targets: Deploy to change the image, and Edit to change other settings. Scope them per deployment so a pipeline serving development and QA can’t reach production.
Separate the build from the deploy #
CI and CD are separate opt-ins. Auto-deploy ties them together, which works well for a development instance fed only from main. That breaks down as soon as builds come from elsewhere. Validating every branch in CI, or triggering a one-off build by hand, sends those images to the same targets.
To keep the decision in your pipeline, leave auto-deploy off and deploy from the workflow instead:
- Trigger a build on every push, so CI validates every branch.
- Wait for the build to finish and read
last_build.image. - Call the deploy API only when your conditions hold, for example, when the branch is
main.
Heroic Cloud has no built-in deploy schedule, but the same split gives you scheduled deploys. To hold QA on one build for a day, add a scheduled job to your CI system, such as a schedule trigger in GitHub Actions. Have it deploy the current image to the QA deployment at a fixed time. QA stays on that image until the next run, however many builds land in between.
Recommended deployment strategy #
| Environment | Deploy method | Why |
|---|---|---|
| Development | Auto-deploy | Fast iteration. Every successful build deploys immediately. |
| QA | Auto-deploy | QA always has the latest build for functional testing. |
| Production | Manual only | Requires explicit human approval after QA validation. This is a deliberate gate. |
The key principle: automate everything up to production, then require a human decision for the final promotion. This gives you speed during development and safety for live traffic.
Auto-deploy to QA assumes your QA team wants the latest build. If they need a stable version for a fixed period, such as a daily build tested until the next one, deploy from a scheduled pipeline job instead. See Separate the build from the deploy.
The complete flow #
With CI and CD fully configured:
- A developer pushes code to the repository.
- GitHub Actions (or GitLab CI) calls the Heroic Cloud API to trigger a build.
- The builder compiles the container image.
- Auto-deploy pushes the image to development and QA instances, or the workflow calls the deploy API for the targets you choose.
- The QA team validates the build on their instance.
- A release engineer manually deploys the validated image to production.
See also #
- Builders and repository setup for creating and configuring builders.
- Nakama deployments for deployment configuration.
- Access control for service user permissions.
- Use the Heroic Cloud API for authentication, allowed operations, and worked examples.
- Service users API for the full endpoint reference.
