Grist
Совместные таблицы на своем сервере: связи между таблицами, права до отдельной строки и формулы на настоящем Python. Каждый документ - обычный файл SQLite, который можно скачать и открыть без Grist. Развернули на Fatmetal Cloud Server и замерили.
Вердикт
- команде, которая живет в гугл-таблицах и хочет те же таблицы у себя
- когда нужно закрыть часть строк или колонок от части сотрудников
- если в команде есть кто-то, знающий Python: формулы пишутся на нем
- когда данные нельзя держать за пределами страны
- если нужна вольная сетка, где в любую ячейку пишут что угодно
- вместо офисного пакета: документов и презентаций тут нет
- если работать будут с телефона - мобильных приложений нет
- если нужны письма-уведомления без доплаты
Что это и какую задачу решает
Grist - таблица, которая ведет себя как база данных. Колонка держит один тип данных и имеет имя, строки связываются между таблицами ссылками, а значения считаются формулами и пересчитываются сами.
Ситуация, из которой в него приходят, узнаваемая. Работа ведется в гугл-таблицах, файлов стало пять, ВПР ходит между ними и ломается при каждой правке, а половина колонок заполнена вручную. Писать приложение никто не станет.
Grist закрывает середину: связи и типы как в базе, но заводится это за вечер и без разработчика. Данные при этом лежат на вашем сервере.
Чем отличается от гугл-таблиц и Airtable
Сравниваем по тому, что меняет решение, а не по длине списка функций.
| Параметр | Grist на своем сервере | Google Sheets / Airtable |
|---|---|---|
| Цена | сервер от 500 руб/мес на всю команду | подписка за каждого человека |
| Где данные | на вашем сервере, файлом | в чужом облаке |
| Формулы | настоящий Python со стандартной библиотекой | свой язык формул, скрипты отдельно |
| Права | до строки и колонки, по значению ячейки | на файл или лист целиком |
| Вынести данные | скопировать файл документа | экспорт по таблицам |
| Вольная сетка | нет, колонка держит один тип | да, пишите что угодно куда угодно |
| Мобильные приложения | нет | есть |
Переезд не теоретический: Grist умеет импорт из Google Drive, Excel и CSV, а из Airtable забирает данные напрямую. Повторный импорт того же CSV догружает новые строки, а не дублирует старые - полезно, когда каждый месяц подгружается выписка.
Как устроен и почему это важно
Сервер на Node.js, формулы считает Python 3.11 в отдельном процессе. Внешних баз нет: каждый документ - самостоятельный файл SQLite в папке данных, рядом лежит служебная база со списком пользователей и документов.
Отсюда два следствия, которые видно в работе. Бэкап - это копия папки, а не выгрузка базы. И документ читается любым инструментом, понимающим SQLite: мы открыли наш файл штатной утилитой и достали из него данные, не запуская Grist.
Схема документа в интерфейсе тоже показана кодом. Раздел «Просмотр кода» рисует таблицы как классы Python, а формульные колонки - как функции. Это не украшение: ровно так они и выполняются.
Сколько ресурсов нужно на самом деле
Документация вендора называет два числа, и они расходятся в сорок раз. Мы померили.
| Вендор: рабочая конфигурация | 8 ГБ RAM, 2 CPU, 20 ГБ |
| Вендор: замер на одном документе | 100-200 МБ RAM |
| Наш замер: простой | 230 МиБ |
| Наш замер: документ на 100 000 строк | 419 МиБ |
| Наш замер: пик при выгрузке в Excel | 657 МиБ |
| Рекомендуем тариф | CPU2-RAM4-DISK50 - 500 руб/мес |
Восемь гигабайт не нужны. Продукт занимает шестую часть тарифа CPU2-RAM4-DISK50 даже с открытым документом на сто тысяч строк. Тариф побольше нужен не размеру базы, а числу людей, работающих одновременно: каждый открытый документ - это свой процесс Python на 70-90 МиБ.
В маркетплейсе Fatmetal
Не хотите ставить руками?
Этот стек есть в маркетплейсе Fatmetal - можно не повторять установку из этого разбора вручную. Заказываете сервер, за пару минут получаете рабочий сервис на своем домене, валидный TLS и файл с доступами.
Рекомендуемая конфигурация: CPU2-RAM4-DISK50
Развертывание на Fatmetal
Один контейнер, один том, никаких внешних баз. От чистой машины до рабочего адреса - около четырех минут.
Взять сервер
Тариф CPU2-RAM4-DISK50, Ubuntu 24.04 LTS. Docker ставится по официальному репозиторию, это около минуты.
Описать сервис
Порт держим на локальном адресе - наружу продукт смотрит через прокси с сертификатом, а не голым портом.
services: grist: image: gristlabs/grist:1.7.20 container_name: grist restart: unless-stopped ports: - "127.0.0.1:8484:8484" volumes: - ./persist:/persist environment: GRIST_SESSION_SECRET: "СЛУЧАЙНАЯ_СТРОКА" GRIST_DEFAULT_EMAIL: "вы@вашдомен.ru" GRIST_BOOT_KEY: "ВАШ_КЛЮЧ_ПЕРВОГО_ВХОДА" GRIST_SANDBOX_FLAVOR: "gvisor" GRIST_DEFAULT_LOCALE: "ru" GRIST_OFFER_ALL_LANGUAGES: "true"Запустить и войти
docker compose up -d curl -s localhost:8484/statusВ ответ должно прийти
Grist server is alive. Первый вход идет на страницу/boot, там спрашивают ключ из переменной выше.
Про почту адреса. Владелец адреса из GRIST_DEFAULT_EMAIL становится администратором установки. Менять переменную после первого входа нельзя: права уедут к новому адресу, а старый останется обычным пользователем.
Что измерили после запуска
Цифры с нашей машины: тариф CPU2-RAM4-DISK50, Ubuntu 24.04, Docker 29.8.1, Grist 1.7.20.
| Скачивание образа | 87 с (1.45 ГБ) |
| Старт контейнера | 5 с |
| Вся установка с нуля | ~4 минуты |
| RAM в простое | 230 МиБ |
| Контейнеров | 1 |
| Отклик страницы состояния | 6.5 мс |
Отдельно проверили то, о чем в сообществе спрашивают и не получают ответа: сколько строк выдержит документ. Завели таблицу с числовой колонкой и формулой на Python в каждой строке и загрузили сто тысяч записей.
| Строк | Файл документа | Память | Чтение записи |
|---|---|---|---|
| 10 000 | 0.7 МБ | 348 МиБ | 173 мс |
| 50 000 | 2.8 МБ | 408 МиБ | 308 мс |
| 100 000 | 5.6 МБ | 419 МиБ | 503 мс |
Загрузка всех ста тысяч строк заняла 31 секунду, формула посчиталась на каждой. Упирается не память, а отклик: чтение записи замедлилось втрое. Выгрузка того же документа в Excel заняла 11 секунд, а скачивание самого файла - 0.64 секунды, потому что конвертировать нечего.
Память возвращается. После тяжелой выгрузки контейнер занимал 657 МиБ и за три минуты отдал лишнее, вернувшись к 277 МиБ: неактивные документы закрываются вместе со своими процессами. Ничего не копится.
Проверено на версии v1.7.20, сентябрь 2026. На новых версиях результаты могут отличаться.
Где может сломаться
Три вещи, на которые мы наткнулись сами.
Изоляции формул по умолчанию нет. Формулы - настоящий Python, и без переменной GRIST_SANDBOX_FLAVOR они выполняются прямо внутри контейнера. Любой, кто может править формулу, получает исполнение кода. Включать обязательно: в замерах изоляция стоила 68 МиБ памяти и нисколько не замедлила пересчет.
Ключ первого входа печатается в журнале. Если не задать его переменной, Grist сгенерирует свой и выведет в логи контейнера. Человек, который просто открыл адрес, упрется в форму и не поймет, где взять ключ.
Когда. Изоляция включена, при старте написано «gvisor check ok», страница состояния отвечает - а первая же запись в таблицу возвращает ошибку.
Причина. Grist ускоряет запуск Python снимком состояния, а восстановление снимка сверяет возможности процессора. Наш сервер стоит на процессоре старого поколения, где нужного набора нет: missing features: map[xsave:{}]. Проверить свой можно командой grep -c xsave /proc/cpuinfo - ноль означает, что вы в этой ситуации.
Решение. Запускать сервер без снимка состояния. Сама изоляция при этом работает - мы проверили, формулы считаются. В карточке маркетплейса это уже учтено: режим выбирается по процессору автоматически.
Колонка помнит свой тип. Числовая колонка отдает в формулу дробное число, и привычное range($A) падает с ошибкой типа на каждой строке. Лечится обертыванием в int(). Это общая черта продукта: строгие типы - цена связей между таблицами.
Кто что видит
Главное отличие от гугл-таблиц в правах. Там доступ выдается на файл или лист целиком, здесь - на отдельные строки и колонки, причем условием может быть значение в ячейке или атрибут сотрудника.
На практике это значит, что менеджер видит только свои заявки, а колонку со ставкой не видит вовсе - без создания отдельных копий таблицы под каждого. Правила включаются в разделе с тем же названием и пишутся условиями, а не кодом.
Русский интерфейс включается двумя переменными из примера выше. Переведено не все: меню, панели и подсказки - да, часть админской области осталась английской, и местами перевод хромает. Мы замерили покрытие по файлам локализации - около 71 процента строк.
Что входит в бесплатную версию
Ядро под лицензией Apache-2.0: таблицы, формулы, права, формы, дашборды, вебхуки, API. Отдельно продается полная версия - уведомления на почту, автоматизации, вход через корпоративную учетную запись, журнал действий, помощник на базе языковой модели.
Тут важная деталь, о которой редко пишут. Полная версия бесплатна для организаций и частных лиц с годовым доходом меньше миллиона долларов - ключ выдается по заявке. То есть малому бизнесу платные функции достаются даром, а платят те, у кого выручка есть.
Помощник по формулам есть и в бесплатном ядре - он подсказывает код по описанию словами. Ему нужен ключ провайдера моделей на ваш выбор; на серверах Fatmetal обращения к внешним API идут через наш прокси, он уже включен в сервер и настраивать его не надо. Мы проверили это живым запросом: помощник вернул рабочую формулу.
Обновления и бэкап
Обновление - смена тега образа и перезапуск. Мы обновились с 1.7.19 на 1.7.20 прямо во время разбора: полторы минуты на загрузку, данные на месте, изоляция формул продолжила работать.
docker compose pull && docker compose up -d
Бэкап - копия папки данных целиком, а не выгрузка базы. Внутри лежат документы, служебная база и сессии.
tar czf grist-backup-$(date +%F).tar.gz ./persist
Файлы документов не переименовывать. Grist находит их по имени, и переименованный файл перестает быть документом. Отдельный документ выгружается кнопкой из интерфейса - это тот же файл, его можно загрузить в другую установку.
Перед выводом наружу закрыть нужно немного: обратный прокси с сертификатом, свой ключ первого входа, случайная строка в секрете сессий и включенная изоляция формул. Порт наружу не открывать.
Связь с другими стеками
- Обратный прокси - Caddy или Nginx Proxy Manager, чтобы отдать таблицы наружу по HTTPS.
- NocoDB - сосед по нише. Он ближе к базе данных поверх Postgres, Grist - к таблице с формулами. Выбор между ними зависит от того, кто будет работать: разработчик или аналитик.
- n8n - автоматизации снаружи. В бесплатном ядре Grist их нет, но есть исходящие вебхуки, и связка закрывает тот же сценарий.
- S3-хранилище - если в таблицы грузят много вложений, их выносят из документов во внешнее хранилище.
Когда это НЕ ваш выбор
Вам нужна вольная сетка
Если в таблице принято писать в любую ячейку что угодно, ставить итоги посреди листа и держать в одной колонке то числа, то текст - Grist будет мешать. Колонка держит один тип, и это не настройка.
Работают в основном с телефона
Мобильных приложений нет, интерфейс рассчитан на экран. Для внесения данных на ходу лучше сделать форму - она в Grist есть и работает в браузере телефона.
Нужны письма-уведомления прямо сейчас
В бесплатном ядре почты нет: код отправки писем лежит в платной части образа и включается только активацией полной версии. Либо заявка на бесплатный ключ, либо внешняя автоматизация через вебхуки.
Нужен офисный пакет
Это только таблицы. Документов, презентаций и совместного редактирования текста тут не будет.
Частые вопросы
Хватит ли тарифа CPU2-RAM4-DISK50?
Да, с запасом. В простое продукт занимает 230 МиБ, с открытым документом на сто тысяч строк - 419 МиБ. Это шестая часть памяти тарифа CPU2-RAM4-DISK50.
Нужна ли отдельная база данных?
Нет. Каждый документ - самостоятельный файл SQLite, служебные данные тоже. Внешний Postgres подключается по желанию, для одной команды он не нужен.
Сколько строк выдержит таблица?
Сто тысяч строк с формулой на каждой работают: файл 5.6 МБ, память 419 МиБ. Заметно другое - чтение записи замедляется втрое по сравнению с десятью тысячами.
Можно ли перенести данные из гугл-таблиц?
Да, есть импорт из Google Drive, Excel и CSV, а также прямой импорт из Airtable. Повторная загрузка того же файла догружает новые строки без дублей.
Интерфейс на русском?
Включается двумя переменными окружения. Переведено около 71 процента строк: меню и панели по-русски, часть админской области осталась английской.
Что с лицензией для коммерческого использования?
Ядро под Apache-2.0, использовать в компании можно свободно. Платные функции бесплатны для организаций с доходом меньше миллиона долларов в год по заявке на ключ.
Как отдать таблицы наружу безопасно?
Порт держать на локальном адресе, снаружи - обратный прокси с сертификатом. Обязательно включить изоляцию формул: по умолчанию ее нет.
Итог
Grist - рабочая замена гугл-таблицам для команды, которой нужны связи между таблицами и права до отдельной строки. Ставится одним контейнером за четыре минуты, живет на тарифе за 500 руб/мес, занимая 230 МиБ в простое, и держит сто тысяч строк с формулами. Данные остаются файлом, который можно забрать и открыть без Grist. Взамен придется принять строгие типы колонок, отсутствие мобильных приложений и то, что почтовые уведомления живут в платной версии - бесплатной, впрочем, для большинства небольших компаний.
Этот стек у нас запущен на тарифе CPU2-RAM4-DISK50. Нашли баг в гайде - напишите, поправим в течение дня.