
Календарь как личная инфраструктура
Я тут задумался по поводу календаря.
Много лет использую гугловский. Немного пытался использовать календарь от Microsoft, но он в итоге всё равно интегрировался с гугловским. Как и эпловский. То есть как ни крути, всё равно получается один центр тяжести — Google.
И вроде всё работает, интеграций море. «Созвон по ссылке», «приглашение на встречу», «напоминание» — всё привычно и понятно.
Но вот наступила эпоха деглобализации, а значит, есть вероятность, что по политическим причинам меня, как и других жителей РФ, лишат доступа к гуглосервисам. Не сам Google заблокирует, так Роскомнадзор подсуетится. И в связи с этим появились опасения.
Не такие, которые доводили бы до стрессового состояния. Скорее конструктивные: «хм, неплохо бы подстелить соломки». Чтобы не зависеть ни от доброй воли ИТ-гигантов, ни от непрошенной заботы со стороны родного государства.
А ещё есть второй слой, менее драматичный, но более личный: я вообще-то не хочу делиться с третьими лицами своим расписанием. Всё-таки это штука часто довольно интимная. Календарь — это же не только встречи и звонки. Это лог жизни: где был, куда иду, что планирую, когда «дырки», когда занят, когда нет. И совсем не улыбается, чтобы какой-нибудь Google или Яндекс обучали свои языковые модели на моих конфиденциальных данных.
Да, Яндекс-календарь я уже попробовал, конечно. Он работает и в целом его вполне можно было бы применять — если бы не сомнения в конфиденциальности. Ну и интеграций с ним я пока не наблюдаю. Все заточены на Google.
Поиск решения: от очевидного к реальному
Что же остаётся?
Первая мысль — заселфхостить какой-нибудь NextCloud и получить всё в одном. Логично. Но останавливает отсутствие адекватных предложений VDS в РФ. А хостить за рубежом, как показывает личный опыт — дело неблагодарное: заслуживший всеобщую нелюбовь регулятор зачем-то ограничивает скорость доступа к зарубежным хостингам до околонулевой, причём даже к тем, на которых нет никаких запрещённых ресурсов. ТСПУ делает своё дело: подключение к зарубежному дедику иногда напоминает работу через dial-up.
Есть ещё вариант разместить сервер дома, и он в целом норм, но вот только есть ряд важных моментов:
- стабильность электропитания (отключения, как ни печально, случаются);
- охлаждение (летом в квартире и так жарко);
- шум (не хочу слушать вентиляторы круглосуточно);
- белый IP (у меня он есть, к счастью).
Ну и всё техобслуживание и сопровождение этого сервера ложится на мои пусть не хрупкие, но довольно нагруженные множеством задач плечи.
И вот тут интересный момент: чем дольше об этом думаешь, тем яснее становится, что календарь — это не «приложение». Это элемент личной инфраструктуры. Такой же, как электричество, интернет и батарейка в телефоне.
Если он есть — живёшь. Если его внезапно нет — удивляешься, насколько много завязано на эту маленькую штуку.
В чём настоящая задача — и почему «просто переехать» не получается
Проблема не в том, что «нет календарей». Календарей море. Проблема в том, что календарь без экосистемы — это как телефон без связи.
Календарь — это:
- якорь для задач, встреч, дедлайнов;
- напоминания (без них всё рассыпается);
- интеграция с почтой (инвайты), мессенджерами, видеозвонками;
- и — самое неприятное — метаданные о жизни.
И поэтому выбор часто выглядит так:
- либо «удобно, но я — продукт и заложник рубильника»;
- либо «автономно, но это превращается во вторую работу».
А мне, если честно, хочется третий путь: чтобы было надёжно и достаточно приватно, но без героизма. Без ощущения, что я теперь админ собственного дата-центра, а календарь стал pet-проектом на полгода.
После долгих раздумий и изучения вопроса я сформулировал два адекватных решения.
Решение №1. Прагматичное: остаюсь на Google, но делаю себе аварийный выход
Это подход для тех, кто не хочет превращать переезд в эпопею, но хочет одного: не умереть вместе с сервисом, если его отрубят.
Суть: не «уходим навсегда», а делаем так, чтобы в момент, когда Google внезапно станет недоступен, не остаться с пустым экраном.
Как это выглядит на практике.
1) Регулярный экспорт и резервные копии
Не «однажды сохранил и забыл», а привычка: раз в неделю или раз в месяц выгрузка календаря в формате .ics (или нескольких календарей, если они разделены) в место, которое контролируешь сам.
Даже банально — в локальную папку на маке плюс резервная копия на внешний диск. Уже лучше, чем ничего.
Смысл здесь простой: в худшем случае хотя бы не теряется история и планы.
Экспорт можно делать руками через Google Takeout, но это быстро надоедает. Дальше в этом посте будет скрипт, который делает это автоматически.
2) Локальный «аварийный» календарь, который живёт без облака
Нужен способ открыть своё расписание, даже если облако недоступно. На macOS это решается банально: стандартный Calendar.app умеет хранить локальные календари и импортировать .ics. На Android — аналогично, чтобы можно было быстро импортировать файл и жить дальше.
То есть задача не «идеально синхронизироваться», а не остаться без расписания.
3) Разделить «личное» и «сервисное»
Самый токсичный канал утечки — это приглашения, корпоративные созвоны, всякие интеграции. Они по умолчанию тянут в Google.
Поэтому можно сделать очень простую и полезную вещь: держать личные события (врачи, семья, здоровье, бытовые планы, то, что реально интимно) в отдельном календаре, который не участвует ни в каких интеграциях и вообще нигде не светится.
А «рабочие созвоны и внешние приглашения» пусть живут там, где им удобно.
Так снижается объём «интимного лога», который отдаётся наружу. Рабочие встречи пусть знает Google — там и так всё корпоративное. А вот когда я иду к врачу или встречаюсь с семьёй — это не его дело.
4) Резервный провайдер «на случай пожара»
Это не обязательно «переезд». Это страховка: иметь вторую площадку, куда можно быстро «перелить» расписание и продолжить жить.
Идея здесь простая, как аптечка в машине: пусть лежит — лучше пусть никогда не пригодится. Но если понадобится, не придётся в этот момент метаться.
Плюсы решения №1: минимум усилий, максимум практической пользы, почти нет риска превратить всё в долгострой.
Минусы: это не полный уход от зависимости и не абсолютная приватность. Это «умный компромисс».
Решение №2. Автономия без фанатизма: отдельный сервер CalDAV/CardDAV вместо комбайна Nextcloud
Если хочется действительно снять зависимость, но без «домашнего сервера с вентиляторами, бесперебойником и нервным тиком», то главный трюк вот какой:
Не пытаться решать всё Nextcloud’ом.
Nextcloud — классная штука, но это комбайн: файлы, фоточки, офис, совместная работа, пользователи, права, обновления, плагины… и всё это ради календаря и контактов выглядит как оверкилл. У меня уже есть файлы, заметки (Obsidian), офис (ну, вот он, локально стоит). Зачем мне ещё один слой абстракции?
А календарь и контакты решаются отдельно и намного легче:
- CalDAV — для календарей;
- CardDAV — для контактов.
Это открытые стандарты. Их понимают macOS, iOS и Android (на Android иногда нужен клиент-синхронизатор типа DAVx⁵, но это решается за пять минут). Плюс сохраняется самая важная вещь: независимость от конкретного приложения. Если клиент сменился — сервер остался. Если телефон поменялся — календарь остался.
У решения №2 два подварианта:
Вариант 2A: управляемый хостинг (платишь деньгами, экономишь голову)
В теории можно взять сервис, где CalDAV/CardDAV уже поднят, обновляется, бэкапится — и заниматься только пользованием.
Но тут есть проблема: большинство privacy-ориентированных сервисов заблокированы в РФ:
- Proton — заблокирован РКН с 2019–2020
- Fastmail — заблокирован с 2021 (отказались выполнять требования о локализации данных)
- mailbox.org — был в процессе блокировки, статус неопределённый
- Tutanota — заблокирован
То есть как «аварийный выход» на случай отключения Google — эти сервисы не годятся. Они уже требуют VPN для доступа, а значит, добавляют ещё одну точку отказа вместо того, чтобы её убирать.
Остаются либо российские сервисы (Яндекс, Mail.ru) — но там те же вопросы к приватности, что и у Google, плюс добавляется риск «внутренней» блокировки. Либо — свой сервер.
Вариант 2B: лёгкий VPS + минимальная поддержка
Если хочется контролировать больше и платить меньше, можно поднять лёгкий сервер на VPS. Но именно лёгкий, без «платформы для всего». С автообновлениями, с нормальными бэкапами, с минимальной площадью атаки.
И важный момент: не нужен «идеальный VPS в РФ». Нужен вариант, который доступен стабильно и не превращается в черепаху по скорости. Иногда это локальный хостинг, иногда — ближнее зарубежье с хорошим пирингом (Финляндия, Казахстан, Армения — у кого что лучше работает).
Плюсы решения №2: настоящая независимость, приватность, стандарты, переносимость между устройствами, меньше «рубильников».
Минусы: всё равно есть элемент ответственности и настройки. Не огромный, но не нулевой.
Легковесные серверы для CalDAV/CardDAV: что реально работает
Вот мы и добрались до конкретики. Какие есть лёгкие решения, которые можно поднять за вечер и не тратить на них потом нервы?
Radicale — минимализм в чистом виде
Radicale — это Python-сервер для CalDAV и CardDAV, который весит почти ничего и делает ровно одну вещь: хранит календари и контакты. Никаких веб-интерфейсов для редактирования (хотя есть простой веб-интерфейс для просмотра), никаких пользовательских порталов. Просто сервер, который отвечает на запросы по стандарту.
Плюсы:
- Установка в одну команду (
pip install radicale) - Конфигурация — один файл
- Потребляет считанные мегабайты RAM
- Данные хранятся в обычных файлах (легко бэкапить, можно даже в Git положить)
- Работает за reverse proxy (nginx, Caddy)
- Поддерживает несколько пользователей
Минусы:
- Нет красивого веб-интерфейса для редактирования событий (нужен клиент)
- Нужно самому настраивать HTTPS (но с Caddy это тривиально)
- Нет встроенного механизма напоминаний (напоминания — дело клиента)
Baikal — если хочется веб-интерфейс
Baikal — PHP-сервер, тоже лёгкий, но с веб-интерфейсом для администрирования. Можно создавать пользователей, календари и адресные книги через браузер.
Плюсы:
- Веб-интерфейс для управления
- Чуть более «законченный» продукт
- Данные в SQLite (один файл) или MySQL
Минусы:
- Нужен PHP (а значит, чуть больше настройки)
- Немного тяжелее Radicale
- Веб-интерфейс — только для администрирования, не для редактирования событий
Xandikos — для тех, кто любит Git
Xandikos — ещё один Python-сервер, который хранит данные в Git-репозитории. Это значит, что вся история изменений сохраняется, и можно откатиться на любой момент.
Плюсы:
- История изменений из коробки
- Можно пушить в удалённый Git-репозиторий для бэкапа
- Лёгкий
Минусы:
- Более экзотический выбор
- Меньше документации
Что выбрать?
Для большинства случаев я бы рекомендовал Radicale:
- Минимум зависимостей (только Python)
- Минимум потребления ресурсов
- Данные в plain-text файлах (легко понять, что происходит)
- Достаточно зрелый проект
Если хочется кнопочки в браузере для создания пользователей — Baikal.
Если хочется гиковского контроля над историей — Xandikos.
Caddy: современный веб-сервер с автоматическим HTTPS
Прежде чем переходить к настройке Radicale, стоит сказать пару слов о Caddy — потому что именно он превращает «голый сервер на localhost» в нормальный защищённый сервис.
Caddy — это веб-сервер, написанный на Go. Его главная особенность: автоматическое получение и обновление SSL-сертификатов от Let’s Encrypt. То есть не нужно возиться с certbot, cron-задачами для обновления, ручной конфигурацией — Caddy делает всё сам.
Почему Caddy, а не nginx:
- Конфигурация в разы проще. Вместо десятков строк nginx-конфига — буквально три строчки.
- HTTPS из коробки. Просто указываем домен — и Caddy сам получает сертификат.
- Меньше шансов ошибиться. Меньше настроек — меньше дыр в безопасности.
Установка на Ubuntu/Debian:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
После установки Caddy автоматически запускается как systemd-сервис.
Минимальная конфигурация для проксирования Radicale (/etc/caddy/Caddyfile):
cal.example.com {
reverse_proxy localhost:5232
}
Это всё. Три строки. Caddy сам:
- Получит сертификат для
cal.example.com - Настроит редирект с HTTP на HTTPS
- Будет автоматически обновлять сертификат
После изменения конфига:
sudo systemctl reload caddy
Настройка Radicale: пошаговый рецепт
Допустим, есть VPS с Ubuntu 22.04. Вот минимальный рецепт для production-ready установки.
1. Установка зависимостей
sudo apt update
sudo apt install python3-pip python3-bcrypt apache2-utils
pip3 install --user radicale
(Caddy устанавливается отдельно — см. раздел выше.)
2. Создание структуры директорий и конфига
sudo mkdir -p /var/lib/radicale/collections
sudo mkdir -p /etc/radicale
# Конфигурация Radicale
sudo tee /etc/radicale/config << 'EOF'
[server]
hosts = 127.0.0.1:5232
[auth]
type = htpasswd
htpasswd_filename = /etc/radicale/users
htpasswd_encryption = bcrypt
[storage]
filesystem_folder = /var/lib/radicale/collections
[logging]
level = warning
mask_passwords = True
EOF
# Создание пользователя для доступа к календарю
sudo htpasswd -B -c /etc/radicale/users myuser
# Введите пароль при запросе
3. Systemd-юнит для автозапуска
sudo tee /etc/systemd/system/radicale.service << 'EOF'
[Unit]
Description=Radicale CalDAV/CardDAV server
After=network.target
[Service]
Type=simple
User=radicale
Group=radicale
ExecStart=/home/myuser/.local/bin/radicale --config /etc/radicale/config
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# Создание системного пользователя (без домашней директории, без shell)
sudo useradd -r -s /bin/false radicale
sudo chown -R radicale:radicale /var/lib/radicale /etc/radicale
# Запуск
sudo systemctl daemon-reload
sudo systemctl enable radicale
sudo systemctl start radicale
4. Настройка Caddy для HTTPS
sudo tee /etc/caddy/Caddyfile << 'EOF'
cal.example.com {
reverse_proxy localhost:5232
}
EOF
sudo systemctl reload caddy
Caddy автоматически получит сертификат от Let’s Encrypt (при условии, что DNS для cal.example.com указывает на этот сервер). Всё, сервер готов.
URL для подключения клиентов: https://cal.example.com/myuser/
Настройка клиентов
macOS / iOS
- Открыть «Системные настройки» → «Интернет-аккаунты»
- Нажать «Добавить другую учётную запись…»
- Выбрать «Учётная запись CalDAV» (или CardDAV для контактов)
- Ввести:
- Тип учётной записи: «Вручную»
- Имя пользователя:
myuser - Пароль: тот, что создали в htpasswd
- Адрес сервера:
cal.example.com
Android
На Android стандартный календарь обычно не умеет CalDAV напрямую. Нужен синхронизатор:
- Установить DAVx⁵ из F-Droid или Google Play
- Добавить аккаунт, ввести URL:
https://cal.example.com/myuser/ - Ввести логин и пароль
- DAVx⁵ будет синхронизировать календарь и контакты со стандартными приложениями Android
Автоматическая синхронизация с Google
А теперь самое интересное: как не терять данные из Google и при этом иметь их копию на своём сервере?
Есть два подхода:
- Односторонняя синхронизация — периодически копировать данные из Google к себе (бэкап)
- Двусторонняя синхронизация — изменения в обе стороны (сложнее, больше риск конфликтов)
Для большинства случаев достаточно первого варианта.
Подготовка: получение доступа к Google API
Для работы скриптов понадобится создать проект в Google Cloud Console и получить credentials. Это делается один раз, но шагов довольно много.
Создание проекта и включение API:
- Зайти на https://console.cloud.google.com/
- Создать новый проект (или использовать существующий)
- В боковом меню: APIs & Services → Library
- Найти и включить Google Calendar API
- Найти и включить Google People API (для контактов)
Настройка OAuth consent screen:
- В боковом меню: APIs & Services → OAuth consent screen
- Нажать Get Started (или Configure, если уже настраивался)
- Заполнить App name (например, «CalSync») и выбрать User support email
- В разделе Audience выбрать External (если не Google Workspace)
- Заполнить Contact information и согласиться с политикой
Добавление себя как тестировщика (важно!):
- После создания OAuth consent screen перейти в раздел Audience
- Пролистать до секции Test users
- Нажать + Add users
- Ввести свой Google-аккаунт (тот, с которого будете авторизовываться)
- Сохранить
Без этого шага при авторизации будет ошибка «access_denied» — приложение в тестовом режиме доступно только одобренным тестировщикам.
Создание credentials:
- В боковом меню: APIs & Services → Credentials
- Нажать + Create Credentials → OAuth client ID
- Выбрать Application type: Desktop app
- Скачать JSON-файл и сохранить как
credentials.jsonрядом со скриптами
Скрипты для бэкапа и синхронизации
Я написал набор скриптов на Python, которые делают всю работу:
- google_calendar_backup.py — экспорт всех календарей из Google в формате ICS
- google_contacts_backup.py — экспорт контактов из Google в формате vCard (VCF)
- sync_google_to_caldav.py — односторонняя синхронизация событий Google → CalDAV-сервер
Скрипты написаны с явной типизацией, валидацией входных данных и понятными сообщениями об ошибках. Никаких голых except, никаких неявных зависимостей.
Установка зависимостей
pip install google-auth-oauthlib google-api-python-client caldav
Или через requirements.txt:
pip install -r scripts/requirements.txt
Использование скриптов
Бэкап календарей:
# Положите credentials.json рядом со скриптом
python3 scripts/google_calendar_backup.py
# При первом запуске откроется браузер для авторизации
# Бэкапы сохранятся в backup/calendars/
Бэкап контактов:
python3 scripts/google_contacts_backup.py
# Бэкапы сохранятся в backup/contacts/
Синхронизация с CalDAV:
# Вариант 1: через переменные окружения
export CALDAV_URL="https://cal.example.com"
export CALDAV_USER="myuser"
export CALDAV_PASSWORD="mypassword"
python scripts/sync_google_to_caldav.py
# Вариант 2: через файл конфигурации
cp scripts/config.example.ini scripts/config.ini
# Отредактируйте config.ini
python scripts/sync_google_to_caldav.py
Альтернатива: vdirsyncer
Для полноценной двусторонней синхронизации есть замечательный инструмент vdirsyncer. Он умеет синхронизировать CalDAV/CardDAV серверы между собой, с локальными файлами и даже с Google (через специальные адаптеры).
pip install vdirsyncer
Конфигурация ~/.config/vdirsyncer/config:
[general]
status_path = "~/.local/share/vdirsyncer/status/"
# Локальное хранилище
[storage local_calendar]
type = "filesystem"
path = "~/.local/share/calendars/"
fileext = ".ics"
# Google Calendar
[storage google_calendar]
type = "google_calendar"
token_file = "~/.config/vdirsyncer/google_token"
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
# Пара для синхронизации
[pair calendars]
a = "local_calendar"
b = "google_calendar"
collections = ["from b"]
conflict_resolution = "b wins"
Запуск:
vdirsyncer discover
vdirsyncer sync
Автоматизация через cron или systemd
Чтобы синхронизация работала автоматически:
Вариант 1 — cron:
# crontab -e
# Синхронизация каждые 6 часов
0 */6 * * * cd /path/to/scripts && python3 sync_google_to_caldav.py >> /var/log/calendar-sync.log 2>&1
Вариант 2 — systemd timer:
# /etc/systemd/system/calendar-sync.service
[Unit]
Description=Sync Google Calendar to CalDAV
[Service]
Type=oneshot
User=myuser
WorkingDirectory=/home/myuser/scripts
ExecStart=/usr/bin/python3 sync_google_to_caldav.py
Environment="CALDAV_URL=https://cal.example.com"
Environment="CALDAV_USER=myuser"
Environment="CALDAV_PASSWORD=mypassword"
# /etc/systemd/system/calendar-sync.timer
[Unit]
Description=Run calendar sync every 6 hours
[Timer]
OnCalendar=*-*-* 00/6:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl enable calendar-sync.timer
sudo systemctl start calendar-sync.timer
Почему эти два решения оптимальны
У меня нет желания делать из календаря отдельный проект жизни. Нужны две вещи:
- Чтобы не остаться без инфраструктуры, если что-то отвалится.
- Чтобы личные данные не были бесплатным кормом для чужих систем.
И вот тут логика простая:
- Решение №1 — для спокойствия прямо сейчас. Это «страховка», а не революция. Минимум телодвижений, максимум пользы.
- Решение №2 — для тех, кто всё-таки хочет сделать шаг к автономии, но не готов платить за это шумом в квартире и вторым рабочим местом «администратор собственной жизни».
Radicale на маленьком VPS за 3–5 долларов в месяц — это не «домашний дата-центр». Это скорее как внешний диск для бэкапов: купил, настроил один раз, работает.
Календарь — это вход в более широкую тему
Если уж заниматься «анти-рубильниковой» гигиеной, календарь — это хороший первый шаг. Но в идеале рядом с ним в скелете личной инфраструктуры должны быть ещё:
- контакты (CardDAV, Radicale их тоже поддерживает)
- менеджер паролей (Bitwarden self-hosted или хотя бы KeePass с синхронизацией)
- 2FA-коды (Aegis на Android, не завязанный на облако)
- резервные копии (не в одном месте, не только в облаке)
- заметки (Obsidian, Logseq — локально с синхронизацией через Syncthing)
Потому что календарь — это больно, но не единственная точка зависимости. Просто самая заметная.
Вывод
Вся эта история, на самом деле, не про «какой календарь выбрать». Она про то, чтобы перестать жить в мире, где одна кнопка (у корпорации или у регулятора) может выключить кусок жизни.
И хорошая новость: между «пофиг, живём как жили» и «поднимаю сервер дома и становлюсь системным администратором» есть нормальная человеческая середина.
Вариант №1: остаюсь на Google, но делаю аварийный выход и разделяю личное/сервисное.
Вариант №2: строю автономию аккуратно — через CalDAV/CardDAV без тяжёлых комбайнов и без домашнего дата-центра. Radicale + VPS + скрипт синхронизации = календарь, который принадлежит мне.
А дальше уже дело вкуса: хочется ли просто подстелить соломки — или хочется действительно забрать себе обратно кусок цифровой свободы.