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

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

MAATRIX

Если Google Docs или даже самохостнутый Nextcloud с Collabora вас не устраивают по одной конкретной причине — вы не хотите, чтобы содержимое документов вообще было доступно серверу, — вариант один: CryptPad. Это редактор документов, таблиц, презентаций и канбан-досок с шифрованием на стороне браузера: сервер хранит только зашифрованный блоб и никогда не видит открытый текст. Ниже — рабочая установка из исходников на Ubuntu 24.04, с двумя доменами (это обязательное требование самого CryptPad) и nginx перед ним.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

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

Что такое CryptPad и как устроено шифрование

CryptPad — открытый (AGPL) пакет офисных инструментов: текстовый редактор, таблицы, презентации, код, канбан-доски, опросы и общий диск (Drive). Ключевое отличие от Nextcloud+Collabora или OnlyOffice в том, что шифрование и расшифровка происходят в браузере — ключ пада живёт во фрагменте ссылки (после #), который браузер по определению не отправляет на сервер. Сервер физически хранит только шифротекст в файловой системе и не может ни прочитать содержимое пада, ни восстановить его без ссылки.

Из этого вытекает практическое следствие: если пользователь потеряет ссылку на пад (или удалит её из истории браузера), восстановить документ вы как администратор сервера не сможете — у вас на диске лежит только шифрованный блоб. Это плата за приватность, и её стоит явно проговорить с командой перед началом использования.

Второе следствие архитектуры — CryptPad требует два разных домена (или поддомена): основной, где живёт интерфейс, и «песочница» (sandbox), с которого подгружается содержимое конкретных падов в iframe. Разделение доменов — не прихоть, а часть модели безопасности: изоляция origin не даёт скомпрометированному содержимому одного пада получить доступ к куки и localStorage основного домена.

Требования перед установкой

Подготовьте заранее:

  • Два поддомена, например pad.example.com (основной) и pad-sandbox.example.com (песочница), оба указывающие A-записью на IP вашего сервера.
  • Ubuntu 24.04 LTS, минимум 2 vCPU / 4 ГБ RAM для команды до 10–15 человек — это ориентир, не точный расчёт: реальное потребление CPU растёт при интенсивном совместном редактировании больших документов, а место на диске — с ростом библиотеки файлов, которые в CryptPad не дедуплицируются (каждый блоб зашифрован своим ключом).
  • Node.js актуальной LTS-ветки — версия из штатного репозитория Ubuntu 24.04 обычно отстаёт от требований CryptPad, поэтому ставим через NodeSource (ниже) или nvm. Точную минимальную версию всегда сверяйте в package.json репозитория на момент установки — требования CryptPad периодически поднимаются вместе с релизами.
  • git, build-essential для сборки нативных зависимостей.
  • Nginx — можно взять за основу настройку nginx как reverse proxy.
  • Домены, готовые к выпуску SSL-сертификатов Let's Encrypt для обоих origin.

Проверка версии системы:

lsb_release -a
# Description: Ubuntu 24.04.x LTS

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка Node.js и системных зависимостей

Ставим Node.js из репозитория NodeSource (актуальную LTS на момент установки), плюс инструменты для сборки:

sudo apt update
sudo apt install -y ca-certificates curl gnupg build-essential git

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs

node --version
npm --version

Создаём отдельного системного пользователя — CryptPad не должен работать из-под root:

sudo adduser --system --group --home /opt/cryptpad cryptpad

Сборка CryptPad из исходников

CryptPad распространяется только в виде исходников — официального Docker-образа с полной поддержкой у проекта исторически не было, ставить принято именно через git и сборку. Клонируем и собираем от имени созданного пользователя:

sudo -u cryptpad git clone https://github.com/cryptpad/cryptpad.git /opt/cryptpad/app
cd /opt/cryptpad/app

sudo -u cryptpad npm ci
sudo -u cryptpad npm run build

Сборка (npm run build) компилирует и минифицирует клиентский код — на слабом сервере (1–2 vCPU) она может занять несколько минут, это нормально. Если сборка падает с ошибкой нехватки памяти — временно добавьте своп:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Настройка config.js и systemd-сервис

Копируем пример конфига и правим под свои домены:

sudo -u cryptpad cp config/config.example.js config/config.js
sudo -u cryptpad nano config/config.js

Ключевые параметры, которые обязательно нужно поменять:

// config/config.js
httpUnsafeOrigin: 'https://pad.example.com',
httpSafeOrigin: 'https://pad-sandbox.example.com',

httpAddress: '127.0.0.1',
httpPort: 3000,

adminEmail: 'admin@example.com',

// список публичных ключей администраторов, изначально пустой
adminKeys: [
],

httpAddress: '127.0.0.1' держит Node.js-процесс недоступным напрямую снаружи — весь внешний трафик пойдёт через nginx с SSL. Оставлять сервис смотрящим наружу без reverse proxy не стоит: CryptPad сам не занимается TLS-терминацией.

Запуск через systemd:

# /etc/systemd/system/cryptpad.service
[Unit]
Description=CryptPad server
After=network.target

[Service]
Type=simple
User=cryptpad
Group=cryptpad
WorkingDirectory=/opt/cryptpad/app
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now cryptpad
sudo systemctl status cryptpad

Если сервис не стартует — первым делом смотрите журнал:

sudo journalctl -u cryptpad -n 50 --no-pager

Чаще всего проблема в правах на директорию /opt/cryptpad/app (процесс должен работать строго от пользователя cryptpad, а не root) либо в занятом порту 3000.

Nginx как reverse proxy и SSL для двух доменов

Здесь важное отличие от типовой установки за nginx: нужны два server-блока по числу доменов, оба проксирующие на один и тот же локальный порт 3000, и с рядом заголовков безопасности, которые CryptPad ожидает от фронта. В репозитории есть эталонный пример cryptpad.nginx — берите его за основу, ниже упрощённый вариант с ключевыми частями:

# /etc/nginx/sites-available/pad.example.com
server {
    listen 80;
    server_name pad.example.com pad-sandbox.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name pad.example.com pad-sandbox.example.com;

    ssl_certificate     /etc/letsencrypt/live/pad.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pad.example.com/privkey.pem;

    client_max_body_size 150M;

    # заголовки изоляции, нужны для WebAssembly-криптографии в браузере
    add_header Cross-Origin-Resource-Policy cross-origin always;
    add_header Cross-Origin-Opener-Policy same-origin always;
    add_header Cross-Origin-Embedder-Policy require-corp always;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 3600s;
    }
}

Обратите внимание на client_max_body_size — по умолчанию nginx режет загрузку файлов на 1 МБ, а в CryptPad Drive пользователи будут закидывать файлы заметно больше. proxy_read_timeout увеличен по той же причине, что и для любого совместного редактора с постоянным WebSocket-соединением: короткий таймаут будет рвать активные сессии.

Выпуск сертификата сразу на оба домена одной командой:

sudo ln -s /etc/nginx/sites-available/pad.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d pad.example.com -d pad-sandbox.example.com

Если certbot ругается на один из доменов — проверьте, что A-запись обновилась именно для обоих поддоменов, а не только для основного; разбор частых причин отказа — в статье про ошибки Let's Encrypt.

Первый запуск, права администратора и бэкапы

Откройте https://pad.example.com в браузере — должна открыться страница входа CryptPad. Зарегистрируйте первый аккаунт (регистрация локальная, никакой внешний сервис не задействован), затем выдайте ему права администратора:

  1. Войдите под этим аккаунтом → Settings → раздел с ключами аккаунта → скопируйте свой публичный подписывающий ключ (Public Signing Key).
  2. Вставьте его в config/config.js в массив adminKeys:
adminKeys: [
  'ВАШ_PUBLIC_SIGNING_KEY',
],
  1. Перезапустите сервис:
sudo systemctl restart cryptpad

После этого у аккаунта появляется пункт Admin panel — там видна статистика инстанса, список пользователей (по псевдонимам, не по содержимому), можно настраивать квоты и лимиты регистрации.

Данные пользователей лежат на диске в директориях datastore/ и blob/ внутри /opt/cryptpad/app — именно их нужно резервировать. Поскольку каждый файл зашифрован своим ключом, обычное сжатие бэкапа даёт слабый эффект (энтропия шифротекста высокая), но дедупликация по неизменным блокам всё равно работает, если файл не менялся между бэкапами — этим удобно пользоваться в BorgBackup. Разобраться с самой настройкой бэкапов можно в статье про BorgBackup на Ubuntu 24.04, а базовую защиту самого сервера — брутфорс SSH, файрвол, fail2ban — стоит закрыть отдельно, см. базовую защиту Ubuntu от взлома.

Обновление CryptPad — это git pull плюс пересборка:

cd /opt/cryptpad/app
sudo -u cryptpad git pull
sudo -u cryptpad npm ci
sudo -u cryptpad npm run build
sudo systemctl restart cryptpad

Перед обновлением на проде обязательно сверьтесь с release notes в репозитории — иногда меняется формат конфига, и после git pull нужно вручную перенести новые поля из обновлённого config.example.js.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем CryptPad принципиально отличается от Collabora Online или OnlyOffice?

Те рендерят документы на сервере — сервер в моменте видит открытое содержимое файла, пусть и не хранит его в открытом виде постоянно. CryptPad шифрует контент в браузере, и сервер работает только с шифротекстом, никогда не имея ключа расшифровки. Плата за это — свой формат хранения данных вместо привычных .docx/.xlsx на диске сервера и невозможность администратору восстановить документ при утере ссылки.

Обязательно ли использовать два разных домена?

Да, это часть модели безопасности CryptPad — так реализована изоляция origin для содержимого падов. Работать на одном домене без sandbox origin можно только с существенно урезанной защитой от XSS внутри отдельных документов, штатно это не поддерживается.

Можно ли поставить CryptPad в Docker?

Сообщество поддерживает неофициальные Docker-образы, но исторически проект рекомендует именно сборку из исходников как основной путь установки — это даёт больше контроля над версией Node.js и процессом обновления. Если предпочитаете контейнеры, изучите Dockerfile в самом репозитории перед тем как брать сторонний образ в прод.

Сколько места на диске нужно закладывать?

Точный расчёт зависит от того, сколько файлов заливают пользователи и как часто — зашифрованные данные не сжимаются и не дедуплицируются между разными файлами. Для команды из нескольких человек с документами и таблицами без тяжёлых вложений старта в 20–40 ГБ обычно достаточно с запасом, но это ориентир — стоит мониторить занятое место и расширять диск по факту.

Что будет, если я потеряю ссылку на важный пад?

Без ссылки (точнее — без ключа во фрагменте после #) восстановить содержимое невозможно даже администратору сервера. Единственная защита — Drive аккаунта, где сохранённые в него пады остаются доступными по логину, поэтому важные документы стоит сразу сохранять в личный Drive, а не полагаться только на прямую ссылку.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

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