DAViCal в Docker Compose: готовый файл
Если команде нужен не просто личный календарь, а общий сервер с несколькими пользователями, разделяемыми календарями переговорок и внятной моделью прав — Radicale и Baïkal быстро упираются в потолок своих возможностей. DAViCal старше и выглядит скромнее, но именно он много лет остаётся рабочей лошадкой у хостеров и внутри компаний, потому что построен на PostgreSQL и с самого начала проектировался для многопользовательских сценариев. Ниже — рабочий docker-compose.yml, который поднимает DAViCal с базой данных и объясняет, где у этого решения острые углы.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое DAViCal и когда он оправдан
DAViCal — CalDAV/CardDAV-сервер на PHP, который хранит все данные в PostgreSQL и реализует стандарт RFC 4791 (CalDAV) и RFC 6352 (CardDAV) с поддержкой ACL на уровне principals — то есть у каждого пользователя, группы или ресурса (переговорки, проектора, служебной машины) есть своя учётная запись с собственными правами на чтение и запись в конкретные календари. Проект живёт с середины 2000-х, активно им пользовались хостинг-провайдеры для предоставления календарных сервисов клиентам, и заброшенным его назвать нельзя: репозиторий на GitHub получает коммиты, хотя ритм разработки далёк от модных SaaS-стартапов.
Где DAViCal реально выигрывает у более молодых альтернатив:
- Ресурсы как отдельные сущности. Переговорку или служебный автомобиль можно завести как principal с собственным календарём и дать сотрудникам право «предложить бронирование», которое утверждает ответственный.
- Гибкие ACL. Права выдаются не файлом конфигурации, а через административный веб-интерфейс — можно дать бухгалтерии доступ на чтение календаря отпусков, не открывая туда запись.
- PostgreSQL под капотом. Если у вас уже крутится Postgres для других сервисов, DAViCal логично встраивается в ту же инфраструктуру бэкапов и мониторинга.
Минусы тоже стоит проговорить сразу: администраторский UI выглядит так, будто его не трогали лет пятнадцать (потому что почти так и есть), у проекта нет мастера первоначальной настройки как у Baïkal, а схему базы приходится инициализировать вручную SQL-скриптами. Если нужен сервер на одного-двух пользователей без ресурсов и сложных прав — Radicale или Baïkal поднимутся быстрее. DAViCal имеет смысл, когда календарём пользуется команда от пяти человек с реальной потребностью в ролях и общих ресурсах.
Из чего состоит стек: PostgreSQL, Apache и PHP
Официальной Docker-поставки от команды DAViCal нет — проект исторически распространяется как пакет для Debian/Ubuntu (apache2 + php + davical + библиотека awl) либо разворачивается вручную из исходников. В контейнерном виде используются сборки сообщества, которые упаковывают тот же стек в один образ. Прежде чем брать первый попавшийся образ с Docker Hub, проверьте две вещи в его README: версию PHP и DAViCal, которой он соответствует, и какими переменными окружения задаётся подключение к базе — у разных сборок имена отличаются, и это единственное реально уязвимое место автоматизации.
Схема простая:
- PostgreSQL — единственное хранилище данных: пользователи, календари, события, адресные книги, ACL.
- Apache + PHP — отдаёт CalDAV/CardDAV-эндпоинты и веб-интерфейс администратора.
- Инициализация схемы — при первом запуске нужно накатить SQL-скрипты из каталога
dba/образа (они идут в комплекте с пакетом davical) — это создание ролей, таблиц, функций и базовых данных.
Ниже — compose-файл, рассчитанный именно на такую связку: отдельный контейнер PostgreSQL плюс контейнер с Apache/PHP/DAViCal.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверГотовый docker-compose.yml
services:
davical-db:
image: postgres:16-alpine
container_name: davical-db
restart: unless-stopped
environment:
POSTGRES_USER: davical_app
POSTGRES_PASSWORD: change_me_strong_password
POSTGRES_DB: davical
volumes:
- davical_db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U davical_app -d davical"]
interval: 10s
timeout: 5s
retries: 5
networks:
- davical_net
davical:
image: robbertkl/davical:latest
container_name: davical
restart: unless-stopped
depends_on:
davical-db:
condition: service_healthy
environment:
TZ: Europe/Moscow
DB_HOST: davical-db
DB_NAME: davical
DB_USER: davical_app
DB_PASS: change_me_strong_password
DAVICAL_DOMAIN: caldav.example.com
DAVICAL_ADMIN_EMAIL: admin@example.com
ports:
- "127.0.0.1:8080:80"
volumes:
- davical_data:/var/lib/davical
networks:
- davical_net
volumes:
davical_db_data:
davical_data:
networks:
davical_net:
driver: bridge
Порт Apache намеренно опубликован только на 127.0.0.1 — наружу сервис отдаёт HTTPS-прокси (об этом ниже), а не голый HTTP-контейнер. Перед запуском обязательно замените change_me_strong_password на реальный пароль в обеих секциях (davical-db и davical) и укажите свой домен в DAVICAL_DOMAIN. Если возьмёте другой community-образ, сверьте имена переменных с его документацией — принцип работы у всех один и тот же: контейнер должен знать хост, имя базы, пользователя и пароль PostgreSQL.
Инициализация базы и первый вход администратора
Поднимаем стек:
docker compose up -d
docker compose logs -f davical
При первом старте большинство образов сами накатывают схему DAViCal на пустую базу — в логах вы увидите вывод SQL-скриптов из каталога dba/ (создание ролей, таблиц usr, caldav_props, collection, функций и т.д.). Если образ этого не делает автоматически, схему накатывают вручную, зайдя внутрь контейнера:
docker compose exec davical bash
cd /usr/share/davical/dba
./create-database.sh -h davical-db -U davical_app -d davical
Точное имя и путь скрипта зависят от версии пакета — смотрите содержимое /usr/share/davical/dba/ или /var/www/davical/dba/ внутри контейнера, если команда выше не найдётся.
После накатки схемы в базе появляется учётная запись администратора по умолчанию — обычно admin с паролем admin (или паролем, заданным при накатке). Первым делом:
- Откройте
http://127.0.0.1:8080/davical/(или через настроенный ниже reverse-proxy) и войдите подadmin. - Сразу смените пароль администратора в разделе Administration → Users.
- Создайте учётную запись под каждого реального пользователя — DAViCal требует явного создания principal на каждого человека, автоматической регистрации нет.
- Для переговорки или ресурса создайте отдельного principal с типом «Resource» и выдайте нужным пользователям права на бронирование в разделе Manage collections.
Это самый нетерпимый к спешке этап: DAViCal не прощает пропущенных прав — если пользователь не видит свой календарь, чаще всего дело в ACL, а не в клиенте.
Подключение календарей и адресных книг клиентов
CalDAV- и CardDAV-адреса в DAViCal строятся по предсказуемому шаблону:
https://caldav.example.com/davical/caldav.php/<username>/calendar/
https://caldav.example.com/davical/caldav.php/<username>/addresses/
Практика подключения по клиентам:
- macOS Calendar / Contacts. Настройки → Интернет-аккаунты → Добавить учётную запись → CalDAV, тип «Расширенный», указать URL сервера и логин/пароль.
- Thunderbird. Через встроенную поддержку CalDAV (меню календаря → «Новый календарь» → «В сети») — вставляете полный URL до конкретного календаря.
- Android. Штатной поддержки CalDAV в системе нет, практически все ставят DAVx5 — вводите базовый URL
https://caldav.example.com/davical/и логин, приложение само находит доступные календари и адресные книги через discovery. - Outlook. Нативной поддержки CalDAV у Outlook нет, нужен коннектор вроде CalDAV Synchronizer — это отдельная настройка, не входящая в объём этой статьи.
Автообнаружение по /.well-known/caldav и /.well-known/carddav в стандартной поставке DAViCal не настроено «из коробки» — если хотите, чтобы клиенты находили сервер по одному домену без полного пути, добавьте в конфиг веб-сервера редиректы на caldav.php/carddav.php вручную.
HTTPS через reverse-proxy
CalDAV-клиенты, особенно на iOS и macOS, крайне нетерпимы к самоподписанным сертификатам — авторизация может просто молча не проходить. Контейнер выше отдаёт голый HTTP на 127.0.0.1:8080, поэтому перед ним нужен TLS-терминатор. Минимальный вариант на Traefik:
davical:
# ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.davical.rule=Host(`caldav.example.com`)"
- "traefik.http.routers.davical.entrypoints=websecure"
- "traefik.http.routers.davical.tls.certresolver=letsencrypt"
- "traefik.http.services.davical.loadbalancer.server.port=80"
networks:
- davical_net
- traefik_net
и уберите публикацию ports: 8080:80, оставив сервис доступным только внутри docker-сети с Traefik. Если вы ещё не поднимали Traefik на сервере — полный разбор с сертификатами есть в статье про Traefik как reverse-proxy для Docker. Вариант с nginx работает так же: proxy_pass на 127.0.0.1:8080, но обязательно проксируйте заголовок Authorization и методы PROPFIND/REPORT/MKCALENDAR — некоторые типовые конфиги nginx по умолчанию режут нестандартные HTTP-методы, и CalDAV-клиенты перестают работать без внятной ошибки в логах.
Отдельно про базу: если вы разворачиваете DAViCal не первым сервисом на сервере и уже управляете PostgreSQL вручную (а не только контейнером из compose-файла), пригодится общий разбор установки и настройки в статье про PostgreSQL на Ubuntu 24.04 — те же принципы бэкапов и мониторинга применимы и к базе DAViCal.
Бэкап и обслуживание
Все данные DAViCal живут в PostgreSQL, поэтому бэкап сервиса — это бэкап одной базы:
docker compose exec davical-db pg_dump -U davical_app davical > davical_backup_$(date +%F).sql
Восстановление — обратная операция через psql на пустую базу с той же схемой. Дополнительно бэкапьте volume davical_data — там могут лежать загруженные вложения к событиям и файл конфигурации, если образ хранит его вне переменных окружения.
По обслуживанию — три вещи:
- Обновления образа выходят редко. Это не баг, а особенность зрелого проекта. Перед обновлением на новую версию делайте дамп базы: миграции схемы иногда требуют ручного запуска upgrade-скриптов из
dba/. - PostgreSQL — узкое место по производительности. На команду до 30-50 активных пользователей хватает 1-2 vCPU и 2 ГБ RAM с запасом; при росте синхронизаций от мобильных клиентов первым упирается диск под WAL, а не CPU.
- Логи Apache — основной источник диагностики. Если клиент получает 401 или 403,
docker compose logs davicalпочти всегда указывает, какого доступа не хватает.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем DAViCal принципиально отличается от Radicale и Baïkal?
Все три — CalDAV/CardDAV-серверы, но DAViCal хранит данные в PostgreSQL и рассчитан на многопользовательские сценарии с ролями и ресурсами из коробки; Radicale хранит календари в файлах и проще в развёртывании, но управление правами там минимальное; Baïkal ближе к DAViCal по возможностям, но использует MySQL/SQLite и более современный веб-интерфейс.
Можно ли перенести календари из Google Calendar или Nextcloud в DAViCal?
Да, экспортом в формате .ics с последующим импортом через клиент (например, Thunderbird умеет читать .ics-файл и записывать события в подключённый CalDAV-календарь) — прямого миграционного инструмента у DAViCal нет.
DAViCal поддерживает CardDAV для контактов?
Да, полноценно — адресные книги создаются так же, как календари, через раздел управления коллекциями в админке.
Нужен ли отдельный сервер под DAViCal или можно на VPS с другими сервисами?
Можно совмещать — DAViCal легковесен по CPU, основное потребление ресурсов приходится на PostgreSQL, который у вас, скорее всего, уже есть под другие задачи.
Что делать, если после установки не открывается веб-интерфейс администратора?
Проверьте, что схема базы действительно накатилась (в логах контейнера должны быть SQL-команды без ошибок) и что Apache внутри контейнера слушает порт 80 — docker compose exec davical apachectl -S покажет активные виртуальные хосты.
Нужен ли fail2ban или подобная защита от перебора паролей?
Да, обязательно, если сервис смотрит в интернет — DAViCal использует базовую HTTP-аутентификацию, и без внешней защиты от брутфорса (fail2ban на логи Apache или ограничение попыток на уровне reverse-proxy) учётные записи уязвимы к подбору пароля.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →