Architecture
Architecture
Section titled “Architecture”ShipSquares is a lean, AI-native, multi-tenant deploy platform. It runs well on a single small server, with no external managed services required.
The stack
Section titled “The stack”Control plane ....... Node.js / TypeScript, Fastify, REST + OpenAPI, WebSocketDatabase ............ PostgreSQL + Drizzle ORM (native)Queue / schedules ... pg-boss (on Postgres) (no extra broker)Auth ................ better-auth + an RBAC policy layerEdge / SSL .......... Caddy (native; pluggable driver)Workloads ........... Docker + docker compose (local socket / over SSH)MCP ................. Model Context Protocol server (streamable HTTP)Web ................. React + Vite + TailwindMobile .............. native Swift/SwiftUI + Kotlin/ComposeNative vs. Docker
Section titled “Native vs. Docker”ShipSquares splits infrastructure from workloads:
- Native (systemd) — infrastructure: Caddy, the control-plane PostgreSQL, and the
control plane itself. OS-managed, own
:80/:443, standard backups, and they survive a Docker restart. - Docker — workloads: every deployed app and its accessory databases (per-app Postgres/MySQL/Mongo) — isolated, version-pinned, disposable.
- No extra broker: pg-boss (queue) + Postgres
LISTEN/NOTIFY+ in-process events keep the queue and pub/sub in Postgres itself.
Components
Section titled “Components” ┌──────────────── Control server (native base) ────────────────┐push/MCP │ Caddy (:80/:443) → Control plane (Node/TS) │web/app │ ├─ REST API + OpenAPI + WebSocket │ │ ├─ MCP server │ │ ├─ deploy engine → docker.sock (local) │ │ └─ pg-boss queue │ │ PostgreSQL (single source of truth) │ │ Docker: [apps] [app DBs] │ └─────────────────────────────┬────────────────────────────────┘ │ SSH (agentless) ┌──────────────────────────────▼──── Added VM ────────────────┐ │ Caddy (native) + Docker: [apps] — stateless Docker host │ └──────────────────────────────────────────────────────────────┘Reverse proxy & SSL
Section titled “Reverse proxy & SSL”The control plane drives Caddy through its admin API: when an app or domain is added, it writes a route plus a TLS policy, and Caddy issues and renews the certificate automatically — including on-demand TLS for customer custom domains. The proxy is a pluggable driver (Caddy by default; Traefik / nginx alternates) so advanced users can swap it.
API, MCP & mobile
Section titled “API, MCP & mobile”- REST + OpenAPI — orgs, teams, members, servers, apps, domains, env/secrets, deployments, logs, webhooks, and API keys. One OpenAPI spec generates the clients for web, iOS, Android, and the MCP server.
- MCP server — exposes tools (
deploy_app,rollback,get_status,tail_logs,set_env,add_domain,list_apps, …) over streamable HTTP with API-key auth, all audited — so “ship it” is something an AI agent can do. - Mobile — native iOS + Android built on the same OpenAPI client, with push for deploy status and a WebSocket for live logs.
Deploy flow (per push)
Section titled “Deploy flow (per push)”- git push → webhook (HMAC-verified) hits the control plane.
- Resolve repo + branch → app → target server.
- Build & run — locally via the Docker socket, or remotely over SSH →
docker compose; pre-up hooks (e.g. migrations) run first. - Route — write the domain → container into that server’s Caddy; the certificate is issued automatically.
- Stream & record — live logs over WebSocket; the deployment and its steps are persisted; you get a push/web notification.
Install model
Section titled “Install model”- Control server: one command installs Caddy + PostgreSQL + the control plane as systemd units and creates the first owner account. See Installation.
- Add a server: enter an SSH host/key in the UI and the platform installs Docker + Caddy on the remote VM — agentlessly.
Security
Section titled “Security”Every action is RBAC-checked, secrets are sealed and never logged, and only the webhook endpoint is internet-facing beyond the proxy. See Security for the full model.