Deploy from CI with the Cloudgate CLI
A CI job deploys with the same CLI you run locally. It needs a Personal key in CLOUDGATE_KEY and the target named by flags or variables, because nothing can answer a question there.
Applies to: Hosted and self-hostedApplications onlyBeta
In CI the CLI reads its key from CLOUDGATE_KEY, never saves it, and asks no question when CI
is set: anything it would have asked is refused with exit 2, naming the flag it needed. The commands
are the ones in the command reference; this page has jobs you can copy.
What does a CI job need?
| What | How |
|---|---|
| Node 22 or newer | The CI image or a setup step |
| A Personal key | CLOUDGATE_KEY, stored as a masked secret |
| The target | --project, --env, --service, or CLOUDGATE_PROJECT, CLOUDGATE_ENV, CLOUDGATE_SERVICE |
| The Organization | --org or CLOUDGATE_ORG, only if the key’s owner belongs to more than one |
| A self-hosted Instance | --instance or CLOUDGATE_INSTANCE; leave it out for the Hosted instance |
--switch-source |
Only if the Service builds from git or an image today |
Create a Personal key for CI
In the console, open Settings, then Account, and press Create a key under Personal keys. Name it after the pipeline, choose when it Expires, and copy it: it is shown once. See Personal keys for revoking and rotating.
Deploy from GitHub Actions
Store the key as a repository secret named CLOUDGATE_KEY, then add a job:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci && npm run build
- run: npx --yes @octabyte-io/cloudgate@next deploy
env:
CLOUDGATE_KEY: ${{ secrets.CLOUDGATE_KEY }}
CLOUDGATE_PROJECT: storefront
CLOUDGATE_ENV: production
CLOUDGATE_SERVICE: web
The upload respects .gitignore and .cloudgateignore, so build output that .gitignore lists is
left out. If the Application builds the code itself, skip the build step; if you upload built
files, list in .cloudgateignore a ! line for the output folder, such as !dist/.
Deploy from GitLab CI
Store the key as a masked CI/CD variable named CLOUDGATE_KEY, then:
# .gitlab-ci.yml
deploy:
stage: deploy
image: node:22
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
CLOUDGATE_PROJECT: storefront
CLOUDGATE_ENV: production
CLOUDGATE_SERVICE: web
script:
- npx --yes @octabyte-io/cloudgate@next deploy
Deploy each branch to its own Environment
--env deploys the Service with the same Config name in another Environment, so one job can serve
several branches. The Environment must already exist; the CLI never creates one.
cloudgate deploy --project storefront --service web --env "$TARGET_ENV"
For a short-lived copy of a branch, use preview deployments instead.
Can CI deploy a whole Project folder?
No. A whole-Project deploy runs only in a
Project folder, whose link and cloudgate.yaml
are never committed, so a CI job has neither, and with no terminal a first deploy asks nothing. In
CI, deploy one Service per command with the target flags, as above, and run the whole-Project deploy
from your terminal.
Each CI run uploads only the files that differ from the Service’s last upload, compared by SHA-256,
so a fresh checkout does not mean a full upload. --full sends every file.
Deploy to a self-hosted Instance
Add the Instance’s address. A Personal key belongs to one Instance:
env:
CLOUDGATE_KEY: ${{ secrets.CLOUDGATE_KEY }}
CLOUDGATE_INSTANCE: https://cloud.northwind.example
Queue the deploy without waiting
--detach exits 0 once the Deployment is queued. With --json it prints one object a later step
can read:
cloudgate deploy --detach --json > deployment.json
# {"deploymentId":"Xq7Tn2LwP9aRk4sVb1cHd","status":"pending","consoleUrl":"https://cloudgate.octabyte.app/applications/…/deployments"}
Follow it later with cloudgate logs --deployment <id> -f, which ends by itself when the Deployment
does.
Set a secret from CI
vars set KEY reads the value from stdin, so it never appears in the job’s command line:
printf %s "$STRIPE_KEY" | cloudgate vars set STRIPE_KEY
cloudgate deploy
Setting a variable redeploys nothing; the next deploy picks it up.
How does the job know it failed?
By the exit code. With --json, stdout is empty on failure; the message is on stderr.
| Code | Meaning in CI |
|---|---|
0 |
The Deployment is done (or queued, with --detach) |
1 |
The Instance refused, or the Deployment failed or was cancelled |
2 |
Wrong use: a flag or value is missing and there is no one to ask |
3 |
The key is missing, ended or was refused |
Troubleshooting lists the common errors and their fixes.
Questions
Which key does a CI job use?
A Personal key in CLOUDGATE_KEY. It acts as the person who made it, with their role. An agent key does not work with the CLI: it is accepted only at the MCP endpoint and the Gateway.
Does the job wait for the build?
Yes, by default. cloudgate deploy prints the Deployment log and exits 0 only when the Deployment is done, so a failed build fails the job. Add --detach to exit as soon as it is queued.
Do I need to commit the .cloudgate folder?
No. The CLI adds .cloudgate/ to .gitignore. In CI, name the Project, Environment and Service with flags or CLOUDGATE_* variables instead.
Why does the job stop with exit code 2 and mention --switch-source?
The Service builds from git or an image, and deploying a folder would switch it to uploaded files. With no terminal to ask, the CLI refuses unless you pass --switch-source.
Something missing or wrong on this page? Email support@octabyte.io, or start a free trial and try it in the console.