Deployments
Every git push to a connected repository triggers a deployment. This page explains what happens, the two deploy modes, how preview URLs are shaped, and the actions you can take on a running environment.
From git push to live URL
- You
git pushto any branch. - GitHub delivers a webhook to
POST /webhooks/github. - Nexos verifies the HMAC-SHA256 signature, finds the matching project, and decides whether this is a brand new or incremental deploy based on whether an environment already exists for the branch.
- A build job lands on the BullMQ
buildqueue. - The scheduler checks your quota, picks a provider node with free capacity (preferring one that has built this project before for cache affinity), and dispatches the job over gRPC.
- The agent on the selected node builds your image with BuildKit, starts the containers, and streams logs back. Nexos wires Caddy to route your preview URL to the new container.
For most apps this takes 30–60 seconds. You can watch every step stream into the dashboard in real time.
Brand new vs. incremental deploys
The single most important concept on Nexos: we know the difference between “this is a new branch” and “this is another push to a branch I'm already running.”
Brand new deployments
Fires the first time Nexos sees a branch. Full stack gets provisioned from scratch:
- App container built from your Dockerfile
- Fresh Postgres container (empty)
- Fresh Redis container
- New Caddy route for the preview URL
- Both
on_deployandon_newhooks run
Expect this to take longer than an incremental — you're paying for cold starts.
Incremental deployments
Fires on subsequent pushes to a branch that's already running. Only the app container is rebuilt:
- App image rebuilt (with BuildKit layer cache — often fast)
- Old app container stopped
- New app container started, pointed at the same database, Redis, and S3 bucket
- Only the
on_deployhook runs
Your database persists across incremental deploys. That's the whole point: test data survives, user sessions survive, multi-step workflows survive. Fix a bug on branch, push, keep testing.
Environment states
An environment moves through these states over its lifetime:
| State | What's happening |
|---|---|
provisioning | Scheduler picked a node, containers are being allocated. |
building | BuildKit is building your image on the assigned node. |
deploying | Containers are starting. Health checks are running. |
running | Live at the preview URL. Ready for traffic. |
paused | App container stopped. Database and storage persist. |
failed | Build or deploy failed. Check build logs for the reason. |
destroyed | All resources released. Environment can't be resumed. |
Preview URLs
Preview URLs follow a predictable pattern:
{branch-slug}-{project-slug}.{platform-domain}Example: project my-app, branch feature/login-page →
feature-login-page-my-app.nexos.devBranch names are slugified: slashes become hyphens, special characters are stripped, and the whole thing is lowercased. Because URLs are deterministic you can share them in PR descriptions, Slack messages, or automation — they'll still point to the same environment on every push.
Build logs
Build output streams into the dashboard over WebSocket. Open your environment and click Logs to watch BuildKit, container startup, and hook execution live.
Logs are also available programmatically at GET /api/deployments/:id/logs — useful for CI bots and Slack integrations.
Environment actions
From the dashboard or API you can act on a running environment in several ways:
- Restart — stops the app container and runs a fresh incremental deploy from the latest commit. Database stays intact. Use this to re-run startup or pull in a new env var.
- Pause — stops the app container. Database and storage keep persisting. Environment enters
paused. Useful for freeing quota on idle previews. - Resume — kicks off an incremental deploy from the latest commit and reconnects to the existing database. Back to
running. - Reset Database — destroys the current database and reprovisions an empty one. All environment data is lost.
- Destroy — tears down every container, storage, and Caddy route. Environment enters
destroyedand can't be brought back.