From f4559e96dd22132b00ed5ed54aaf60078de7a6a9 Mon Sep 17 00:00:00 2001 From: Defang SAM Agent Date: Fri, 14 Aug 2026 22:15:52 +0000 Subject: [PATCH] feat(deploy): add Defang (BYOC) deployment bundle Deploy a Buzz relay to your own cloud (AWS/GCP/Azure/DigitalOcean) with Defang, using managed Postgres/Redis + external object storage instead of the bundled containers, so no persistent volumes are required. --- deploy/defang/README.md | 84 +++++++++++++++++++++++ deploy/defang/compose.yaml | 132 +++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 deploy/defang/README.md create mode 100644 deploy/defang/compose.yaml diff --git a/deploy/defang/README.md b/deploy/defang/README.md new file mode 100644 index 00000000000..d2e66048ad3 --- /dev/null +++ b/deploy/defang/README.md @@ -0,0 +1,84 @@ +# Deploy Buzz to your own cloud with Defang + +This bundle deploys a Buzz relay to **your** cloud account (AWS, GCP, Azure, or +DigitalOcean) using [Defang](https://defang.io) — a Docker-Compose-compatible +"bring your own cloud" deployment. It's the managed-services counterpart to the +single-node [`deploy/compose`](../compose/) bundle. + +## Why a separate bundle + +The VPS bundle runs Postgres, Redis, and MinIO as containers with persistent +volumes. Defang runs each service as a managed cloud primitive instead, which +means **no persistent volumes are required** — Buzz's durable git state is +object-store-backed, so the relay keeps no local state. + +| Dependency | VPS (`deploy/compose`) | Defang (`deploy/defang`) | +|---|---|---| +| Database | `postgres` container + volume | managed Postgres (`x-defang-postgres`, e.g. RDS) | +| Cache/pubsub | `redis` container + volume | managed Redis (`x-defang-redis`, e.g. ElastiCache) | +| Object storage | `minio` + volume | your cloud's S3-compatible store (external S3) | +| TLS | Caddy | Defang load balancer + auto-cert | + +## Prerequisites + +- The [Defang CLI](https://docs.defang.io/docs/getting-started/installation) and + cloud credentials for your provider (e.g. `AWS_ACCESS_KEY_ID` / + `AWS_SECRET_ACCESS_KEY` for AWS). +- An S3-compatible bucket in your account for media + git objects, and + credentials scoped to it. (Defang doesn't yet provision object storage, so + create the bucket out-of-band.) + +## Configure + +Generate stable secrets and set every value with `defang config set`: + +```bash +cd deploy/defang + +# stable secrets (generate once, keep safe) +defang config set BUZZ_RELAY_PRIVATE_KEY # 64-char hex +defang config set BUZZ_GIT_HOOK_HMAC_SECRET # 32+ random chars +defang config set POSTGRES_PASSWORD # also used by managed Postgres +defang config set DATABASE_URL # postgres://buzz:@postgres:5432/buzz?sslmode=require + +# owner identity (64-char hex Nostr pubkey) +defang config set RELAY_OWNER_PUBKEY + +# object storage (AWS example) +defang config set BUZZ_S3_ENDPOINT # https://s3..amazonaws.com +defang config set BUZZ_S3_REGION # e.g. us-east-1 +defang config set BUZZ_S3_BUCKET +defang config set BUZZ_S3_ACCESS_KEY +defang config set BUZZ_S3_SECRET_KEY + +# public URL (set to your custom domain, or fill in after the first deploy with +# the Defang-assigned *.defang.app URL, then redeploy — do this before members join) +defang config set RELAY_URL # wss:// +defang config set BUZZ_DOMAIN # +defang config set BUZZ_MEDIA_BASE_URL # https:///media +defang config set BUZZ_MEDIA_SERVER_DOMAIN # +defang config set BUZZ_CORS_ORIGINS # https:// +``` + +## Deploy + +```bash +defang compose up +``` + +Defang provisions the managed database, cache, load balancer, and TLS cert, then +starts the relay. The first deploy prints the public URL. If you're using the +auto-assigned `*.defang.app` domain, set the `RELAY_URL`/`BUZZ_*` URL values to +it and redeploy once — before adding members, since the relay URL selects the +community. + +## Notes + +- The managed database/cache are reached over their compose **service names** + (`postgres`, `redis`); Defang wires those to the managed endpoints. +- Managed Redis is reached in-VPC without a password (`redis://redis:6379`). +- The load-balancer health check targets `/_liveness` on port 3000 (served by the + relay, no auth). The Buzz image ships no `curl`, so the healthcheck falls back + to a bash `/dev/tcp` probe for the in-container check. +- Back up `BUZZ_RELAY_PRIVATE_KEY`, your owner key, the database, and the object + store; the relay identity key is your community's identity. diff --git a/deploy/defang/compose.yaml b/deploy/defang/compose.yaml new file mode 100644 index 00000000000..eba88df18ae --- /dev/null +++ b/deploy/defang/compose.yaml @@ -0,0 +1,132 @@ +name: buzz-relay + +# Deploy a Buzz relay to your own cloud (AWS / GCP / Azure / DigitalOcean) with +# Defang (https://defang.io) — a Docker-Compose-compatible BYOC deployment that +# runs entirely in your cloud account. +# +# How this differs from deploy/compose (single-node / VPS): +# * postgres -> Defang managed database (x-defang-postgres; e.g. RDS on AWS) +# * redis -> Defang managed cache (x-defang-redis; e.g. ElastiCache) +# * minio -> your cloud's object store (real S3/GCS/etc. via Buzz's native +# external-S3 support) +# * no volumes: Buzz's durable git state is object-store-backed, so the relay +# keeps no persistent local state and needs no volumes. +# * caddy/TLS -> Defang's load balancer terminates TLS and gives the relay a +# public HTTPS/WSS URL automatically. +# +# One-time setup (values are stored encrypted, injected at runtime): +# defang config set RELAY_OWNER_PUBKEY BUZZ_RELAY_PRIVATE_KEY \ +# BUZZ_GIT_HOOK_HMAC_SECRET POSTGRES_PASSWORD DATABASE_URL \ +# BUZZ_S3_ENDPOINT BUZZ_S3_REGION BUZZ_S3_BUCKET \ +# BUZZ_S3_ACCESS_KEY BUZZ_S3_SECRET_KEY \ +# RELAY_URL BUZZ_DOMAIN BUZZ_MEDIA_BASE_URL BUZZ_MEDIA_SERVER_DOMAIN \ +# BUZZ_CORS_ORIGINS +# then: defang compose up +# +# See deploy/defang/README.md for the full walkthrough. + +services: + relay: + image: ${BUZZ_IMAGE:-ghcr.io/block/buzz:main} + restart: unless-stopped + ports: + - mode: ingress + target: 3000 + published: 3000 + environment: + BUZZ_BIND_ADDR: 0.0.0.0:3000 + BUZZ_HEALTH_PORT: "8080" + BUZZ_METRICS_PORT: "9102" + + # Closed community relay (owner + members). + BUZZ_REQUIRE_AUTH_TOKEN: "true" + BUZZ_REQUIRE_RELAY_MEMBERSHIP: "true" + BUZZ_ALLOW_NIP_OA_AUTH: "true" + BUZZ_AUTO_MIGRATE: "true" + BUZZ_GIT_CONFORMANCE_PROBE: "true" + RUST_LOG: "buzz_relay=info,buzz_db=info,buzz_auth=info,buzz_pubsub=info,tower_http=info" + + # Managed cache (ElastiCache/etc.) — reachable in-VPC on the service name. + REDIS_URL: redis://redis:6379 + + BUZZ_S3_ADDRESSING_STYLE: virtual + BUZZ_GIT_REPO_PATH: /data/git + + # ---- injected from `defang config` (blank = supplied at deploy time) ---- + # Public URL / identity. + RELAY_URL: + BUZZ_DOMAIN: + BUZZ_MEDIA_BASE_URL: + BUZZ_MEDIA_SERVER_DOMAIN: + BUZZ_CORS_ORIGINS: + # Owner + stable relay secrets. + RELAY_OWNER_PUBKEY: + BUZZ_RELAY_PRIVATE_KEY: + BUZZ_GIT_HOOK_HMAC_SECRET: + # Managed database connection string (contains the DB password). + DATABASE_URL: + # Object storage (e.g. AWS S3: BUZZ_S3_ENDPOINT=https://s3..amazonaws.com). + BUZZ_S3_ENDPOINT: + BUZZ_S3_REGION: + BUZZ_S3_BUCKET: + BUZZ_S3_ACCESS_KEY: + BUZZ_S3_SECRET_KEY: + healthcheck: + # Defang configures the load-balancer health check from this URL. The relay + # serves /_liveness on the main port 3000 (no auth). The runtime image has + # no curl, so an equivalent bash /dev/tcp probe runs the in-container check. + test: + - CMD-SHELL + - "curl -fsS http://localhost:3000/_liveness || bash -c 'exec 3<>/dev/tcp/127.0.0.1/3000; printf \"GET /_liveness HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n\" >&3; grep -q \"200 OK\" <&3'" + interval: 10s + timeout: 5s + retries: 12 + start_period: 40s + deploy: + resources: + reservations: + cpus: "0.5" + memory: 1024M + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + + postgres: + image: postgres:17 + x-defang-postgres: true + restart: unless-stopped + ports: + - mode: host + target: 5432 + environment: + POSTGRES_USER: buzz + POSTGRES_DB: buzz + POSTGRES_PASSWORD: + healthcheck: + test: ["CMD-SHELL", "pg_isready -U buzz -d buzz"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 20s + deploy: + resources: + reservations: + cpus: "0.5" + memory: 1024M + + redis: + # Defang derives the managed-cache engine version from the image tag; use + # . (a bare "7" is rejected by ElastiCache). + image: redis:7.1 + x-defang-redis: true + restart: unless-stopped + ports: + - mode: host + target: 6379 + deploy: + resources: + reservations: + cpus: "0.25" + memory: 512M