Deploy from your terminal with the Cloudgate CLI
The CLI uploads a folder to an Application and follows its Deployment to the end. Use it when your code is on your machine or in a CI job rather than in a connected git repository.
Applies to: Hosted and self-hostedApplications onlyBeta
The CLI is cloudgate, published on npm as @octabyte-io/cloudgate. It logs in through your
browser, remembers which Service a folder belongs to, uploads the files that changed and prints the
Deployment log as it is written. Linked to a whole Project instead, a folder such as a monorepo’s
root deploys every app in it with one command. It is early software: commands and flags can still change before
1.0. For the short tour, see the CLI overview; this page is the full walk-through, and
every command and flag has its own reference.
Install the CLI
Install it from npm on Node 22 or newer. The commands on these pages are in the beta on the npm
next tag, 0.0.2-beta.3; the latest tag is still 0.0.1:
npm install -g @octabyte-io/cloudgate@next
cloudgate --version
On an older Node it refuses to start and names both versions. It never updates itself: at most once
a day it prints a line on stderr when a newer version is on npm, and never in CI or when output is
not a terminal. Set CLOUDGATE_NO_UPDATE_NOTIFIER=1 to silence it.
A new version is out: 0.4.0 (you have 0.3.2).
Update: npm install -g @octabyte-io/cloudgate@latest
Log in to Cloudgate
Run cloudgate login, open the address it prints on any device, check the code and approve it.
Without --instance it logs in to the Hosted instance, https://cloudgate.octabyte.app.
$ cloudgate login
Using instance https://cloudgate.octabyte.app
Open https://cloudgate.octabyte.app/device and enter the code WDJB-MJHT
Waiting for you to approve…
✓ Logged in to https://cloudgate.octabyte.app as sam@northwind.example
Your key is in the system keychain and ends on 2027-02-10.
Approving gives this computer a Personal key that acts as you and ends 90 days after you log in. Because the code is approved in a browser, it works over SSH too: run the command on the server and approve on your laptop.
The key goes in the system keychain. Where there is none, as on most servers, it goes in
credentials.json in the settings folder, readable only by you, and the CLI says so on one line.
The settings folder is ~/.config/cloudgate/ on Linux and macOS (or $XDG_CONFIG_HOME/cloudgate/)
and %APPDATA%\cloudgate\ on Windows; CLOUDGATE_CONFIG_DIR moves it.
Check who you are logged in as, and where:
$ cloudgate whoami
Instance https://cloudgate.octabyte.app
Logged in as sam@northwind.example
Organization Northwind Labs
Key ends 2027-02-10 (in 90 days)
cloudgate logout deletes this computer’s key on the Instance and forgets the login. Logging in
again on the same Instance replaces the login and deletes the old key.
Link a folder to a Service
Run cloudgate link in the folder you deploy, or skip it: a first cloudgate deploy in a terminal
asks the same questions. It asks for the Organization (skipped when you belong to one), the Project,
the Environment and the Service, and remembers the answer:
$ cloudgate link
? Project
1) storefront
2) marketing-site
Pick 1-2: 1
? Environment
1) staging
2) production
Pick 1-2: 2
? Service
1) web
2) worker
Pick 1-2: 1
✓ Linked ./ to web in production of Project storefront on cloudgate.octabyte.app
The link is .cloudgate/link.json, and the CLI adds .cloudgate/ to .gitignore. It holds the
Instance’s address, the Organization, Project and Environment ids and the Service’s Config name
(its name in the Project config), never a key. Every later command run
in this folder, or any folder below it, goes to the same Service.
- It never creates a Service and never changes the Project config. Make the Service in the console first, or deploy a whole Project whose config describes it.
- When a Project keeps its config in this folder’s git
originrepository, that Project is listed first. - With no terminal, or with
--yes, it asks nothing: pass--project,--envand--service(and--orgif you belong to more than one Organization), or it stops naming the first flag it needs. Replacing an existing link needs--yes. cloudgate unlinkremoves the link and changes nothing on the Instance.
Which Service does a command use?
A flag wins over its variable, and both win over the folder’s link:
| Level | Flag | Variable |
|---|---|---|
| Organization | --org <name or id> |
CLOUDGATE_ORG |
| Project | --project <name or id> |
CLOUDGATE_PROJECT |
| Environment | --env <name or id> |
CLOUDGATE_ENV |
| Service | --service <Config name or id> |
CLOUDGATE_SERVICE |
A value is tried as an id first, then as a name ignoring case. If two share that name, the command
refuses and lists their ids. The link’s Service Config name always applies, so
cloudgate deploy --env staging deploys the Service with the same Config name in staging.
Deploy the folder
Run cloudgate deploy. It uploads the files that changed in the linked folder, starts a Deployment
and prints the Deployment log until the Deployment ends. It exits 0 only when the Deployment is done.
$ cloudgate deploy
Using instance https://cloudgate.octabyte.app
Deploying ./ to web in production of Project storefront on cloudgate.octabyte.app
Uploading 3 changed files, 12.0 kB (211 unchanged)…
Deployment Xq7Tn2LwP9aRk4sVb1cHd queued
…the build log…
✓ Deployment Xq7Tn2LwP9aRk4sVb1cHd done in 1m 42s
The CLI sends the list of the folder’s files with a SHA-256 of each, and the Instance answers which
ones its build host lacks or holds different; only those are uploaded, and a file you deleted is
deleted there too. --full sends every file. An Instance older than 0.2.0 always gets the whole
folder.
There is no confirmation for any Environment, production included. Ctrl-C stops watching, not the build: the CLI prints the command to follow it again and where to cancel it in the console.
What does cloudgate deploy upload?
The folder as it is on disk, uncommitted and untracked files included (of those, only the ones that changed since the last upload are sent), minus:
.git/and.cloudgate/, always;- anything any
.gitignorein the folder lists, whether or not the folder is a git repository; - anything a
.cloudgateignorelists (the same syntax, applied on top: its!lines bring back a file a.gitignoreleft out); .envand.env.*except.env.example, with a line naming them;- symlinks, with a warning naming each one. File modes are not kept.
node_modules has no rule of its own: add it to .gitignore or .cloudgateignore if you do not
want it uploaded. The CLI always says how many files it is sending and the size of the zip; above
100 MB it warns and names the five biggest folders, then carries on.
What if the Service builds from git or an image?
Deploying a folder switches the Service’s source to uploaded files. In a terminal the CLI asks
first; with no terminal it refuses unless you pass --switch-source. A Service whose source is set
by a Project config kept in a repository is refused every time, even with --switch-source, because
the next Plan would put the git source back.
What if a build is already running?
The CLI waits for it, printing waiting for Deployment <id> to finish, then uploads. It goes
ahead with a warning past a Deployment held by a Plan, or one pending or running for more than 60
minutes.
Deploy a whole Project from one folder
A Project folder is a folder linked to a whole Project rather than one Service, usually a
monorepo’s root. It holds a working copy of the Project config as
cloudgate.yaml, and one cloudgate deploy there builds every app the config builds from a
subfolder of it.
Link the folder to the Project
cloudgate link --whole-projectIt asks for the Organization, Project and Environment, never a Service, and downloads the Project config as
cloudgate.yaml. Both.cloudgate/and/cloudgate.yamlgo into.gitignore: the working copy is yours, and Cloudgate keeps the config. Only a Project whose config is kept in Cloudgate can have a Project folder.Name each app's subfolder
Give each app you build from this folder a
foldersource. Aweb,worker,staticorcroncan take one; aweb-privatecannot.services: web: kind: web source: { folder: apps/web } jobs: kind: worker source: { folder: apps/jobs }Deploy
cloudgate deployIt sends
cloudgate.yamlas a Plan, prints each Environment’s creates, changes and destroys, and applies it on a yes. Then it uploads the whole folder to each app, so shared code beside it is there too, builds each from its own subfolder, and prints one line per app at the end. Apps from a repository or an image, and databases, are listed as skipped.
cloudgate config plan sends the Plan without building anything, and cloudgate config pull gets
the current config again. If someone changed the config in the console or from another Project
folder since your download, the Plan is refused and nothing is sent: pull, then make your edits
again. In a Project folder, status, logs and vars ask which Service, or take --service.
A first cloudgate deploy in a folder with no link offers the same: pick a Project and answer
The whole Project, or pick Create a new Project, which makes the Project, a production
Environment on a Server or Cloud account you choose, and a starter cloudgate.yaml to add your apps
to. See the command reference.
Check the Service and follow its logs
cloudgate status shows the Service, where its source comes from, its Domains and its latest
Deployment:
$ cloudgate status
Service web (Application)
Environment production
Project storefront
Instance https://cloudgate.octabyte.app
State running
Source uploaded files
Domains shop.northwind.example
Latest Deployment Xq7Tn2LwP9aRk4sVb1cHd done 4 minutes ago
cloudgate logs prints the last 100 lines of the Service’s Runtime log, what it writes while it
runs. -f keeps printing new lines until Ctrl-C, and --deployment reads a
Deployment log instead:
cloudgate logs -f # follow the Runtime log
cloudgate logs -n 500 # the last 500 lines
cloudgate logs --deployment -f # follow the latest Deployment from its first line
Only log lines go to stdout, so cloudgate logs | grep ERROR works.
Set environment variables
cloudgate vars lists, sets and unsets the Service’s own runtime variables in one Environment.
Values are never printed, and nothing redeploys until you deploy.
$ cloudgate vars set STRIPE_KEY
Value for STRIPE_KEY (hidden):
✓ Set STRIPE_KEY on web in production. Run cloudgate deploy to pick it up.
$ cloudgate vars list
NAME VALUE
DATABASE_URL linked to db.url
STRIPE_KEY set
cloudgate vars set KEY=VALUE also works, but leaves the value in your shell history; vars set KEY
asks for it hidden, or reads it from stdin. A variable wired to another Service’s output, such as
DATABASE_URL above, cannot be set here. Shared Project and Environment variables, build arguments
and build secrets stay in the console: see environment variables.
Use the CLI in CI
Set CLOUDGATE_KEY to a Personal key and name the target with flags or
variables. The key wins over any saved login, is never saved, and nothing asks a question when CI
is set:
CLOUDGATE_KEY=$CLOUDGATE_KEY npx @octabyte-io/cloudgate@next deploy \
--project storefront --env production --service web
CI recipes has complete GitHub Actions and GitLab CI jobs.
Use a self-hosted Instance
Pass your console’s address to login once. It becomes the current Instance, and every link made
afterwards records it:
cloudgate login --instance cloud.northwind.example
An address without a scheme gets https://. Plain http:// is refused except for localhost and
127.0.0.1; --allow-http allows it anywhere, and sends your key unencrypted. Before it sends a key,
the CLI checks that the address answers as a Cloudgate Instance of version 0.1.0 or newer.
Logged in to more than one Instance? cloudgate instance list shows them and
cloudgate instance use <url> switches. A command uses --instance, then CLOUDGATE_INSTANCE,
then the folder’s link, then the current Instance, then the Hosted instance. More on running your own
in self-hosting.
Where to go next
- Command reference: every command, flag, output and exit code.
- Project config and Plans: what
cloudgate.yamlcan describe. - CI recipes: GitHub Actions and GitLab CI.
- Troubleshooting: exit codes and common errors.
- Deployments: what happens after the upload.
Questions
Does cloudgate deploy upload my .env file?
No. .env and .env.* are left out, except .env.example, and the CLI says so. Put secrets in with cloudgate vars set. A !.env line in .cloudgateignore brings one back if you really mean it.
Can the CLI create a Project or a Service?
A first cloudgate deploy can create a Project, with one production Environment, from Create a new Project. Services come from the Project config: add them to the Project folder's cloudgate.yaml and deploy or config plan applies the Plan that creates them. link never creates anything.
Does every deploy upload the whole folder?
No. Against an Instance of version 0.2.0 or newer it uploads only the files that changed since the last upload, and deletes the ones you deleted. --full sends every file.
Does it ask before deploying to production?
No. There is no confirmation for any Environment. It does say where it is going, on one line, before it uploads anything.
Can I deploy a Compose stack or a database with it?
No. cloudgate deploy, logs and vars work on Applications only. cloudgate status reads any kind of Service, and cloudgate logs --deployment also reads a Compose stack's Deployment logs.
Which Node version does it need?
Node 22 or newer. On an older Node it refuses to start and names both versions.
Something missing or wrong on this page? Email support@octabyte.io, or start a free trial and try it in the console.