Despliegue en Coolify (Contabo)¶
Runbook corto para desplegar FarmAPI en el proyecto farmaestudio de Coolify usando el repo privado 686f6c61/farmapi.
Artefacto de despliegue¶
- fichero Compose:
docker-compose.coolify.yml - plantilla de variables:
.env.coolify.example
Qué levanta en Contabo¶
app: FastAPI pública + admin + docs in-appcoordinate-worker: reparación automática de coordenadasops-scheduler: sync diario + retry de territorios degradados + retry de webhookspostgres: base de datos propia de FarmAPIredis: rate limiting y soporte operativo
Ruta pública esperada¶
- dominio canónico:
https://estudioapi.com/farmapi - alias www:
https://www.estudioapi.com/farmapi - admin:
https://estudioapi.com/farmapi/admin - docs:
https://estudioapi.com/farmapi/docs/
Alta en Coolify¶
- Crear una nueva aplicación en el proyecto
farmaestudio, entornoproduction. - Elegir
Private GitHub App. - Repositorio:
686f6c61/farmapi. - Branch:
main. - Build pack:
Docker Compose. - Compose path:
docker-compose.coolify.yml. - Servicio público:
app. - Dominio/FQDN:
https://estudioapi.com/farmapihttps://www.estudioapi.com/farmapi
Variables mínimas obligatorias en Coolify¶
Base¶
FARMAAPI_ENV=prodAPP_BASE_PATH=/farmapiPUBLIC_EXAMPLE_BASE_URL=https://estudioapi.com/farmapiTRUSTED_HOSTS_CSV=estudioapi.com,www.estudioapi.comADMIN_ALLOWED_ORIGINS_CSV=https://estudioapi.com,https://www.estudioapi.comGITHUB_REDIRECT_URI=https://estudioapi.com/farmapi/auth/github/callbackTZ=Europe/MadridDOCKER_STARTUP_PREFLIGHT_MODE=prod
Seguridad¶
ADMIN_SESSION_SECRETADMIN_PII_ENCRYPTION_KEYADMIN_PII_HASH_PEPPERAPI_KEY_HASH_PEPPERINTERNAL_API_TOKEN
GitHub SSO¶
GITHUB_CLIENT_IDGITHUB_CLIENT_SECRET[email protected]
Geocoding¶
MAPS_GEOCODING_API_KEYMAPS_GEOCODING_ENABLED=trueOSM_GEOCODING_ENABLED=falseARCGIS_GEOCODING_ENABLED=true
Raw oficial¶
RAW_STORAGE_BACKEND=localRAW_LOCAL_DIR=/app/.local/rawRAW_BUCKET=
En Contabo/Coolify el raw oficial se guarda en el volumen persistente farmaapi_local. No uses RAW_STORAGE_BACKEND=gcs salvo que hayas montado credenciales ADC de GCP y un bucket real.
Resend¶
RESEND_API_KEYRESEND_FROM_EMAILRESEND_API_BASE_URL=https://api.resend.com[email protected]
Publicación al SaaS¶
SAAS_BASE_URL=https://estudioapi.com/farmapiSAAS_OAUTH_TOKEN_URL=https://estudioapi.com/farmapi/oauth/tokenSAAS_OAUTH_CLIENT_IDSAAS_OAUTH_CLIENT_SECRETSAAS_MOCK_MODE=false
Variables operativas recomendadas¶
SYNC_DAILY_LOCAL_TIME=03:00SYNC_RUN_MISSED_DAILY_ON_START=trueWEBHOOK_RETRY_INTERVAL_SECONDS=60WEBHOOK_RETRY_LIMIT=200DEGRADED_RETRY_INTERVAL_SECONDS=7200COORD_REPAIR_INTERVAL_SECONDS=60COORD_REPAIR_LIMIT=200COORD_REPAIR_INCLUDE_MISSING=trueSYNC_MAX_PARALLEL_TERRITORIES=4SYNC_MAX_PARALLEL_REGCESS_TERRITORIES=1
Nota importante¶
Con el guard de arranque actual, el contenedor no arrancará en prod si faltan:
- Resend real
- OAuth GitHub real
- credenciales reales del SaaS (
SAAS_MOCK_MODE=false)
Esto es intencionado: evita sacar a producción una instalación “a medias”.
DNS en Cloudflare¶
Usar el mismo patrón que farmaestudio.com:
A estudioapi.com -> 5.189.187.104A www.estudioapi.com -> 5.189.187.104proxied = truettl = 60
Cloudflare queda en modo SSL Full. El proxy de Cloudflare evita que www.estudioapi.com exponga certificados internos si Traefik tarda en renovar.
Verificacion tras cada despliegue¶
Sin API key real, una ruta publica protegida debe responder 401, no 404:
curl -sS -o /tmp/farmapi-nearby.out -w '%{http_code}\n' \
'https://estudioapi.com/farmapi/v1/farmacias/nearby?territory_code=ES-MD&lat=40.4168&lng=-3.7038&radius_m=750'
Con API key, el verificador live debe dejar en verde api_nearby:
uv run python scripts/verify_live_surface.py \
--base-url https://estudioapi.com/farmapi \
--api-key "$FARMAAPI_API_KEY" \
--trial-territory ES-MD \
--require-ok