← All work

Canopy Host & Forest

Connect a repository, push, and the platform detects the framework, builds it, and serves it over HTTPS, with per-stage logs, a diff view, and one-click rollback.

2024–present built solo closed beta

Overview

Canopy Host is an EU-first developer cloud for deploying applications and AI workloads straight from Git. A developer connects a repository, pushes a branch, and gets a running application: the platform detects the framework, builds it, and serves it over HTTPS, with per-stage build logs, a diff view between deploys, and one-click rollback.

Context

Most teams that want to stop managing servers end up choosing between two extremes: a fully managed PaaS that hides everything and gets expensive fast, or raw Kubernetes, which is powerful and also a full-time job to operate correctly. Canopy Host is built for the space in between: push-to-deploy simplicity, without giving up the ability to see and reason about what is actually running.

Constraints

The hard constraint was avoiding two failure modes at once: a single-node setup that cannot grow, and a general cluster scheduler complex enough to become its own mini distribution of Kubernetes that only I could operate. Forest, the control plane underneath Canopy Host, exists specifically to schedule builds onto whichever cluster (a Grove, in Canopy’s internal naming) has the most free capacity, without requiring every customer-facing decision to route through a general-purpose orchestration layer.

Role

Designed and built solo: backend, infrastructure, system design, deployment automation, and the operational trade-offs day to day. No team, no outside engineering input on the architecture.

Architecture

How a deploy moves through Canopy Host and ForestA git push triggers canopy-build-runner to build the application. forest-controller checks capacity across running Groves (cluster groups) and schedules the build onto whichever has room. Envoy Gateway then routes traffic to the new deployment and issues its TLS certificate through ACME, after which the deployment is live and serving traffic, on the same path that carries Canopy’s own production API. If a health check fails, the rollback path keeps the previous artifact serving traffic instead, so a bad deploy never reaches customers.git pushgrove-a · busygrove-b · freegrove-c · busyforest-controller · capacity check across running Grovesschedule: grove-bbuild imagefreeroute + TLSlive, servinghealthycanopy.pm toorollback: prior build livehealth check fails

Plate IEnvoy Gateway only starts routing to a new deployment once it is healthy. Canopy’s own production API (prod-runtime-1) runs on this same path today, with a real ACME-issued certificate.

Decisions

  • Deployment configuration is parsed from a single config.canopy file per project, rather than spread across platform UI settings.
  • Database provisioning is one click, scoped to an isolated network per project, instead of a shared multi-tenant instance.
  • Forest schedules by free capacity across Groves rather than by any more elaborate bin-packing scheme, since the operational goal was correctness first.

Alternatives

Deliberately did not build a general-purpose Kubernetes abstraction layer on day one. Forest’s scheduler solves the specific problem of picking a Grove with room, not the general problem of arbitrary workload orchestration. Expanding that scope only happens when a real deployment need demands it.

Implementation

  • Repo-to-production deploys, with framework detection and a Dockerfile or Docker Compose fallback
  • A CLI for managing projects and deployment workflows
  • Configurable Nginx handling and automatic SSL and domain setup

Reliability

Still in closed beta, and still hardening deploy success rates as real projects with real edge cases move through the pipeline. Rollback exists precisely because deploys sometimes fail in ways that are only visible once traffic hits them.

Results

This site, giovanni.pw, deploys through this same pipeline. Canopy’s own production API runs on the same Forest-managed infrastructure it schedules for customers.

Lessons

Capacity-aware scheduling across Groves was the straightforward part. The harder, ongoing part has been making single-node operation feel exactly as solid as multi-cluster operation, rather than treating single-node as a lesser mode that happens to also work.