Guía del desarrollador de Goooy
Los fundamentos técnicos para quienes construyen, despliegan e integran Goooy: de qué está hecho el sistema, cómo desplegarlo y cómo se configura.
Goooy es una suite de groupware completa que alojas tú mismo: correo, calendario, contactos, tareas, notas, chat, archivos, videorreuniones, ofimática colaborativa y una consola de administración, todo desde una única aplicación, un único modelo de datos y un único chart de Helm. Tú eres el dueño de los servidores, los datos y las claves.
Esta guía cubre la plataforma en sí. La operación del día a día (la consola de
administración, organizaciones y usuarios, la política de autenticación, el servidor de
correo, la gestión de dispositivos, la migración, la multitenencia y las copias de
seguridad) está en la Guía del administrador; la visión de las
aplicaciones desde el punto de vista del usuario final está en la
Guía del usuario. Para obtener detalles técnicos profundos, la
carpeta docs/ del código fuente del producto contiene referencias específicas
(arquitectura, seguridad, servidor de correo, multitenencia, despliegue, migración y los
protocolos de cliente nativo).
Contenido
Qué estás ejecutando
Goooy es un monolito modular: una única API de Fastify/TypeScript respaldada por PostgreSQL, Redis y almacenamiento de objetos compatible con S3, además de una aplicación web de página única en React servida por nginx. Los clientes nativos (Outlook, Thunderbird, Apple Mail, teléfonos) se conectan mediante los protocolos estándar. Opcionalmente, un servidor de correo real (Postfix + Dovecot + Rspamd) convierte la API en el centro de entrega del correo de internet entrante y saliente.
Browser ───────▶ web (React SPA, nginx) ──proxies /api, /ws──▶
Native clients ─▶ api (Fastify, modular monolith)
(DAV · EAS · │ │ │
Autodiscover · ┌───────▼──┐ ┌───▼────┐ ┌──▼───────┐
IMAP/POP3/SMTP) │PostgreSQL│ │ Redis │ │ S3/MinIO │
│ (Prisma) │ │pub/sub │ │ (blobs) │
└──────────┘ └────────┘ └──────────┘
Servicios de respaldo y qué almacenan:
| Almacén | Función | Si se pierde |
|---|---|---|
| PostgreSQL | Sistema de referencia: todos los datos estructurados y la vista de webmail de los mensajes | Catastrófico; esto es lo que respaldas |
| S3 / MinIO | Blobs opacos: archivos subidos (con versiones) y adjuntos de correo | Se pierde el contenido de archivos/adjuntos |
| Redis | Solo efímero: pub/sub en tiempo real, presencia, listas de participantes de reuniones | El tiempo real se degrada brevemente; no se pierde ningún dato duradero |
Toda la suite se distribuye como un chart de Helm (deploy/helm/goooy) que puede
incluir Postgres/Redis/MinIO por ti o apuntar a instancias externas gestionadas.
Desplegar Goooy
Kubernetes (recomendado)
Una instalación mínima levanta la suite completa: los Deployments de api + web,
PostgreSQL/Redis/MinIO incluidos y un Ingress que enruta por ruta la aplicación y cada
ruta de protocolo de cliente nativo:
helm install goooy ./deploy/helm/goooy \
--namespace goooy --create-namespace \
--set ingress.host=mail.example.com
El Ingress enruta / a la aplicación web y /api, /ws, /dav, /share,
/autodiscover, /.well-known/autoconfig, /mail/config y
/Microsoft-Server-ActiveSync a la API. TLS termina aquí.
Servicios de respaldo incluidos frente a externos. Cada almacén puede estar incluido (lo predeterminado) o ser externo:
helm install goooy ./deploy/helm/goooy \
--set postgresql.enabled=false --set externalDatabase.url=postgresql://… \
--set redis.enabled=false --set externalRedis.url=redis://… \
--set minio.enabled=false --set externalS3.endpoint=https://s3… \
--set externalS3.accessKey=… --set externalS3.secretKey=…
Refuerzo para producción. Activa el autoescalado, los presupuestos de interrupción, las copias de seguridad nocturnas, el TLS automático y tu propio secreto:
helm upgrade goooy ./deploy/helm/goooy \
--set autoscaling.enabled=true \ # HPA for api + web (needs metrics-server)
--set podDisruptionBudget.enabled=true \
--set backup.enabled=true \ # nightly pg_dump CronJob
--set ingress.tls.clusterIssuer=letsencrypt-prod \
--set secret.existingSecret=goooy-prod-secret
Cada parámetro está documentado en
deploy/helm/goooy/values.yaml; la topología
completa está en Despliegue.
Evaluación local (Docker Compose)
Para probar Goooy en un portátil:
cp .env.example .env # sets JWT_SECRET, DATABASE_URL, …
docker compose up -d postgres redis minio mailpit # backing services
npm install
npm run db:migrate --workspace @goooy/api # apply schema
npm run db:seed --workspace @goooy/api # bootstrap org + admin + demo users
npm run dev # api :4000 + web :5173
Abre http://localhost:5173 e inicia sesión como el administrador de arranque. Dos
usuarios de demostración (alice@goooy.local / bob@goooy.local, contraseña demo) te
permiten enviar correo entre cuentas y ver cómo funciona la entrega local.
Imágenes de contenedor
Compilaciones multietapa, todas ejecutándose sin root (uid 1000) bajo un contexto de seguridad de pod restrictivo:
- api: Node 22, ejecuta
prisma migrate deployy luego el servidor; expone HTTP (4000) y los puertos de ingesta SMTP/LMTP (2525/2526). - web: compilación de Vite servida por nginx; hace de proxy inverso para
/api,/wsy las rutas de protocolo, establece cabeceras de seguridad y realiza el respaldo SPA. - marketing: un sitio público estático de Astro (opcional; consulta la Guía del administrador).
- mail: Postfix, Dovecot, Rspamd (solo cuando el servidor de correo está habilitado).
Configuración esencial
La configuración está centralizada y validada con Zod en el arranque. La API falla
rápido si falta JWT_SECRET (≥16 caracteres) o DATABASE_URL, o si no son válidos,
de modo que un despliegue mal configurado nunca arranca en un estado a medio romper.
Todo lo demás tiene valores predeterminados sensatos.
Las variables más importantes:
| Grupo | Variables clave |
|---|---|
| Núcleo | PUBLIC_WEB_URL, PUBLIC_API_URL, API_PORT (4000) |
| Autenticación (obligatorio) | JWT_SECRET (≥16 caracteres), JWT_ACCESS_TTL (900s), JWT_REFRESH_TTL (30d) |
| Datos (obligatorio) | DATABASE_URL, REDIS_URL |
| Almacenamiento de objetos | S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY / S3_SECRET_KEY |
| Correo (saliente) | SMTP_HOST / SMTP_PORT / SMTP_SECURE |
| Correo (entrante) | SMTP_INGEST_*, LMTP_INGEST_*, RSPAMD_URL, DOVECOT_LMTP_* |
| Reuniones | MEET_ICE_SERVERS (servidores STUN/TURN en formato JSON) |
| Arranque | BOOTSTRAP_ORG / BOOTSTRAP_DOMAIN / BOOTSTRAP_ADMIN_EMAIL / BOOTSTRAP_ADMIN_PASSWORD |
Secretos.
JWT_SECRETyDATABASE_URLdeberían provenir de un Secret de Kubernetes que tú proporcionas (secret.existingSecret). Nunca lleves el valor predeterminado del chart a producción.JWT_SECRETcumple una doble función: también sella las claves privadas S/MIME, los secretos de cliente de SSO y las credenciales de migración en reposo, de modo que cambiarlo invalida esos valores sellados. Rótalo de forma deliberada. La tabla completa de variables de entorno está en Despliegue.
Adónde ir después
- La Guía del administrador cubre la operación de la suite desplegada: la consola de administración, organizaciones y usuarios, la política de autenticación, el servidor de correo, la gestión de dispositivos, la migración, la multitenencia y las copias de seguridad.
- La Guía del usuario es la visión de cada aplicación desde el punto de vista del usuario final.
- La referencia técnica completa (arquitectura, modelo de datos, servidor de correo, multitenencia, despliegue, migración y los protocolos de cliente nativo) se distribuye con el código fuente del producto.