Skip to main content

Platform Architecture

Cubby uses a multi-server architecture to deploy and run your applications reliably.

Overview

┌─────────────────────────────────────────────────────────────┐
│                      Control Plane                          │
│  ┌─────────┐  ┌─────────┐  ┌────────────┐  ┌───────────┐  │
│  │   API   │  │ Traefik │  │ Prometheus │  │  cAdvisor │  │
│  └─────────┘  └─────────┘  └────────────┘  └───────────┘  │
└───────────────────────────┬─────────────────────────────────┘

                   SSH / Docker API

┌───────────────────────────┴─────────────────────────────────┐
│                      App Servers                            │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐              │
│  │  Your App │  │  Database │  │  Another  │              │
│  │ Container │  │ Container │  │    App    │              │
│  └───────────┘  └───────────┘  └───────────┘              │
└─────────────────────────────────────────────────────────────┘

Control Plane

The control plane handles:
  • API: Receives deploys, manages apps, serves the dashboard
  • Traefik: Routes HTTPS traffic to the right container
  • Prometheus: Collects metrics for monitoring
  • Authentication: Manages Cubby SSO across all apps
The control plane never runs user application containers directly.

App Servers

App servers run your containerized applications:
  • Each app runs in an isolated Docker container
  • Databases run alongside apps in separate containers
  • Resource limits (CPU, memory) are enforced per container
  • Multiple apps can run on the same server

Deployment Flow

When you run cubby deploy:
  1. Package: Your code is packaged into a tarball (respects .gitignore)
  2. Upload: Tarball is sent to the Cubby API
  3. Server Selection: API selects an app server with capacity
  4. Transfer: Tarball is sent to the app server via SSH
  5. Build: Docker image is built on the app server
  6. Database: If Prisma is detected, a Postgres container is provisioned
  7. Migrate: prisma db push runs automatically
  8. Start: Container starts with secrets injected
  9. Route: Traefik config is updated to route traffic

Routing

Traefik handles all incoming traffic:

SSL Certificates

  • Wildcard certificates via Let’s Encrypt
  • Cloudflare DNS challenge for validation
  • Automatic renewal

URL Structure

https://<app>.<username>.cubby.pro
        │       │
        │       └── Your Cubby username
        └── Your app name

Health Checks

Traefik monitors container health and only routes to healthy instances.

Database Provisioning

When Cubby detects Prisma in your project:
  1. A Postgres 17 container is created alongside your app
  2. A named Docker volume persists data across deploys
  3. DATABASE_URL is automatically injected
  4. Migrations run on each deploy via prisma db push

Data Persistence

Data persists in Docker volumes even when you redeploy. The volume naming convention:
cubby-db-<username>-<appname>-data

Container Resources

Default resource allocation:
ResourceDefaultConfigurable
Memory512 MBYes (cubby.yaml)
CPU0.5 coresYes (cubby.yaml)
StorageUnlimitedShared volume

Security

Network Isolation

  • Each app container has its own network namespace
  • Apps cannot communicate with each other directly
  • Only Traefik can route traffic to containers

Secret Management

  • Secrets are encrypted at rest
  • Injected at container startup
  • Never exposed in logs or API responses

Authentication

  • ForwardAuth middleware validates all requests
  • User identity passed via headers (X-Cubby-User-Id)
  • Headers are stripped and re-added by the control plane (prevents spoofing)

Monitoring

The control plane collects:
  • Container CPU and memory usage (cAdvisor)
  • Request counts and latencies (Traefik)
  • Container health status
These metrics power the dashboard and alerting.