Bex supports two configuration workflows:
| Workflow | Format | Use it when |
|---|---|---|
| Platform deployment | render.yaml Blueprint | You want authenticated, workspace-scoped deployment through the Bex API. |
| Direct operator deployment | Kubernetes App resource | You operate the cluster or are following the local quickstart. |
These formats have different field names. A Blueprint is compiled into Bex
resources; it is not a Kubernetes manifest and cannot be applied with
kubectl apply.
Declare a Blueprint
Save this as render.yaml. Replace the repository URL with a repository you
can deploy that contains a Dockerfile and an HTTP application listening on
0.0.0.0:$PORT.
services:
- name: api
type: web
runtime: docker
repo: https://github.com/your-org/your-app
branch: main
plan: free
numInstances: 1
autoDeployTrigger: off
envVars:
- key: LOG_LEVEL
value: infoThis example disables automatic deployment on later commits. Choose the plan
appropriate to your Bex instance; a plan name in a manifest is not a price
quote. Add healthCheckPath only when your app provides an endpoint that
returns a successful health response.
The canonical filename is render.yaml. bex.yml is a deprecated filename
alias using the same grammar. Older examples with an apps: root,
type: private, a scalar image, or replicas inside a Blueprint must be
converted; renaming the file alone does not convert those fields.
Common Blueprint fields
| Field | Purpose |
|---|---|
services | Web/private services, workers, cron jobs, static sites, and Key Value. |
databases | Managed PostgreSQL declarations. |
services[].type | web, pserv, worker, cron, or keyvalue. Static sites use web with runtime: static. |
runtime | Build/runtime selection, such as docker, image, or a supported native language runtime. |
repo, branch, rootDir | Git source and optional monorepo root. |
image.url | Container image reference when using runtime: image. |
buildCommand, startCommand | Build and launch commands for native runtimes. |
numInstances | Requested instance count for services that support replication. |
envVars | Literal configuration or supported references; keep credentials out of Git. |
domains | Custom hostnames for a public service. |
healthCheckPath | HTTP health endpoint for a web or private service. |
autoDeployTrigger | commit or off; validate other policies against Bex before use. |
Bex validates against a pinned Render schema and its own capability rules. Unknown and unsupported fields are rejected instead of silently ignored. The Render YAML reference describes Render's current schema; use Bex validation to determine what your Bex version accepts. See the Bex Blueprint contract for implementation details.
Validate and deploy through the API
The repository helper requires bash, jq, curl, an accessible Bex API,
and an OAuth access token authorized for the target workspace. For machine
access, exchange an API key for that token first.
It does not use your kubeconfig.
From a clone of the Bex repository:
export BEX_API_URL="https://your-bex-api.example.com"
export BEX_OWNER_ID="your-workspace-id"
# Set BEX_API_TOKEN securely in your shell to an authorized token.
DRY_RUN=1 scripts/app-apply.sh /path/to/render.yamlDRY_RUN=1 calls POST /v1/blueprints/validate without deploying. Inspect the
response body for validation errors and the proposed plan; an HTTP success
alone does not establish that the manifest is valid.
After resolving errors and reviewing the target workspace and plan:
scripts/app-apply.sh /path/to/render.yamlThis calls POST /v1/blueprints/deploy. Deployment submission is not readiness;
follow the resulting resources in the dashboard or API until their deployments
finish. See How deploys work.
You can pass a project directory instead of a file. If it contains both
render.yaml and bex.yml, the helper requires an explicit file path.
Removing a resource declaration from a Blueprint does not delete the existing
resource. Plan deletions explicitly through the platform's resource controls.
Apply an App directly to Kubernetes
This example is for cluster operators. It requires installed Bex CRDs and a running operator, as described in the Quickstart.
apiVersion: app.bex.co/v1alpha1
kind: App
metadata:
name: whoami
namespace: default
spec:
image: traefik/whoami
port: 8080
env:
- name: WHOAMI_PORT_NUMBER
value: "8080"
replicas: 2Save it as whoami-app.yaml, then run:
kubectl apply -f whoami-app.yaml
kubectl get apps.app.bex.co whoami -wUse a high container port such as 8080: tenant containers drop Linux
capabilities, including the capability needed to bind privileged ports. Bex
injects PORT; images that use their own setting, such as traefik/whoami,
need that setting configured too.
Selected App spec fields
| Field | Purpose |
|---|---|
type | web_service (default), private_service, background_worker, cron_job, or static_site. |
image | Prebuilt container image; unlike Blueprint image, this is a string. |
repo, branch, rootDir | Git build source and optional monorepo root. |
port | Container listener port; defaults to 3000. The injected PORT follows this value. |
replicas | Replica count, subject to service-type and storage constraints. |
env | Environment entries using name and value, or supported secret references. |
envFromSecret, envFromSecrets | Same-namespace Kubernetes Secrets providing environment values. |
healthCheckPath | HTTP startup, readiness, and liveness check; an unset path uses TCP for web/private services. |
suspended | Suspend the workload while retaining its configuration. |
host, hosts, expose | Requested public hostnames and platform-domain exposure; require configured routing infrastructure. |
The full field contract lives in
AppSpec.
Do not copy these field names into a Blueprint.
Read status
kubectl get apps.app.bex.co displays phase, revision, and URL. Use
kubectl describe apps.app.bex.co <name> to inspect conditions and errors.
Pending, Building, and Deploying describe work in progress. Running
indicates convergence; Hibernated, Canceled, and Failed describe other
lifecycle outcomes. status.activeRevision identifies the active revision;
status.url and status.urls report addresses. A .svc address is internal
to Kubernetes and does not imply public routing.
Related guides
See Manage Blueprints for Git-connected synchronization and ownership.