-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrender.yaml
More file actions
153 lines (151 loc) · 8.23 KB
/
Copy pathrender.yaml
File metadata and controls
153 lines (151 loc) · 8.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Render deployment configuration for OpenCheck.
#
# Two services:
# opencheck-api — FastAPI backend (Docker web service)
# opencheck — Vite/React frontend (static site)
#
# Deploy steps:
# 1. Push this repo to GitHub (or connect it to Render directly).
# 2. In Render dashboard → New → Blueprint, point at this repo.
# Render will create both services automatically.
# 3. Set the secret env vars below in the Render dashboard:
# COMPANIES_HOUSE_API_KEY
# OPENSANCTIONS_API_KEY
# OPENCORPORATES_API_KEY
# OPENALEPH_API_KEY (optional)
# 4. Once the backend service is deployed, copy its URL
# (e.g. https://api.opencheck.world) and set it as
# VITE_API_BASE_URL on the frontend static site, then trigger
# a redeploy of the frontend.
services:
# ------------------------------------------------------------------ #
# Backend — FastAPI served via uvicorn inside Docker #
# ------------------------------------------------------------------ #
- type: web
name: opencheck-api
env: docker
dockerfilePath: ./backend/Dockerfile
dockerContext: .
# Phase 180: the GLEIF mirror lives on a persistent disk (below), which
# Render offers on paid instance types only — the service has run on a
# 2 GB instance since the Phase 98 OOM work (/memstats reports a 2048 MB
# limit), so the plan here matches what the dashboard already runs.
# Confirm in the dashboard before syncing this Blueprint: a plan change
# here is a billing change.
plan: standard
healthCheckPath: /health
# --- Phase 180: persistent disk for the GLEIF mirror ---
# entity_pages.sqlite (~1.8 GB; the Phase 178 mirror) survives deploys and
# restarts here, so the backend stops re-downloading a ~0.9 GB asset on
# every boot and the in-process delta refresh (opencheck/mirror_refresh.py)
# has a file to keep current. Boot rule (opencheck/entity_pages.py):
# download the asset when the file is absent, replace it when the monthly
# rebuild published a newer one, otherwise use what is there. Trade-off
# per https://render.com/docs/disks: a service with a disk runs as a
# single instance and deploys are not zero-downtime (a few seconds).
# 10 GB leaves room for the download-and-rename (2 x 1.8 GB) and growth.
disk:
name: entity-pages
mountPath: /var/data
sizeGB: 10
envVars:
- key: OPENCHECK_ALLOW_LIVE
value: "true"
# Cap glibc malloc arenas. Long-running Python with threadpools
# (asyncio.to_thread for OG-card renders, SQLite reads, warm-ups)
# fragments per-thread malloc arenas, which shows up as RSS that climbs
# between traffic spikes and never returns — a contributor to the
# 2026-08-05/06 OOM restarts on the 512 MB instance. 2 is the standard
# container setting (same trade Heroku/Cloud Foundry ship by default):
# slightly more allocator contention, materially lower fragmentation.
- key: MALLOC_ARENA_MAX
value: "2"
# Allow all origins so the static frontend can call the API.
# Once the custom domain is live you can tighten this to the frontend
# origin: OPENCHECK_CORS_ORIGIN = https://opencheck.world
- key: OPENCHECK_CORS_ORIGIN
value: "*"
- key: WIKIDATA_SPARQL_ENDPOINT
value: https://query.wikidata.org/sparql
# --- Secret keys: set these in the Render dashboard, not here ---
- key: COMPANIES_HOUSE_API_KEY
sync: false
- key: OPENSANCTIONS_API_KEY
sync: false
- key: OPENCORPORATES_API_KEY
sync: false
- key: OPENALEPH_API_KEY
sync: false
# OpenFIGI — securities (ISIN) typing for the /securities endpoint.
# Optional: the endpoint works without it at a lower rate limit.
- key: OPENFIGI_API_KEY
sync: false
# --- Bulk-file adapters: stub-only on Render ---
# ARIREGISTER_DB_FILE and BCE_BELGIUM_DB_FILE are intentionally omitted.
# Both adapters return stub responses when no DB path is set.
# To activate locally, set these in .env pointing at the downloaded .db files.
# --- Phase 88: SEO entity pages ---
# URL of the prebuilt GLEIF-derived entity_pages.sqlite(.gz) (e.g. a
# GitHub Release asset from the monthly refresh). Downloaded at boot
# (Render's disk is ephemeral); /entity, /sitemaps and /browse answer
# 503 until it lands. Leave unset to disable entity pages entirely.
- key: OPENCHECK_ENTITY_PAGES_DB_URL
sync: false
# Phase 180: with the disk mounted, the file lives here. Both set = the
# persistent-disk arrangement described above; unset this (keeping the
# URL) to fall back to the Phase 88 per-boot download into /tmp.
- key: OPENCHECK_ENTITY_PAGES_DB_FILE
value: /var/data/entity_pages.sqlite
# Phase 179/180: mirror-first stays OFF until the measurement gate on
# the Golden Copy ticket passes (read /mirror); flip it here when it does.
- key: OPENCHECK_GLEIF_MIRROR_FIRST
value: "false"
# --- Phase 186: the UK PSC graph ---
# psc_graph.sqlite (~2.2 GB) — every active Companies House PSC record,
# built daily from the register's own snapshot by refresh-psc-graph.yml
# and published as the psc-graph-latest release asset (the URL is the
# config default). Same boot rule as the mirror: download when absent,
# replace when the asset changed, keep otherwise; re-checked every six
# hours in-process so the daily seed lands without a deploy. Shares the
# disk above: mirror 1.8 GB + graph 2.2 GB + one replace in flight fits
# in 10 GB. Nothing walks it until OPENCHECK_CH_GRAPH_FIRST is flipped
# (Phase 188); until then the Companies House adapter walks live.
- key: OPENCHECK_PSC_GRAPH_DB_FILE
value: /var/data/psc_graph.sqlite
# Phase 187: the register's *streaming* key (a different credential
# from COMPANIES_HOUSE_API_KEY; one connection per key — bods-stream
# has its own). With the file above, the app holds one connection to
# the PSC stream and applies every change to the graph as it happens;
# unset, the graph stays as the daily seed left it.
- key: COMPANIES_HOUSE_STREAM_KEY
sync: false
# --- Phase 91: IndexNow (SEO Phase D) ---
# Shared key echoed back at /{key}.txt (root — IndexNow scopes a
# submission to the key file's directory) so IndexNow-participating
# engines can verify we own the host. MUST equal the INDEXNOW_KEY Actions
# secret used by refresh-entity-pages-db.yml — if the two drift apart the
# engines fetch the key file, see a mismatch, and reject the whole
# submission with a bare 403. Unset = key route 404s, submission no-ops.
- key: OPENCHECK_INDEXNOW_KEY
sync: false
# --- Phase 88 cutover switch (single-service mode) ---
# Render static-site rewrites CANNOT proxy /entity/* to this service
# (verified: https://render.com/docs/redirects-rewrites — rewrites are
# same-site only; redirects would index the api host instead). The
# cutover therefore serves the SPA from the backend: set this to
# /app/frontend_dist (baked into the Docker image), then point the
# opencheck.world custom domain at THIS service and retire the static
# site. Unset = split deploy unchanged, SPA not served from here.
# - key: OPENCHECK_FRONTEND_DIST
# value: /app/frontend_dist
# ------------------------------------------------------------------ #
# Frontend static site — RETIRED (Phase 88 single-service cutover) #
# #
# Since 2026-08-03 the SPA is served by opencheck-api itself #
# (OPENCHECK_FRONTEND_DIST=/app/frontend_dist, baked into the Docker #
# image) and the opencheck.world custom domain points at that #
# service — Render static-site rewrites cannot proxy /entity/* to #
# another service, which forced the single-service arrangement. #
# The old `opencheck` static site is suspended in the dashboard and #
# removed from this Blueprint so a future sync doesn't resurrect it. #
# ------------------------------------------------------------------ #