لماذا Grist بدلاً من Google Sheets أو Airtable
Google Sheets جدول بيانات: يخزن البيانات مستوية والحسابات محدودة بدوال الورقة والعلاقات تعتمد على VLOOKUP هشة. Airtable يحل هذا بقواعد علائقية لكن بـ 20 دولاراً للمستخدم شهرياً، تتراكم الفاتورة بسرعة.
Grist يجمع العالمين: واجهة جداول بيانات مألوفة فوق قاعدة بيانات علائقية حقيقية. كل مستند يحتوي على جداول بأعمدة مكتوبة (نص، رقمي، تاريخ، مرجع، مرفق)، علاقات صريحة بين الجداول وصيغ Python تعمل من جانب الخادم. على VPS الخاص بك، Grist يكلف 0 دولار إضافي شهرياً.
ما يفعله Grist ولا يستطيع Google Sheets فعله
- علاقات بين الجداول: عمود مرجع في
الطلباتيشير إلىالعملاء— ليس VLOOKUP هشاً بل مفتاح أجنبي حقيقي مع إكمال تلقائي. - صيغ Python من جانب الخادم:
import datetime،import re،import uuid— وأي مكتبة Python نقية. الصيغ تعمل في صندوق رملي على الخادم. - واجهة برمجية REST تلقائية: كل مستند يعرض
/api/docs/<id>/tables/<table>/recordsبلا إعداد. دمج Grist مع n8n أو Make أو أي عميل HTTP. - طرق عرض متعددة على نفس البيانات: شبكة، بطاقة، مخطط، تقويم، ودجت مخصص — كل طريقة عرض قابلة للتصفية والإعداد بشكل مستقل.
- قواعد وصول لكل صف وعمود: قيّد القراءة والكتابة بناءً على سمات المستخدم — دقيق بما يكفي للمستندات متعددة المستأجرين.
المتطلبات ومعمارية Docker
VPS بـ 1 غيغابايت RAM على الأقل مع Docker المثبت كافٍ للبدء. Grist ينتشر في حاوية واحدة gristlabs/grist تضم Node.js (الخادم) وPython (صندوق الصيغ) وSQLite (تخزين المستندات). حجم مسمى /persist يخزن ملفات .grist — ملف واحد لكل مستند. لا خدمة خارجية مطلوبة.
المنفذ الافتراضي هو 8484. تحقق من إمكانية الوصول قبل إعداد الـ reverse proxy (curl -sI http://localhost:8484/).
Docker Compose الكامل والنشر
إنشاء الدليل وdocker-compose.yml
اتصل بـ SSH على VPS وأنشئ مجلد الـ stack:
mkdir -p /opt/stacks/grist && cd /opt/stacks/gristأنشئ ملف
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: "REPLACE_WITH_openssl_rand_hex_32" APP_HOME_URL: "https://grist.yourdomain.com" GRIST_DEFAULT_EMAIL: "[email protected]" GRIST_SANDBOX_FLAVOR: "gvisor" volumes: grist_data:ولّد سر الجلسة قبل البدء:
openssl rand -hex 32.الإطلاق والتحقق
docker compose up -d docker compose logs -f gristانتظر رسالة
Grist server ready. تحقق من حالة HTTP:curl -sI http://localhost:8484/يجب أن تحصل على
HTTP/1.1 200 OKأو إعادة توجيه302.إعداد nginx كـ reverse proxy مع HTTPS
ثبّت nginx وcertbot على VPS ثم أنشئ
/etc/nginx/sites-available/grist.conf:server { listen 80; server_name grist.yourdomain.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name grist.yourdomain.com; ssl_certificate /etc/letsencrypt/live/grist.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/grist.yourdomain.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; 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-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 300s; } }احصل على الشهادة وفعّل الـ vhost:
certbot certonly --nginx -d grist.yourdomain.com ln -s /etc/nginx/sites-available/grist.conf /etc/nginx/sites-enabled/ nginx -t && systemctl reload nginx
صيغ Grist المتقدمة: VLOOKUP والمراجع بين الجداول
Grist يستبدل VLOOKUP الهش بـ أعمدة المراجع ودوال البحث المكتوبة. في جدول الطلبات بعمود العميل من نوع Reference → العملاء، الوصول لاسم العميل ببساطة $العميل.الاسم — لا VLOOKUP.
للتجميعات، يوفر Grist lookupRecords() وlookupOne():
# في جدول العملاء — إجمالي مبالغ الطلبات لعميل
SUM(الطلبات.lookupRecords(العميل=$id).المبلغ)
# في جدول الطلبات — استرجاع الرمز البريدي للعميل
العملاء.lookupOne(الاسم=$العميل.الاسم).الرمزالبريدي
# حساب الخصم التدريجي مع استيراد Python
import datetime
التأخير = (datetime.date.today() - $تاريخالطلب).days
$المبلغ * (1 - 0.02 * التأخير // 30)تعمل الصيغ في صندوق رملي gVisor (GRIST_SANDBOX_FLAVOR=gvisor): لا وصول لنظام الملفات أو الشبكة.
مصادقة SSO مع OIDC (اختياري)
للنشر متعدد المستخدمين مع مصادقة حقيقية، يدعم Grist OpenID Connect (OIDC) مع Authentik أو Keycloak أو Google Workspace:
environment:
GRIST_OIDC_IDP_ISSUER: "https://auth.yourdomain.com/application/o/grist/"
GRIST_OIDC_IDP_CLIENT_ID: "your-client-id"
GRIST_OIDC_IDP_CLIENT_SECRET: "your-client-secret"
GRIST_OIDC_IDP_SCOPES: "openid email profile"
GRIST_OIDC_SP_HOST: "https://grist.yourdomain.com"احذف GRIST_DEFAULT_EMAIL بمجرد إعداد OIDC — المتغيران غير متوافقين. أول مستخدم يسجل دخوله عبر OIDC يصبح مدير الموقع.
النسخ الاحتياطية: أحجام Docker والتصدير
مستندات Grist في حجم Docker grist_data، ضمن /persist/docs/. استراتيجيتان متكاملتان:
لقطة الحجم (موصى به): اربط /persist/docs/ بمهمة Backrest (متاح في كتالوج ServOrbit). Backrest يأخذ لقطات عبر restic ويرسل الزيادات المشفرة إلى S3 أو Backblaze B2 أو SFTP — دون إيقاف Grist.
# نسخة احتياطية طارئة يدوية
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 .تصدير المستندات: في Grist، قائمة Document → Export → .grist (تنسيق SQLite الأصلي) أو CSV/XLSX لكل جدول. Grist يحفظ أيضاً تاريخ لقطات لكل مستند (Document → History).
استكشاف الأخطاء الشائعة
الحاوية تعيد التشغيل باستمرار: تحقق من السجلات (docker compose logs grist). السبب الأكثر شيوعاً هو GRIST_SESSION_SECRET فارغ أو قصير — يجب أن يكون 32 حرفاً سداسياً على الأقل.
أخطاء CORS على API: أضف GRIST_ALLOWED_HOSTS=grist.yourdomain.com وتأكد أن APP_HOME_URL يطابق URL العام بالضبط (مع https://، بدون شرطة مائلة في النهاية).
بطء على مجموعات البيانات الكبيرة: على الجداول التي تتجاوز 100,000 صف، حدّد lookupRecords() بالأعمدة المفهرسة وتجنب صيغ Python مع استيرادات ثقيلة.
مشاكل الوصول بعد تغيير النطاق: حدّث APP_HOME_URL، امسح ملفات تعريف الارتباط وأعد تشغيل الحاوية.
Grist مقابل NocoDB مقابل Baserow
مرّر الجدول أفقيًا
| المعيار | Grist | NocoDB | Baserow |
|---|---|---|---|
| التخزين | SQLite لكل مستند (ملف .grist) | PostgreSQL أو MySQL (قاعدة مشتركة) | PostgreSQL (قاعدة مشتركة) |
| الصيغ | Python من جانب الخادم (صندوق رملي) | لا توجد صيغ أصلية | صيغ محدودة، JS من جانب العميل |
| REST API | تلقائية لكل مستند | تلقائية لكل قاعدة | تلقائية |
| SSO | OIDC أصلي | LDAP، OIDC (Enterprise) | SSO مدفوع |
| النسخ الاحتياطية | ملف .grist واحد لكل مستند | تفريغ PostgreSQL | تفريغ PostgreSQL |
| حالة الاستخدام المثالية | نمذجة البيانات، صيغ معقدة | بديل Airtable للفرق | واجهة no-code للفرق |
| الموارد (البدء) | 1 GB RAM, Docker | 2 GB RAM, Docker + PostgreSQL | 2 GB RAM, Docker + PostgreSQL |
لتحديث Grist، غيّر وسم الصورة في Compose (gristlabs/grist:1.7.20 → الإصدار التالي)، أوقف الحاوية (docker compose down), ثم أعد تشغيلها (docker compose up -d). حجم grist_data يستمر بين الإصدارات. راجع ملاحظات الإصدار على github.com/gristlabs/grist-core قبل كل تحديث.