Včera som sa konečne dostal k presmerovaniu virtualhostov na reverznom proxy nginx. Ako som spomínal v tomto blogu tak na LAMP stacku prevádzkujem niekoľko virtualhostov. Vzhľadom k tomu, že ma čaká inštalácia nového NextClud Hub a starý NextCloud musím nechať v prevádzke, tak všetky weby musím smerovať cez reverzný proxy nginx. Presmerovanie bolo vcelku hladké, ale problém bol s WordPressom.
Vysetlíme si to len na jednom servery (resp. virtualhoste), ostatne sa robia analogicky. Modelová situácia je nasledovná.

- PFsense – na PPPoE je verejná IPv4 adresa
- Apache – 4x vhost (4 verejne doménové mená)
Podľa topológie (viď obrázok) to funguje následovne. Klient zadá požiadavku na doménové meno, ktoré obsluhuje jeden z virtualhostov na Apache servery. Predpokladajme, že klient od DNS serverov obdržal správnu IPv4 adresu a paket doputuje na našu Public IP. Keďže Apache je za NATom, tak paket sa preloží z verejnej IP na IP adresu webového servera. Server vygeneruje odpoveď a odosiela paket klientovi (opačným spôsobom ako paket prijal). Znova sa odvolám na predošlý blog, kde sme vedľa apache servera postavili ďalší (prip. viac) apache server. Pozri nasledujúci obrázok.

Je známe, že webové služby fungujú na štandardných portoch 80 (bez šifrovania) a 443 (so šifrovaním). Ak vlastníme jednu verejnú IPv4 adresu, tak tieto porty môžeme NAT(ovať) len na jednu privátnu IPv4 adresu. Ako je vidieť z obrázka, webové servery máme na troch privátnych IP adresách. Takže pred ne sme postavili reverzný proxy server. Teraz sa pozrieme ako je nakonfigurovaný virtualhost na bežnom apache servery. Tento server momentálne rieši aj SSL/TLS šifrovanie.
<VirtualHost *:80>
DocumentRoot /var/www/www.first-domain.com
ServerName first-domain.com
ServerAlias www.first-domain.com
ServerAdmin webmaster@first-domain.com
RewriteEngine on
RewriteCond %{HTTP_HOST} ^first-domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.first-domain.com$1 [R=301,NE,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /var/www/www.first-domain.com
ServerName first-domain.com
ServerAlias www.first-domain.com
ServerAdmin webmaster@first-domain.com
<IfModule mod_ssl.c>
SSLEngine on
SSLCertificateKeyFile /etc/letsencrypt/live/first-domain.com/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/first-domain.com/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/first-domain.com/chain.pem
</IfModule>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^first-domain\.com$ [NC]
RewriteRule ^(.*)$ https://www.first-domain.com$1 [R=301,NE,L]
</VirtualHost>
Tento konfiguračný súbor nahradíme týmto a reštartujeme služby
<VirtualHost *:80>
ServerAdmin admin@first-domain.com
ServerName first-domain.com
ServerAlias www.first-domain.com
DocumentRoot /var/www/www.first-domain.com/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
sudo systemctl restart apache2
Následne
- Prihlásime sa na reverzný proxy cez SSH
- Vytvorime konfiguračný súbor
- Naplníme ho obsahom
- Skontrolujeme syntax konfigurácie
- Vytvoríme symbolicky link na súbor
- Reloadneme nginx službu
ssh name@192.168.1.10
sudo nano /etc/nginx/sites-available/www.first-domain.com
server {
listen 80;
server_name first-domain.com;
return 301 http://www.first-domain.com$request_uri;
}
server {
listen 80;
server_name www.first-domain.com;
location / {
proxy_pass http://192.168.1.12;
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 $scheme;
}
}
sudo nginx -t
sudo ln -s /etc/nginx/sites-available/www.first-domain.com /etc/nginx/sites-enabled/www.first-domain.com
sudo systemctl reload nginx
Nesmieme zabudnúť na zmenu IP adresy v NAT tabuľke. Nastavovali sme to už minule. Teraz nás čaká obstaranie certifikátov od Let’s Encrypt. To sme už ale tiež robili. Pre istotu sem napíšem aj príkaz
sudo certbot --nginx -d first-domain.com -d www.first-domain.com
Týmto spôsobom spravíme aj ďalšie weby, resp. virtualhosty. Všetko prebehlo takmer bez problémov až na CMS WordPress (na ktorom beží napr. aj tento web). Doména na ktorej beží WordPress jednoducho neodpovedala. Takže som začal pátrať v čom je zakopaný pes. Celkom rýchlo som našiel riešenie môjho problému. Musel som upraviť konfiguračný súbor pre WordPress a vložiť tam jeden skript. Vysvetlenie je na podpore wordpressu.
sudo nano /path_to_wordpress/wp-config.php
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
$_SERVER['HTTPS']='on';
Záver
Z pohľadu backendových serverov nie je potrebné nastavovať nič extra. Stačí zmeniť konfiguračný súbor a reštartovať apache server. Na frontende sa musí vytvoriť nový konfig, ktorý na základe smernice proxy_pass smeruje prevádzku na správny backend. Frontendový nginx sa tak isto postará o SSL/TLS šifrovanie, takže tým sa odľahčia backendové servery.