v1.0 — Self-hosted

Deploy with zero downtime.
Own your infra.

ZeroShift is a self-hosted deployment engine that runs blue-green Docker deployments on your own server. Push to GitHub — ZeroShift pulls the source, builds the image, starts the container, switches Nginx traffic, and tears down the old one. No downtime. No cloud lock-in.

Get started → View on GitHub
zeroshift — deploy log
0s
downtime per deploy
2
live container slots (blue / green)
1-click
rollback to previous deployment
projects on a single server

// dashboard

Everything in one view.

localhost:9090
◈  Overview
⟳  Deployments
▣  Server
4
Projects
4
Running
0
Failed
0
Deploying
Projects 4 + New
SP
speedtype
nithin2k5/speedtyper.git
v2 · 1h ago ACTIVE
NI
nithin
nithin2k5/Portfolio
v3 · 2h ago ACTIVE
MO
monix
dinexh/monix.git
v4 · 3h ago ACTIVE

// how it works

Push. Build. Switch. Done.

Every deploy targets the idle container slot. The live app is never touched until the new one is healthy.

Deploy pipeline
Blue / Green
Rollback
1
Acquire lock
Per-project in-memory lock prevents concurrent deploys on the same project. Other projects deploy in parallel.
DeploymentService.locks.set(projectId, true)
2
Pull source
Git clone or fetch + reset to branch HEAD. Auto-generates a Dockerfile if one isn't present (detects Node, Bun, Python).
git fetch origin && git reset --hard origin/main
3
Build image
Runs docker build with the project's build context. Full stdout/stderr captured — build errors surface directly in the dashboard.
docker build -t zeroshift-myapp:1740000000 ./myapp
4
Start container
Pre-cleans stale containers by name and frees the target port before starting. Injects project env vars.
docker run -d --name myapp-green -p 3101:3000 zeroshift-myapp:...
5
Switch traffic
Rewrites the Nginx upstream config to point to the new container's port. Reloads Nginx with zero dropped connections.
nginx -s reload # upstream localhost:3101
6
Retire old slot
Previous ACTIVE deployment is stopped, removed, and marked ROLLED_BACK — ready for the next rollback.
docker stop myapp-blue && docker rm myapp-blue

Each project has two container slots — BLUE on basePort and GREEN on basePort+1. One is always live. Every deploy targets the idle one. Click the buttons to simulate.

BLUE LIVE
port:3100
containermyapp-blue
statusACTIVE
GREEN LIVE
port:3101
containermyapp-green
statusidle
nginx upstream → localhost:3100 (blue)
1
Find previous deployment
Queries the most recent deployment with status ROLLED_BACK and a lower version number than current.
2
Re-run old container
Starts the previous image on its original port. If the image was pruned, rollback is aborted safely — the current deployment stays live.
docker run -d --name myapp-blue -p 3100:3000 zeroshift-myapp:prev
3
Verify health
Health check runs before switching traffic. If it fails, the restarted container is cleaned up and the current deployment stays active.
4
Switch traffic & swap statuses
Nginx is reloaded to the old container. The old deployment becomes ACTIVE, the current one becomes ROLLED_BACK.

// features

Everything you need.
Nothing you don't.

Built for real deployments on real hardware, not abstract cloud primitives.

Blue-green deployments

Two container slots per project. Traffic switches in milliseconds via Nginx upstream reload. Zero dropped connections.

Git-native workflow

Webhook triggers on push. ZeroShift clones or fetches your repo, checks out the configured branch, and deploys.

One-click rollback

Every previous deployment is stored. Roll back to any ROLLED_BACK version instantly — health-checked before traffic switches.

Cancel mid-deploy

Stuck on a long build? Hit Stop. The pipeline is interrupted at the next checkpoint, the container stopped, and the lock released.

📄
Auto Dockerfile

No Dockerfile? ZeroShift generates one — detects Node.js, Bun, Python. Scans subdirectories. Regenerated each deploy, never overwrites yours.

Crash recovery

On startup, reconciliation scans for DEPLOYING records (process died mid-deploy), marks them FAILED, and cleans up orphaned containers.

Per-project env vars

Inject environment variables per project via the dashboard. Applied to the next deploy — no restart required.

Server monitoring

Live CPU, memory, disk, and network stats for the host server. Per-container metrics — CPU %, memory used, net I/O, block I/O, PIDs. All polled in real-time from the dashboard.

Automatic CI pipeline

AI-generates a production GitHub Actions workflow for your project — detects runtime, caches deps, runs build & test, then fires the ZeroShift webhook to deploy on every push.


// why zeroshift

Simple, self-hosted, yours.

No vendor lock-in. No monthly bill for a deployment tool. Just your server, running your code.

Feature ZeroShift Heroku / Render Kubernetes Raw Docker
Zero-downtime deploys
Self-hosted
No cloud fees depends
Dashboard UI 3rd party
One-click rollback limited
Git-native workflow via CI
AI CI pipeline gen
Setup complexity Low Low High Medium
Open source

// setup

Local setup in 6 steps.

Requires Bun, Docker, Nginx, and a PostgreSQL database (Neon free tier works).

1
Clone & install

Clone the repo and install dependencies with Bun.

bash
git clone https://github.com/dinexh/ZeroShift-Engine
cd ZeroShift-Engine
bun install
2
Configure .env

Create a .env file at the repo root. Only DATABASE_URL is required.

.env
# Required
DATABASE_URL=postgresql://user:pass@host/db

# Optional
PORT=9090
DOCKER_NETWORK=bridge
NGINX_CONFIG_PATH=/etc/nginx/conf.d/upstream.conf
PROJECTS_ROOT_PATH=/var/zeroshift/projects
GEMINI_API_KEY=           # for AI pipeline generation
3
Push database schema

Creates the Project and Deployment tables. Re-run after any schema change.

bash
bunx prisma db push
4
Build the dashboard

Next.js static export. Fastify serves it automatically from dashboard/out/.

bash
cd dashboard && bun install && bun run build && cd ..
5
Start the engine

Dev mode with watch, or production via PM2.

bash — dev
bun --watch src/server.ts
bash — production
pm2 start ecosystem.config.cjs
pm2 save                 # persist across reboots

Engine + dashboard available at http://localhost:9090

6
Create a project & deploy

basePort is auto-assigned. webhookSecret is auto-generated — copy the URL from the dashboard after creation.

bash
# Create project
curl -X POST http://localhost:9090/api/v1/projects \
  -H 'Content-Type: application/json' \
  -d '{ "name": "myapp", "repoUrl": "https://github.com/you/myapp",
       "branch": "main", "appPort": 3000 }'

# Trigger first deploy
curl -X POST http://localhost:9090/api/v1/deploy \
  -H 'Content-Type: application/json' \
  -d '{ "projectId": "<id>" }'

Environment variables

Variable Default Description
DATABASE_URL requiredPostgreSQL connection string
PORT9090API + dashboard port
DOCKER_NETWORKbridgeDocker network for containers
NGINX_CONFIG_PATH/etc/nginx/conf.d/upstream.confNginx upstream file
PROJECTS_ROOT_PATH/var/zeroshift/projectsRoot dir for cloned repos
GEMINI_API_KEYGoogle AI Studio key (optional)
GEMINI_MODELgemini-2.5-proGemini model ID
LOG_LEVELinfoPino log level

// api reference

REST API

All endpoints are prefixed with /api/v1. Responses are JSON.

Projects

MethodPathDescription
POST/projectsCreate project
GET/projectsList all projects
GET/projects/:idGet project
PATCH/projects/:idUpdate branch / ports / build context
PATCH/projects/:id/envUpdate env vars
DELETE/projects/:idDelete project
POST/projects/:id/rollbackRollback to previous deployment
POST/projects/:id/cancel-deployCancel in-progress deployment

Deployments

MethodPathDescription
POST/deployTrigger deployment { projectId }
GET/deploymentsList all deployments
GET/statusCurrent active deployment

Webhooks & System

MethodPathDescription
POST/webhooks/:secretGitHub push webhook — triggers auto-deploy
GET/system/server-statsHost CPU / memory / disk / network
POST/system/reconcileManual crash recovery
GET/healthEngine health check