Модул 7 · 7.2
Уеб сървър с nginx
Модул 7: Домейн, уеб сървър и https · Време за четене: 12 минути
Цел на урока: След този урок ще можете да инсталирате nginx, да настроите уебсайт и reverse proxy със server block, да тествате безопасно и да презареждате конфигурация, както и да задавате правилно правата на Вашата webroot.
Основни понятия: nginx, server block, sites-available и sites-enabled, conf.d, listen, server_name, root, index, try_files, default server, nginx -t, reload, reverse proxy, proxy_pass, Host, X-Forwarded-For, X-Forwarded-Proto, webroot, PHP-FPM
Какво прави уеб сървърът
Уеб сървърът слуша на порт 80 (http) и 443 (https), приема заявки от браузърите и връща отговор: файл от диска (статичен сайт) или отговора на програма, която работи зад него (PHP, Node.js приложение, контейнер). Във втория случай уеб сървърът се нарича reverse proxy: той стои отпред, грижи се за https и предава заявката на приложението, което слуша само на 127.0.0.1.
В Linux най-известните уеб сървъри са nginx и Apache, а Caddy (урок 7.4) е модерна алтернатива, която сама се грижи за сертификатите. В този урок използваме nginx: той присъства във всяка дистрибуция, пести памет и е стандартът в много ръководства.
Инсталиране и първи поглед
anna@web1:~$ sudo apt install nginx
anna@web1:~$ systemctl status nginx
anna@web1:~$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.26.3
Content-Type: text/html(Номерът на версията е пример.) Не забравяйте защитната стена: портове 80 и 443 трябва да са отворени (урок 5.2). Ако сега отворите http://192.0.2.10, ще видите страницата за добре дошли на nginx.
Конфигурацията се намира в /etc/nginx/:
| Път | Какво |
|---|---|
nginx.conf | основен файл; обикновено не го пипате |
sites-available/ | по един файл за всеки сайт (Debian и Ubuntu) |
sites-enabled/ | връзки (symlinks) към включените сайтове |
conf.d/*.conf | отделни настройки, които се зареждат винаги |
snippets/ | части, които използвате повторно в няколко сайта |
sites-available и sites-enabled са практика на Debian и Ubuntu: така включвате или изключвате сайт, като създавате или премахвате връзка, без да изтривате самия файл.
Първият сайт
Създайте папка за сайта и тестова страница:
anna@web1:~$ sudo mkdir -p /var/www/example.com
anna@web1:~$ echo '<h1>Het werkt</h1>' | sudo tee /var/www/example.com/index.htmlСлед това създайте server block: описанието на един сайт.
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}Ето как да го четете:
listen 80;иlisten [::]:80;карат nginx да слуша както по IPv4, така и по IPv6. Ако забравите втория ред, Вашият AAAA запис няма да работи (урок 7.1).server_nameуказва за кои имена важи този блок. При всяка заявка nginx гледа името, което браузърът иска (заглавката Host), и избира подходящия блок.rootе папката с файловете, аindexе файлът, който се показва при заявка към папка.try_filesопитва поискания файл, след това папка, а иначе връща 404. Без такъв ред грешна конфигурация може да покаже повече, отколкото искате.- Отделните лог файлове за всеки сайт много улесняват търсенето (урок 6.2).
Включете сайта, премахнете сайта по подразбиране, тествайте и презаредете:
anna@web1:~$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
anna@web1:~$ sudo rm /etc/nginx/sites-enabled/default
anna@web1:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
anna@web1:~$ sudo systemctl reload nginx
anna@web1:~$ curl -I http://example.com
HTTP/1.1 200 OKПревърнете nginx -t преди всяко презареждане в постоянен навик. При грешка командата Ви казва кой файл и кой ред, а работещият Ви сайт остава незасегнат. Ако рестартирате без тест, nginx с грешка вече не стартира и всичките Ви сайтове спират (урок 6.1).
Default server: какво получава непознато име?
Какво става, ако някой поиска Вашия сървър с име, което не фигурира в нито един server_name, или просто с IP адреса? Тогава nginx избира default server: блока с default_server след listen, или иначе първия блок, който е срещнал. Ако не сте помислили за това, това е някой от истинските Ви сайтове.
По-изрядно е да имате отделен блок, който отхвърля такива заявки:
# /etc/nginx/sites-available/000-default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}444 е специален код на nginx: връзката се затваря без отговор. Така скенерите, които обхождат IP адреси, не виждат нищо. За https (порт 443) default server работи малко по-различно, защото към него е нужен сертификат; към това ще се върнем в урок 7.3.
nginx като reverse proxy
Ако на 127.0.0.1:3000 работи приложение (урок 6.3) или на 127.0.0.1:3001 контейнер (урок 9.3), nginx ги прави достъпни отвън:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}Четирите реда с proxy_set_header са важни. Без Host приложението не знае под какво име е посетено. Без X-Forwarded-For приложението вижда всяко посещение като идващо от 127.0.0.1 (proxy) вместо от истинския адрес на посетителя. Без X-Forwarded-Proto приложението смята, че всичко минава по http, и понякога създава връзки или бисквитки за http, макар сайтът Ви да работи по https. Много приложения имат настройка, с която да се доверяват на тези заглавки („trusted proxy“); посочете там само 127.0.0.1, иначе всеки посетител може да изпрати фалшив адрес.
Приложенията, които използват websockets (обновявания на живо, например Uptime Kuma), се нуждаят от още два реда: proxy_http_version 1.1; и предаване на Upgrade и Connection. Документацията на приложението обикновено посочва точно кои.
Права на webroot
В Debian и Ubuntu nginx изпълнява работните си процеси като потребителя www-data. Той трябва да може да чете Вашите файлове, но не бива да може да ги записва. Добро разпределение (урок 3.1):
anna@web1:~$ sudo chown -R anna:www-data /var/www/example.com
anna@web1:~$ sudo find /var/www/example.com -type d -exec chmod 750 {} \;
anna@web1:~$ sudo find /var/www/example.com -type f -exec chmod 640 {} \;Вие (anna) управлявате файловете, групата www-data може да чете, а останалите нямат никакъв достъп. Ако сайтът трябва да записва някъде, например в папка за качени файлове, дайте права за запис на www-data само за тази папка. Никога chmod 777 (урок 10.2). Ако получите 403 Forbidden, погледнете лога за грешки на сайта: там ще намерите permission denied с пътя.
Още няколко добри навика:
- Без тайни в webroot. Резервни копия (
site.zip), файлове.envи папки.gitнямат място там; ако все пак попаднат там по невнимание, те могат да бъдат изтеглени. Допълнителна предпазна мрежа:location ~ /\. { deny all; }блокира всички файлове, чието име започва с точка (освен изрично разрешеното, например/.well-known/, вижте уроци 7.3 и 7.4). - Скриване на версията.
server_tokens off;вnginx.confпремахва номера на версията от заглавкатаServerи от страниците за грешки. Това не е истинска защита, но дава на скенерите по-малко информация.
PHP накратко
За PHP сайтове (например WordPress) nginx комуникира с PHP-FPM, отделна услуга. В Debian инсталирате php-fpm и в server block добавяте блок location ~ \.php$ с include snippets/fastcgi-php.conf; и fastcgi_pass unix:/run/php/php8.4-fpm.sock; (номерът на версията се различава според изданието). Курсът за WordPress разглежда това по-подробно.
В AlmaLinux и Rocky Linux
Там няма sites-available: поставяте всеки сайт като отделен файл в /etc/nginx/conf.d/<naam>.conf. nginx работи като потребителя nginx вместо www-data, а webroot по подразбиране е /usr/share/nginx/html. SELinux по подразбиране не позволява на nginx да се свързва с приложение зад proxy_pass; разрешете това с setsebool -P httpd_can_network_connect 1. Файловете извън обичайните папки се нуждаят от SELinux етикет (semanage fcontext и restorecon).
Обобщение
- nginx сервира файлове или като reverse proxy предава заявките на приложение на
127.0.0.1. - По един server block за всеки сайт в
sites-available, включване с връзка вsites-enabled; слушайте както на80, така и на[::]:80. - Винаги
nginx -tпредиsystemctl reload nginx. - Собствен default server с
return 444не позволява непознато име или голият IP адрес да покажат някой от Вашите сайтове. - Като reverse proxy предавате
Host,X-Forwarded-ForиX-Forwarded-Proto; webroot е четим заwww-data, но не и записваем, и не съдържа тайни.
Тест (quiz)
Задача
Задача O7.2: Вашият първи сайт. Инсталирайте nginx (или използвайте Caddy от урок 7.4), създайте server block за (под)домейн, който сочи към Вашия сървър, с listen за IPv4 и IPv6, собствени лог файлове и собствен default server. Тествайте с nginx -t, презаредете и проверете с curl -I по IPv4 и IPv6. Задайте правата на webroot както в урока. Попълнете контролния списък и поставете Вашия server block.
Задача O7.2: Вашият първи сайт
Тази задача изпълнявате сами; никой не я проверява. Отбележете какво сте направили и маркирайте задачата като изпълнена.
На голия IP адрес нищо (връзката се затваря) или неутрална страница, никога сайт на клиент. Само папката за качване е с права за запис за www-data, останалото е само за четене. Зад proxy: Host, X-Real-IP, X-Forwarded-For и X-Forwarded-Proto.
Вашите отметки и бележки остават само в този браузър; не ги изпращаме никъде. Ако сте влезли, в Моите курсове запазваме само че сте изпълнили задачата.
Още за четене
- Забранено (403): Нямате разрешение за достъп до / на този сървър
- Документация на nginx, How nginx processes a request (server_name и default server): https://nginx.org/en/docs/http/request_processing.html
- Документация на nginx, Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Документация на nginx,
ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html - VPS: от първото влизане до сигурен сървър 5.2: nginx със сертификат от Let's Encrypt
