docs: ADR 0022 hosting on DigitalOcean (WeOwn Cloud)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SdXCbrN5PtGExkpvMaMHx
This commit is contained in:
@@ -50,6 +50,7 @@ The `.agents/skills/` directory is a family of rigor skills modeled on Cursor's
|
|||||||
- Frontend: Next.js (App Router) + React + TypeScript. Server layer holds tokens; browser gets a session cookie only (ADR 0018). Existing Vite shell is being migrated.
|
- Frontend: Next.js (App Router) + React + TypeScript. Server layer holds tokens; browser gets a session cookie only (ADR 0018). Existing Vite shell is being migrated.
|
||||||
- Sign-in: emailed 8-character code, emailed link and passkeys (ADR 0019)
|
- Sign-in: emailed 8-character code, emailed link and passkeys (ADR 0019)
|
||||||
- Cloud sites: provisioned on WeOwn Cloud behind the platform interface (ADR 0020)
|
- Cloud sites: provisioned on WeOwn Cloud behind the platform interface (ADR 0020)
|
||||||
|
- Hosting: DigitalOcean for Wursor and WeOwn Cloud, one VPC per plane, Terraform (ADR 0022)
|
||||||
- Direction: see PRD.md (Headless, revision 4) and IMPLEMENTATION.md section 0
|
- Direction: see PRD.md (Headless, revision 4) and IMPLEMENTATION.md section 0
|
||||||
- Sandboxes: Docker on VPS, pre-baked WordPress image, overlayfs layers, media proxied (not copied)
|
- Sandboxes: Docker on VPS, pre-baked WordPress image, overlayfs layers, media proxied (not copied)
|
||||||
- Plugin: standard WordPress PHP plugin, REST API + token auth
|
- Plugin: standard WordPress PHP plugin, REST API + token auth
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ The project is pre-1.0. Versions below `1.0.0` are internal milestones, not publ
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- ADRs 0018 to 0021: Next.js web app (partly supersedes ADR 0011), sign-in by code, link and passkeys, Cloud provisioning on WeOwn Cloud, and keeping the "never sees a diff" rule wording. PRD, IMPLEMENTATION and AGENTS.md updated to match.
|
- ADRs 0018 to 0022 (0022: hosting on DigitalOcean): Next.js web app (partly supersedes ADR 0011), sign-in by code, link and passkeys, Cloud provisioning on WeOwn Cloud, and keeping the "never sees a diff" rule wording. PRD, IMPLEMENTATION and AGENTS.md updated to match.
|
||||||
- `docs/prd-assets/headless-architecture.png`, the architecture diagram used in the PRD.
|
- `docs/prd-assets/headless-architecture.png`, the architecture diagram used in the PRD.
|
||||||
- Design reference: Figma file "Wursor - Experiment" (Design system, Product Design, Marketing site and Brand Guideline pages).
|
- Design reference: Figma file "Wursor - Experiment" (Design system, Product Design, Marketing site and Brand Guideline pages).
|
||||||
- **Monorepo workspace** — `pnpm` workspace (`api`, `web`, `e2e`), root `package.json` / `pnpm-workspace.yaml` / `tsconfig.base.json`, and a PHP `plugin` package (`composer.json`). Empty packages by design (see [ADR 8](docs/decisions/0008-empty-packages-not-stubs.md)).
|
- **Monorepo workspace** — `pnpm` workspace (`api`, `web`, `e2e`), root `package.json` / `pnpm-workspace.yaml` / `tsconfig.base.json`, and a PHP `plugin` package (`composer.json`). Empty packages by design (see [ADR 8](docs/decisions/0008-empty-packages-not-stubs.md)).
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# 22. Wursor and WeOwn Cloud run on DigitalOcean
|
||||||
|
|
||||||
|
- **Status:** Accepted for the platform choice. The service-level picks below are recommendations to confirm in the infrastructure spike (see Consequences).
|
||||||
|
- **Date:** 2026-10-12
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
[ADR 0020](0020-weown-cloud-provisioning.md) puts Cloud sites on WeOwn Cloud, and WeOwn uses DigitalOcean. Wursor itself will be hosted there too. The PRD describes three separate environments that must not share a network trust boundary: the control plane (Next.js app, Wursor API, Conductor, identity), the execution plane (sandboxes, verification workers, evidence store) and the hosting plane (Cloud sites). The existing infrastructure brief ([DEVOPS.md](../../infrastructure/DEVOPS.md)) assumes a single Docker VPS and a Vite static web build, and `infrastructure/terraform/` is empty.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Host all three planes on **DigitalOcean**, each in its own VPC, defined as code with **Terraform** (DigitalOcean provider) in `infrastructure/terraform/`.
|
||||||
|
|
||||||
|
Recommended mapping:
|
||||||
|
|
||||||
|
| Need | DigitalOcean product | Why |
|
||||||
|
|---|---|---|
|
||||||
|
| Next.js app, Wursor API, Conductor | App Platform (containers) if its streaming and timeout limits fit the run stream; otherwise Droplets or DOKS | Managed TLS, deploys from the container registry, small ops load. |
|
||||||
|
| Wursor database | Managed PostgreSQL with point-in-time recovery | PRD section 21 requires PITR and 15-minute backups, and a quarterly restore drill. |
|
||||||
|
| Queue and cache | Managed Redis or Valkey | Event queue and short caches. |
|
||||||
|
| Evidence store, site archives, backups | Spaces (S3-compatible) with versioning, private by default | Signed expiring links for evidence and archive downloads. |
|
||||||
|
| Sandboxes (execution plane) | Droplets running Docker, in a separate VPC | Matches the existing `DockerodeClient`, warm pool and GC. |
|
||||||
|
| Cloud sites (hosting plane) | Droplets (or DOKS) in a separate VPC, one isolated container per site, own database credentials and file space | PRD SH-14 and the Cloud isolation rows in section 18.1. |
|
||||||
|
| Images | Container Registry | Base WordPress image and service images. |
|
||||||
|
| DNS, domains, certificates | DigitalOcean DNS plus automated certificates (for example Caddy with on-demand TLS) for customer domains | SH-12 needs certificates issued as customers connect domains. |
|
||||||
|
| Preview origin | Wildcard certificate on a separate registrable domain behind a load balancer | PRD requires previews on a different site from the app (SB-02). |
|
||||||
|
|
||||||
|
Network rules: the hosting plane has no inbound path to the Wursor API. Sandboxes have deny-by-default egress through a proxy (SB-03). Only the Conductor reaches the hosting plane, with a service token.
|
||||||
|
|
||||||
|
### Options considered
|
||||||
|
|
||||||
|
- **DigitalOcean (chosen).** WeOwn's existing provider, so no new vendor or contract, and the existing Docker and `dockerode` work carries over.
|
||||||
|
- **Another cloud for Wursor, DigitalOcean only for Cloud sites.** More capability, but two clouds to run for a small team.
|
||||||
|
|
||||||
|
### Rejected
|
||||||
|
|
||||||
|
- Another cloud for the control plane: adds a second provider with no stated need.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- [DEVOPS.md](../../infrastructure/DEVOPS.md) is out of date: it describes React + Vite and a single VPS. Update it after the spike.
|
||||||
|
- Confirm these before building on them, each as a short written result in `spikes/`:
|
||||||
|
1. Whether App Platform supports the long-lived run stream (HTTP timeouts, resume after reconnect), or the Conductor needs Droplets or DOKS.
|
||||||
|
2. The isolation level achievable for Cloud sites on Droplets. The PRD's open choice is container versus microVM. Do not assume a microVM runtime is available on Droplets; test it, and treat container hardening plus a cross-site isolation test in CI as the baseline.
|
||||||
|
3. Customer-domain certificate issuance at the expected volume.
|
||||||
|
4. Backup and restore: daily verified restores of Cloud sites, 30-day retention, a backup before every change (SH-04, SH-14).
|
||||||
|
5. Cost per Cloud site and per sandbox, to inform plans and pricing (D-HL-8).
|
||||||
|
- WeOwn operations staffing (on-call, patching to the 72-hour target, abuse handling) is a readiness item from ADR 0020, not something DigitalOcean removes.
|
||||||
|
- Secrets live in the platform secret store and the Terraform state is stored in a private Spaces bucket with locking; never in the repo.
|
||||||
|
- Terraform plans run in CI against a staging project. Nothing is applied to production from a developer machine.
|
||||||
@@ -35,6 +35,7 @@ Each ADR is a single file following the [Nygard format](https://cognitect.com/bl
|
|||||||
| [0019](0019-sign-in-methods.md) | Sign-in supports an emailed code, an emailed link and passkeys | Accepted |
|
| [0019](0019-sign-in-methods.md) | Sign-in supports an emailed code, an emailed link and passkeys | Accepted |
|
||||||
| [0020](0020-weown-cloud-provisioning.md) | Cloud sites are provisioned on WeOwn Cloud | Accepted |
|
| [0020](0020-weown-cloud-provisioning.md) | Cloud sites are provisioned on WeOwn Cloud | Accepted |
|
||||||
| [0021](0021-keep-no-diff-rule-wording.md) | Keep the "never sees a diff" rule in AGENTS.md as written | Accepted |
|
| [0021](0021-keep-no-diff-rule-wording.md) | Keep the "never sees a diff" rule in AGENTS.md as written | Accepted |
|
||||||
|
| [0022](0022-digitalocean-hosting.md) | Wursor and WeOwn Cloud run on DigitalOcean | Accepted (service picks to confirm) |
|
||||||
|
|
||||||
## How to add one
|
## How to add one
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user