MAATRIX / Блог / Vikunja в Docker Compose: готовый файл

Vikunja в Docker Compose: готовый файл

MAATRIX

Если вы устали от Todoist с ограничениями бесплатного тарифа или не хотите держать рабочие списки задач на чужом сервере — Vikunja решает обе проблемы. Это лёгкий self-hosted менеджер задач со списками, метками, напоминаниями и Kanban-досками, который поднимается одним docker compose up и не требует вечной подписки. Ниже — рабочий compose-файл, разбор переменных окружения и то, что обычно упускают при первом запуске: HTTPS, бэкапы и обновления.

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

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

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

Что такое Vikunja и зачем она нужна

Vikunja — open-source альтернатива Todoist, Things и Microsoft To Do. Из коробки есть:

  • списки задач с подзадачами, дедлайнами и повторами;
  • метки (labels) и приоритеты;
  • Kanban-доски и представление в виде таблицы/Ганта;
  • напоминания и уведомления по email;
  • общие проекты и права доступа для команды;
  • мобильные приложения и веб-интерфейс, плюс REST API для интеграций.

По ощущениям это ближе к личному и небольшому командному таск-менеджеру, а не к полноценной системе управления проектами вроде Jira. Если нужна доска в духе Trello без задач-списков — присмотритесь к Wekan или Focalboard; они устроены проще и заточены именно под канбан.

Ресурсы Vikunja просит скромные: 1 CPU и 512 МБ–1 ГБ RAM хватает с запасом для команды в 5–20 человек. На VPS с 1–2 vCPU и 2 ГБ RAM сервис работает без нагрузки на систему даже вместе с базой данных.

Готовый docker-compose.yml

Актуальная схема развёртывания Vikunja — единый образ vikunja/vikunja, который отдаёт и API, и веб-интерфейс на одном порту (3456). База — PostgreSQL: она надёжнее SQLite при параллельной работе нескольких пользователей и проще в бэкапе, чем MySQL, который Vikunja тоже поддерживает.

Создайте директорию проекта и файл docker-compose.yml:

mkdir -p ~/vikunja/data/{db,files}
cd ~/vikunja
services:
  db:
    image: postgres:16-alpine
    container_name: vikunja-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: vikunja
      POSTGRES_PASSWORD: change_me_strong_password
      POSTGRES_DB: vikunja
    volumes:
      - ./data/db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U vikunja"]
      interval: 10s
      timeout: 5s
      retries: 5

  vikunja:
    image: vikunja/vikunja:latest
    container_name: vikunja
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      VIKUNJA_DATABASE_TYPE: postgres
      VIKUNJA_DATABASE_HOST: db
      VIKUNJA_DATABASE_USER: vikunja
      VIKUNJA_DATABASE_PASSWORD: change_me_strong_password
      VIKUNJA_DATABASE_DATABASE: vikunja
      VIKUNJA_SERVICE_JWTSECRET: replace_with_random_32char_string
      VIKUNJA_SERVICE_FRONTENDURL: "https://tasks.example.com/"
      VIKUNJA_SERVICE_ENABLEREGISTRATION: "false"
      VIKUNJA_SERVICE_TIMEZONE: "Europe/Moscow"
    ports:
      - "127.0.0.1:3456:3456"
    volumes:
      - ./data/files:/app/vikunja/files

Перед запуском обязательно замените change_me_strong_password и VIKUNJA_SERVICE_JWTSECRET — второй параметр подписывает сессионные токены, и генерировать его нужно случайно:

openssl rand -hex 32

Тег latest удобен для первого знакомства, но для продакшена лучше зафиксировать конкретную версию образа (посмотрите актуальный тег на Docker Hub перед деплоем) — так обновления происходят осознанно, а не при каждом docker compose pull.

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

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

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

Первый запуск и настройка

Поднимите стек и проверьте логи:

docker compose up -d
docker compose logs -f vikunja

Если всё стартовало штатно, API отвечает на http://127.0.0.1:3456/api/v1/info. Порт специально пробрасывается только на localhost — наружу сервис отдаёт reverse-proxy, о нём ниже.

Первого пользователя Vikunja создаёт через веб-интерфейс при регистрации — если оставить VIKUNJA_SERVICE_ENABLEREGISTRATION: "true" на момент первого входа, зарегистрируйтесь сами, затем верните значение в "false" и перезапустите контейнер (docker compose up -d), чтобы закрыть самостоятельную регистрацию для посторонних.

Полезные переменные, которые стоит проверить сразу:

ПеременнаяНазначение
VIKUNJA_SERVICE_FRONTENDURLдолжен точно совпадать с итоговым адресом (с https:// и слэшем в конце) — иначе будут проблемы с редиректами и CORS
VIKUNJA_SERVICE_ENABLEREGISTRATIONfalse после создания первого аккаунта — иначе может зарегистрироваться кто угодно
VIKUNJA_MAILER_HOST / VIKUNJA_MAILER_USERнужны, если хотите email-напоминания и восстановление пароля
VIKUNJA_SERVICE_MAXITEMSPERPAGEлимит выдачи в API, если у вас много задач и клиент подтормаживает

Настройки email через SMTP добавляются отдельным блоком VIKUNJA_MAILER_* в тот же environment: — без них сервис работает, просто не будет писем-напоминаний о дедлайнах.

HTTPS и reverse-proxy

Наружу пускать Vikunja без TLS не стоит — вы вводите пароль и работаете с личными задачами. Проще всего добавить Traefik с автоматическим Let's Encrypt. Если Traefik уже развёрнут на сервере (см. Traefik как reverse-proxy для Docker), достаточно добавить лейблы к сервису vikunja:

  vikunja:
    # ...остальные настройки как выше
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.vikunja.rule=Host(`tasks.example.com`)"
      - "traefik.http.routers.vikunja.entrypoints=websecure"
      - "traefik.http.routers.vikunja.tls.certresolver=letsencrypt"
      - "traefik.http.services.vikunja.loadbalancer.server.port=3456"
    networks:
      - traefik-network

networks:
  traefik-network:
    external: true

Уберите проброс ports: 3456:3456 наружу — трафик пойдёт через Traefik, а прямой доступ к контейнеру снаружи не нужен.

Если предпочитаете более простую конфигурацию без отдельного docker-сетевого слоя, Caddy с автоматическим SSL — тоже рабочий вариант (см. установку Caddy с авто-SSL на VPS): достаточно одного блока в Caddyfile:

tasks.example.com {
    reverse_proxy 127.0.0.1:3456
}

Caddy сам получит и продлит сертификат, дополнительно ничего настраивать не придётся.

Резервное копирование данных

У Vikunja два места, где живут данные: база PostgreSQL (задачи, пользователи, метки) и директория с файлами (вложения к задачам). Бэкапить нужно оба.

Дамп базы:

docker compose exec db pg_dump -U vikunja vikunja | gzip > vikunja_db_$(date +%F).sql.gz

Файлы вложений — это обычная папка на хосте, ./data/files, её достаточно копировать штатным rsync или tar:

tar -czf vikunja_files_$(date +%F).tar.gz ./data/files

Для регулярного автоматического бэкапа с ротацией и шифрованием удобнее не изобретать cron-скрипты вручную, а поднять BorgBackup — там же есть готовый разбор BorgBackup в Docker Compose с шифрованием и дедупликацией, что для вложений (фото, документы) особенно полезно — экономит место при частых бэкапах.

Восстановление в обратную сторону:

gunzip -c vikunja_db_2026-08-20.sql.gz | docker compose exec -T db psql -U vikunja vikunja
tar -xzf vikunja_files_2026-08-20.tar.gz -C ./

Перед восстановлением базы контейнер vikunja лучше остановить (docker compose stop vikunja), чтобы он не писал в базу во время импорта.

Обновление и типичные проблемы

Обновление — стандартная процедура для Compose-стека:

docker compose pull
docker compose up -d
docker compose logs -f vikunja

Перед обновлением на новую мажорную версию сделайте дамп базы — миграции схемы Vikunja применяет автоматически при старте, и откатить их проще из бэкапа, чем вручную.

Частые проблемы, с которыми сталкиваются при первом деплое:

  • Белый экран или ошибки CORS в консоли браузера. Обычно причина — VIKUNJA_SERVICE_FRONTENDURL не совпадает с реальным адресом (например, забыт слэш в конце или указан http вместо https). Проверьте значение и перезапустите контейнер.
  • 502/504 от reverse-proxy. Контейнер vikunja ещё не готов принимать соединения — дайте ему 10-15 секунд после старта, особенно если это первый запуск с применением миграций базы.
  • Не приходят email-напоминания. Без блока VIKUNJA_MAILER_* почта просто не настроена — это не баг, а отсутствующая конфигурация.
  • Не сохраняются вложения после пересоздания контейнера. Проверьте, что volume ./data/files действительно смонтирован, а не потерян при правке compose-файла — без явного тома Docker при down с флагом -v может удалить анонимный volume вместе с данными.

Для более базовой настройки Docker Compose на сервере — сети, healthchecks, порядок запуска сервисов — пригодится статья про Docker Compose для продакшена, там разобраны общие принципы, которые применимы не только к Vikunja.

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

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

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

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

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

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

Можно ли использовать SQLite вместо PostgreSQL?

Да, Vikunja поддерживает SQLite — достаточно указать VIKUNJA_DATABASE_TYPE: sqlite и путь к файлу базы. Это проще для личного использования на одном пользователе, но при параллельной работе нескольких людей PostgreSQL надёжнее.

Есть ли мобильное приложение?

Да, официальные клиенты для iOS и Android подключаются к вашему серверу по API — в приложении просто укажите адрес вашего инстанса вместо облачного сервиса Vikunja.

Можно ли импортировать задачи из Todoist или Trello?

Да, у Vikunja есть встроенный импорт из нескольких сервисов через раздел настроек — набор поддерживаемых источников меняется от версии к версии, проверьте актуальный список в вашем инстансе.

Сколько нужно ресурсов сервера для команды из 10-15 человек?

Как правило хватает 1-2 vCPU и 2 ГБ RAM с запасом — сама Vikunja лёгкая, основное потребление даёт PostgreSQL при активной работе.

Нужен ли отдельный домен под Vikunja?

Необязательно — можно использовать поддомен (tasks.example.com) на том же сервере, где крутятся другие self-hosted сервисы, если у каждого свой reverse-proxy маршрут.

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

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

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