Ship code, not infrastructure. From git push to a live, production-grade URL.
Architecture Β· Modules Β· Roadmap Β· Getting Started Β· Guides
Forge is a self-hosted, production-grade Platform-as-a-Service. Connect a GitHub repository, pick a branch, set your environment variables, and deploy. Forge builds the Docker image, schedules it onto a node, runs it in an isolated container, routes traffic to it with automatic HTTPS, and lets you roll back to any previous version in one click.
Inspired by Vercel, Render and Railway, but the point of this project is the infrastructure underneath: the build engine, the deployment state machine, the scheduler, the container runtime, and the reliability guarantees that hold it all together.
|
Push to a branch or click deploy. Forge clones, builds, ships and routes. Every deployment is pinned to an immutable commit SHA. |
New version starts beside the old one. Traffic switches only after health checks pass. Old connections drain, then terminate. |
Every LIVE deployment keeps its image. Rolling back reuses it instantly. No rebuild, no surprises. |
|
Organizations, memberships, four roles. Every resource is org-scoped and authorization is enforced on the server. |
Bin-packing across nodes by CPU and memory. Node health detection, draining and rescheduling on failure. |
Prometheus metrics, Grafana dashboards, Loki logs, OpenTelemetry traces. Build logs stream live to the dashboard. |
|
Untrusted builds in restricted sandboxes. Non-root, seccomp, dropped capabilities, encrypted secrets, verified webhooks. |
Lightweight agent per node reporting CPU, memory, disk and container stats over authenticated gRPC. |
PostgreSQL is the source of truth. Idempotent jobs, transactional state, outbox pattern. Nothing accepted is ever lost. |
Forge separates a Control Plane that decides from a Data Plane that executes. The Data Plane keeps serving traffic even if the Control Plane is down.
flowchart TB
Dev([π©βπ» Developer]) --> Web[Next.js Dashboard]
Web --> API[Express API]
subgraph CP[" CONTROL PLANE "]
direction TB
API --> PG[(PostgreSQL<br/>metadata)]
API --> RD[(Redis<br/>BullMQ)]
RD --> BW[Build Workers]
BW --> REG[(Image Registry)]
REG --> DM[Deployment Manager]
DM --> SCH[Scheduler]
end
subgraph DP[" DATA PLANE "]
direction TB
SCH --> N1[Node 1<br/>App A]
SCH --> N2[Node 2<br/>App B]
SCH --> N3[Node 3<br/>App C]
N1 & N2 & N3 --> TR[Traefik<br/>routing Β· TLS]
AG[C++ Agent] -.heartbeat.-> SCH
end
TR --> Net([π Internet])
style CP fill:#1a1f2e,stroke:#4f8cff,stroke-width:2px,color:#fff
style DP fill:#1a2e1f,stroke:#4fcf7f,stroke-width:2px,color:#fff
style Dev fill:#4f8cff,stroke:none,color:#fff
style Net fill:#4fcf7f,stroke:none,color:#000
Note
The Control Plane is a modular monolith plus independently deployable workers. No microservices until scale or isolation demands it. Starts on a single Linux node, designed from day one for multi-node.
Every deployment moves through a persistent state machine stored in PostgreSQL. Transitions are transactional. Every change is recorded as a deployment_event.
stateDiagram-v2
direction LR
[*] --> CREATED
CREATED --> QUEUED
QUEUED --> BUILDING
BUILDING --> BUILD_SUCCEEDED
BUILDING --> BUILD_FAILED
BUILD_SUCCEEDED --> SCHEDULING
SCHEDULING --> DEPLOYING
DEPLOYING --> HEALTH_CHECKING
DEPLOYING --> DEPLOY_FAILED
HEALTH_CHECKING --> LIVE
HEALTH_CHECKING --> HEALTH_CHECK_FAILED
LIVE --> SUPERSEDED
QUEUED --> CANCELLED
BUILDING --> CANCELLED
BUILD_FAILED --> [*]
DEPLOY_FAILED --> [*]
HEALTH_CHECK_FAILED --> [*]
CANCELLED --> [*]
SUPERSEDED --> [*]
Important
If the new version fails its health check, the previous version stays live. Traffic is never switched to an unhealthy instance.
| Layer | Technology | Why |
|---|---|---|
| Frontend | Next.js Β· React Β· TypeScript Β· Tailwind | Fast dashboard, typed end to end |
| Backend | Node.js Β· Express 5 Β· REST Β· WebSockets | Orchestration logic, log streaming |
| Systems | C++20 Β· gRPC | Node agents where OS-level access and performance matter |
| Database | PostgreSQL 16 Β· Prisma | Durable source of truth, typed queries, migrations |
| Queue | Redis 7 Β· BullMQ | Async builds and deploys, retries, backoff, dead-letter |
| Containers | Docker Engine API Β· OCI | Build and run customer workloads |
| Proxy | Traefik | Dynamic hostname routing, automatic TLS |
| Observability | Prometheus Β· Grafana Β· Loki Β· OpenTelemetry | Metrics, dashboards, logs, traces |
| Infra | Docker Compose Β· Terraform Β· AWS EC2 | Reproducible local and cloud environments |
| Testing | Vitest Β· Playwright Β· GoogleTest Β· k6 | Unit, E2E, C++ and load tests |
| CI/CD | GitHub Actions | Lint, typecheck, migrations, build, deploy |
forge/
βββ apps/
β βββ web/ Next.js dashboard
β βββ api/ Express control plane API
βββ workers/
β βββ build/ BullMQ build worker
β βββ deploy/ BullMQ deployment worker
βββ packages/
β βββ db/ Prisma schema, migrations, client
β βββ core/ state machine, scheduler, quotas, outbox
β βββ runtime/ Docker runtime manager
β βββ proxy/ Traefik dynamic config
β βββ github/ OAuth, webhooks, repo access
β βββ shared/ env config, errors, logging, types
βββ agent/ C++ node agent (CMake, gRPC)
βββ infra/
β βββ compose/ local docker-compose stack
β βββ terraform/ AWS EC2 single-node β multi-node
β βββ observability/ Prometheus, Grafana, Loki, OTel
βββ docs/
β βββ adr/ architecture decision records
β βββ guides/ step-by-step implementation guides
β βββ api/ API reference
β βββ benchmarks/ measured, reproducible results
βββ .github/workflows/ CI and deploy pipelines
01 Β· Identity & Multi-tenancy
Users, GitHub OAuth, organizations, roles (Owner / Admin / Developer / Viewer), API tokens, rate limiting. Authorization is enforced server-side on every org-scoped resource.
02 Β· GitHub Integration
Repo selection, webhook registration, signature verification, duplicate webhook detection, immutable commit SHA tracking per deployment.
03 Β· Build Engine
Clone β checkout SHA β detect app type β Dockerfile or generated default β build β validate β push to registry β stream logs. Untrusted code runs in restricted builders. The host Docker socket is never exposed to builds.
04 Β· Asynchronous Jobs
BullMQ with priorities, bounded concurrency, retries with exponential backoff, dead-letter queues, heartbeats, graceful shutdown, abandoned-job recovery and idempotency. PostgreSQL is the source of truth; Redis is only the queue. Transactional outbox for event publishing.
05 Β· Deployment Orchestrator
Persistent state machine with transactional transitions, versioning, traffic switching, rollback, cancellation and a full event history. See Deployment Lifecycle.
06 Β· Container Runtime
Create / start / stop / inspect / health / logs / cleanup via the Docker API. Non-root, dropped capabilities, seccomp, read-only filesystem, resource limits, no privileged containers.
07 Β· C++ Infrastructure Agent
CPU, memory, disk and container stats, heartbeats, node registration over authenticated, versioned gRPC. No privileged operations exposed over the network.
08 Β· Distributed Scheduler
Resource-aware bin-packing across nodes, reservations, draining, failure detection, rescheduling.
09 Β· Networking
Traefik hostname routing, automatic TLS, custom domains, health-aware routing, connection draining.
10 Β· Zero-downtime Deploys
Start new β health check β register β switch traffic β drain old β terminate old. A failed health check leaves the previous version live.
11 Β· Rollback & Versioning
Every LIVE deployment has an immutable image. Rollback reuses that image, never rebuilds.
12 Β· Observability
Prometheus metrics, Grafana dashboards, Loki logs, OpenTelemetry traces across the whole deployment workflow.
13 Β· Resource Quotas
Per-org CPU, memory, concurrent builds, running apps and storage limits. Admission checks before scheduling.
| Phase | Done when | |
|---|---|---|
| π’ | 01 Β· Foundation | Monorepo, API, Prisma schema + migrations, auth, orgs, RBAC, projects, API tokens, audit log, tests, CI |
| π‘ | 02 Β· GitHub | OAuth, repo picker, verified webhooks, push creates a deployment record |
| βͺ | 03 Β· Build Engine | Worker builds a Docker image from a repo, logs stream, cancel + retry |
| βͺ | 04 Β· Orchestration | State machine persisted, container starts with limits, health checks gate LIVE |
| βͺ | 05 Β· Networking | Traefik routes <app>.forge.local, HTTPS, custom domains |
| βͺ | 06 Β· Reliability | Zero-downtime switch, rollback, worker crash recovery, duplicate job handling |
| βͺ | 07 Β· C++ Agent | Node metrics + heartbeats over gRPC, Control Plane shows node health |
| βͺ | 08 Β· Observability | Prometheus, Grafana, Loki, OTel wired end to end |
| βͺ | 09 Β· Multi-node | Scheduler places workloads across nodes, detects failures, reschedules |
| βͺ | 10 Β· Hardening | Tenant isolation tests, secrets encryption, quotas, backups, load + chaos tests |
π’ done Β· π‘ in progress Β· βͺ not started
Infrastructure stages: Local Compose β Single EC2 node via Terraform β Multi-node with C++ agents β Optional Kubernetes backend, only after Forge's own scheduler is proven.
Warning
No accepted deployment request may ever be silently lost.
The test suite covers these failure scenarios:
| Scenario | Expected behaviour |
|---|---|
| Build worker crashes mid-build | Job is recovered and retried, state stays consistent |
| Duplicate GitHub webhooks | Deduplicated by delivery ID, one deployment |
| Duplicate deployment jobs | Idempotent processing, no double deploy |
| Redis temporarily unavailable | Queue reconnects, no accepted work lost |
| PostgreSQL temporarily unavailable | Transitions retried, no partial state |
| App fails to start or goes unhealthy | Previous version stays live |
| Node becomes unreachable | Workloads rescheduled to healthy nodes |
| Container exceeds memory limit | Killed, restarted per policy, surfaced in dashboard |
| New deployment fails during traffic switch | Routing reverts, old version keeps serving |
| Control Plane restarts mid-deployment | Deployment resumes from persisted state |
- Every repository and Dockerfile is untrusted input.
- Builds and apps run non-root, capability-restricted, resource-limited and network-isolated.
- The Docker daemon is never reachable from customer workloads or the public internet.
- Environment variables are encrypted at rest and never logged.
- Webhook signatures are verified, the API is rate limited, sensitive actions are audit-logged.
- The node agent speaks an authenticated, versioned interface and exposes no privileged operations.
| 1 | Reliability over feature count |
| 2 | Durable state in PostgreSQL for anything that matters |
| 3 | Idempotent async processing everywhere |
| 4 | Clear module boundaries. Extract services only when justified |
| 5 | Measure performance (p50 / p95 / p99). Never fabricate benchmarks |
| 6 | Every major decision gets an ADR in docs/adr/ |
Prerequisites: Node 20+ Β· pnpm 9 Β· Docker
git clone https://github.com/Sachinn-64/Forge.git && cd Forge
cp .env.example .env # set SESSION_SECRET: openssl rand -hex 32
pnpm install
pnpm infra:up # postgres + redis
pnpm db:generate
pnpm db:migrate
pnpm dev # api on :4000Run the test suite:
pnpm test:prepare # creates forge_test and applies migrations
pnpm testcurl localhost:4000/health
# {"status":"ok"}Tip
Step-by-step implementation guides live in docs/guides/. Start with 01-auth.md.
MIT Β© 2026 orthodox-64
Developers focus on building software.
Forge handles the infrastructure required to build, deploy, operate, monitor and scale it.