Jakiś już czas temu pisałem jak przekierować ruch ze strony na serwerze Apache2, dziś – zgodnie z zapowiedzią – kolejna odsłona, tylko dla serwera opartego o Nginx…
W przypadku tego serwera (Nginx) nie mamy wprawdzie do dyspozycji pliku .htaccess, ale podobne efekty możemy uzyskać edytując plik konfiguracyjny danej strony (vHosta).
Spis treści w artykule
- 1 Nginx i przekierowania
- 1.1 Przekierowanie www.domena na domena
- 1.2 Przekierowanie całego ruchu na inną domenę
- 1.3 Przekierowanie pojedynczego adresu URL
- 1.4 Przekierowanie „po slashu” (/)
- 1.5 Przekierowanie/zmiana typu pliku
- 1.6 Kilka domen, jeden katalog i jedna główna domena
- 1.7 Przerwa techniczna
- 1.8 Pracujemy nad nową wersją strony, a inni widzą starą wersję
- 2 Nginx, $remote_addr i Cloudflare
Nginx i przekierowania
Jeśli korzystacie z własnego serwera to sami wybieracie z jakiego (web)serwera korzystacie, i jeśli to Apache2 – również odsyłam do tego poradnika. Jeśli wybraliście Nginx – to artykuł dla Was :-)
Więcej na temat konfiguracji serwera WWW opartego o Nginx pisałem tutaj…
R=301, R=302, R=307
Tak jak w przypadku poradnika dotyczącego przekierowań w Apache2 (.htaccess), tak i w tych przykładach mogą pojawiać 3 kody przekierowań:
- R=301 – przekierowanie trwałe/stałe
- R=302 – przekierowanie tymczasowe
- R=307 – przerwa techniczna
Przekierowanie www.domena na domena
Chyba najczęściej prze zemnie wykorzystywane przekierowanie, które kieruje cały ruch bezpośrednio na domenę, z pominięciem „subdomeny” www:
# www.domena -> domena
server {
server_name www.[DOMENA];
return 301 $scheme://[DOMENA]$request_uri;
}
Ew. jakby ktoś chciał odwrotnie:
server {
server_name [DOMENA];
return 301 $scheme://www.[DOMENA]$request_uri;
}
Oczywiście podany wyżej kod (1 z 2) wstawiamy powyżej właściwego „server {„.
Wersja alternatywna:
location / {
if ($http_host ~ "^www.rembiejewski.pl$"){
rewrite ^/?$ /"http\:\/rembiejewski\.pl" redirect;
}
}
Lub prościej i chyba bardziej „OK”:
location / {
if ($host ~* ^www\.(.*)) {
return 301 $scheme://$http_host$request_uri;
}
}
Ten kod spowoduje przekierowanie każdego zapytania w postaci:
www.webinsider.pl/cokolwiek
na:
webinsider.pl/cokolwiek
Przekierowanie całego ruchu na inną domenę
By przekierować cały ruch z jednej domeny na inną – np. po zmianie adresu strony – wystarczy skorzystać z:
location / {
rewrite ^(.*)$ $scheme://nasza-nowa-domena.pl/$1 redirect;
}
Lub (zalecam):
location / {
return 301 $scheme://$http_host$request_uri;
}
Przekierowanie pojedynczego adresu URL
Możemy też przekierować pojedynczy adres URL:
location /stary-adres-url.htm {
rewrite ^(.*)$ http://jakaś-domena.pl/nowy-adres-url.htm redirect;
}
Przekierowanie „po slashu” (/)
Możemy ustawić przekierowanie „po slashu” dla naszej domeny:
location /poczta {
return 301 https://jakiś-serwer-pocztowy.pl/panel-poczty;
}
Spowoduje to, że po wpisaniu adresu:
http://jakaś-nasza-domena.pl/poczta
zostaniemy przekierowani na stronę:
https://jakiś-serwer-pocztowy.pl/panel-poczty
Warto też rozważyć dodanie znaku „=”, tak by przekierowanie dotyczyło tylko tego elementu (poczta), a nie wszystkiego co będzie zaczynać się od „poczta” (np. /poczta-jak-konigurowac):
location = /poczta {
return 301 https://jakiś-serwer-pocztowy.pl/panel-poczty;
}
Przekierowanie/zmiana typu pliku
location ~ (.*).html$ {
rewrite ^(.*)$ http://jakaś-nasza-domena.pl$1.php redirect;
}
I tym sposobem każde odwołanie do pliku HTML zostanie automatycznie zmienione na odwołanie do pliku PHP.
Podstawowe przykłady za nami, teraz kilka troszkę bardziej „skomplikowanych” scenariuszy:
Kilka domen, jeden katalog i jedna główna domena
Załóżmy, że mamy kilka domena:
- nazwa-naszej-firmy.pl
- nazwa-naszej-firmy.com.pl
- nazwa-naszej-firmy.eu
I wszystkie 3 domeny kierują do tego samego katalogu na naszym serwerze, i tym samym wyświetlają tą samą stronę/zawartość, choć pod różnymi domenami.
I pewnie by tak mogło być, ale powiedzmy, że w ramach działań SEO (związanych z pozycjonowaniem strony) zapada decyzja by wszystkie domeny kierowały na główna, a przy okazji nie chcemy generować błędów 404 (nie znaleziono strony) jak ktoś skorzysta z linka do produktu/strony z jedną z alternatywnych domen.
W tym celu korzystamy z wpisu:
server {
server_name nazwa-naszej-firmy.pl nazwa-naszej-firmy.com nazwa-naszej-firmy.com.pl nazwa-naszej-firmy.com.pl nazwa-naszej-firmy.eu;
rewrite ^ http://nazwa-naszej-firmy.pl$request_uri? permanent;
}
Tym sposobem wszystkie adresy z domen innych niż .pl zostaną skierowane na nazwa-naszej-firmy.pl, czyli na główny adres.
Przerwa techniczna
Kolejny scenariusz to przerwa techniczna – chcemy wykonać kilka operacji (mniejszych lub większych ;-)) na stronie, będziemy pracować z konkretnych adresów IP… Pozostałych odwiedzających przekierujemy na przygotowaną w tym celu stronę informacyjna („Przepraszamy, przerwa techniczna. Zapraszamy o…”)
location / {
if (-f $document_root/przerwa_techniczna.html) {
return 503;
}
[STANDARDOWY KOD/PARAMETRY]
}
error_page 503 @maintenance;
location @maintenance {
if ($remote_addr !~ "^123.123.123.123"){
rewrite ^(.*)$ /przerwa_techniczna.html break;
}
}
Korzystamy tu z kilku „trików”:
Wykluczamy nasz adres IP z przekierowania, dzięki czemu sami będziemy mieli pełny dostęp do strony:
if ($remote_addr !~ "^123.123.123.123")
Zamiast 123.123.123.123 wstawcie swój adres IP.
Kolejny ważna linijka to:
if (-f $document_root/przerwa_techniczna.html)
Dzięki niej wykrywamy czy istnieje taki plik (przerwa_techniczna.html) na serwerze – jeśli tak, działa „przekierowanie serwisowe”, w innym wypadku strona działa normalnie.
Jest to o tyle wygodne, że w przypadku Nginx nie korzystamy z pliku .htaccess, a pliku konfiguracyjnego danej domeny (vHosta), i każda zmiana w nim wymaga restart serwera (Nginx, nie całego serwera ;-)) lub chociaż odświeżenia (reload) ustawień… A tak wpis sobie czeka już gotowy, aż na serwerze pojawi się odpowiedni plik.
Pracujemy nad nową wersją strony, a inni widzą starą wersję
Załóżmy, że mamy jakąś stronę, ale chcemy w sposób przezroczysty dla użytkowników przygotować nową odsłonę.
Dla jednego z klientów przygotowuje kilka stron internetowych – część jest nowa, więc wystarczy blokada lub przekierowanie na „zaślepkę” (podobnie jak w opisywanej powyżej sytuacji dotyczącej przerwy technicznej).
Tam gdzie strona już działa – sprawa komplikuje się trochę bardziej, bo chcemy przez te „kilka dni” jeszcze utrzymać starą stronę aktywną, gdy w tym czasie szykujemy nową.
Oczywiście można by tu skorzystać ze środowiska testowego, czy subdomeny – ale uznajmy, że środowisko testowe to jednak środowisko testowe, i często po migracji do środowiska produkcyjnego coś będzie nie tak… A subdomena – niby może być w tym samym środowisku, ale po co komplikować sobie później życie… ;-)
Stara strona trafiła do katalogu „old” (oczywiście „old” to tylko nazwa katalogu na potrzeby tego wpisu), a w katalogu głównym powstaje w tym czasie nowa…
Całość – w sposób (pół)przezroczysty dla użytkowników – załatwia taki wpis:
location / {
if ($remote_addr !~ "^123.123.123.123"){
rewrite ^(.*)$ /old$1 redirect;
}
[ STANDARDOWY KOD, np.:
try_files $uri $uri/ /old/index.php?$args; ]
}
Jak w sytuacji powyżej – tak i tym razem zamiast „123.123.123.123” należy wstawić swój adres (lub adresy) IP, dzięki czemu sami nie będziemy przekierowywani…
W przypadku gdy strona wpadnie w zapętlenie, dodajemy jeszcze kod:
location /old {
[STANDARDOWY KOD]
}
Katalog „z plikami strony” zależnie od IP odwiedzającego
A teraz wersja preferowana przeze mnie, a zarazem naprawdę przezroczysta dla użytkownika i dla wyszukiwarek (SEO ;-)), bo nic się nie zmienia w linkach:
set $WWWDIR "stara_strona";
if ($remote_addr ~ NASZE_IP) {
set $WWWDIR "nowa_strona";
}
root /var/www/[DOMENA]/$WWWDIR/;
Gdy my odwiedzamy stronę (NASZE_IP) to serwer serwuje nam pliki z katalogu „nowa_strona”. Gdy stronę odwiedza „osoba postronna” serwer serwuje „starą stronę”, czyli pliki idą z katalogu „stara_strona”.
Katalog „z plikami strony” zależnie od IP odwiedzającego i przeglądarki
Sytuacja trochę się komplikuje, gdy potrzebujemy skorzystać z różnych warunków łącznie, np. gdy łączymy się ze wskazanego IP i korzystamy z wybranej przeglądarki – przydatne, gdy np. chcemy pracować nad nową wersja strony, a zarazem zachować dostęp do starej.
Niestety Nginx chyba nie obsługuje reguł łącznych (i), więc musimy zastosować tutaj mały trik:
set $WWWDIR "stara_strona";
if ($remote_addr ~ NASZE_IP) {
set $test okA;
}
if ($http_user_agent ~ Firefox) {
set $test "${TEST}okB";
}
if ($test = okAokB) {
set $WWWDIR "public_html";
}
root /var/www/[DOMENA]/$WWWDIR/;
Korzystamy z dodatkowej zmiennej $TEST, która przy pierwszym warunku (poprawny adres IP) otrzymuje wartość „okA”, a następnie przy spełnionym drugim warunku (przeglądarka Firefox) otrzymuje dodatkowe znaki „okB” na końcu, co w rezultacie daje „okAokB”. I tylko gdy zmienna $TEST ma wartość „okAokB” – czyli spełnione oba warunki na raz – zostanie ustawiony odpowiedni (roboczy) katalog (public_html).
Katalog „z plikami strony” zależnie od ciasteczka
O ile w biurze mam stały adres IP, to zdarza się, że nad stroną „muszę” popracować też w drodze, gdzie z IP może być różnie. I choć w takich sytuacjach pomaga mi połączenie po VPNie, to jednak nie zawsze jest to możliwe. Do tego, czasem chcę pokazać projekt strony innej osobie, albo grupie osób, i… robi się żonglowanie adresami IP. pomijając już nawet to, że muszę wtedy klientowi tłumaczyć co to jest IP, i jak ma go uzyskać…
W takim przypadku stosuje jeszcze jeden warunek – sprawdzanie ciasteczka:
server {
[...]
set $WWWDIR "stara_strona";
if ($cookie_webinsiderpl = "test") {
set $WWWDIR "public_html";
}
root /var/www/[DOMENA]/$WWWDIR/;
[...]
}
Jeśli w przeglądarce będzie zapisane ciasteczko „webinsiderpl” o zawartości „test”, to zostaną zaserwowane pliki nowej strony.
Oczywiście potrzebny jest jakiś mechanizm zapisujący odpowiednie ciasteczko w przeglądarce. Tu wystarczy odrobina PHP:
<?php
$cookie_name = "webinsiderpl";
$cookie_value = "test";
setcookie( $cookie_name, $cookie_value, time() + 300, '/' ); // 300 = 300 sekund = 5 minut
echo "Ciasteczko wygenerowane";
?>
Całość zapisuje na serwerze (np. w pliku cookie.php) w katalogu ze starą (by wygenerować ciasteczko) i nową stroną (by odświeżyć ciasteczko zanim wygaśnie), i przekazuje prostą instrukcję:
- Wchodzisz na adres [domena]/cookie.php
- Następnie wchodzisz standardowo na stronę
- I tyle – zamiast starej strony widzisz nową
W powyższym przykładzie ciasteczko jest ważne przez 5 minut (300 sekund), po tym czasie – jeśli nie zostanie wygenerowane ponownie – zamiast nowej strony ponownie będzie się wyświetlać stara strona.
A gdy nowa strona będzie już gotowa – wystarczy usunąć te kilka linijek.
Nginx, $remote_addr i Cloudflare
W przypadku gdy korzystacie z Cloudflare jest spora szansa, że przekierowanie nie będzie działać prawidło dla Waszego IP, tzn. nie rozpozna Was (Waszego IP).
W takim przypadku w pliku z konfiguracją danego vHosta, tuż nad regułką sprawdzającą czy IP należy do Was należy dodać:
# Cloudflare IP
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
# /Cloudflare IP
Jest to lista aktualna „na dziś”, więc może się z czasem zmieniać – na tej stronie znajdziecie aktualną listę adresów wykorzystywanych przez Cloudflare, możecie też skorzystać ze skryptu automatycznie pobierające aktualne adresy IP należące do serwerów Cloudflare.
- Wakacje składkowe ZUS a zawieszenie działalności gospodarczej, czyli uważaj, bo być może nie będziesz mógł skorzystać (w 2024) - 1970-01-01
- Przykładowy kalkulator wyceny usługi druku 3D, czyli nie tylko materiał się liczy - 1970-01-01
- Home Assistant 2024.10, czyli nowa karta „nagłówek” i niedziałający TTS w ramach usługi Google Cloud - 1970-01-01
Jednej rzeczy nie rozumiem. Na początku artykułu były wyszczególnione kody przekierowań. Chodzi mi konkretnie o ten kod: R=307 – przerwa techniczna. W akapicie dotyczącym przerwy technicznej podajecie natomiast kod posiadający kod 503. To są dwa różne kody dotyczące tego samego czy błąd w artykule?
To są różne grupy kodów:
W artykule korzystałem z kodów przekierowań (3xx) gdy mowa o przekierowaniach, i kodów odpowiedzi serwera (5xx), gdy serwer ma wysłać „do użytkownika” odpowiedź.
307 to jest tymczasowe przekierowanie, np. na czas przerwy technicznej, 503 z kolei informuje, że strona jest tymczasowo niedostępna – pewnie jakbym zamiast 503 dał 307 to nic by się nie stało… Tak po prostu jestem przyzwyczajony :-)
Najczęściej używam 301 i 302 (rzadziej 303) do przekierowań, do błędu adresu/strony 404 (nie znaleziono), 403 jako brak uprawnień i np. 503 gdy chcę wysłać komunikat o tymczasowej niedostępności usługi (np. przerwa techniczna) ew. 307, że tymczasowo obowiązuje inny adres.
Więcej informacji – wraz z listą wszystkich kodów – znajdziesz na tej stronie…
A jak przekierować różne domeny na różne podstrony dynamiczne tego samego hostingu, np
mojastrona.pl ma wskazywać na 192.167.8.8:8080/app/#mojastrona
A
twojastrona.pl ma wskazywać na
192.167.8.8:8080/app/#twojastrona
Da się to zrobić?
Nie wiem dokładnie jakie są założenia, ale w takim przypadku może wystarczyć zwykłe przekierowanie:
Z tym że wtedy użytkownik będzie widział, że z domeny nastąpiło przekierowanie na inny adres. Możliwe/Pewnie dałoby się to "zakamuflować" (np. jakieś proxy), ale to już zależy od realnego środowiska.