diff --git a/render.yaml b/render.yaml index 4eed941..3a44f2e 100644 --- a/render.yaml +++ b/render.yaml @@ -1,25 +1,42 @@ # Render Blueprint (#340) for a single-service PARTHA deployment: one web # service (FastAPI serving both the API and the built frontend, per #339), -# one PostgreSQL database, one persistent disk for cloned/uploaded -# repositories. Docker-based rather than Render's native Python runtime, -# because the build needs Node to build the frontend before the Python -# service ever starts -- see ./Dockerfile. +# one persistent disk for cloned/uploaded repositories, and PostgreSQL +# brought in from an external provider (Neon) rather than Render's own +# managed database -- Render's free Postgres expires after 90 days; Neon's +# free tier does not. Docker-based rather than Render's native Python +# runtime, because the build needs Node to build the frontend before the +# Python service ever starts -- see ./Dockerfile. # # Before deploying from this blueprint: -# 1. Choose a plan for both the web service and the database in Render's -# dashboard when you create them -- this file intentionally doesn't -# pin one, since pricing/plan names change and that's a cost decision, -# not an engineering one. The web service's plan must support a -# persistent disk (the free tier does not). -# 2. After the service exists, set AI_ENCRYPTION_KEY manually in the -# Render dashboard (Environment tab) -- generate it with: +# 1. Choose a plan for the web service in Render's dashboard when you +# create it -- this file intentionally doesn't pin one, since +# pricing/plan names change and that's a cost decision, not an +# engineering one. IMPORTANT: this service has a persistent disk +# (below), and Render's free web-service tier does not support +# persistent disks at all (confirmed directly against Render's own +# docs) -- a free-tier deploy of this blueprint as-is will not get to +# keep the disk. That's a real product decision (accept a paid tier to +# keep durable repository storage, or accept ephemeral/ non-persistent +# storage on the free tier), not something to resolve by editing this +# comment -- see the PR/issue discussion for the current status. +# 2. Create a project in Neon (or your Postgres provider of choice) and +# set DATABASE_URL manually in the Render dashboard (Environment tab) +# to its connection string. It is marked `sync: false` below for the +# same reason AI_ENCRYPTION_KEY is: there is nothing here for Render +# to generate or provision -- the value comes from outside Render +# entirely. app.core.config normalizes a bare postgres:// or +# postgresql:// scheme (what Neon and most managed providers hand +# back) to postgresql+psycopg:// itself, so Neon's connection string +# can be pasted in as-is, query parameters (e.g. ?sslmode=require) +# included. +# 3. Set AI_ENCRYPTION_KEY manually in the same tab -- generate it with: # python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" # It is marked `sync: false` below on purpose: Render's generic # generateValue only produces a random string, not the specific # URL-safe-base64-of-32-bytes shape a Fernet key requires. -# 3. AUTH_SECRET_KEY is auto-generated by Render (`generateValue: true`) +# 4. AUTH_SECRET_KEY is auto-generated by Render (`generateValue: true`) # and needs no manual step. -# 4. Update CORS_ORIGINS below if the public domain changes from +# 5. Update CORS_ORIGINS below if the public domain changes from # www.partha.uk. # # Database migrations run as part of the container's own startup command @@ -40,9 +57,7 @@ services: - key: LOG_FORMAT value: json - key: DATABASE_URL - fromDatabase: - name: partha-db - property: connectionString + sync: false - key: STORAGE_PATH value: /var/data/storage - key: CORS_ORIGINS @@ -55,7 +70,3 @@ services: name: partha-storage mountPath: /var/data sizeGB: 5 - -databases: - - name: partha-db - postgresMajorVersion: "16"