disclosure-bureau/infra/coolify/SHARED.md

114 lines
3 KiB
Markdown
Raw Normal View History

# Coolify — Shared services (Meilisearch + Dragonfly + Imgproxy)
These are stateless or namespaceable — one instance can serve all your projects. Saves RAM.
## Meilisearch
Coolify → + New Service → Database → **Meilisearch**.
| Field | Value |
|---|---|
| Project name | `meilisearch-shared` |
| Domain | `search.disclosure.top` |
| Master key | (generate; copy for `MEILI_MASTER_KEY` env in web app) |
| Resource limits | 1 CPU, 1 GB RAM |
Each project uses different index names: `disclosure_pages`, `disclosure_entities`, `projeto_b_xxx` — no cross-talk.
After deploy, in the web app env vars:
```env
MEILISEARCH_URL=https://search.disclosure.top
MEILISEARCH_API_KEY=<master-key>
```
The web app will create + populate indexes on first deploy (see `web/scripts/seed-meili.ts`).
## Dragonfly
Redis-compatible, drop-in, 25× faster than Redis. Coolify has no template, use a custom Docker Compose service:
```yaml
# In Coolify → + New Resource → Service → Custom Docker Compose
services:
dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly:latest
restart: unless-stopped
ulimits:
memlock: -1
ports:
- "6379:6379"
volumes:
- dragonfly-data:/data
command: ["--logtostderr", "--cache_mode=true", "--maxmemory=512mb"]
mem_limit: 600m
volumes:
dragonfly-data:
```
Web app env:
```env
REDIS_URL=redis://dragonfly:6379
```
(Coolify networks the services internally; you reach `dragonfly:6379` from inside the network.)
## Imgproxy
Stateless image resizer:
```yaml
services:
imgproxy:
image: ghcr.io/imgproxy/imgproxy:latest
restart: unless-stopped
environment:
IMGPROXY_KEY: ${IMGPROXY_KEY}
IMGPROXY_SALT: ${IMGPROXY_SALT}
IMGPROXY_USE_ETAG: "true"
IMGPROXY_TTL: "31536000"
IMGPROXY_MAX_SRC_RESOLUTION: "50"
IMGPROXY_ENABLE_WEBP_DETECTION: "true"
IMGPROXY_LOCAL_FILESYSTEM_ROOT: "/data"
volumes:
- /data/ufo/processing:/data:ro
ports:
- "8080:8080"
mem_limit: 256m
```
Generate `IMGPROXY_KEY` and `IMGPROXY_SALT`:
```bash
openssl rand -hex 64 # → key
openssl rand -hex 64 # → salt
```
Add subdomain `img.disclosure.top` → :8080.
Web app uses signed URLs like:
```
https://img.disclosure.top/<signature>/rs:fit:800:0/plain/local:///png/doc-x/p-001.png
```
The `web/lib/imgproxy.ts` helper generates these signatures.
## Backups (restic + Backblaze B2)
Optional but strongly recommended. Coolify has a built-in backup feature per service:
1. Each Supabase project's stack → **Backups** → set schedule (e.g., `0 3 * * *` daily 3am).
2. Destination: configure B2 bucket in Coolify Settings → Backups (one-time setup).
Restic runs encrypted, deduplicated. ~$0.005/GB/mo on B2.
## Done
Stack complete:
- `disclosure.top` (Next.js)
- `db.disclosure.top` (Supabase Kong)
- `studio.disclosure.top` (Supabase Studio)
- `search.disclosure.top` (Meilisearch)
- `img.disclosure.top` (Imgproxy)
- `coolify.disclosure.top` (Coolify panel)
Total RAM in production: ~5-6 GB. Plenty of room for 2-3 more projects.