Skip to main content
Shipyard is a Kubernetes-native multi-tenant deployment platform with a React frontend, OAuth authentication, RBAC, tiered subscriptions, and secrets management.

System Architecture

The platform consists of three main components working together:
┌─────────────────────────────────────────────────────────────────────────────────┐
│                                   CLIENTS                                        │
│                              (Web Browser / API)                                 │
└─────────────────────────────────────┬───────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────────┐
│                              REACT SPA (ui/)                                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │   React 19  │  │  React      │  │  TanStack   │  │     React Router 7      │ │
│  │   + Vite    │  │  Hook Form  │  │   Query     │  │   (Client-side routing) │ │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
│                                                                                  │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │                              Pages                                         │  │
│  │  Dashboard │ Teams │ Secrets │ Billing │ Templates │ Deployments         │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────┬───────────────────────────────────────────┘
                                      │ HTTP API

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              GO SERVER (cmd/server)                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │   OAuth     │  │  Session    │  │   Auth      │  │      Embedded SPA       │ │
│  │  (Google)   │  │   Store     │  │ Middleware  │  │    (go:embed ui/dist)   │ │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
│                                                                                  │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │                            REST API Handlers                               │  │
│  │  /api/deployments  /api/secrets  /api/templates  /api/orgs  /api/teams    │  │
│  │  /api/billing      /api/clients  /api/me         /api/invites             │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
│                                                                                  │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │                            Middleware Stack                                │  │
│  │  Security Headers → Auth → RBAC (Authz) → Audit Logging → Handler         │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
└────────────┬─────────────────────┬─────────────────────┬────────────────────────┘
             │                     │                     │
             ▼                     ▼                     ▼
┌────────────────────┐  ┌──────────────────┐  ┌─────────────────────────────────┐
│    PostgreSQL      │  │  Vault/AWS       │  │        Kubernetes API           │
│    (db.Store)      │  │ (secrets.Store)  │  │   (controller-runtime client)   │
│                    │  │                  │  │                                 │
│  - Users           │  │  - User secrets  │  │  Creates UserDeployment CRs     │
│  - Organizations   │  │  - Template      │  │                                 │
│  - Teams           │  │    secrets       │  └────────────────┬────────────────┘
│  - Deployments     │  │  - Deployment    │                   │
│  - Templates       │  │    secrets       │                   │
│  - Billing Plans   │  │  - Per-service   │                   │
│  - Clients         │  │    secrets       │                   │
│  - Sessions        │  │                  │                   │
└────────────────────┘  └──────────────────┘                   │

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           OPERATOR (cmd/operator)                                │
│                                                                                  │
│  ┌─────────────────────────────────────────────────────────────────────────┐    │
│  │                    UserDeployment Controller                             │    │
│  │                                                                          │    │
│  │   Watches: UserDeployment CRs                                           │    │
│  │   Creates: Deployments, Services, Ingresses, ConfigMaps,                │    │
│  │            ExternalSecrets, NetworkPolicies                             │    │
│  │   Features: Health probes, resource limits, observability               │    │
│  └─────────────────────────────────────────────────────────────────────────┘    │
└────────────────────────────────────┬────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────────┐
│                         KUBERNETES RESOURCES                                     │
│                                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐ │
│  │  Deployment  │  │   Service    │  │   Ingress    │  │   ExternalSecret     │ │
│  │  (per svc)   │  │  (per svc)   │  │  (per svc)   │  │   (syncs from Vault) │ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────────────┘ │
│                                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────────────────────┐   │
│  │  ConfigMap   │  │ K8s Secret   │  │         NetworkPolicy                │   │
│  │  (user data) │  │ (from ESO)   │  │  (tier-based isolation)              │   │
│  └──────────────┘  └──────────────┘  └──────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────────┘

Core Components

1. React Frontend

Modern single-page application built with:
  • React 19 with TypeScript
  • Vite 7 for fast development and optimized builds
  • TanStack Query 5 for server state management
  • React Router 7 for client-side routing
  • React Hook Form + Zod for form validation
  • Tailwind CSS 4 for styling
  • Recharts for metrics visualization
Key features:
  • Dashboard with deployment cards
  • Team management (create, invite, manage members)
  • Secrets management (three-tier: user/template/deployment)
  • Template creation with YAML spec editor
  • Real-time deployment logs and metrics
  • Billing and subscription management
Location: k8s-scheduler/ui/

2. Go Server

REST API backend serving both the API and embedded React application:
  • OAuth Authentication: Google OAuth2 flow
  • Session Management: Memory/PostgreSQL/Redis backends
  • Embedded SPA: React app served via go:embed
  • RBAC Middleware: Permission checks on all endpoints
  • Template Management: CRUD with visibility scopes
  • Deployment Lifecycle: Create/delete/monitor deployments
  • Secrets Management: Three-tier secrets architecture
  • Billing Integration: Stripe subscriptions and webhooks
Location: k8s-scheduler/cmd/server/ Key API endpoints:
# Initiate Google OAuth
GET /oauth/google

# OAuth callback
GET /oauth/google/callback

# End session
POST /logout

3. Kubernetes Operator

Kubernetes operator built with controller-runtime:
  • Watches: UserDeployment custom resources
  • Reconciles: Creates/updates/deletes K8s resources
  • Manages: Deployments, Services, Ingresses, ConfigMaps, ExternalSecrets
  • Features: Health probes, resource limits, Prometheus metrics
Location: k8s-scheduler/cmd/operator/ Custom Resource Definition:
k8s-scheduler/manifests/userdeployment-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: userdeployments.scheduler.shipyard.sh
spec:
  group: scheduler.shipyard.sh
  versions:
    - name: v1alpha1
      served: true
      storage: true

Data Flow

Understanding how a deployment is created:
1

User Action

User clicks Create Deployment in the React UI, fills out the form with template selection and configuration.
2

API Request

React app sends POST request to /api/deployments with deployment configuration.
3

Server Validation

Go server validates the request, checks RBAC permissions, and verifies the user has quota available for their subscription tier.
4

Create Custom Resource

Server creates a UserDeployment custom resource in Kubernetes:
internal/server/server.go
ud := &v1alpha1.UserDeployment{
    ObjectMeta: metav1.ObjectMeta{
        Name:      deployment.Name,
        Namespace: fmt.Sprintf("sandbox-%s", userID),
    },
    Spec: v1alpha1.UserDeploymentSpec{
        UserID:     userID,
        Template:   deployment.Template,
        Services:   deployment.Services,
        // ...
    },
}
kubeClient.Create(ctx, ud)
5

Operator Watches

Operator’s controller watches for new UserDeployment resources and triggers reconciliation loop.
6

Reconcile Loop

Operator creates all necessary Kubernetes resources:
  • Deployments (one per service in the template)
  • Services (for internal networking)
  • Ingresses (for external access)
  • ExternalSecrets (to sync secrets from Vault)
  • ConfigMaps (for user configuration)
  • NetworkPolicies (for tenant isolation)
7

Pods Running

Kubernetes schedules pods, pulls images, mounts secrets, and starts containers.
8

Status Updates

Operator updates the UserDeployment status field with pod health, URLs, and any errors. React UI polls for updates and displays deployment status.

Multi-Tenancy Model

Shipyard implements a hierarchical multi-tenancy model:
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           PLATFORM (Your Instance)                               │
└─────────────────────────────────────┬───────────────────────────────────────────┘

        ┌─────────────────────────────┼─────────────────────────────┐
        ▼                             ▼                             ▼
┌───────────────────┐       ┌───────────────────┐       ┌───────────────────┐
│   Client A        │       │   Client B        │       │   Direct Org      │
│   (White-label)   │       │   (White-label)   │       │   (No client)     │
│   custom domain   │       │   custom domain   │       │                   │
│   own branding    │       │   own branding    │       │                   │
│   billing plans   │       │   billing plans   │       │                   │
└─────────┬─────────┘       └─────────┬─────────┘       └─────────┬─────────┘
          │                           │                           │
    ┌─────┴─────┐               ┌─────┴─────┐                     │
    ▼           ▼               ▼           ▼                     ▼
┌───────┐   ┌───────┐       ┌───────┐   ┌───────┐           ┌───────────┐
│ Org 1 │   │ Org 2 │       │ Org 3 │   │ Org 4 │           │   Org 5   │
└───┬───┘   └───────┘       └───────┘   └───────┘           └─────┬─────┘
    │                                                             │
    ├── Team A (Backend)                                          ├── Team X
    │   ├── [email protected] (developer)                           └── Team Y
    │   └── [email protected] (team_admin)

    └── Team B (Frontend)
        └── [email protected] (viewer)

RBAC Hierarchy

Every user action is validated against their role at the organization and team level.
LevelRolesPermissions
Organizationorg_ownerFull org control, billing, all teams
org_adminManage teams, templates, members
org_memberAccess assigned teams only
Teamteam_adminManage team members, deployments, invites
developerCreate/manage deployments, view secrets
viewerRead-only access to deployments
Implementation: k8s-scheduler/internal/authz/authorizer.go

Secrets Architecture

Three-tier secrets system for flexible secret management:
┌─────────────────────────────────────────────────────────────────┐
│                        VAULT                                     │
│                                                                  │
│  users/{userId}/                                                 │
│  ├── secrets/              # User-level (global) secrets         │
│  ├── templates/{name}/     # Template secrets                    │
│  │   └── services/{svc}/   # Per-service template secrets        │
│  └── deployments/{name}/   # Deployment-specific secrets         │
│      └── services/{svc}/   # Per-service deployment secrets      │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                    EXTERNAL SECRETS OPERATOR                     │
│                                                                  │
│  ExternalSecret CR ──syncs──▶ K8s Secret                        │
│  (references Vault path)      (mounted in pods)                  │
└─────────────────────────────────────────────────────────────────┘

Secret Levels

LevelPathLifecycleUse Case
Userusers/{id}/secretsPersistentAPI keys shared across deployments
Templateusers/{id}/templates/{name}PersistentTemplate-specific config
Service.../services/{svc}PersistentPer-container secrets
Deploymentusers/{id}/deployments/{name}EphemeralDeployment-specific overrides
Implementation: k8s-scheduler/internal/secrets/vault.go

Infrastructure Components

Shipyard consists of three main repository components:

1. k8s-scheduler

Main application code (React frontend + Go backend + Kubernetes operator) Tech stack:
  • Go 1.24 with standard library HTTP server
  • PostgreSQL (pgx/v5) for data persistence
  • controller-runtime for Kubernetes operator
  • React 19 + Vite 7 + TailwindCSS 4

2. terraform-modules

Reusable Terraform modules for AWS infrastructure:
  • VPC: Virtual private cloud with public/private subnets
  • EKS: Amazon EKS cluster with managed node groups
  • RDS: PostgreSQL database
  • Vault: HashiCorp Vault infrastructure (KMS, DynamoDB)
  • EC2: Bastion hosts and utility instances
  • State: S3 + DynamoDB for Terraform state
Location: terraform-modules/

3. infra

Environment-specific infrastructure deployments using the Terraform modules. Three-layer architecture:
  1. Infrastructure Layer: VPC, EKS, Tailscale VPN, Vault
  2. Platform Layer: ALB Controller, cert-manager, External Secrets Operator
  3. Apps Layer: ArgoCD, Traefik, application TLS certificates
Location: infra/terraform/dev/

Subscription Tiers

Feature availability varies by subscription tier:
FeatureFreeBusinessEnterprise
Deployments15Unlimited
Team Members110Unlimited
TemplatesSystem only+ Custom+ Org-wide
Network IsolationSharedNamespaceDedicated
SupportCommunityEmailDedicated
Enforcement: k8s-scheduler/internal/tierlimits/

Next Steps

Quick Start

Get Shipyard running locally in minutes

K8s Scheduler

Multi-tenant deployment platform

Terraform Modules

Reusable infrastructure modules

Infrastructure Guide

Deploy the full stack on AWS

Build docs developers (and LLMs) love