Osy#betaRun it on Osyrin: osyrin.com

Reference / Zones

Deploying an application to a cloud platform — the zone builds it

A cloud deploy hands over the application's bundle — its app blob and the package archives it pins — to the zone the environment runs on, and that zone rebuilds it. The control plane authorizes the deploy, records the version and issues a short-lived upload grant for the zone's store; it never compiles your application and never holds its sources or its DLLs.

previewzonesdeploysecurityguide

Summary#

A deploy is a handover, not a compile — the only deploy there is, through the platform it names (osy deploy --env prod --server <platform>; without --server it is refused, and osy launch runs the app here instead). It builds your application on your machine into a bundle — the app blob, carrying your sources, tests and every package pinned by its hash, plus the package archives themselves — and hands it to the zone your environment runs on. The zone rebuilds it under its own platform release and serves its own build. The control plane authorizes the deploy, records the version and follows it; it never compiles your application and never receives its sources or its package bytes.

Description#

A deploy goes through these steps, each shown by osy deploy as it happens and recorded on the application's platform page:

stepwhere it runswhat happens
buildyour machinethe project is compiled exactly as the zone will compile it; a compile error stops here, before anything is sent
askcontrol planeyour right to deploy is checked, the version is recorded, the zone chosen, and an upload grant for that zone's store issued — with the archives the zone does not hold yet
uploadthe zonethe bundle, and only the archives the zone lacks, go to the zone's gateway under the grant
dry runthe zonethe zone rebuilds the version and plans its environment's database — nothing is written. A version that would leave a live workflow run with nowhere to go (its state renamed or removed, and no workflow migration saying where it goes) is refused here, naming each run and its state: add a Migrating runs that are still in flight to the deploy's --migration file, or end those runs with osy cancel-runs
backupthe zonethe environment's database is backed up, when it has one
movethe zonethe zone rebuilds again, stores its build as the environment's model, and brings the environment's database to it — creating that database, and every table the application stands on, when this is its first deploy
deploythe zonethe version is deployed on the environment's platform release and served once the zone runs it

A failure at any step leaves the environment serving what it served, and says why — on osy deploy, osy status, the platform page, and in an email to the application's team.

On a terminal, osy deploy draws these as rows that update in place — Build the bundle here, Ask the platform to deploy it, Upload the bundle to the zone, The zone builds and rolls it out (the dry run, backup, move and deploy, in the zone's own words), and Its address serves the new version — each with what it is doing and its own clock, and its last word once it ends. In a pipe or CI it prints one line per finished step instead. Either way every line is kept in a log under ~/.osyrin/logs/, whose path it prints first. --json prints the progress on standard error and the result as one JSON line.

Why does the zone build it, and not my machine or the platform?#

Your machine's build is never trusted. It is a convenience that catches mistakes early. The zone compiles your application again from the sources and pins in the bundle, under the platform release the environment runs on, and serves that build. The bundle's model is recorded only by its hash.

The control plane never builds a user application. A platform that runs its applications in zones refuses osy compile, osy test and the debugger for them by name, pointing at osy deploy. So an application's sources and its native DLLs are only ever held by the zone it runs in — for a private zone, the organization's own. A platform with no zones (osyrin dev, a self-hosted install) still compiles there while you develop — but no platform compiles an application to deploy it: every deploy is this handover, and a platform with no zone to hand it to refuses the deploy by name.

The two hashes usually differ, and that is expected. Every deploy records the hash of the blob your machine built and the hash of the zone's build. They differ whenever your machine and the zone run different platform releases, or the zone compiled into the model your environment already serves. The difference is recorded and logged; it is never a refusal.

What happens on the first deploy to an environment?#

An environment has no database until something deploys to it, and that something is always the zone — the platform names the database when the first deploy reaches the environment, and never creates or migrates it itself. The first deploy's move creates the environment's database on the zone's data zone and applies the whole schema its version declares — the application's own tables and the platform's baseline ones (files, workflows, documents and the rest) — then records every statement in that database's own migration ledger. Later deploys apply only what changed, against that ledger.

Until that first build finishes the environment serves nothing, and the platform page says what it is waiting for. A first deploy that fails leaves no half-made database: the move is one transaction, and what it had begun is rolled back. A database the zone cannot create — a data zone whose credential may not create databases, say — fails the deploy like any other step: the environment keeps serving nothing and says why, the operators are alerted, the team is emailed, and osy deploy prints the zone's own words.

What does the upload grant allow?#

Exactly one upload, of one blob, for one version of one application, into one zone's store, for fifteen minutes:

the zone refuses an upload whenanswered
the token is not the grant's403
the grant is for another zone403
the grant expired, or was used403
the bundle's blob is not the one the grant names422
the bundle carries a package the version does not pin, or at another version422
an archive's bytes do not hash to its pin422
a package the version pins is neither carried nor already held by the zone422

The grant is spent before anything is stored, so a second upload under it stores nothing, and a refused upload leaves it usable. A grant nobody uses expires, and the deploy fails with that reason. Nobody but the platform writes a grant — an operator cannot extend one or reset a used one.

Where is my deploy built?#

In a build pod of its own. The zone starts a builder of the release your environment runs — or keeps a few warm, when its operators chose to — and every build runs there in a fresh process, started for that build and stopped when it answers. A build that runs out of memory fails only itself, with that reason; it never takes down the worker your applications' background work runs on, and nothing of one build is in memory for the next. A builder that has finished lingers a few minutes for the next build in line, then goes.

A version is built once per platform release. When the platform releases a new version, the zone builds every active application for it in the background — compiling it and planning its schema change from the two models alone, without touching your database — and keeps that build: the move to the release is served it and compiles nothing. A version that does not build on the new release stays on the one it runs, and the operators are told why.

Why is my deploy waiting?#

A zone builds a limited number of deploys at once — its builders, or on a zone without them its compilation slots, derived from the memory its workers have or set by a platform operator. A deploy past that number waits in an ordered queue rather than overloading the zone, and osy deploy and the platform page show its place:

billing 1.4.0 → prod: dry run — queued on zone eu-north-1 at position 2 for one of 1 compilation slot(s)
billing 1.4.0 → prod: dry run — building on zone eu-north-1, one of 1 compilation slot(s)

The queue has three classes, served in order: the platform's own work first (an operator's move), then what people asked for (your deploys and moves), then the background (a release's pre-builds). Your deploy never waits for a pre-build: a background build that is running is stopped to make room, and built again once the zone is quiet. A build that writes — a move migrating a database — is never stopped.

A deploy that waits longer than twenty minutes for a slot fails with that reason; deploy it again once the zone is less busy, or ask an operator for more slots on the zone.

Can one deploy move my other environments too?#

Yes — that is deploy-follow. An environment can be set to follow the deploys of its application's other environments, so a single osy deploy reaches it without a second command:

the environment followswhat a deploy elsewhere does to it
Never (the default)nothing; only a deploy of its own moves it
PatchVersionsa deploy of a patch version moves it too; a minor or major version still needs osy deploy --env
EveryVersionevery version a deploy brings is deployed here too

A follower is moved from the bundle already in its zone's store — nothing is uploaded again, and nothing is built on the control plane. It gets its own move, so it is dry-run, backed up, built into the model it serves and migrated against its own database, and it can fail on its own without touching the environment you deployed to. Its deployment says what moved it ("follows the deploy of 1.4.0 to Production") on the application's page and in osy status, and only a failure is emailed: you watched the deploy that started it succeed.

An environment that needs an approval is never moved by a follow, whatever its setting says.

A follower that cannot be moved says so. The bundle lives in one zone's store, so an environment placed on another zone has nothing to build from — and neither has the control plane, which holds no copy of it. That environment is not silently left behind: it raises an operator alert ("Environment did not follow a deploy") naming the environment, why, the version it goes on serving, and the command that fixes it — osy deploy --env <that environment> from the machine that built it. The same happens when a move of that environment is already in flight. The alert closes as soon as a deployment into that environment converges.

What about native packages?#

A package that ships native .NET code runs only on dedicated hosting — an organization's private zone. The zone checks this when it rebuilds: on a shared zone the deploy fails naming the package and shared tenancy, however the bundle was built. On a private zone the package's assemblies are checked against this platform's seams before anything runs.

What does the control plane keep about my application?#

Its version, both hashes, the diagnostics the zone reported, the packages it pins by hash, and a short summary of what the zone's build declares — its entity, function and page names — so the platform's pages and alerts can say what failed. It keeps no source, no package archive and no model.

See also#

Deploying your app to an environment — the osy deploy and osy status verbs.

Upgrading an application to a newer platform release — moving an environment to a newer platform release, which the zone also builds.

Related

Upgrading an application to a newer platform release

Each environment of an application runs on its own platform release, and stays on it until its team moves it. A move…

Deploying your app to an environment

Builds your app on this machine and hands it to the zone one of its organization's environments runs on — `osy deploy…