Nginx
NGINX - Один из самых популярных веб-серверов в этом вашем интернете. Может выступать не только веб-сервером, но и load-балансером, а так же прокси. Все то что ты сейчас читаешь тут работает именно через NGINX, потому как апач не то чтобы совсем безопасен в использовании, но как говорится - в кривых руках и NGINX не панацея.
Тема с конфигурацией NGINX очень обширна, большинство фич обычному обывателю врядли понадобятся, но чуток посмотрим что тут есть для нас.
Простой минимальный конфиг для работы сервера
В случае если необходимо обеспечить работу виртуального хоста для работы необходимо прописать в /etc/nginx/sites-available/hosnaname.conf такие данные:
NGINX Proxy Pass (полезно в случае если крутится сервис Docker на 3000 порту
server { listen 80; listen [::]:80; server_name hostname.ru; location / { proxy_pass http://localhost:3000/; } }
Или ссылаемся на папку (Вариант без PHP. Только HMTL странички):
server { listen 80; listen [::]:80; server_name hostname.ru; root /var/www/public_html; index.html index.htm; location / { try_files $uri $uri/ =404; } }
Далее делаем символическую ссылку в /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/hostname.ru.conf /etc/nginx/sites-enabled/hostname.ru.conf
Проверить конфиг можно командой:
mayekkuzu@yet-another-hostname:~# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
SSL Certbot
Для обеспечения доступа к сайту по HTTPS необходимо запросить сертификат Let's Encrypt и прописать в конфиг. Это можно сделать автоматически с помощью certbot. В Debian, к примеру можно установить пакеты certbox и python3-certbot-nginx
sudo apt install certbot python3-certbot-nginx
После того как создана символическая ссылка на конфиг и проверка конфига прошла успешно, перезапускаем службу nginx и запрашиваем сертификат у ACME Let's Encrypt.
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d hostname.ru
В автоматическом режиме будет установлен сертификат и прописан в конфиг фаил. В процессе запроса необходимо согласиться с правилами обслуживания и прописать свою электронную почту. Теперь посмотрим каким образом выглядит наш конфигурационный фаил:
root@hostname:~# sudo cat /etc/nginx/sites-enabled/hostname.ru.conf server { server_name hostname.ru; location / { proxy_pass http://localhost:8080/; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/hostname.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/hostname.ru/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = hostname.ru) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name hostname.ru; return 404; # managed by Certbot }
Или же в случае с конфигом с root папкой на html-файлы:
server { root /var/www/hostname-folder-with-htmls; index index.html; server_name hostname.ru; location / { try_files $uri $uri/ =404; } listen [::]:443; # managed by Certbot listen 443; # managed by Certbot ssl_certificate /etc/letsencrypt/live/hostname.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/hostname.ru/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = hostname.ru) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name hostname.ru; return 404; # managed by Certbot }
Скрипт автоматически создает редирект с HTTP на HTTPS, а так же указывает пути к к приватному ключу и всей цепочке сертификатов для корректной работы. Стоит отметить, что сертификат выдается на 90 дней. Для автоматического продления предусмотрен запуск скрипта через crontab, который прописывается после получения сертификата/сертификатов Let's Encrypt для всех хостов в системе. Посмотреть можно через crontab:
root@hostname:~# crontab -l 8 18 * * * "/opt/acmesh/.acme.sh"/acme.sh --cron --home "/opt/acmesh/.acme.sh" > /dev/null
В случае, если сертификат не продлился или же подходит срок по каким-то причинам, вы получите письмо на почту от Let's Encrypt Expiry Bot, примерно такого содержания:
Hello, Your certificate (or certificates) for the names listed below will expire in XX days (on XXXX-XX-XX). Please make sure to renew your certificate before then, or visitors to your web site will encounter errors. We recommend renewing certificates automatically when they have a third of their total lifetime left. For Let's Encrypt's current 90-day certificates, that means renewing 30 days before expiration. See https://letsencrypt.org/docs/integration-guide/ for details. hostname.ru For details about when we send these emails, please visit: https://letsencrypt.org/docs/expiration-emails/ In particular, note that this reminder email is still sent if you've obtained a slightly different certificate by adding or removing names. If you've replaced this certificate with a newer one that covers more or fewer names than the list above, you may be able to ignore this message.
WebSocket
Некоторые веб-приложения требуют возможность работы с WebSocket (чаще всего это приложения docker через proxy-pass. Для этого блок location приведем к такому виду:
... location / { proxy_pass http://localhost:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } ...
После чего перезапустим службу NGINX.
Host Headers и X-Real-IP
Иногда может быть ситуация, когда при обращении к странице в аппку которая крутится внутри контейнера, страница обращается по локальному IP или IP-контейнера, в следствии чего JS и прочие штуки не загружаются. Так же тут добавлена директива, которая позволяет видеть реальные IP-адреса клиентов.
... location / { proxy_pass http://ip:port/; add_header X-Served-By $host; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_http_version 1.1; } ...
Настройка iptables для NGINX
Целевая статья по настройке HaProxy - тут
Предварительно уточню, что произведен проброс портов на роутере по 443 и 80 портам к виртуальной машине NGINX.
Для того чтобы NGINX отвечал только на сервер Haproxy и игнорировал запросы от других IP настроим iptables. В моем случае это Rocky Linux. Мне лениво ебаться с firewall-cmd, поэтому тушу его нахуй и ставлю пакет iptables и активирую сервис:
sudo systemctl stop firewalld sudo systemctl disable firewalld dnf install iptables-services iptables-utils sudo systemctl enable iptables sudo systemctl start iptables
Далее добавляем такие правила для веб-сервисов (имя интерфейса посмотрите через ip a
):
sudo iptables -I INPUT -s IP-сервера-haproxy -p tcp --dport 443 -i ens18 -j ACCEPT sudo iptables -I INPUT -s IP-сервера-haproxy -p tcp --dport 80 -i ens18 -j ACCEPT
Себе я добавляю правила которые позволят работать с домашней сети по SSH:
sudo iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 22 -i ens18 -j ACCEPT
В конце добавляем правила отклоняющие остальные соединения по 80 и 443 порту:
iptables -A INPUT -j DROP -p tcp -i ens18 --dport 80 iptables -A INPUT -j DROP -p tcp -i ens18 --dport 443
И сохраняем правила. Так же смотрим статус:
[mayekkuzu@nginx-edge ~]$ sudo /sbin/service iptables save [mayekkuzu@nginx-edge ~]$ sudo iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 192.168.1.0/24 anywhere tcp dpt:ssh ACCEPT tcp -- XX.XX.XX.XX anywhere tcp dpt:http ACCEPT tcp -- XX.XX.XX.XX anywhere tcp dpt:https DROP tcp -- anywhere anywhere tcp dpt:http DROP tcp -- anywhere anywhere tcp dpt:https Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination