MAATRIX / Блог / Baïkal в Docker Compose: готовый файл

Baïkal в Docker Compose: готовый файл

MAATRIX

Если вы устали от того, что календарь и контакты живут в чужом облаке, а синхронизация между телефоном, ноутбуком и рабочим компьютером то работает, то нет — самое время поставить свой CalDAV/CardDAV-сервер. Baïkal делает это без боли: лёгкий PHP-движок, встроенная веб-панель администрирования и полная поддержка стандартных протоколов, которые понимают iPhone, Android, Thunderbird и любой другой клиент. Ниже — рабочий docker-compose.yml, который поднимает Baïkal с нуля и переживает перезапуски сервера.

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

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

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

Что такое Baïkal и зачем он вам

Baïkal — это открытый сервер календарей и адресных книг на базе sabre/dav, той же библиотеки, что лежит в основе многих корпоративных CalDAV-решений. По сути это лёгкая альтернатива Nextcloud, если вам не нужны файлы, фото и десяток других модулей — только календарь и контакты, но зато без раздутого интерфейса и с минимальным потреблением ресурсов.

Типичные сценарии использования:

  • Личный или семейный календарь, синхронизированный между всеми устройствами без Google/Apple аккаунта.
  • Контакты (адресная книга) для небольшой команды или семьи с общим доступом.
  • Бэкенд для расписания встреч, который потом подключается к другим сервисам через CalDAV API.

Веб-панель администрирования Baïkal позволяет создавать пользователей, календари и адресные книги без единой команды в консоли — это отличает его от «голого» sabre/dav или Radicale, где всё настраивается через конфиг-файлы.

Требования к серверу

Baïkal — очень лёгкое приложение, оно не требует мощного сервера. Для личного использования или небольшой команды (до 10-15 пользователей) хватит минимальной конфигурации:

РесурсМинимумКомфортно
CPU1 vCPU1-2 vCPU
RAM512 МБ1 ГБ
Диск5 ГБ10-15 ГБ (с запасом под бэкапы)
ОСUbuntu 22.04/24.04Ubuntu 24.04 LTS

Если сервер уже используется под другие сервисы (например, тот же VPS с почтой или сайтом), Baïkal спокойно уживётся рядом — он практически не нагружает CPU в состоянии покоя, единственное потребление ресурсов приходится на синхронизацию клиентов раз в несколько минут.

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

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

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

Структура проекта и docker-compose.yml

Создаём рабочую директорию и файлы конфигурации:

mkdir -p /opt/baikal/{config,data}
cd /opt/baikal

Файл docker-compose.yml:

services:
  baikal:
    image: ckulka/baikal:nginx
    container_name: baikal
    restart: unless-stopped
    ports:
      - "8800:80"
    volumes:
      - ./config:/var/www/baikal/config
      - ./data:/var/www/baikal/Specific
    environment:
      - TZ=Europe/Moscow

Здесь используется готовый образ ckulka/baikal со встроенным nginx и PHP-FPM — не нужно поднимать отдельный веб-сервер. Директория config хранит настройки самого приложения (создаётся при первом запуске мастером установки), Specific (в docker-compose смонтирована как data) — базу данных SQLite, если вы не подключаете внешний MySQL/PostgreSQL.

Порт 8800 выбран произвольно, чтобы не конфликтовать с другими сервисами на сервере — измените под свою схему портов.

Запускаем:

docker compose up -d

Проверяем, что контейнер поднялся и слушает порт:

docker compose ps
curl -I http://localhost:8800

Ожидаемый ответ — HTTP/1.1 302 Found с редиректом на /admin/install/ (мастер первичной настройки).

Вариант с MySQL вместо SQLite

Для команды больше 10-15 человек или если вы уже гоняете бэкапы через MySQL-дамп, разумнее использовать полноценную СУБД вместо SQLite-файла. Вот вариант с MariaDB:

services:
  baikal-db:
    image: mariadb:11
    container_name: baikal-db
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=change_me_root
      - MYSQL_DATABASE=baikal
      - MYSQL_USER=baikal
      - MYSQL_PASSWORD=change_me_db
    volumes:
      - ./mysql-data:/var/lib/mysql

  baikal:
    image: ckulka/baikal:nginx
    container_name: baikal
    restart: unless-stopped
    depends_on:
      - baikal-db
    ports:
      - "8800:80"
    volumes:
      - ./config:/var/www/baikal/config
      - ./data:/var/www/baikal/Specific
    environment:
      - TZ=Europe/Moscow

Обратите внимание: образ ckulka/baikal не подхватывает параметры БД через переменные окружения автоматически — тип хранилища и данные подключения указываются в самом мастере установки (/admin/install/), где на шаге настройки БД вы выбираете MySQL и вводите хост baikal-db, имя базы, пользователя и пароль, заданные выше.

Замените change_me_root и change_me_db на реальные пароли — генерировать их удобно так:

openssl rand -base64 24

Настройка через веб-панель администрирования

После первого запуска открываем http://ваш-сервер:8800/admin/install/ и проходим мастер установки:

  1. Часовой пояс — выбираем ваш регион (важно для корректных напоминаний в календаре).
  2. Тип хранилища — SQLite (по умолчанию) или MySQL, если настроили по варианту выше.
  3. Учётная запись администратора — логин и пароль для панели /admin/.

После установки заходим в /admin/ под созданным аккаунтом и создаём:

  • Пользователей (Users) — по одному на каждого, кто будет синхронизировать календарь/контакты.
  • Календари (Calendars) — можно создать несколько на пользователя (личный, рабочий, общий).
  • Адресные книги (Address Books) — аналогично, можно разделить контакты по назначению.

Дальше открывается страница /dav.php — именно этот URL используется для подключения клиентов, полный адрес для конкретного календаря выглядит так:

https://cal.example.com/dav.php/calendars/username/calendar-name/

Подключение клиентов (iPhone, Android, Thunderbird)

Baïkal реализует стандартные протоколы CalDAV и CardDAV, поэтому подключение занимает пару минут в любом клиенте.

iOS (Настройки → Календарь → Учётные записи → Добавить учётную запись → Другая):

  • Сервер: cal.example.com
  • Путь: /dav.php/calendars/username/calendar-name/
  • Логин/пароль — от созданного пользователя Baïkal.

Android — напрямую CalDAV не поддерживается системными приложениями, нужен клиент вроде DAVx⁵ (свободное приложение, доступно в F-Droid и Google Play). В нём указываете базовый URL https://cal.example.com/dav.php/ и логин/пароль — DAVx⁵ сам обнаружит доступные календари и адресные книги.

Thunderbird — через расширение TbSync или встроенную поддержку CalDAV: Календарь → Новый календарь → В сети, вводите тот же URL.

Важный нюанс: Baïkal должен быть доступен по HTTPS, иначе iOS и многие клиенты откажутся синхронизироваться (или будут ругаться предупреждениями о небезопасном соединении). Для базовой публикации проще всего поставить перед контейнером Baïkal reverse proxy с автоматическим SSL — например, Traefik, который сам получает и продлевает сертификаты Let's Encrypt.

Reverse proxy, HTTPS и безопасность

Минимальный вариант — Nginx на хосте с проксированием на порт контейнера:

server {
    listen 443 ssl http2;
    server_name cal.example.com;

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

    location / {
        proxy_pass http://127.0.0.1:8800;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    client_max_body_size 20M;
}

Сертификат получаем через certbot — подробный разбор есть в статье про настройку Let's Encrypt SSL на VPS. Если предпочитаете полностью контейнерный подход без ручного certbot на хосте, логичнее сразу взять Traefik или Caddy — они получают сертификаты автоматически и продлевают их без вашего участия.

Дополнительно стоит:

  • Закрыть порт 8800 от внешнего доступа (ufw deny 8800), оставив только 443 через прокси.
  • Включить fail2ban с фильтром на брутфорс /dav.php — Baïkal не блокирует подбор паролей сам по себе.
  • Использовать сложные пароли для каждого пользователя, особенно если сервер доступен из интернета.

Бэкапы и обновление

Все данные Baïkal лежат в двух местах: ./config (настройки приложения) и ./data (база SQLite или файлы, специфичные для инсталляции). Если используете MySQL — добавьте бэкап базы отдельно.

Простой скрипт бэкапа:

#!/bin/bash
DATE=$(date +%Y%m%d)
tar -czf /backups/baikal-$DATE.tar.gz -C /opt/baikal config data
# если используется MySQL:
docker exec baikal-db mysqldump -u baikal -pchange_me_db baikal > /backups/baikal-db-$DATE.sql
find /backups -name "baikal-*" -mtime +14 -delete

Для более надёжной схемы с версионированием и дедупликацией имеет смысл взглянуть на Baïkal в связке с BorgBackup — он экономит место при регулярных снапшотах.

Обновление до новой версии:

cd /opt/baikal
docker compose pull
docker compose up -d

Образ сам применит миграции базы при следующем обращении к /admin/ — перед обновлением на проде всё же рекомендуется сделать бэкап (см. выше).

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

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

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

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

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

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

Чем Baïkal отличается от Nextcloud для календаря?

Baïkal — это только CalDAV/CardDAV, без файлового хранилища, заметок и остальных модулей Nextcloud. Он легче, быстрее стартует и требует меньше ресурсов, если календарь — единственное, что вам нужно.

Можно ли использовать Baïkal вместе с Google Calendar?

Нативной двусторонней синхронизации с Google нет. Если нужен мост, придётся использовать сторонние инструменты синхронизации (например, через промежуточные скрипты на CalDAV/Google API) — это отдельная и не всегда надёжная задача.

Почему iPhone не подключается к календарю?

Чаще всего причина — отсутствие HTTPS или самоподписанный сертификат. iOS требует валидный SSL-сертификат для CalDAV-подключений в большинстве случаев, поэтому reverse proxy с Let's Encrypt обязателен для мобильных клиентов.

Нужен ли отдельный сервер под Baïkal?

Нет, это очень лёгкое приложение — спокойно работает на минимальном VPS вместе с другими сервисами (сайтом, почтой, другими Docker-контейнерами), не требуя выделенных ресурсов.

Как перенести данные при миграции на другой сервер?

Достаточно скопировать директории config и data (либо дамп MySQL, если использовали её) на новый сервер и поднять тот же docker-compose.yml — Baïkal подхватит существующую конфигурацию без переустановки.

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

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

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