Skip to content
Docs
opendesk.shOpen app

Domains, AWS and Cloudflare

How the hosted opendesk service is laid out across domains, AWS, Cloudflare and Neon.

The hosted service at opendesk.sh runs the same code as a self-hosted install, split into roles and spread across managed infrastructure. The infrastructure is defined in Terraform in deploy/terraform.

Domain Serves Runs on
opendesk.sh Marketing site and install.sh Cloudflare Pages
docs.opendesk.sh This documentation Cloudflare Pages
app.opendesk.sh The web app, help center, widget/v1.js, config.json for the native apps and the iPhone app’s apple-app-site-association Cloudflare Pages
api.opendesk.sh The REST API, /docs and /v1/openapi.json AWS ECS behind an ALB
gateway.opendesk.sh The realtime gateway (/socket) AWS ECS behind the same ALB
in.opendesk.sh Forwarding addresses (<token>@in.opendesk.sh) Cloudflare Email Routing and an Email Worker
The hosted service. Browsers and apps load the web app from Cloudflare Pages and reach the API and the realtime gateway through Cloudflare and an AWS load balancer. On AWS, ECS Fargate runs the api, gateway and worker services; workers publish events to a three-node NATS cluster, which the gateways subscribe to. The api uses Neon through the pooled host, the worker through the direct host. Cloudflare Email Routing and an Email Worker receive forwarded mail and post it to the API. S3, SES and Secrets Manager serve the api and workers.CloudflareAWSBrowsersand the appsMail sendersto <token>@in…Pagesapp.opendesk.sh,staticDNS and edgeapi. and gateway.Email Routingin.opendesk.sh,then the EmailWorkerALBTLS from ACMapiECS Fargate, the REST APIgatewayECS Fargate, PhoenixNATSthree-node JetStream clusterworkerECS Fargate, relay and jobsS3attachmentsSESplatform emailSecrets Managerand KMSNeon Postgrespooled and direct hostspublishsubscribeposts mailpooleddirect
The same code as a self-host, split into roles: api, worker and gateway scale on their own.
  • ECS Fargate runs the opendesk API (OPENDESK_ROLE=api), workers (OPENDESK_ROLE=worker) and the realtime gateway as separate services, each scaled independently.
  • NATS runs as a three-node JetStream cluster on ECS. Every API, worker and gateway task connects to it.
  • An Application Load Balancer terminates TLS for the API and gateway, with certificates from ACM.
  • S3 stores attachments and raw email, in a private bucket. Downloads use short-lived signed URLs.
  • SES sends platform email (verification, password reset, invitations) with DKIM, a custom MAIL FROM domain and DMARC.
  • Secrets Manager and KMS hold every secret; tasks receive them at start.
  • Deployments use short-lived credentials through GitHub OIDC. Images are immutable and tagged by commit.
  • DNS and zone security settings for every domain.
  • Pages hosts the site, docs and web app as static builds.
  • Email Routing receives all mail for in.opendesk.sh with a catch-all rule and hands each message to the Email Worker, which posts it to POST /v1/inbound/email with a shared secret. If the API is unavailable, the worker reports a temporary failure so the sending server retries later.

Postgres runs on PlanetScale in the same AWS region, and the services reach it only over AWS PrivateLink: database traffic never crosses the public internet, and the database accepts no connections from outside private networks. Request handlers go through PgBouncer; background jobs and the event relay use a direct connection, because they need session features such as LISTEN/NOTIFY.

The services connect with a role that reads and writes data but cannot change the schema. Only the migration step, run once per deploy, uses a role that can. opendesk uses no PlanetScale-only features, so the same code runs on stock Postgres.

The events catalog draws this path, including how a private team’s events are kept to that team.

  1. An agent’s request writes the change and an event in one Postgres transaction.
  2. A worker’s event relay publishes the event to NATS on od.events.<workspace_id>.
  3. Every gateway node pushes it to the browsers subscribed to that workspace.
  4. The relay also queues webhook deliveries.

Edit this page on GitHub