Назад | Перейти на главную страницу

NGINX выдает ошибку 404 на всех страницах, кроме HTML.

Я настраиваю nginx как обратный прокси в контейнере докеров для ссылки на сайты за пределами контейнера. У меня есть настройка конфигурации vhost следующим образом (я пробовал добавить ^ ~ перед местом для домашнего помощника):

server { # simple reverse-proxy
    listen       80;

    location / {
        proxy_pass http://192.168.1.99:6789;
    }

    location ^~ /home-assistant {
        proxy_pass http://192.168.1.99:8123/;
    }

    location /calibre-web/ {
        proxy_pass http://192.168.1.99:8181/;
    }

  }

Как для сайтов home-assistant, так и для сайтов caliber-web страница загружается, но я получаю 404 ошибки для всех остальных элементов (изображений, CSS и т. Д.). Если я попытаюсь щелкнуть ссылку в приложениях, она свяжет меня с 192.168.1.99/file, а не с 192.168.1.99/site-folder/file, как следовало бы.. Ниже приведены несколько записей из журналов (обратите внимание на один ответ 200 и другие ответы 404). Что я здесь делаю не так? Заранее спасибо за помощь.

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:15:42 +0000] "GET /frontend/panels/logbook-66108d82763359a218c9695f0553de40.html HTTP/1.1" 404 199 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:54 +0000] "GET /home-assistant/ HTTP/1.1" 200 1654 "-" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/icons/favicon-192x192.png HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

192.168.1.6 - randy [15/Aug/2016:03:17:55 +0000] "GET /static/core-457d5acd123e7dc38947c07984b3a5e8.js HTTP/1.1" 404 91 "http://192.168.1.99/home-assistant/" "Mozilla/5.0 (X11; CrOS x86_64 8350.60.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.85 Safari/537.36"

Вот копия моего корневого nginx.conf. Я предполагаю, что ошибка где-то здесь, я просто не могу понять где.

Вы пытаетесь отправлять запросы proxy_pass из местоположения, неизвестного исходному приложению. В приложении docker-контейнера все еще считается, что к нему обращаются из корня веб-сайта (http://192.168.1.99:8123/), поэтому он генерирует все URL-адреса относительно /не твоему /home-assistant/ или /calibre-web/.

Есть множество способов решить эту проблему, вы должны выбрать то, что вам больше всего подходит:

1. Замена ссылок в проксированном html

Прежде всего, это замена каждой ссылки, полученной от прокси-приложения, перед отправкой результата клиенту возможна с ngx_http_sub_module. По умолчанию он не включен, поэтому вам, возможно, придется скомпилировать nginx из исходников если в вашем дистрибутиве его нет (чтобы проверить доступность этого модуля, запустите nginx -V, который должен отображать --with-http_sub_module где-то по параметрам конфигурации).

Если вы выберете этот метод, добавьте в конфигурацию следующие директивы:

location ^~ /home-assistant {
    rewrite ^/home-assistant(/.*)$ $1 break;
    proxy_pass http://192.168.1.99:8123/;
    sub_filter "<head>" "<head><base href=\"${scheme}://${host}/home-assistant\">";
}

2. Изменение пути к приложению внутри контейнера.

Перенос приложения из контейнера докеров в /home-assistant вместо root, поэтому он будет генерировать все URL-адреса в обслуживаемом контенте, связанные с этим путем, вместо root /. Это очевидное (и, вероятно, самое простое) решение, которое вообще не требует касания конфигураций nginx (вместо этого вы редактируете конфигурацию внутри докера)

3. Выбор восходящего потока на основе заголовка Referer

Определение того, какой восходящий поток следует использовать на основе Referer заголовок. Взято отсюда. Выглядит довольно умно, хотя я бы сам не стал использовать его в продакшене (обратите внимание, что он работает только для файлов css / js).

location ~* ^/(css|js)/.+\.(css|js)$ {
    #checking if referer is from home-assistant
    if ($http_referer ~ "^.*/home-assistant"){
        return 417;
    }

    #checking if referer is from calibre-web
    if ($http_referer ~ "^.*/calibre-web"){
        return 418;
    }
}

error_page   417  /home-assistant$request_uri;
error_page   418  /calibre-web$request_uri;

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123/;
}

location /calibre-web {
    proxy_pass http://192.168.1.99:8181/;
}

На вашем месте я бы выбрал второй вариант - перемещение приложений внутри контейнера как самый простой и наименее подверженный ошибкам способ получить то, что вам нужно.

P.S. Я совершенно забыл, что вы можете обслуживать статические файлы прямо со своего жесткого диска, поскольку ваш бэкэнд находится на том же сервере, что и nginx. Это потребует некоторой настройки, зависящей от приложения, но в результате вы получите наиболее эффективное решение.

Одним из решений может быть не передавать URI в proxy_pass директива:

location ^~ /home-assistant {
    proxy_pass http://192.168.1.99:8123;
}

location ^~ /calibre-web/ {
    proxy_pass http://192.168.1.99:8181;
}

Обратите внимание на отсутствие / символ после номера порта в proxy_pass заявление. Это означает, что nginx будет передавать URI, отправленный на сервер, на сервер приложения.

С / символ (URI), он заменит URI запроса этим.

Это поведение задокументировано в http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass