Vikunja на сервере: частые ошибки и решения
Vikunja выглядит как один из самых простых self-hosted менеджеров задач — списки, метки, напоминания, docker-compose на десяток строк. Но именно из-за этой простоты первые же грабли выбивают из колеи: интерфейс открывается, а данные не грузятся с ошибкой Network Error; после недели работы падает «database is locked»; вложение зависает на загрузке; календарь в телефоне не хочет синхронизироваться. Разберём эти ошибки по отдельности — с конкретными переменными окружения и конфигами, а не общим советом «перезапустите контейнер».
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Как обычно разворачивают Vikunja и откуда берутся проблемы
Vikunja распространяется в docker-образе, который включает и API, и веб-фронтенд в одном контейнере — это упрощает деплой по сравнению со старыми версиями, где api и frontend были двумя разными образами. По умолчанию база данных — SQLite-файл внутри контейнера, что отлично работает для одного-двух человек, но становится источником проблем при росте нагрузки (об этом ниже).
Минимальный рабочий docker-compose.yml:
services:
vikunja:
image: vikunja/vikunja
restart: unless-stopped
environment:
VIKUNJA_SERVICE_PUBLICURL: https://tasks.example.com
VIKUNJA_SERVICE_JWTSECRET: замените-на-случайную-строку-32+-символа
VIKUNJA_DATABASE_TYPE: sqlite
VIKUNJA_SERVICE_TIMEZONE: Europe/Moscow
volumes:
- ./data:/app/vikunja/files
- ./db:/db
ports:
- 3456:3456
Почти все ошибки ниже растут из трёх мест: VIKUNJA_SERVICE_PUBLICURL не совпадает с реальным адресом, том для данных не смонтирован (или смонтирован не туда), либо SQLite упирается в конкурентный доступ. Если вы ещё не разворачивали продакшен-стек на Docker Compose вообще, полезно сначала пройтись по общим граблям — они разобраны в статье про частые ошибки Docker Compose для продакшена.
«Network Error» и не открывается интерфейс
Самая частая жалоба новичков: страница логина загружается, но при попытке войти или открыть список задач фронтенд выдаёт Network Error в консоли браузера. Причина почти всегда одна — фронтенд обращается не туда, куда реально проксирует сервер.
Проверьте по порядку:
VIKUNJA_SERVICE_PUBLICURLдолжен указывать на реальный внешний адрес, включая протокол и без завершающего слэша в неправильном месте:https://tasks.example.com, а неhttp://localhost:3456или IP-адрес сервера. Это значение попадает в конфиг фронтенда при рендере страницы и используется для API-запросов, CalDAV-ссылок и вложений.- Reverse-proxy должен передавать заголовок
Host— без него Vikunja не может корректно сверить запрос сPUBLICURL. Пример для Caddy:
tasks.example.com {
reverse_proxy localhost:3456 {
header_up Host {host}
header_up X-Forwarded-Proto {scheme}
}
}
Аналогично для nginx:
location / {
proxy_pass http://127.0.0.1:3456;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
- После смены
PUBLICURLконтейнер нужно пересоздать, а не просто перезапустить — переменные окружения читаются при старте:docker compose up -d --force-recreate vikunja.
Если вы настраивали TLS через Caddy и сталкивались с похожими проблемами на других сервисах, стоит свериться со статьёй про частые ошибки Caddy с авто-SSL — там разобраны смежные ситуации с сертификатами и заголовками, которые бьют по любому приложению за прокси, не только по Vikunja.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать сервер«database is locked» и другие ошибки SQLite
SQLite в Vikunja по умолчанию отлично тянет одного-двух пользователей, но у него принципиальное ограничение — один писатель на файл базы в любой момент времени. Как только несколько человек одновременно двигают задачи, комментируют или дергают API через мобильное приложение, в логах начинает появляться:
docker compose logs vikunja | grep -i "database is locked"
Что реально помогает:
- Смонтировать том для базы на быстрый локальный диск, а не на сетевую файловую систему (NFS, некоторые облачные тома) — SQLite особенно чувствителен к блокировкам файлов на сетевых ФС, там
database is lockedможет появляться даже при одном активном пользователе. - Не запускать несколько экземпляров Vikunja на одну и ту же SQLite-базу — это частая ошибка при попытке масштабировать API отдельно от фронтенда через несколько реплик контейнера.
- Перейти на Postgres или MySQL, если у вас больше 3-5 активных пользователей или общие проекты с частыми правками. Честно предупредим: штатного инструмента миграции между движками БД у Vikunja нет — переезд с накопленными данными означает перенос задач вручную через API. Поэтому решение о движке БД лучше принять до того, как в системе появятся реальные данные.
Пример перехода на Postgres при первой установке:
services:
vikunja:
image: vikunja/vikunja
environment:
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_HOST: db
VIKUNJA_DATABASE_USER: vikunja
VIKUNJA_DATABASE_PASSWORD: замените-на-свой-пароль
VIKUNJA_DATABASE_DATABASE: vikunja
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: vikunja
POSTGRES_PASSWORD: замените-на-свой-пароль
POSTGRES_DB: vikunja
volumes:
- ./pgdata:/var/lib/postgresql/data
Если раньше не разворачивали Postgres в контейнере, пригодится статья про частые ошибки PostgreSQL на сервере — там разобраны типичные проблемы с подключением и правами, которые всплывают на любом приложении с внешней базой.
Файлы не загружаются или обрываются на крупных вложениях
Загрузка вложений к задачам — вторая по частоте болевая точка, и здесь путают два независимых лимита, которые нужно поднимать оба:
- Лимит самого Vikunja — переменная
VIKUNJA_SERVICE_MAXFILESIZE. Значение по умолчанию рассчитано на небольшие файлы (скриншоты, документы), а не на видео или архивы — если планируете крупные вложения, поднимите его явно:
environment:
VIKUNJA_SERVICE_MAXFILESIZE: 100MB
- Лимит reverse-proxy, который отдаёт
413 Request Entity Too Largeраньше, чем запрос вообще дойдёт до Vikunja. Для nginx:
client_max_body_size 100M;
Для Caddy отдельно поднимать обычно не нужно — по умолчанию лимита на размер тела запроса нет, но если вы явно ограничивали его директивой request_body, проверьте и её.
Отдельная частая ошибка — пропавшие вложения после обновления контейнера. Файлы хранятся не в базе данных, а на диске по пути /app/vikunja/files внутри контейнера. Если при первом запуске забыли смонтировать том (volumes: - ./data:/app/vikunja/files), все вложения живут только внутри контейнера и исчезают при docker compose up -d --force-recreate или обновлении образа. Проверить, что том реально примонтирован:
docker compose exec vikunja ls -la /app/vikunja/files
docker inspect vikunja | grep -A3 Mounts
Если том на месте, но пуст — значит, файлы уже потеряны при одном из прошлых пересозданий контейнера, и восстанавливать их неоткуда без бэкапа.
Почта, напоминания о задачах и CalDAV подводят
Три смежные, но разные проблемы, которые обычно путают друг с другом.
Письма не уходят. Почтовый клиент настраивается отдельным блоком переменных:
environment:
VIKUNJA_MAILER_ENABLED: "true"
VIKUNJA_MAILER_HOST: smtp.yourprovider.com
VIKUNJA_MAILER_PORT: 587
VIKUNJA_MAILER_USERNAME: vikunja@example.com
VIKUNJA_MAILER_PASSWORD: пароль-приложения
VIKUNJA_MAILER_FORCESSL: "false"
VIKUNJA_MAILER_FROMEMAIL: vikunja@example.com
После правки — пересоздание контейнера, не просто рестарт. Если письма всё равно не идут, сначала смотрите docker compose logs vikunja | grep -i mail — там видна конкретная ошибка SMTP, а не просто «не работает». Как и с любой другой почтой с VPS, без настроенных SPF/DKIM и обратной PTR-записи на IP сервера письма могут формально уходить, но падать в спам или отклоняться получателем — это стоит проверить отдельно от конфига самого Vikunja.
Напоминания о задачах не срабатывают вовремя. Это почти всегда проблема часового пояса: если VIKUNJA_SERVICE_TIMEZONE не совпадает с тем, что вы имели в виду, выставляя дедлайн, напоминание сработает по времени контейнера (по умолчанию UTC), а не по вашему местному. Проверьте, что переменная реально попала внутрь:
docker compose exec vikunja date
CalDAV не синхронизируется с телефоном или календарём на компьютере. URL для подключения имеет вид https://tasks.example.com/dav/principals/username/, и здесь работает то же требование к PUBLICURL и заголовкам прокси, что и в разделе про Network Error. Отдельная ловушка: CalDAV-клиенты спрашивают логин и пароль по Basic Auth, а у пользователей, заведённых через LDAP или OIDC, локального пароля в Vikunja может не быть вовсе — подключение у них не заработает без дополнительной настройки.
Авторизация: JWT, LDAP/OIDC и CORS между доменами
Токены разлогинивают всех после перезапуска. Если VIKUNJA_SERVICE_JWTSECRET не задан явно, Vikunja сгенерирует случайный секрет сама — но если конфиг или переменные окружения не сохраняются постоянно (например, значение генерируется на лету скриптом при каждом деплое), при пересоздании контейнера секрет меняется, и все выданные ранее токены разом становятся невалидными. Решение простое: сгенерировать секрет один раз и зафиксировать его в docker-compose.yml или .env-файле, который не перезаписывается:
openssl rand -base64 32
LDAP-авторизация. Базовый набор переменных:
environment:
VIKUNJA_AUTH_LDAP_ENABLED: "true"
VIKUNJA_AUTH_LDAP_HOST: ldap.example.com
VIKUNJA_AUTH_LDAP_PORT: 389
VIKUNJA_AUTH_LDAP_BASEDN: "dc=example,dc=com"
VIKUNJA_AUTH_LDAP_BINDDN: "cn=readonly,dc=example,dc=com"
VIKUNJA_AUTH_LDAP_BINDPASSWORD: пароль-сервисной-учётки
VIKUNJA_AUTH_LDAP_USERFILTER: "(&(objectClass=person)(uid=%s))"
Типичная ошибка — сервисная учётка без прав на чтение атрибутов пользователей: логин молча не проходит, в логах LDAP bind failed или пустой результат поиска. Проверяйте фильтр через ldapsearch до того, как разбираться с самим Vikunja.
CORS-ошибки в консоли браузера. Возникают только если фронтенд и API разнесены на разные домены или порты — например, отдельный api.example.com и tasks.example.com. При едином домене через один reverse-proxy (как в примерах выше) CORS не нужен вообще. Если всё же разносите:
environment:
VIKUNJA_CORS_ENABLE: "true"
VIKUNJA_CORS_ORIGINS: "https://tasks.example.com"
Без явного перечисления origin браузер будет резать запросы с ошибкой has been blocked by CORS policy, даже если сам API отвечает корректно.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Vikunja зависает или падает на маленьком VPS — сколько ресурсов ей реально нужно?
Сам Go-бинарник Vikunja лёгкий и работает на 1 vCPU / 1 ГБ RAM для небольшой команды. Основной расход ресурсов дают не сама Vikunja, а выбранная СУБД (Postgres/MySQL заметнее едят память, чем SQLite) и объём вложений на диске — закладывайте запас именно под них.
Можно ли перенести Vikunja с SQLite на Postgres без потери данных?
Штатного инструмента для этого нет. На практике либо переносят задачи вручную/через API, либо принимают решение о движке БД заранее, до накопления реальных данных — это стоит учитывать при первой установке.
После обновления образа пропали вложения к задачам — что делать?
Скорее всего, том /app/vikunja/files не был смонтирован на хосте, и файлы хранились только внутри старого контейнера. Восстановить их без бэкапа не получится — на будущее обязательно монтируйте volumes для файлов и базы данных.
Не приходят напоминания о задачах, хотя дедлайн стоит правильно?
Проверьте VIKUNJA_SERVICE_TIMEZONE — по умолчанию контейнер живёт в UTC, и без явно заданного часового пояса срабатывание «поедет» на разницу с вашим локальным временем.
Стоит ли вместо Vikunja присмотреться к канбан-инструменту вроде Wekan?
Если задача — именно списки дел с дедлайнами и метками, Vikunja подходит лучше; для командной канбан-доски стоит сравнить с вариантом из статьи про Wekan в Docker Compose — это разные модели работы с задачами, а не конкурирующие версии одного и того же.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →