Habitica self-hosted: полный гайд по развёртыванию, настройке Nginx и docker-compose

от автора

Предыстория

В данный момент я работаю над проектом ServeHub-2. Если кратко, я создаю свою домашнюю лабораторию, которой планирую пользоваться в повседневной жизни. В неё я решил внедрить и трекер задач, так как это был единственный инструмент, который выбивался из моего привычного workflow и существовал полностью отдельно. Из-за этого список ежедневных дел мне приходилось копировать в Obsidian, чтобы в случае удаления старого трекера не бояться, что мои планы пропадут.

После недолгих поисков меня привлекли два варианта: Habitica и Vikunja. До сих пор оба кажутся мне отличными решениями, но я решил остановиться на Habitica. Геймификация в ней меня действительно зацепила, и, пользуясь этим подходом последние несколько дней, я не жалею. Возможно, Habitica в какой-то степени помогает справиться с известной проблемой: когда появляется слишком много дел, в обычные игры играть не хочется совсем, хотя у меня уже собран список из более чем 50 тайтлов, которые я хочу пройти.

Также стоит сразу отметить, что Habitica — весьма специфический to-do инструмент, и многим он может не подойти. Перед тем как разворачивать его самостоятельно, советую просто скачать официальное приложение и некоторое время попользоваться им через серверы разработчиков, чтобы понять, подходит оно вам или нет.

И последнее, о чём хотелось бы упомянуть перед переходом к настройке, — это трекер HabitNow, которым я пользовался раньше. Если честно, большого практического смысла в этом блоке нет, просто я считаю данный трекер лучшим из тех, что использовал (если вам не нужна геймификация). Информации о нём мало, поэтому хочется привлечь к нему внимание. Если вам не нравится Habitica или self-hosted решения, обязательно попробуйте HabitNow.

HabitNow

HabitNow

Настройка

Если вы планируете использовать этот гайд при развёртывании Habitica, советую также ознакомиться с информацией в официальном форке для self-hosted. Всё, что я делаю здесь — это скорее кастомные решения, которые мне пришлось применить для корректной работы в моих условиях. В вашем случае ситуация может отличаться, и стандартного руководства вполне может хватить: https://github.com/awinterstein/habitica

Для развёртывания я использовал docker-compose, поэтому показывать процесс буду на его примере. Мне кажется, это самый простой и автоматизированный вариант.

Также в своей конфигурации я использовал Nginx в качестве reverse proxy для проксирования трафика в Habitica.

docker-compose.local.yaml:

  habitica:    image: docker.io/awinterstein/habitica-server:5.48.6 # Используем образ от awinterstein, адаптированный для self-hosted    container_name: habitica-server    restart: unless-stopped    logging: *default-logging    depends_on:      habitica-db:        condition: service_healthy    environment:      - NODE_DB_URI=mongodb://habitica-db/habitica # Подключение к базе данных      - BASE_URL=http://habitica.${SERVER_NAME} # Использование поддомена (запустить Habitica в subpath не удалось). При работе через reverse proxy используйте http во избежание бесконечного редиректа.      - INVITE_ONLY=false # Открытая регистрация. Рекомендуется отключить (true) после создания пользователя, если доступ не ограничен на уровне VPN как в моем случае.    networks:      default:        aliases:          - server # Алиас необходим, так как встроенный Caddy в клиенте жестко завязан на хост "server"          - habitica-server    expose: # Лишние порты наружу не открываем      - 3000    deploy:      resources:        limits:          memory: 1G    habitica-client:    image: docker.io/awinterstein/habitica-client:5.48.6 # Веб-интерфейс для доступа через браузер (помимо приложения)    container_name: habitica-client    restart: unless-stopped    logging: *default-logging    depends_on:      habitica:        condition: service_started    expose:      - 80    deploy:      resources:        limits:          memory: 512M  habitica-db:    image: docker.io/mongo:7.0 # Используем v7.0 из-за совместимости с новыми ядрами Linux (на Arch Linux), но вы можете выбрать другую версию    container_name: habitica-db    restart: unless-stopped    hostname: habitica-db    command: ["--replSet", "rs", "--bind_ip_all", "--port", "27017"] # Включение ReplicaSet (требуется для поддержки транзакций в Node.js)    logging: *default-logging    healthcheck:      # Инициализация ReplicaSet в одну строку при первом запуске      test: echo "try { rs.status() } catch (err) { rs.initiate() }" | mongosh --port 27017 --quiet      interval: 10s      timeout: 30s      start_period: 5s      start_interval: 1s      retries: 30    volumes:      - ./apps-data/habitica-db:/data/db:rw # Монтирование в отдельную папку для удобного переноса и бэкапов    deploy:      resources:        limits:          memory: 1G

Теперь перейдём к конфигурации Nginx. У меня используется каскад из двух Nginx (внешний проксирует трафик на внутренний, который затем направляет его в Habitica). Я покажу оба конфига. Если вы планируете использовать только один Nginx, то логику SSL нужно будет перенести из nginx.remote в nginx.local.

nginx.local.conf.template: (часть, относящаяся к Habitica)

server {    listen 80; # Слушаем порт 80, так как SSL-терминация происходит на внешнем Nginx, а далее трафик идет по защищенному VPN    server_name habitica.${SERVER_NAME}; # Поддомен для Habitica    location / { # Браузерный клиент (для использования с ПК)        proxy_pass http://habitica-client:80/;         proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        # Передаем исходный протокол HTTPS, чтобы Node.js внутри контейнера корректно обрабатывал ссылки        proxy_set_header X-Forwarded-Proto https;     }    location /api/ { # API для работы мобильного приложения        proxy_pass http://habitica:3000/api/;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto https;    }}

nginx.remote.conf.template: (внешний Nginx, который проксирует в nginx.local)

server {    listen 443 ssl; # Здесь обрабатываются SSL-сертификаты. Если каскад не требуется, этот блок можно объединить с nginx.local    server_name habitica.${SERVER_NAME};    ssl_certificate /etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem;    ssl_certificate_key /etc/letsencrypt/live/${SERVER_NAME}/privkey.pem;    client_max_body_size 2G; # Лимит на размер загружаемых файлов с запасом    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;        # Доверенные IP-диапазоны. Если VPN не используется, эти строки вместе с allow/deny можно убрать    set_real_ip_from 172.16.0.0/12;     set_real_ip_from 10.0.0.0/8;    set_real_ip_from 127.0.0.1;    real_ip_recursive on;    allow 127.0.0.1;    allow 172.16.0.0/12;    allow 10.8.0.0/24;    deny all;    location / {        proxy_pass http://10.8.0.2:80; # Проксируем на внутренний Nginx в цепочке        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection $connection_upgrade; # Для работы вебсокетов (требует наличия map $http_upgrade $connection_upgrade в nginx.conf)        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto https;    }}

Заключение

Habitica

Habitica

В принципе, это всё, что я хотел показать. Надеюсь, что кому-то мои решения помогут сэкономить время, так как с Nginx у меня сначала возникли небольшие трудности из-за конфликтов со встроенным Caddy, но в итоге всё удалось успешно настроить.

Буду рад вашему фидбеку в комментариях!

ссылка на оригинал статьи https://habr.com/ru/articles/1060178/