Чистая установка возвращает 502 Bad Gateway

Всем привет,

Я установил Discourse дважды: один раз в контейнере, а текущую версию — на виртуальной машине (ВМ). В обоих случаях Discourse недоступен. Не совсем понимаю, в чём может быть проблема.

Виртуальная машина Discourse:

  • Ядра: 4
  • ОЗУ: 6 ГБ
  • Хранилище: 50 ГБ
  • ОС: Ubuntu 22.04.3

Команды для чистой установки после установки ОС:

apt update -y && apt upgrade -y && apt install wget curl zip git docker.io -y && reboot

Затем я следовал следующему руководству: discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

После завершения установки я вижу, что контейнер запущен, но возвращается ошибка 502 Bad Gateway.

Как я это настроил: Nginx Reverse Proxy (включая SSL) → ВМ. Это не работает.
Даже при добавлении записи напрямую в файл hosts страница не загружается.

Из последних строк установки видно, что Docker создал новую сеть:

DOCKER_HOST_IP=172.17.0.1 --name app -t -p 80:80 -p 443:443

Как заставить его использовать IP-адрес хостовой машины?
Мне не нужна сеть внутри сети. Я готов, чтобы Docker использовал IP-адрес хоста, так как на этой ВМ работает только этот сервис.

Буду очень признателен за любую помощь!

Существует ли официальный способ установки без использования Docker?

Расположен ли контейнер на машине с публичным IP-адресом? Есть ли у этого публичного IP-адреса назначенное доменное имя?

Вы запускали discourse-setup? Удалось ли вам пройти этап проверки корректности DNS и доступности хоста?

Вы выполняли множество пересборок, из-за чего попали под ограничение скорости от Let’s Encrypt и не можете получить сертификат?

Нет, этой машине назначен локальный IP-адрес, и трафик перенаправляется на него через мой межсетевой экран. Это не проблема.
У публичного IP есть A-запись для сервера, и маршрутизация работает корректно. forum.somedomain.com указывает на правильный сервер.

Да, установка завершена. Я провёл её до конца (трижды) до момента запуска контейнера.
Все проверки домена/DNS пройдены успешно. Система сообщает, что всё валидно.

Нет, здесь невозможно попасть под ограничение скорости, так как SSL-сертификат выдаётся через мой обратный прокси. У меня есть сертификат.

Эта установка завершена на 100%. Проблема в том, что Docker создаёт новую сеть 172.17.0.1, что не нужно, поскольку я хочу использовать локальный IP-адрес хоста 192.xx.xx.xx.

Контейнер запущен, но в другой сети. Мне не удаётся привязать его к IP-адресу хоста.

IP-адрес Docker-хоста должен соответствовать IP-адресу сервера-хоста (192.xxx.xxx.xxx), а не новой сети. Скорее всего, всё работает, но в этой сети.
Как указать установке использовать мой локальный IP, а не 172.17.0.1?

@pfaffman Что-то вроде этого. Из вашего комментария

Как мне настроить ./discourse-setup так, чтобы он использовал IP-адрес хоста 192.168.1.X и сеть при установке?

Вы не можете использовать discourse-setup с обратным прокси-сервером. Вам придется отредактировать файл yml вручную. Существуют темы о запуске Discourse вместе с другими сайтами на одной машине.

Если вы используете обратный прокси-сервер, который обрабатывает SSL, вам нужно будет удалить шаблоны ssl и let’s encrypt.

Дело в том, что я не запускаю никаких других служб на этой машине. Это отдельная виртуальная машина.

Кажется, здесь возникло недопонимание.

./docker-setup устанавливается успешно. Он создаёт собственную сеть для приложения с адресом 172.17.0.1.

Как мне настроить установку или docker-контейнер так, чтобы они использовали IP-адрес хоста 192.168.1.X, то есть работали в режиме мостовой сети, а не создавали свою собственную?

Но вы сказали следующее:

Если вы используете обратный прокси, вы не можете использовать discourse-setup.

Да, обратный прокси находится на другом сервере, но я понимаю, что вы имеете в виду.

У меня есть идея. Я просто направлю весь трафик из моей сети в сеть контейнеров Docker.

Есть ли руководство по установке для запуска Discourse за обратным прокси nginx?

Или способ собрать Discourse самостоятельно?

Это довольно просто. Вы разрешили HTTP-порт в app.yml, куда Nginx отправляет трафик, и отключили SSL. Нужно исправить только эти две вещи. Конечно, нужно указать реальный IP, но это требуется делать всегда для любого бэкенда: Discourse, Moodle, WordPress или чего-то ещё. UFW пытается ограничить доступ только между фронтендом и бэкендом, так как нет необходимости разрешать прямой доступ к бэкенду.

Если я не ошибаюсь, вот документация по настройке Apache2. Nginx делает то же самое, но, конечно, по-своему.

Или что я сейчас упустил?

Давайте начнём с самого начала, чтобы вы могли понять, что я упускаю.

У меня есть обратный прокси-сервер Nginx. Он работает с публичным IP-адресом и выполняет маршрутизацию трафика к сервисам.

Например: запрос клиента к cloud.domain.com → Обратный прокси Nginx (обрабатывает SSL) → перенаправляет на cloud.domain.com.

Теперь я настроил виртуальную машину для Discourse и выполнил следующие команды:
Ubuntu 23.04. Команды после установки ОС:

apt update -y \
apt upgrade -y \
apt install wget curl zip git docker.io -y

Затем я следовал этому руководству от Discourse: discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

Установка завершилась успешно, но затем начались проблемы.

Я не могу получить доступ к контейнеру Docker с хоста из-за сети docker0. Я могу выполнить ping до 172.17.0.2, и контейнер работает, но с хоста машины по адресу 192.168.1.10:80/443 трафик не передаётся в контейнер.

Моя цель — чтобы контейнер Docker использовал сеть хоста, так как в контейнере открыты порты 80 и 443.

Первый обратный прокси Nginx обрабатывает трафик извне и корректно передаёт его на виртуальную машину. Если бы это не работало, утилита ./discourse-setup не смогла бы определить доменное имя правильно и не смогла бы получить SSL-сертификаты для контейнера.

В итоге: я знаю, что контейнер работает на 100%, просто я не могу получить к нему доступ из-за сети Docker.

Если вам нужна дополнительная информация, пожалуйста, дайте знать.

Другой подход — использовать базовый образ Discourse

и создать собственную систему оркестрации, например, с помощью Docker Compose (помня, что вам понадобятся дополнительные сервисы, такие как Redis и PostgreSQL).

Я могу настроить это с помощью Nginx или Nginx + Varnish для Discourse на одном VPS или на разных VPS с разными IP-адресами. Вы не уточнили, что именно вы делаете с вашим Nginx, выступающим в роли обратного прокси. Ваши примеры немного запутаны, так как непонятно, являются ли они просто примерами или вы действительно пытаетесь использовать частную сеть.

Однако:

Конечно, нет, потому что она отвечает за входящий трафик. Для бэкенда вам нужно использовать другой порт.

Что-то вроде этого (что на самом деле используется с Varnish, но принцип точно такой же и это очень базовые вещи):

proxy_pass http://127.0.0.1:8080;
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;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $host;
proxy_pass_header Server;

Понимаю, спасибо за конкретику :).

Не совсем уверен, потому что эта Docker-сеть запутывает.

Именно поэтому я так расстраиваюсь из-за Docker, lol.

Ниже показано точно, как WAN-сеть пропускает и маршрутизирует трафик от моего обратного прокси-сервера Nginx к нужному хосту.

map $scheme $hsts_header {
    https   "max-age=63072000;includeSubDomains; preload";
}

server {
  set $forward_scheme https;
  set $server         "10.10.1.38";
  set $port           443;

  listen 80;
listen [::]:80;

listen 443 ssl http2;
listen [::]:443 ssl http2;


  server_name forum.domainname.com;

  # Let's Encrypt SSL
  include conf.d/include/letsencrypt-acme-challenge.conf;
  include conf.d/include/ssl-ciphers.conf;
  ssl_certificate /srv/ssl/domainname.pem;
  ssl_certificate_key /srv/ssl/domainname-ke.pem;


# Кэширование ассетов
include conf.d/include/assets.conf;

# Блокировка эксплойтов
include conf.d/include/block-exploits.conf;

# HSTS (требуется модуль ngx_http_headers_module) (63072000 секунд = 2 года)
add_header Strict-Transport-Security $hsts_header always;

# Принудительное использование SSL
include conf.d/include/force-ssl.conf;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;


access_log /var/logs/domainname-access.log proxy;
error_log /var/logs/domainame_error.log warn;

proxy_set_header  X-Real-IP $remote_addr;
proxy_set_header  X-Forwarded-For $http_x_forwarded_for;
proxy_set_header  X-Forwarded-Proto $scheme;

location / {

  # HSTS (требуется модуль ngx_http_headers_module) (63072000 секунд = 2 года)
  add_header Strict-Transport-Security $hsts_header always;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_http_version 1.1;
    
    # Прокси!
    include conf.d/include/proxy.conf;
  }
}

Странно то, что я однажды настроил Docker-контейнер для клиента, которому нужен был менеджер обратного прокси-сервера Nginx, и это было чрезвычайно просто.

docker-compose up -d
Всё. Частный IP 192.168.1.3 мог обращаться к открытым портам 80/443 контейнеров, а исходящий трафик корректно маршрутизировался на 192.168.1.3.

Она запутанная, потому что это пакетная система, работающая в собственном изолированном окружении. По сути, всё в этом и заключается.

Но понимание Docker — это одно, а его использование — совсем другое (и теперь целая куча разработчиков начала ныть :rofl:). Ваш обратный прокси отправляет трафик на IP-адрес через брандмауэр, и вам нужно указать этот IP и порт прослушивания. У вас на этом IP запущен Discourse (то есть Docker), а порт вы указываете в app.yml. Внутренний Nginx, работающий непосредственно с Discourse, берёт на себя остальное.

Discourse не должен слушать порт 443, так как вы уже завершили SSL-соединение.

И, по сути, вы не можете использовать кэширование на обратном прокси. Бэкенд, то есть Discourse, — это не веб-страница. Это веб-приложение, отправляющее JavaScript и JSON.

Я вроде бы уже понял это.

С этим я согласен. Я бы не сказал, что они плачут, просто это бесполезно для системных администраторов и разработчиков, которые действительно разбираются в Linux. Создание LXC или виртуальной машины, которая изолирована, чтобы затем позволить Docker создать ещё одну изолированную среду, — это излишне и бессмысленно.

Вот эта часть сбивает с толку. В app.yml порты 80:80 и 443:443 пробрасываются на 172.17.0.2, который находится в сети Docker 172.17.0.1/16, в то время как IP-адрес виртуальной машины — 10.10.1.38.

Как мне настроить Discourse/Docker так, чтобы весь входящий трафик на 10.10.1.38 перенаправлялся на 172.17.0.2, а весь исходящий трафик шёл через 10.10.1.38? Это всё, что нужно для решения этой проблемы. Буквально всё.

Мой обратный прокси будет обрабатывать маршрутизацию от WAN к forum.domainname.com.

Кэширование было отключено.

Только если вы не измените их. Как и следовало бы, используя только один порт.

80:80 и 443:443 — это значения по умолчанию, которые используются только в том случае, если нет обратного прокси-сервера или чего-либо ещё, выступающего в качестве фронтенда.

Ты дал мне идею.

Я был занят проверкой всех базовых файлов и, думаю, разобрался.

Так просто, лол. Я сейчас занимаюсь восстановлением, и это может сработать на 100%, если использовать стандартные официально поддерживаемые методы установки.

Успех! Форум теперь установлен и работает.

Используя стандартный и поддерживаемый метод установки :smiley:


@pfaffman Вы можете переместить это в раздел установки, так как сейчас это поддерживаемая установка.

Оно там есть. Просто помечено как неподдерживаемое :smirking_face:

А в чём была проблема изначально, из-за чего вы не начали установку без обратного прокси? Мне просто интересно.