mirror of
https://github.com/runbear-io/beardrive.git
synced 2026-08-25 08:08:08 +02:00
Add a CGO-free static Dockerfile (distroless) and a one-shot Cloud Run deploy recipe (deploy/gcp-cloudrun.sh + README): single-instance hub on Cloud Run, metadata in Cloud SQL Postgres (the new `database` backend), blobs/journals in a GCS bucket, config + DB password in Secret Manager, least-privilege runtime service account. Pinned to max-instances=1 (the current build assumes one writer). Verified end to end against a live deployment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7Q9ZKSZRTdvrSJkYLUmYs
91 lines
3.8 KiB
Markdown
91 lines
3.8 KiB
Markdown
# Deploy BearDrive to Google Cloud (Cloud Run)
|
||
|
||
Single-instance hub on **Cloud Run**, metadata in **Cloud SQL Postgres**,
|
||
blobs/journals in a **GCS bucket**. Matches Phase 0 of the managed PRD.
|
||
|
||
> The current build is single-process: Cloud Run is pinned to
|
||
> `max-instances=1` because the in-memory caches assume one writer. Do **not**
|
||
> raise it until the "stateless app" work (PRD §5.1) lands.
|
||
|
||
## Architecture
|
||
|
||
```
|
||
browser / bdrive CLI
|
||
│ https
|
||
┌─────▼─────┐ metadata ┌──────────────┐
|
||
│ Cloud Run │◀────────────▶│ Cloud SQL │ (accounts, orgs,
|
||
│ bdrive │ unix socket │ Postgres │ projects, invites…)
|
||
│ (1 inst.) │ └──────────────┘
|
||
└─────┬─────┘
|
||
│ ADC (runtime SA)
|
||
┌─────▼─────┐
|
||
│ GCS │ blobs/ + journal/ (file content + sync log)
|
||
└───────────┘
|
||
```
|
||
|
||
## Prerequisites
|
||
|
||
- `gcloud` installed and logged in (`gcloud auth login`).
|
||
- A **billing account** id (`gcloud billing accounts list`) if the script
|
||
creates the project.
|
||
- Values: `PROJECT_ID`, `ADMIN_EMAIL`, `ADMIN_DOMAIN` (the rest have defaults).
|
||
|
||
## Run it
|
||
|
||
From the repo root:
|
||
|
||
```sh
|
||
PROJECT_ID=beardrive-prod \
|
||
BILLING_ACCOUNT=0X0X0X-0X0X0X-0X0X0X \
|
||
ADMIN_EMAIL=you@runbear.io \
|
||
ADMIN_DOMAIN=runbear.io \
|
||
REGION=us-central1 \
|
||
bash example/deploy/gcp-cloudrun.sh
|
||
```
|
||
|
||
The script: creates/links the project → enables APIs → creates the GCS bucket
|
||
and Cloud SQL instance → generates a DB password (stored in Secret Manager) →
|
||
writes the hub config to a secret → builds the image from the repo `Dockerfile`
|
||
via Cloud Build → deploys Cloud Run with the Cloud SQL socket, the config
|
||
secret mounted at `/config/config.json`, and a dedicated runtime service
|
||
account granted GCS + Cloud SQL access. It prints the service URL.
|
||
|
||
## First-run: bootstrap the admin, then lock down
|
||
|
||
The hub ships **invite-only by default**, but a brand-new hub has no accounts,
|
||
so the deploy config temporarily allows **domain-gated self-signup**
|
||
(`allowed_domains: [ADMIN_DOMAIN]`). Steps:
|
||
|
||
1. Open the printed URL → **Sign up** as `ADMIN_EMAIL` (must be on
|
||
`ADMIN_DOMAIN`). The account is active immediately and is a hub admin.
|
||
2. Create your org/projects and invite teammates from the UI.
|
||
3. **Tighten to invite-only:** edit the config secret to `"allow_signup": false`
|
||
and redeploy:
|
||
```sh
|
||
gcloud secrets versions access latest --secret bdrive-config > /tmp/c.json
|
||
# …set "allow_signup": false …
|
||
gcloud secrets versions add bdrive-config --data-file=/tmp/c.json
|
||
gcloud run services update bdrive --region "$REGION" # picks up latest secret
|
||
```
|
||
|
||
## Rough cost
|
||
|
||
- **Cloud Run**: scales to ~zero when idle (min-instances=1 keeps one warm;
|
||
set `--min-instances 0` to save more, at the cost of cold-start journal
|
||
folding on first hit). ~$5–15/mo warm.
|
||
- **Cloud SQL** `db-f1-micro`: ~$8–15/mo (smallest shared-core tier).
|
||
- **GCS**: pay per GB stored + egress. Cheap for text; consider a lifecycle
|
||
policy later.
|
||
|
||
## Notes / limits (single-instance build)
|
||
|
||
- `max-instances=1` is required. Metadata correctness depends on one writer.
|
||
- `BDRIVE_HOME=/tmp` is ephemeral on Cloud Run → the server's own device id
|
||
regenerates on cold start (cosmetic in history). Mount a volume later to
|
||
persist it.
|
||
- Large **downloads/sync** stream through Cloud Run (bounded by the request
|
||
timeout, up to 60 min). Uploads go direct to storage when the backend can
|
||
presign. See PRD §5.2 for offloading these at scale.
|
||
- Put a custom domain on the service via `gcloud run domain-mappings` (gives
|
||
managed TLS).
|