Standard Notes в Docker Compose: готовый файл
Если вы храните заметки в облачном сервисе, вы доверяете чужому серверу не только текст, но и метаданные — когда писали, как часто открывали, с какого IP. Standard Notes решает это шифрованием на клиенте: сервер видит только зашифрованный блоб, ключ не покидает ваше устройство. Но чтобы получить полный контроль, сервер должен быть тоже вашим. Ниже — рабочий docker-compose.yml для self-hosted Standard Notes Server, с пояснением каждого блока и типичными граблями.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Почему self-hosted, а не облако Standard Notes
Официальный Standard Notes уже шифрует данные end-to-end — это не маркетинг, а архитектура: приложение шифрует заметку локально алгоритмом XChaCha20-Poly1305 (в актуальных версиях протокола 004), и на сервер уходит уже нечитаемый контейнер. Даже если облако Standard Notes скомпрометируют, содержимое заметок не достать без вашего пароля.
Тогда зачем свой сервер? Три причины, с которыми реально сталкиваются:
- Юрисдикция и метаданные. Сервер видит IP, время синхронизаций, размер зашифрованных блобов и структуру тегов. Для дневника это может быть неважно, для рабочих заметок с NDA — уже вопрос.
- Лимиты бесплатного тарифа. Бесплатный аккаунт Standard Notes ограничивает историю версий и часть функций расширений — при самостоятельном хостинге таких ограничений на сервере нет (клиентские фичи, зависящие от подписки, всё равно определяются самим приложением, это стоит проверить отдельно под вашу версию).
- Долговечность формата. Standard Notes годами держит принцип "открытый формат экспорта, который переживёт сам сервис". Свой сервер логично продолжает эту идею — вы не зависите от того, что будет с компанией через 5 лет.
Минус тоже есть, и его нужно проговорить честно: бэкапы, обновления и мониторинг теперь ваша забота. Если вы не готовы хотя бы раз в месяц проверять логи и накатывать обновления — облачная версия окажется надёжнее.
Что входит в стек
Standard Notes Server — это не один контейнер, а набор сервисов, разговаривающих друг с другом. В официальном self-hosted репозитории (standardnotes/server) используется такая схема:
| Сервис | Роль |
|---|---|
syncing-server-js | основной API синхронизации заметок |
auth | регистрация, логин, сессии, ключи шифрования |
api-gateway | единая точка входа, маршрутизация к сервисам |
db (MySQL) | хранение зашифрованных данных пользователей |
cache (Redis) | очереди и кеш сессий |
files (опционально) | серверная часть для вложений через расширение Filesafe |
Разворачивать всё вручную по одному контейнеру — плохая идея: сервисы жёстко завязаны на общие переменные окружения и сеть. Разработчики поддерживают готовый docker-compose.yml в репозитории проекта — берите оттуда актуальную версию, а дальше настраивайте под себя. Ниже — рабочий каркас, который стоит сверить со свежим upstream-файлом перед деплоем (структура сервисов Standard Notes меняется реже, чем у большинства self-hosted проектов, но переменные окружения — стоит перепроверять).
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверГотовый docker-compose.yml
Создайте директорию и файл окружения:
mkdir -p /opt/standardnotes && cd /opt/standardnotes
.env:
# Генерируйте случайные значения, не оставляйте примеры
DB_HOST=db
DB_PORT=3306
DB_DATABASE=standardnotes
DB_USERNAME=standardnotes
DB_PASSWORD=CHANGE_ME_STRONG_PASSWORD
REDIS_URL=redis://cache:6379
# Секреты сессий и шифрования JWT — по 32+ случайных символа каждый
JWT_SECRET=CHANGE_ME_RANDOM_32_CHARS
AUTH_JWT_SECRET=CHANGE_ME_RANDOM_32_CHARS
ENCRYPTION_SERVER_KEY=CHANGE_ME_RANDOM_32_CHARS
PSEUDO_KEY_PARAMS_KEY=CHANGE_ME_RANDOM_32_CHARS
# Публичный адрес, по которому клиенты будут стучаться к API
AUTH_JWT_TTL=60
PUBLIC_HOST=https://notes.example.com
Секреты удобно сгенерировать так, чтобы не подглядывать значения из чужих примеров:
openssl rand -hex 24
docker-compose.yml:
version: "3.8"
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/mysql
networks:
- sn-net
cache:
image: redis:7-alpine
restart: unless-stopped
volumes:
- cache-data:/data
networks:
- sn-net
auth:
image: standardnotes/auth:latest
restart: unless-stopped
env_file: .env
depends_on:
- db
- cache
networks:
- sn-net
syncing-server-js:
image: standardnotes/syncing-server-js:latest
restart: unless-stopped
env_file: .env
depends_on:
- db
- cache
- auth
networks:
- sn-net
api-gateway:
image: standardnotes/api-gateway:latest
restart: unless-stopped
env_file: .env
ports:
- "3000:3000"
depends_on:
- auth
- syncing-server-js
networks:
- sn-net
networks:
sn-net:
driver: bridge
volumes:
db-data:
cache-data:
Запуск:
docker compose up -d
docker compose logs -f api-gateway
Если всё поднялось, api-gateway должен слушать на 3000-м порту и отвечать на health-check без ошибок подключения к MySQL и Redis.
Публикация через reverse proxy с SSL
Отдавать API напрямую по 3000-му порту без TLS нельзя — Standard Notes-клиенты требуют HTTPS для сервера синхронизации, да и открытый порт без шифрования транспорта сводит на нет весь смысл затеи с приватностью. Поставьте перед стеком reverse proxy — Caddy проще всего заводит автоматический SSL:
notes.example.com {
reverse_proxy localhost:3000
}
Один блок конфига, и Caddy сам получит сертификат Let's Encrypt и продлит его. Если вы уже используете nginx на сервере под другие сайты, добавьте отдельный server-блок с proxy_pass http://127.0.0.1:3000; и получите сертификат через certbot. Разница подходов и когда что выбирать разобрана в статье Caddy или nginx — что выбрать для сервера.
Не забудьте прокинуть домен в DNS на IP сервера заранее — без A-записи ни Caddy, ни certbot сертификат не выпустят.
Подключение клиентов
После того как https://notes.example.com отдаёт корректный SSL, в приложении Standard Notes (веб, десктоп, мобильное) на экране входа выберите "Advanced options" → "Custom sync server" и укажите ваш адрес. Дальше — обычная регистрация: приложение сгенерирует ключи шифрования локально, на сервер уйдёт только зашифрованный контейнер данных.
Важный нюанс: если вы позже смените адрес сервера или потеряете пароль восстановления, расшифровать старые заметки без ключа не сможет никто — ни вы, ни разработчики Standard Notes, ни мы. Это плата за настоящее сквозное шифрование, а не недоработка. Сохраните пароль восстановления (recovery codes) в отдельном защищённом месте отдельно от самого сервера.
Бэкапы и обновления
Зашифрованные данные лежат в MySQL-томе db-data. Бэкапить нужно именно его — дамп базы уже содержит зашифрованный контент, расшифровать который без клиентских ключей всё равно нельзя, так что можно не переживать за хранение дампа на третьем сервере:
docker compose exec db mysqldump -u root -p${DB_PASSWORD} ${DB_DATABASE} > backup-$(date +%F).sql
Заведите это в cron и складывайте архивы за пределами сервера — на объектное хранилище или второй VPS. Если нужен инструмент посерьёзнее ежедневного dump'а, посмотрите на BorgBackup в Docker Compose — дедупликация и шифрование бэкапа "на лету" пригодятся, даже если основные данные уже зашифрованы на уровне приложения.
Обновление стека — обычная процедура для Compose-проектов:
docker compose pull
docker compose up -d
Перед обновлением на проде стоит сначала прогнать его на тестовом сервере с копией базы — у Standard Notes Server бывают миграции схемы между релизами, и откатить их назад сложнее, чем накатить вперёд.
Альтернативы, если Standard Notes не подошёл
Прежде чем разворачивать сервер, стоит понимать, чем Standard Notes отличается от соседей по нише self-hosted заметок:
- Trilium Notes — куда богаче по структуре: иерархия заметок, связи между ними, скрипты. Шифрование там опциональное и по отдельным заметкам, а не сквозное по умолчанию. Смотрите Trilium в Docker Compose, если важнее гибкость структуры, чем приватность "из коробки".
- CryptPad — тоже шифрование на клиенте, но заточен под совместные документы и таблицы, а не под личный архив заметок. Разворачивается через CryptPad в Docker Compose.
- Joplin Server — синхронизация заметок с опциональным E2E-шифрованием (нужно включить отдельно, по умолчанию выключено), богатая экосистема плагинов.
Если приоритет — именно шифрование по умолчанию без возможности случайно его отключить, Standard Notes остаётся самым прямолинейным выбором среди self-hosted заметочников.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужен ли отдельный сервер только под Standard Notes, или можно на общем VPS?
Можно на общем — стек лёгкий (MySQL + Redis + три Node-сервиса), 1-2 GB RAM достаточно для личного и небольшого командного использования. На VPS с другими сервисами просто убедитесь, что порт 3000 не конфликтует и proxy настроен на отдельный домен.
Что будет, если я потеряю пароль от аккаунта?
Без пароля или сохранённых recovery codes расшифровать заметки невозможно в принципе — это и есть сквозное шифрование. Сервер не хранит ключ, и обойти это административно нельзя. Сохраняйте recovery codes сразу при регистрации.
Можно ли перенести заметки с облачного Standard Notes на свой сервер?
Да — в приложении есть экспорт всех заметок в незашифрованный или зашифрованный JSON-файл (Settings → Data → Export), а на новом сервере после регистрации — импорт того же файла. Это тот самый принцип "открытый формат, который переживёт сервис".
Чем self-hosted версия отличается по функциональности от облачной?
Ядро синхронизации и шифрования одинаковое. Отличия — в клиентских расширениях, которые в официальном облаке идут по подписке (продвинутая история версий заметок, некоторые темы и редакторы); на своём сервере такие функциональные ограничения снимаются, если сама версия клиента их поддерживает без проверки подписки — стоит свериться с документацией конкретного релиза.
Стоит ли использовать сквозное шифрование, если сервер и так мой?
Да — оно защищает не только от чужого сервера, но и от кражи диска, ошибки конфигурации бэкапа, случайно расшаренного дампа базы. Шифрование на клиенте — это защита данных независимо от того, что происходит с инфраструктурой.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →