MAATRIX / Блог / Penpot на Ubuntu 24.04: пошаговая установка

Penpot на Ubuntu 24.04: пошаговая установка

MAATRIX

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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →