Deploying
A service comes from a Git repository, a directory, or a prebuilt image.
Connect a code host in Settings, or paste any public Git URL.
How the build is chosen
Left on Auto, the builder picks the first of these that fits:
- a
Dockerfile at the path you named under Advanced;
- a
Dockerfile at the repository root;
- the repository's only
Dockerfile, wherever it sits
(up to four directories down) — the build log names the one it picked.
More than one and the build stops and asks which, rather than guessing;
- an
index.html at the root — served as a static site;
- otherwise nixpacks, which detects the language and builds an image.
The build context is always the repository root, whichever Dockerfile
is used — so a monorepo Dockerfile can COPY the workspace
manifests it needs from above its own directory.
You can pin it instead: Dockerfile, Nixpacks or Static.
A pinned choice sticks to the service and is reused by webhook and rollback
rebuilds, so a redeploy cannot silently switch strategy.
Config as code
A shebaka.toml at the repository root sets what the Advanced
panel sets — shebaka.yaml, shebaka.yml and
shebaka.json work too. The file wins over the console for the
fields it names, and the build log says so each time it does. Unknown keys
and anything that looks like a secret fail the build rather than being
ignored.
Rebuilding and rolling back
Pushing to the branch you chose redeploys it. Redeploy without cache
in the drawer rebuilds from scratch when a cached layer has gone stale —
it affects only your build. Rollback returns the service to its
previous image.
When a build fails
The log is above the form, with Copy log next to it. Where the
failure is one we recognise, the drawer names the field that caused it and
opens the section it lives in. Where it is not, you get the log and no
invented explanation.
Environment variables
Set them under Advanced when you create a service, or in the
service drawer afterwards. Changing one redeploys the service.
Variables a database gives you
While a database is attached, these six names are set for you and are
reserved — your own values for them are ignored:
DATABASE_URL — the whole connection string
DB_HOST, DB_PORT, DB_NAME,
DB_USER, DB_PASSWORD
They are rendered before your own variables, so you can build on them with
Kubernetes' $(VAR) expansion. That is how an image expecting
its own names works without a wrapper script:
WORDPRESS_DB_HOST = "$(DB_HOST):$(DB_PORT)"
WORDPRESS_DB_USER = "$(DB_USER)"
WORDPRESS_DB_PASSWORD = "$(DB_PASSWORD)"
Secrets
Values are stored with the service and are not printed in build logs.
A secret committed to shebaka.toml fails the build on purpose
— put it here, not in the repository.
Build-time secrets (credentials a Dockerfile needs while
building, rather than at run time) are not supported yet.
Databases
Managed PostgreSQL 18 and MySQL 8.4. Create one from the New
dialog's Database tab, or alongside a service on its Data step.
Attaching
A service attaches a database from its own project. That boundary is
deliberate: a connection string that crosses projects outlives whatever
reason it was made for. Move a database between projects if you need it
elsewhere — the move is metadata, nothing redeploys.
Sizes
Small is 0.5 vCPU / 1 GiB; medium is 2 vCPU / 4 GiB. Storage is billed on
what is provisioned, not what is used. Trial accounts are pinned to small.
Backups
Every managed database gets a nightly dump. Where off-node backups are
configured, a base backup plus continuous log shipping goes to object
storage, which is what makes a restore into another region possible. A
restore lands in a new database beside the original — nothing is
overwritten, and you decide what to keep.
Deleting a database destroys its data and its backups. There is no
undo and no retention window.
Domains & TLS
Every service answers at
https://<service>-<workspace>.apps.shebaka.com
as soon as it is running. The certificate is issued on the first request to
that hostname, so the very first load can take a second longer than the
rest.
Your own domain
- Add the domain in the service drawer.
- Point it at the platform with the record shown there.
- Load it once. The certificate is issued on that request.
If your DNS provider offers a proxy in front of the record (Cloudflare's
orange cloud, for instance), leave it off. A proxied record breaks
certificate issuance, and the failure looks like a certificate problem
rather than a DNS one.
Disaster recovery
Recovery is per service, and what you get depends on whether the service
keeps data.
Stateless services — warm standby
A copy runs in a second region. If the primary stops answering, the edge
fails over to it per request, automatically. You can also fail over
deliberately from the DR tab.
Services with a database — cutover
These move by restoring from backup into the other region, so the recovery
point is the last backup shipped, not the last write. It is never
automatic: moving a database on a false alarm is worse than the outage.
- Planned — the primary is reachable. Everything is quiesced, a
fresh backup is taken, and the loss window is effectively nil.
- Unplanned — the primary is gone. The last shipped log is what
arrives, and the API refuses until you acknowledge the data loss
explicitly.
Whole projects
Cut over project… on the project canvas moves every member together:
one quiesce, all fences before any restore, and a verification barrier
before any record moves. If it fails partway, everything stays fenced and
it says so loudly rather than half-moving your project.
Un-fencing
A fenced service is one that was scaled to zero with its database paused,
ready to be moved. If a cutover failed after that point, the service drawer
shows a fenced banner with an Un-fence button that resumes the
database and scales the service back up where it already was.
Measured recovery times vary by workload and are published per drill rather
than as a single marketing number — ask if you need the figures for a
workload like yours.
CLI
curl -fsSL https://get.shebaka.com | sh
shebaka login # paste the API key from Settings
The CLI has no dependencies and talks to the same API the console does.
shebaka deploy --git https://github.com/you/app.git
shebaka deploy ./site # a directory
shebaka logs <app> -f
shebaka apps list
shebaka apps rollback <app>
shebaka db create <name> --engine postgres|mysql --size small|medium
shebaka db dsn <name>
shebaka db list
shebaka dr status <app>
shebaka dr cutover <app> --to <cluster> --planned
shebaka dr unfence <app>
shebaka usage
shebaka db delete destroys data and backups. It asks first.
API reference
The console is a client of this API and uses nothing private. Authenticate
with your account's API key from Settings:
curl -H "Authorization: Bearer $SHEBAKA_API_KEY" \
https://console.shebaka.com/v1/apps
An API key is bound to one workspace. It cannot switch workspaces, accept
an invitation, or create one — those belong to a signed-in person.
The endpoints you are most likely to want
| Method & path | What it does |
GET /v1/apps | Services, with their URLs and status |
POST /v1/apps/deploy | Deploy or redeploy a service |
GET /v1/apps/{name}/logs | Runtime logs |
POST /v1/apps/{name}/rollback | Back to the previous image |
GET /v1/databases | Managed databases |
GET /v1/databases/{name}/dsn | Connection string |
GET /v1/usage | Month-to-date usage and the open statement |
GET /v1/tenants/{id}/statements | Closed monthly statements |
POST /v1/apps/{name}/dr/failover | Fail a stateless service to its standby |
POST /v1/apps/{name}/dr/unfence | Reverse a fence left by a failed cutover |
There is no versioned public API contract or SDK yet: these
paths are what the console and CLI use, and they can change. If you are
building against them, say so — that is the signal that turns them into a
contract.