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

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

Предыстория

В данный момент я работаю над проектом 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, но в итоге всё удалось успешно настроить.

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

Автор: ITsuperiorRF

Источник

Оставить комментарий