Сколько RAM нужно для Penpot
Penpot — open-source альтернатива Figma, и в отличие от неё вы сами отвечаете за то, чтобы сервер не задыхался под нагрузкой команды. Проблема в том, что Penpot — это не один процесс, а связка из пяти сервисов: фронтенд, backend на JVM, экспортер на headless-браузере, PostgreSQL и Redis, и каждый ест память по-своему. Разберём, что конкретно нагружает RAM в self-hosted Penpot и сколько закладывать под разные размеры команды.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Архитектура: из чего состоит self-hosted Penpot
Официальный способ развернуть Penpot — Docker Compose с пятью контейнерами, и это не прихоть разработчиков, а следствие архитектуры продукта:
- penpot-frontend — статика (собранный ClojureScript SPA) плюс nginx, который её отдаёт и проксирует запросы к backend. Памяти почти не требует — это самый лёгкий контейнер в связке.
- penpot-backend — ядро системы, написано на Clojure и работает на JVM. Обрабатывает API, сохраняет объекты досок, держит WebSocket-соединения для совместного редактирования (курсоры коллег в реальном времени, синхронизация правок).
- penpot-exporter — отдельный Node.js-сервис, который поднимает headless-браузер (Chromium) для рендера экспорта в PNG, SVG и PDF. Это единственный компонент, чьё потребление скачет резко и кратковременно.
- penpot-postgres — основное хранилище: файлы, доски, компоненты, версии хранятся как JSON-объекты в PostgreSQL.
- penpot-redis — pub/sub для событий совместного редактирования (кто что сейчас двигает на доске) и часть кеша сессий.
Ключевое отличие от связок вроде Nextcloud или Collabora: тяжёлого рендеринга самих файлов на сервере нет почти никогда — редактирование происходит в браузере клиента через WebGL/Canvas, и backend лишь синхронизирует и сохраняет операции. Сервер нагружается не на «открыл доску», а на конкурентный realtime и на экспорт.
Сколько RAM закладывать: по сценариям
Цифры ниже — практический ориентир, а не гарантированный бенчмарк: реальное потребление зависит от того, сколько человек одновременно редактируют доски (а не сколько зарегистрировано аккаунтов) и как часто дергают экспорт больших PDF.
| Сценарий | Одновременно активных дизайнеров | vCPU | RAM | Диск (SSD) |
|---|---|---|---|---|
| Соло / фрилансер | 1 | 1–2 | 3–4 ГБ | 20 ГБ |
| Малая команда, 3–10 человек | до 8 | 2 | 4–6 ГБ | 40 ГБ |
| Студия, 10–30 человек | до 20 | 2–4 | 8 ГБ | 80–120 ГБ |
| Отдел / компания, 30–50+ человек | 30+ | 4–8 | 12–16 ГБ | 150+ ГБ, вынесите PostgreSQL на отдельный сервер |
Даже для одного человека закладывайте не меньше 3 ГБ: JVM-процесс backend без тюнинга сам по себе резервирует заметную часть heap на старте, плюс PostgreSQL и Redis держат свою базовую память вне зависимости от нагрузки — на голом 2 ГБ VPS система живёт впритык уже без единого пользователя.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверУстановка через Docker Compose
Разделение на пять сервисов — плюс для памяти: каждый компонент можно ограничить и мониторить отдельно, а не гадать, что именно съело RAM внутри монолита.
services:
penpot-frontend:
image: penpotapp/frontend:latest
ports:
- "9001:8080"
environment:
- PENPOT_FLAGS=enable-registration disable-email-verification
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
mem_limit: 256m
penpot-backend:
image: penpotapp/backend:latest
volumes:
- penpot_assets:/opt/data/assets
environment:
- PENPOT_FLAGS=enable-registration disable-email-verification
- PENPOT_SECRET_KEY=замените-на-случайную-строку
- PENPOT_DATABASE_URI=postgresql://penpot-postgres/penpot
- PENPOT_DATABASE_USERNAME=penpot
- PENPOT_DATABASE_PASSWORD=penpot
- PENPOT_REDIS_URI=redis://penpot-redis/0
- PENPOT_ASSETS_STORAGE_BACKEND=assets-fs
- PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets
- PENPOT_TELEMETRY_ENABLED=false
depends_on:
- penpot-postgres
- penpot-redis
mem_limit: 2g
penpot-exporter:
image: penpotapp/exporter:latest
environment:
- PENPOT_PUBLIC_URI=http://penpot-frontend:8080
- PENPOT_REDIS_URI=redis://penpot-redis/0
mem_limit: 1g
penpot-postgres:
image: postgres:15
environment:
- POSTGRES_INITDB_ARGS=--data-checksums
- POSTGRES_DB=penpot
- POSTGRES_USER=penpot
- POSTGRES_PASSWORD=penpot
volumes:
- penpot_postgres_v15:/var/lib/postgresql/data
mem_limit: 2g
penpot-redis:
image: redis:7
volumes:
- penpot_redis_data:/data
mem_limit: 512m
volumes:
penpot_postgres_v15:
penpot_redis_data:
penpot_assets:
mem_limit здесь — «мягкая» страховка на уровне Docker Compose (не Swarm), а не точная настройка каждого сервиса: если контейнер упрётся в лимит, ядро пришлёт ему OOM-kill, а не аккуратно попросит освободить память. Реальное потребление проверяйте docker stats в течение недели-двух и корректируйте лимиты по факту, а не по теории.
Backend на JVM: где настраивается память
Backend Penpot — это JVM-процесс, и у JVM своя логика с памятью, отличная от Node.js или PHP: она резервирует heap заранее, а не растёт постепенно по мере надобности. Без явных настроек JVM сама вычисляет лимит heap исходя из памяти, видимой контейнеру, — и на маленьких VPS (2 ГБ и меньше) это может оставить слишком мало места для PostgreSQL и Redis, которые часто стоят рядом на том же хосте.
Ограничить heap backend вручную можно через переменную JDK_JAVA_OPTIONS:
environment:
- JDK_JAVA_OPTIONS=-Xmx1536m -Xms512m
-Xmx — жёсткий потолок heap, -Xms — сколько выделить сразу при старте. Разумное соотношение — heap примерно 60–70% от mem_limit контейнера backend, остальное — под стек потоков (у backend их несколько десятков на активные WebSocket-соединения) и off-heap буферы. Если видите в логах OutOfMemoryError: Java heap space — это почти всегда означает, что -Xmx выставлен ниже реальной нагрузки, а не утечку: сначала поднимите лимит и понаблюдайте, и только если рост продолжается на плато пользователей — ищите проблему в конкретной версии образа.
Отдельно держите в уме число WebSocket-соединений: каждый открытый в браузере таб с активной доской — это одно долгоживущее соединение к backend. На команду в 20 человек, работающих с несколькими вкладками, легко набегает 30–50 одновременных соединений — сам по себе это не тяжело для памяти, но при скачке до сотен соединений (например, публичная доска, куда зашли смотреть много гостей одновременно) стоит заранее поднять и -Xmx, и лимит CPU.
Экспортер: самый непредсказуемый по памяти компонент
Экспортер — единственный сервис в связке, чьё потребление памяти не растёт плавно, а скачет резко: каждая задача экспорта (кнопка «Export» в PNG, SVG или PDF) поднимает headless-браузер, рендерит доску и закрывает страницу. Одна такая задача на сложную доску с десятками слоёв и векторных путей вполне может занять несколько сотен мегабайт на короткое время — и если несколько человек в команде одновременно жмут экспорт больших PDF (частый сценарий перед дедлайном), пики суммируются.
На практике это означает: не ставьте mem_limit для penpot-exporter впритык к минимуму (короткий пик важнее среднего потребления), закладывайте под него отдельный запас 1–2 ГБ, если команда регулярно выгружает большие макеты, и мониторьте не среднее потребление, а именно пики — docker stats в момент массового экспорта покажет картину точнее, чем усреднённые графики за сутки. Если экспортер регулярно падает по OOM в конце спринта перед релизом — это сигнал поднять лимит или временно масштабировать сервер на день выгрузки, а не урезать mem_limit.
PostgreSQL и Redis: как считать их долю
PostgreSQL хранит все объекты Penpot — доски, компоненты, историю версий — как JSON внутри реляционных таблиц, и его аппетит к памяти растёт вместе с объёмом и сложностью файлов, а не с числом активных пользователей напрямую. Главный параметр, влияющий на RAM, — shared_buffers: классическое правило «25% от доступной серверу памяти» подходит и здесь как стартовая точка, если PostgreSQL стоит на том же хосте, что и остальные сервисы Penpot. Подробно про настройку — в статье PostgreSQL: тюнинг на сервере, а если база уже падает по памяти — в разборе PostgreSQL out of memory: причины и решение.
Redis в связке Penpot используется под pub/sub для realtime-событий (кто что двигает на доске прямо сейчас) — эти данные не персистентны по своей природе и не накапливаются бесконечно, поэтому Redis обычно остаётся самым лёгким из тяжёлых компонентов: 256–512 МБ достаточно даже на команду в 30–50 человек. Если видите иную картину — стабильный рост RSS процесса Redis без остановки — проверьте, не включена ли ненужная персистентность (RDB/AOF) с большими интервалами снапшотов, это разобрано в статье Redis: высокое потребление памяти — причины и решение.
Для команд свыше 30–50 человек имеет смысл вынести PostgreSQL на отдельный сервер: это разгружает основной хост под backend и экспортер, а pg_dump на активно используемой базе перестаёт конкурировать с остальными сервисами за I/O и, косвенно, за файловый кеш ОС.
Мониторинг, диск и что делать при нехватке памяти
Проверять реальную картину стоит с первого дня эксплуатации, а не после первого падения под нагрузкой перед дедлайном:
# Потребление по каждому контейнеру Penpot
docker stats penpot-frontend penpot-backend penpot-exporter penpot-postgres penpot-redis
# Сколько всего свободно на хосте
free -h
# Кто съедает диск (ассеты растут быстрее, чем кажется)
du -sh /var/lib/docker/volumes/*penpot* 2>/dev/null
Диск в Penpot часто оказывается узким местом раньше памяти: загруженные изображения, шрифты, экспортированные превью и история версий объектов в PostgreSQL накапливаются, а команда обычно не думает об этом, пока не закончится место. Планируйте диск отдельно от RAM — эти два ресурса в Penpot почти не связаны напрямую, кроме файлового кеша ОС.
Если бюджет ограничен и RAM впритык, файл подкачки не заменяет расчёт объёма, но снимает риск моментального OOM-килла в момент пика (несколько человек разом жмут «Export» на большие доски). Как настроить — в статьях swap-файл: когда нужен и как настроить и правильный размер swap для VPS. Для Penpot 2 ГБ swap как страховка достаточно даже на инстансах с 8 ГБ RAM — это буфер на короткие пики экспортера и JVM, а не постоянно расходуемый ресурс.
Если после нескольких недель docker stats стабильно показывает потребление backend или PostgreSQL близко к лимиту даже в спокойные часы — это сигнал не тюнить -Xmx до бесконечности, а перейти на тариф с большим объёмом RAM: устойчивый рост почти всегда означает, что реальное число активных дизайнеров и объём файлов превысили тот сценарий, под который сервер считался изначально.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Хватит ли 2 ГБ RAM для Penpot?
Технически связка запустится, но впритык: JVM-процесс backend, PostgreSQL и Redis вместе резервируют заметную часть памяти уже без единого пользователя, а любой пик экспортера легко выбьет систему в OOM. Для рабочего использования безопасный минимум — 3–4 ГБ даже для одного человека.
Почему backend написан на JVM и это влияние на память серьёзное?
Да, JVM резервирует heap иначе, чем Node.js — не постепенно, а по заранее заданному потолку через -Xmx. Без явной настройки JVM сама оценивает лимит по памяти контейнера, что на маленьких VPS может оставить слишком мало для соседних сервисов — настройте JDK_JAVA_OPTIONS вручную.
Экспорт большого PDF может «уронить» сервер?
При жёстком mem_limit впритык — да, headless-браузер экспортера на сложной доске с десятками артбордов способен на короткое время занять несколько сотен мегабайт. Закладывайте под экспортер запас, а не минимум.
Нужен ли Penpot GPU на сервере?
Нет. Рендеринг досок происходит в браузере клиента через WebGL/Canvas — сервер только синхронизирует операции, хранит данные и по запросу рендерит экспорт headless-браузером на CPU.
Можно ли обойтись без Redis, если команда маленькая?
Формально Redis обязателен для текущей архитектуры Penpot — он держит pub/sub для realtime-совместного редактирования. Отключить его нельзя, но по памяти это почти не ощущается: 256–512 МБ хватает даже среднему отделу.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →