Project config and Plans
The Project config is one YAML file that says what a Project runs. You change the file; Cloudgate shows a Plan for each Environment, and nothing happens until you Apply it.
Applies to: Members can read and planApplying needs permission on each Service
The Project config describes each Service by its Config name: its kind, size, source, build,
port and variable names. It is kept either in Cloudgate, edited on the Project’s Config tab,
or in your repository as cloudgate.yaml (or cloudgate.yml) at the root, unless you name another
path.
A Plan is one Environment’s list of what applying the config would create, change and destroy. Each Environment has at most one open Plan.
What you can do
- Describe Applications (
web,web-private,worker,cron,static), PostgreSQL, MySQL, Redis, buckets and Compose stacks in one file. - Link variables to another Service’s Outputs, such as a database’s URL.
- Keep the file in Cloudgate or in your repository, and move it either way.
- Edit a Cloudgate-kept config from a folder on your computer with the CLI, and build apps from that folder’s subfolders.
- Review each Environment’s Plan, including drift in a cloud, and Apply or dismiss it.
An example cloudgate.yaml
A shop with a web app, a background worker, a nightly report, PostgreSQL, Redis and a bucket for uploads:
# yaml-language-server: $schema=https://cloudgate.octabyte.app/backend/schema/project-config/v1.json
version: 1
services:
web:
kind: web
description: The storefront
size: small
source:
github: northwind-labs/storefront
path: apps/web
build:
type: nixpacks
port: 3000
env:
- SESSION_SECRET
- DATABASE_URL: pg-main.url
- REDIS_URL: cache.url
- S3_BUCKET: uploads.name
- S3_ENDPOINT: uploads.endpoint
- AWS_ACCESS_KEY_ID: uploads.access_key_id
- AWS_SECRET_ACCESS_KEY: uploads.secret_access_key
build_args: [NEXT_PUBLIC_SITE_URL]
jobs:
kind: worker
size: xsmall
source:
github: northwind-labs/storefront
path: apps/jobs
command: node
args: [dist/worker.js]
env:
- DATABASE_URL: pg-main.url
- REDIS_URL: cache.url
nightly-report:
kind: cron
source:
github: northwind-labs/storefront
path: apps/jobs
command: node dist/report.js
schedule: "0 3 * * *"
timezone: Europe/Berlin
timeout: 30m
env:
- DATABASE_URL: pg-main.url
pg-main:
kind: postgres
size: small
version: "18"
database: storefront
user: storefront
cache:
kind: redis
version: "8"
uploads:
kind: bucket
What the fields mean:
- Config names (
web,pg-main) are lower-case letters, digits and hyphens, starting with a letter, at most 63 characters. A Plan matches entries by Config name, so a renamed entry reads as a new Service to create and the old one to destroy. envlists names only.SESSION_SECRETis set in the console.DATABASE_URL: pg-main.urlis a wired variable: Cloudgate fills it frompg-main’surlOutput at each Deployment and never saves it.sizeisxsmallto2xlarge, or{ cpu: 1, memory: 2 GB }. See Applications for the table.- A database
versionis its image tag and must be quoted:"18"runspostgres:18. sourcetakesgithub,gitlab,giteaorbitbucketwithowner/repo, agitURL (no credentials in it), animage, or afolder: a subfolder of a Project folder, such as{ folder: apps/web }. Aweb,worker,staticorcroncan take afolder; aweb-privatecannot, and afolderis never combined with another source key.build.typeisnixpacks,railpack,dockerfile,heroku_buildpacksorpaketo_buildpacks.kind: composenames a compose file in a repository (source,file,type). The file’s contents stay in the repository.
Kinds the config cannot describe yet, such as MongoDB, MariaDB and libSQL, appear as
kind: mongo with managed: console. A Plan never changes or destroys a console-managed entry.
Edit a config kept in Cloudgate
Open the Config tab
Open the Project, for example
storefront, and its Config tab.The text above, one plan card per Environment below. Edit and plan
Change the text and press Save and plan. Cloudgate plans each Environment below; nothing is applied, and the text is stored only when a Plan of it is applied. Discard edits throws the change away.
Review the Plan
Each Environment’s Plan lists Creates, Changes and Destroys, plus drift, notes, held builds and major version upgrades. In a cloud, each line can show the real resources it makes, with CPU, memory and cost.
Review what each line does before you apply. Apply
Press Apply. Creates run first, then changes, then destroys, each as its own step. Or press Dismiss to drop the Plan.
Native settings for Swarm, AWS and Google Cloud
An entry the config describes can carry a native block with settings Cloudgate’s own fields do
not cover, written in the platform’s own spelling. Each value is laid over what Cloudgate writes
for the Service, never adds a resource, and shows as its own Plan line marked native.
services:
web:
kind: web
source: { folder: apps/web }
native:
docker:
StopGracePeriod: 30000000000 # nanoseconds, as docker service inspect shows it
aws:
"aws_ecs_service.service":
health_check_grace_period_seconds: 60
| Block | Where it applies | What it holds |
|---|---|---|
native.docker |
A Server | Labels, HealthCheck, RestartPolicy, UpdateConfig, RollbackConfig, StopGracePeriod and Ulimits, as the Docker Engine API takes them. A cron takes Labels, StopGracePeriod and Ulimits; a bucket takes Labels |
native.aws |
AWS | hashicorp/aws arguments, keyed by the OpenTofu address the Plan’s cloud lines show, such as "aws_db_instance.database". The ECS container is "aws_ecs_task_definition.service".container_definitions, in ECS’s camelCase |
native.gcp |
Google Cloud | hashicorp/google arguments, keyed the same way, such as "google_cloud_run_v2_service.service" or "google_sql_database_instance.database" |
Every Plan checks every block on every Deploy target, so a typo shows on a Server’s staging Plan
rather than on the first deploy to AWS. A refusal names the full path and the reason: an address
the entry’s kind does not make, an argument the pinned provider does not have, an OpenTofu
meta-argument, or a locked setting such as tags, region,
labels in traefik.*, com.docker.* or io.cloudgate.*, or CPU and memory (use size). An exact
cloud size, such as an RDS instance class or a Cloud SQL tier, wins over size.
Edit the config from a Project folder
A config kept in Cloudgate can also be edited as a file on your computer, with the
CLI. cloudgate link --whole-project makes the
folder a Project folder and downloads the config into it as cloudgate.yaml: a working copy.
Cloudgate keeps the config, never reads the working copy on its own, and the console still edits
it. The CLI adds /cloudgate.yaml to .gitignore, so the copy is never committed.
cloudgate config plansends the working copy as a Plan for each Environment, prints it and applies it on a yes.cloudgate deploythere does the same, then builds each app whosesourceis afolder.cloudgate config pullreplaces the working copy with the current config.
An entry with source: { folder: apps/web } is built from that subfolder after the whole folder is
uploaded. Applying the Plan that creates such an app queues no Deployment: it waits for its first
upload, since there is nothing to build before one.
What is the Config version?
Every Project config has a Config version, a counter that every Apply moves, a console Save
included. Storing the text it already holds moves nothing. A working copy remembers the version it
was downloaded at, and a Plan sent from it names that version. When the config has moved on since,
the Plan is refused with CONFIG_VERSION_STALE, saying when and by whom it changed, and nothing is
stored, so your copy never undoes a teammate’s change. Pull, make your edits again, and plan.
Keep the config in your repository
On the Config tab, Move to a repository asks for the git provider connection, the
repository and the path. Each Environment reads the file from its Config branch (Environment >
Settings; empty means the default branch), so staging can read develop while production
reads main.
From then on, a push to the Config branch makes a Plan for that Environment, and Check for changes makes one on demand. The console shows the file read-only and never writes to your repository. Move into Cloudgate brings it back, keeping the copy from the default branch or from an Environment’s branch. A move applies nothing; it shows each Environment’s Plan first.
Drift in a cloud
Drift is a change someone made by hand in the AWS or Google Cloud console. A Plan lists it on its own. Applying always puts Cloudgate’s version back (the button reads, for example, “Apply: put AWS back”). A cloud change that finds drift stops before changing anything, and the drift becomes the open Plan. To keep a hand change, write it into the config. See Cloud accounts.
Plan states
| State | Meaning |
|---|---|
| open | Waiting for Apply or Dismiss. One per Environment. |
| applied | Every step ran. |
| partly applied | Some steps ran; the results say which failed. |
| dismissed | Someone dropped it. |
| superseded | A newer Plan replaced it. |
| unchanged | The config matched what runs; nothing to do. |
A Plan whose commit or settings moved on since it was made is refused; make a new one.
What you cannot do
- A push never applies by itself; a person always presses Apply.
- An Agent can ask for a Plan but never applies or dismisses one.
- A field Cloudgate does not know refuses the Plan.
- The config never holds variable values, replica counts or per-Environment settings such as Domains and branches.
- One Service you may not change refuses the whole Apply.
Related pages
- Projects and Environments: Config branch and Deploy target.
- Wired variables and secrets.
- Deployments: why a build is held by a Plan.
- Deploy a whole Project from one folder with the CLI.
- Templates add ready-made entries to your config.
- Ask for a Plan from an AI agent, and AI agents on Cloudgate.
Questions
Does a push to my repository change what runs?
No. A push to the Config branch makes a Plan, which waits for someone to Apply it. Nothing is applied by itself.
Can I put secret values in cloudgate.yaml?
No. The config holds variable names only. Values are set in the console, encrypted at rest, and never written to the file.
Can an AI agent apply a Plan?
No. An Agent can ask for a Plan and read it, but only a person can Apply or dismiss one.
What happens to a field Cloudgate does not know?
The Plan is refused and names the field, so a typo never passes silently.
Can I edit the config from my editor?
Yes, for a config kept in Cloudgate. cloudgate link --whole-project downloads it as a working copy, and cloudgate config plan sends it back as a Plan. An edit made from an older version is refused, so it never undoes a teammate's change.
Something missing or wrong on this page? Email support@octabyte.io, or start a free trial and try it in the console.