Por qué Grist en lugar de Google Sheets o Airtable
Google Sheets es una hoja de cálculo: almacena datos planos, los cálculos se limitan a funciones de hoja y las relaciones entre hojas se apoyan en VLOOKUP frágiles. Airtable resuelve eso con bases relacionales, pero a 20 $ por usuario al mes la cuenta sube rápido para una agencia o un equipo técnico.
Grist combina ambos mundos: una interfaz de hoja de cálculo familiar sobre una base de datos relacional real. Cada documento contiene tablas con columnas tipadas (texto, numérico, fecha, referencia, adjunto), relaciones explícitas entre tablas mediante columnas de referencia y fórmulas Python que se ejecutan en el servidor, no en el navegador. En su VPS, Grist cuesta 0 $ al mes adicionales.
Lo que Grist hace y Google Sheets no
- Relaciones entre tablas: una columna de referencia en
Pedidosapunta aClientes— no un VLOOKUP que se rompe, sino una clave foránea real con autocompletado. - Fórmulas Python del lado del servidor:
import datetime,import re,import uuid— y cualquier librería Python pura. Las fórmulas se ejecutan en un sandbox del servidor, no en el navegador. - API REST automática: cada documento expone
/api/docs/<id>/tables/<table>/recordssin configuración. Integre Grist en n8n, Make o cualquier cliente HTTP. - Múltiples vistas sobre los mismos datos: grid, tarjeta, gráfico, calendario, widget personalizado — cada vista se filtra y se configura de forma independiente sin duplicar los datos.
- Reglas de acceso por fila y por columna: limite la lectura o la escritura de una fila según el atributo del usuario — lo bastante fino para documentos multi-tenant.
Requisitos y arquitectura Docker
Un VPS con al menos 1 GB de RAM y Docker instalado es suficiente para empezar. Grist se despliega en un solo contenedor gristlabs/grist que incorpora Node.js (servidor web), Python (sandbox de fórmulas) y SQLite (almacenamiento de documentos). Un volumen con nombre /persist guarda los archivos .grist — un archivo por documento. No se requiere ningún servicio externo.
El puerto por defecto es 8484. Verifique que es accesible desde localhost antes de configurar el reverse proxy (curl -sI http://localhost:8484/).
Docker Compose completo y despliegue
Crear el directorio y docker-compose.yml
Conéctese por SSH a su VPS y cree el directorio de stack:
mkdir -p /opt/stacks/grist && cd /opt/stacks/gristCree el siguiente
docker-compose.yml:services: grist: image: gristlabs/grist:1.7.20 container_name: grist restart: unless-stopped ports: - "127.0.0.1:8484:8484" volumes: - grist_data:/persist environment: GRIST_SESSION_SECRET: "REEMPLACE_CON_openssl_rand_hex_32" APP_HOME_URL: "https://grist.sudominio.com" GRIST_DEFAULT_EMAIL: "[email protected]" GRIST_SANDBOX_FLAVOR: "gvisor" volumes: grist_data:Genere el secreto de sesión antes de iniciar:
openssl rand -hex 32. No reutilice este valor en otras instancias.Arrancar y verificar
docker compose up -d docker compose logs -f gristEspere el mensaje
Grist server ready. Compruebe el estado HTTP:curl -sI http://localhost:8484/Debe obtener
HTTP/1.1 200 OKo una redirección302. Si el contenedor sigue reiniciándose, consulte la sección de Resolución de problemas.Configurar nginx como reverse proxy HTTPS
Instale nginx y certbot en el VPS, luego cree
/etc/nginx/sites-available/grist.conf:server { listen 80; server_name grist.sudominio.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name grist.sudominio.com; ssl_certificate /etc/letsencrypt/live/grist.sudominio.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/grist.sudominio.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; add_header X-Frame-Options SAMEORIGIN always; add_header X-Content-Type-Options nosniff always; add_header Referrer-Policy strict-origin-when-cross-origin always; location / { proxy_pass http://127.0.0.1:8484; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 300s; } }Obtenga el certificado y active el vhost:
certbot certonly --nginx -d grist.sudominio.com ln -s /etc/nginx/sites-available/grist.conf /etc/nginx/sites-enabled/ nginx -t && systemctl reload nginxActualice
APP_HOME_URLen el Compose y reinicie:docker compose up -d.
Fórmulas Grist avanzadas: VLOOKUP y referencias cruzadas entre tablas
Grist reemplaza los VLOOKUP frágiles de Google Sheets con columnas de referencia y funciones de búsqueda tipadas. En una tabla Pedidos con una columna Cliente de tipo Reference → Clientes, acceder al nombre del cliente es simplemente $Cliente.Nombre — sin VLOOKUP.
Para agregaciones, Grist proporciona lookupRecords() y lookupOne():
# En la tabla Clientes — importe total de pedidos de un cliente
SUM(Pedidos.lookupRecords(Cliente=$id).Importe)
# En la tabla Pedidos — obtener el código postal del cliente
Clientes.lookupOne(Nombre=$Cliente.Nombre).CodigoPostal
# Cálculo de descuento progresivo con Python estándar
import datetime
retraso = (datetime.date.today() - $FechaPedido).days
$Importe * (1 - 0.02 * retraso // 30)Las fórmulas Python se ejecutan en un sandbox gVisor (GRIST_SANDBOX_FLAVOR=gvisor): el proceso Python no tiene acceso al sistema de archivos ni a la red.
Autenticación SSO con OIDC (opcional)
Para despliegues multiusuario con autenticación real, Grist soporta OpenID Connect (OIDC) con Authentik, Keycloak, Google Workspace o cualquier proveedor compatible.
Añada estas variables al Compose:
environment:
GRIST_OIDC_IDP_ISSUER: "https://auth.sudominio.com/application/o/grist/"
GRIST_OIDC_IDP_CLIENT_ID: "su-client-id"
GRIST_OIDC_IDP_CLIENT_SECRET: "su-client-secret"
GRIST_OIDC_IDP_SCOPES: "openid email profile"
GRIST_OIDC_SP_HOST: "https://grist.sudominio.com"Eliminar GRIST_DEFAULT_EMAIL una vez configurado OIDC — las dos variables son incompatibles. El primer usuario que inicie sesión mediante OIDC se convierte en administrador del sitio.
Copias de seguridad: volúmenes Docker y exportación
Los documentos Grist residen en el volumen Docker grist_data, bajo /persist/docs/. Dos estrategias complementarias:
Snapshot del volumen (copia completa, recomendado): monte /persist/docs/ en un job de Backrest (disponible en el catálogo ServOrbit). Backrest hace snapshots de la carpeta con restic y envía los incrementos cifrados a S3, Backblaze B2 o SFTP — sin detener Grist.
# Copia de seguridad manual de emergencia
docker run --rm \
-v grist_data:/source:ro \
-v /backups/grist:/dest \
alpine tar czf /dest/grist-$(date +%Y%m%d).tar.gz -C /source .Exportación por documento: en Grist, menú Document → Export → .grist (formato SQLite nativo) o CSV/XLSX por tabla. Grist también conserva un historial de snapshots por documento (Document → History).
Resolución de problemas frecuentes
El contenedor sigue reiniciándose: revise los logs (docker compose logs grist). La causa más frecuente es un GRIST_SESSION_SECRET vacío o demasiado corto — debe tener al menos 32 caracteres hexadecimales.
Errores CORS en la API: si llama a /api/docs/… desde un dominio diferente, añada GRIST_ALLOWED_HOSTS=grist.sudominio.com y asegúrese de que APP_HOME_URL coincida exactamente con la URL pública (con https://, sin barra final).
Lentitud en grandes conjuntos de datos: en tablas con más de 100.000 filas, limite los lookupRecords() a columnas indexadas y evite fórmulas Python con importaciones pesadas en columnas de trigger.
Problemas de acceso tras cambio de dominio: actualice APP_HOME_URL, borre las cookies del navegador y reinicie el contenedor.
Grist vs NocoDB vs Baserow: elegir su hoja de cálculo open-source
Desplace la tabla
| Criterio | Grist | NocoDB | Baserow |
|---|---|---|---|
| Almacenamiento | SQLite por documento (archivo .grist) | PostgreSQL o MySQL (BD compartida) | PostgreSQL (BD compartida) |
| Fórmulas | Python del lado del servidor (sandbox) | Sin fórmulas nativas | Fórmulas limitadas, JS en cliente |
| REST API | Automática por documento | Automática por base | Automática |
| Auth SSO | OIDC nativo | LDAP, OIDC (Enterprise) | SSO de pago |
| Copias de seguridad | Un archivo .grist por documento | Dump PostgreSQL | Dump PostgreSQL |
| Caso de uso ideal | Modelado de datos, fórmulas complejas | Reemplazo de Airtable para equipos | Interfaz no-code para equipos de negocio |
| Recursos (inicio) | 1 GB RAM, Docker | 2 GB RAM, Docker + PostgreSQL | 2 GB RAM, Docker + PostgreSQL |
Para actualizar Grist, cambie la etiqueta de imagen en el Compose (gristlabs/grist:1.7.20 → siguiente versión), detenga el contenedor (docker compose down) y reinícielo (docker compose up -d). El volumen grist_data persiste entre versiones. Consulte las notas de versión en github.com/gristlabs/grist-core antes de cada actualización — algunas versiones introducen migraciones de esquema irreversibles.