Penpot на Ubuntu 24.04: пошаговая установка
Figma удобна, пока не встаёт вопрос, где физически лежат макеты продукта и можно ли доверять их облаку — санкционные риски с доступом из России, NDA с заказчиком, требования к хранению данных внутри своей инфраструктуры. Penpot — зрелая open-source альтернатива с похожим интерфейсом, векторным редактором и поддержкой открытого формата SVG, которую можно поднять на своём сервере и полностью контролировать. Ниже — рабочая установка на Ubuntu 24.04 через официальный Docker Compose: от чистого сервера до закрытого от посторонней регистрации инстанса за доменом с TLS.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Из чего состоит Penpot и что для него нужно
Penpot — не одно приложение, а стек из нескольких сервисов, которые вместе обслуживают редактор:
- penpot-frontend — статика (собранный ClojureScript) плюс nginx внутри контейнера, который отдаёт файлы и проксирует запросы к backend и exporter. Это единственный сервис, который слушает порт наружу.
- penpot-backend — ядро на Clojure: API, аутентификация, бизнес-логика, работа с файлами проектов.
- penpot-exporter — отдельный сервис на Node.js с headless-Chromium (через Playwright), который рендерит экспорт макетов в PNG/SVG/PDF. Он самый прожорливый по памяти компонент стека.
- PostgreSQL — основная база: пользователи, проекты, история версий файлов.
- Redis — очереди задач и pub/sub для совместного редактирования в реальном времени.
По ресурсам Penpot заметно тяжелее одностраничных инструментов вроде Excalidraw — уже не «статика плюс тонкий релей», а полноценный бэкенд с базой и headless-браузером под капотом. Официально рекомендуют от 4 ГБ RAM и 2 vCPU для комфортной работы небольшой команды; это ориентир, а не жёсткая граница — при малом числе пользователей может хватить и меньшего объёма, но экспорт с Chromium под капотом первым упрётся в нехватку памяти, если её мало.
Подготовка сервера: Docker, домен, firewall
Понадобится чистый Ubuntu 24.04 и Docker с плагином Compose. Если Docker ещё не стоит — подробный разбор установки с нуля есть в статье про установку Docker на Ubuntu 24.04, здесь — минимальный набор команд:
apt update && apt upgrade -y
apt install -y ca-certificates curl git ufw
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Базовый firewall — открываем только SSH и веб-порты, подробности параметров ufw разобраны отдельно в статье про настройку ufw на Ubuntu 24.04:
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Заведите поддомен (например, design.example.com) и направьте A-запись на IP сервера — она понадобится и для TLS-сертификата, и для переменной PENPOT_PUBLIC_URI на следующем шаге. Если домен для сервера настраиваете впервые, есть отдельный разбор в статье про настройку домена и DNS на Ubuntu 24.04.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОфициальный docker-compose и структура сервисов
Проект поставляет готовый docker-compose.yaml в репозитории — тянуть его руками надёжнее, чем копировать из статей, потому что версии образов и переменные со временем меняются:
mkdir -p /opt/penpot && cd /opt/penpot
curl -o docker-compose.yaml \
https://raw.githubusercontent.com/penpot/penpot/main/docker/images/docker-compose.yaml
Файл поднимает пять сервисов: penpot-frontend, penpot-backend, penpot-exporter, penpot-postgres, penpot-redis — плюс именованные тома под данные Postgres и загруженные пользователями ассеты (обложки, изображения в макетах). По умолчанию penpot-frontend публикует порт 9001 наружу — этого достаточно, чтобы проверить установку по http://IP-сервера:9001 до того, как настроите TLS.
Обратите внимание на два момента, которые стоит проверить в скачанном файле перед запуском:
- Хранение ассетов по умолчанию — на локальном диске через volume
penpot_assets, без внешнего S3. Для одного сервера этого достаточно; если позже понадобится вынести хранилище на объектный сторедж, в проекте есть переменные для подключения S3-совместимого бэкенда — например, самостоятельно поднятого MinIO. - В
docker-compose.yamlиз main-ветки нет открытого наружу порта для Postgres и Redis — они видны только внутри Docker-сети, что уже правильно с точки зрения безопасности и трогать не нужно.
Настройка .env: домен, флаги, регистрация, почта
Ключевая настройка Penpot идёт через переменные окружения — удобнее вынести их в отдельный .env рядом с docker-compose.yaml, чем редактировать сам файл:
cd /opt/penpot
cat > .env <<'EOF'
PENPOT_PUBLIC_URI=https://design.example.com
PENPOT_SECRET_KEY=замените-на-случайную-строку-минимум-32-символа
PENPOT_FLAGS=enable-registration disable-email-verification enable-smtp
PENPOT_SMTP_DEFAULT_FROM=penpot@example.com
PENPOT_SMTP_DEFAULT_REPLY_TO=penpot@example.com
PENPOT_SMTP_HOST=smtp.example.com
PENPOT_SMTP_PORT=587
PENPOT_SMTP_USERNAME=penpot@example.com
PENPOT_SMTP_PASSWORD=пароль-от-smtp
PENPOT_SMTP_TLS=true
EOF
PENPOT_SECRET_KEY сгенерируйте сами, например openssl rand -hex 32 — это ключ, которым backend подписывает сессии, менять его после первого запуска нельзя (все выданные токены станут невалидными).
Флаг PENPOT_FLAGS определяет поведение инстанса построчно через пробел, самые важные дляself-host сценария:
| Флаг | Что делает |
|---|---|
enable-registration | Разрешает создавать аккаунты через форму на фронтенде |
disable-email-verification | Не требует подтверждения почты — удобно, если письма ещё не настроены или инстанс закрытый |
enable-smtp | Включает отправку писем (приглашения, восстановление пароля) через настроенный SMTP |
enable-login-with-ldap | Аутентификация через LDAP, если в компании уже есть каталог пользователей |
Для команды, где регистрация не должна быть публичной, самый частый рабочий сценарий такой: на первом запуске оставить enable-registration, создать нужные аккаунты вручную через форму, затем убрать enable-registration из PENPOT_FLAGS и перезапустить penpot-backend — новые самостоятельные регистрации станут невозможны, а существующие пользователи продолжат работать как обычно.
Пропишите переменные из .env в сервис penpot-backend и penpot-frontend файла docker-compose.yaml (в новых версиях файла для этого уже есть секция env_file: .env — проверьте, что она на месте, иначе добавьте её в оба сервиса).
TLS и домен через Caddy перед penpot-frontend
Сам penpot-frontend отдаёт только HTTP на порту 8080 внутри контейнера — TLS он не терминирует. Проще всего поставить перед ним Caddy отдельным сервисом, он получит сертификат Let's Encrypt автоматически. Логика ACME и параметры разобраны в статье про Caddy с автоматическим SSL, здесь — минимальная конфигурация под Penpot.
Добавьте в docker-compose.yaml сервис caddy, уберите публикацию порта 9001 у penpot-frontend (замените ports на expose: ["8080"]) и добавьте:
caddy:
image: caddy:2-alpine
container_name: penpot-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- penpot-frontend
volumes:
caddy_data:
caddy_config:
Файл /opt/penpot/Caddyfile:
design.example.com {
reverse_proxy penpot-frontend:8080
}
Совместное редактирование в Penpot тоже идёт через websocket, но, в отличие от голого nginx, Caddy 2 определяет апгрейд соединения автоматически — отдельно прописывать заголовки Upgrade/Connection не нужно. Запускаем весь стек:
cd /opt/penpot
docker compose up -d
docker compose logs -f caddy
В логах Caddy должна появиться строка о выпуске сертификата. Если не появляется — проверьте, что A-запись домена уже резолвится на IP сервера и порты 80/443 действительно открыты снаружи (а не только в ufw — некоторые провайдеры дополнительно фильтруют на уровне облачного firewall).
Первый запуск, бэкап и обновление
Откройте https://design.example.com — попадёте на экран входа/регистрации. Создайте первый аккаунт через форму, затем при необходимости отключите enable-registration, как описано выше, и перезапустите backend:
docker compose restart penpot-backend
Данные, которые нужно бэкапить регулярно, — это два места: дамп PostgreSQL (все проекты, файлы, история версий) и volume с ассетами (загруженные изображения):
# дамп базы
docker compose exec penpot-postgres pg_dump -U penpot penpot > /opt/penpot/backups/penpot-$(date +%F).sql
# бэкап тома с ассетами
docker run --rm -v penpot_penpot_assets:/data -v /opt/penpot/backups:/backup \
alpine tar czf /backup/assets-$(date +%F).tar.gz -C /data .
Имя тома с ассетами зависит от того, как назван проект в docker-compose.yaml (Docker подставляет префикс каталога) — точное имя уточните командой docker volume ls | grep penpot. Восстановление — обратная операция: psql для дампа базы и распаковка архива обратно в volume перед повторным запуском стека.
Обновление сводится к загрузке новых образов и перезапуску:
cd /opt/penpot
docker compose pull
docker compose up -d
Перед крупным обновлением backend (особенно при переходе через несколько минорных версий) стоит сначала сделать дамп базы — Penpot накатывает миграции схемы автоматически при старте, и откат назад без бэкапа будет уже не таким тривиальным. Если сервис после обновления не поднимается — первым делом смотрите логи backend:
docker compose logs -f penpot-backend
Отдельная частая проблема именно с Penpot — падение penpot-exporter по памяти на больших макетах: headless Chromium при рендере сложной страницы с множеством слоёв и шрифтов ест заметно больше RAM, чем остальной стек вместе взятый. Если экспорт периодически обрывается, а в docker compose logs penpot-exporter видно ошибки нехватки памяти — это сигнал добавить серверу RAM, а не искать баг в конфигурации.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем self-hosted Penpot отличается от бесплатного облачного penpot.app?
Функциональность редактора та же — это один и тот же открытый код. Разница в том, где физически лежат данные и кто ими управляет: на своём сервере вы сами отвечаете за доступность, бэкапы и обновления, зато не зависите от чужой инфраструктуры и политики доступа.
Можно ли импортировать файлы из Figma?
Penpot умеет импортировать .fig-файлы через встроенный плагин импорта — качество переноса зависит от сложности макета (компоненты, авто-лейауты переносятся не всегда один в один), поэтому после импорта стоит проверить макет вручную.
Нужен ли SMTP обязательно?
Нет, если отключить enable-email-verification и не рассчитывать на восстановление пароля по почте — для закрытой команды из нескольких человек это рабочий вариант. Для инстанса с самостоятельной регистрацией пользователей SMTP всё же нужен — без него не отправить письмо-приглашение и не сбросить пароль.
Как ограничить доступ к инстансу, помимо регистрации через Penpot?
Добавьте Basic Auth на уровне Caddy перед reverse_proxy как дополнительный слой, либо держите Penpot доступным только через VPN/приватную сеть, если он не должен быть виден в интернете вообще.
Сколько диска нужно под растущий инстанс?
Основной рост — том с ассетами (загруженные изображения, экспортированные превью), база данных обычно заметно легче. Точный темп роста зависит от команды и объёма материалов, это стоит закладывать с запасом и мониторить, а не рассчитывать заранее.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →