По принцип предпочитам за WEB сървър да ползвам Apache, но на няколко пъти ми се случи да боравя с Nginx. На пръв поглед ми се видя лек и удобен затова ще покажа как се инсталира върху Debian и как се настройва. За целта ни трябва: - инсталирана ОС, в случая Debian, - инсталирана и конфигурирана защитна стена (ufw), при условие, че нямате друга такава, - пренасочени портове TCP 80 и 443 Започваме с инсталацията.
apt update apt dist-upgrade apt install nginx -y
Ако ползвате защитна стена на самия Debian то трябва и тя да се инсталира.
apt install ufw -y
Ако не ползвате то тази стъпка и няколко надолу отнасящи се за стената можете да ги пропуснете. Активираме стената.
ufw enable ufw status Firewall is active and enabled on system startup Status: active
Трябва да отговори че е активна. Между другото добра практика е винаги да има защитна стена, независимо, че имате рутер с такава. Това ще помогне за защита в локалната мрежа. Сега да позволим няколко порта, за да управляваме през тях машината.
ufw allow 22 ufw allow 80 ufw allow 443
Разрешихме портове, 22 за SSH, 80 за HTTP и 443 за HTTPS. Ако за тези услуги ползвате други портове то трябва да укажете които ползвате. Между другото, можете да боравите с защитната стена и чрез приложения. Нека да видим кои са позволени.
ufw app list ... ... Bind9 ... ... DNS SSH WWW ... и т.н.
Не показвам целия списък защото е дълъг. Нарочно по-горе не позволих порт 53 UDP за DNS-a. ще го позволим чрез ufw app. Има и още една разлика, специално в този случай. SSH-a ми работи на порт 6705, а тук сме позволили порт 22. Да проверим кои правила са активни.
ufw status Status: active To Action From -- ------ ---- 22 ALLOW Anywhere 80 ALLOW Anywhere 443 ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6) 80 (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6)
Разрешени портове 22, 80 и 443. Да позволим нашия SSH.
ufw allow 6705
Забележете, не използвах ufw allow SSH, защото щеше отново да освободи порт 22, а дефинирах точно порт 6705. Да разрешим и DNS-a
ufw allow dns Rule added Rule added (v6) ufw status Status: active To Action From -- ------ ---- 22 ALLOW Anywhere 80 ALLOW Anywhere 443 ALLOW Anywhere 6705 ALLOW Anywhere DNS ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6) 80 (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6) 6705 (v6) ALLOW Anywhere (v6) DNS (v6) ALLOW Anywhere (v6)
За сега това ни стига.
Да се върнем на Nginx.
systemctl status nginx
Активиран и работи без грешки. Самите конфигурационни файлове се намират в /etc/nginx. От там за сега ни вълнуват файла nginx.conf и папката sites-available. Първият е за общите настройки на Nginx, а папката е за създаване на виртуални сайтове.
nano /etc/nginx/nginx.conf user www-data; worker_processes 1; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/conf-enabled/*.conf; include /etc/nginx/sites-enabled/*.conf; }
Обърнете внимание на редовете маркирани в червено. Указва, че конфигурационните файлове на виртуалните хостове трябва да завършват на .conf. Сега да видим какви виртуални сайтове имаме създадени по подразбиране.
ls -l /etc/nginx/sites-available total 4 -rw-r--r-- 1 root root 2412 Mar 14 2023 default
Наличен един виртуален сайт default. Това е глобален файл за всички виртуални сайтове. Има се на предвид следното. Примерно имаме два домейна (tlan.net и tachko.com). При използване на този глобален файл както и да напишем (http://tachko.com, http://tlan.net, https://tlan.net, https://tachko.com) винаги ще се отваря една и съща страница. Затова не трябва да е активен. Активирането на даден виртуален сайт става с линк на дадения файл, отговарящ за даден сайт към папка /etc/nginx/sites-enabled. Да проверим:
ls -l /etc/nginx/sites-enabled/ total 0 lrwxrwxrwx 1 root root 34 Apr 20 17:00 default -> /etc/nginx/sites-available/default
Точно така, в /etc/nginx/sites-enabled имаме линк default сочещ към файла /etc/nginx/sites-available/default Деактивирането на виртуалния сайт става, чрез триене на линка сочещ към дадения виртуален сайт. Задачата ни е да изтрием виртуалния сайт default и да създадем нов, примерно my.tlan.net.conf. За ръководство ще ползваме файла default.
### Деактивираме глобалния сайт. rm /etc/nginx/sites-enabled/default ### Стандартно конфигурационния файл изглежда така: # Default server configuration # server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf; root /var/www/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } # pass PHP scripts to FastCGI server # #location ~ \.php$ { # include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): # fastcgi_pass unix:/run/php/php7.4-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # Virtual Host configuration for example.com # # You can move that to a different file under sites-available/ and symlink that # to sites-enabled/ to enable it. # #server { # listen 80; # listen [::]:80; # # server_name example.com; # # root /var/www/example.com; # index index.html; # # location / { # try_files $uri $uri/ =404; # } #} ### Създаваме виртуален сайт gost.tachko.com nano /etc/nginx/sites-available/gost.tachko.com.conf server { listen 80; listen [::]:80; root /var/www/gost.tachko.com; index index.html index.htm; server_name gost.tachko.com; error_log /var/log/nginx/gost.tachko.com_error.log; access_log /var/log/nginx/gost.tachko.com_access.log; location / { try_files $uri $uri/ =404; } } server { listen 80; listen [::]:80; root /var/www/gost.tachko.com; index index.html index.htm; server_name mail.tachko.com; error_log /var/log/nginx/gost.tachko.com_error.log; access_log /var/log/nginx/gost.tachko.com_access.log; location / { try_files $uri $uri/ =404; } }
Обърнете внимание на червения ред. Дефинирахме два виртуални хоста от един ранг в един конфигурационен файл. Двата сайта гледат в едно и също място (/var/www.gost.tachko.com). С една дума ще вършат една и съща работа, но на по-късен етап единия ще е с удостоверен сертификат а другия с локален. Също важен момент е местоположението на логовете ( /var/log/nginx/). Тук често ще проверяваме при грешки в работата на виртуалния сайт и съответно кой достъпва сайта. Не е грешка двата сайта да сочат на отделни собствени папки с отделни логове. По-надолу ще създадем още по-семпъл конфигурационен файл за gost.tlan.net и mail.tlan.net. Между другото можете всички виртуални хостове да ги опишете в един файл, както горния пример но става много голям и мъчно се следи за грешки. Пътя за разполагане на файловете за сайта е /var/www/gost.tachko.com/. Имената на сайтовете е: gost.tachkok.com и mail.tachko.com. Да се заемем със създаване на папка за сайта и правата върху нея.
mkdir -p /var/www/gost.tachko.com/ chown -R www-data:www-data /var/www/gost.tachko.com/
Активираме сайта.
ln -s /etc/nginx/sites-available/gost.tachko.com.conf /etc/nginx/sites-enabled/
Рестартираме Nginx.
service nginx restart service nginx status
Да създадем HTML файл в папката на gost.tachko.com
echo "gost.Tachko.COM" > /var/www/gost.tachko.com/index.html
Да проверим как работи сайта. Едновременно ще гледаме какво става в логовете.
tail -f /var/log/nginx/gost.tachko.com_access.log
Отваряме сайта през браузър на адрес http://gost.tachko.com. В лога трябва да се получи следния отговор.
109.160.80.230 - - [16/Mar/2025:17:41:01 +0000] "GET / HTTP/1.1" 200 16 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.9) Gecko/20100101 Goanna/4.4 Firefox/68.9 PaleMoon/28.8.4"
Наистина показва, че сме отворили страницата чрез PaleMoon и т.н. В сгъстен ред да оправим виртуалния хост gost.tlan.net
### Създаваме виртуален сайт gost.tlan.net nano /etc/nginx/sites-available/gost.tlan.net.conf server { listen 80; listen [::]:80; root /var/www/gost.tlan.net; index index.html index.htm; server_name gost.tlan.net mail.tlan.net; error_log /var/log/nginx/gost.tlan.net_error.log; access_log /var/log/nginx/gost.tlan.net_access.log; location / { try_files $uri $uri/ =404; } } mkdir -p /var/www/gost.tlan.net/ chown -R www-data:www-data /var/www/gost.tlan.net/ ln -s /etc/nginx/sites-available/gost.tlan.net.conf /etc/nginx/sites-enabled/ service nginx restart service nginx status echo "gost.Tlan.NET" > /var/www/gost.tlan.net/index.html tail -f /var/log/nginx/gost.tlan.net_access.log
Ще създадем безплатни SSL сертификати на Let’s Encrypt чрез certbot. За начало да я инсталираме, а след това да я настроим за нашия случай.
### Инсталираме certbot и плъгина за работа с Nginx apt install certbot python3-certbot-nginx -y ### За начало да тестваме дали можем да генерираме сертификатите Вижте по-долу коя опция за какво е преди да пуснете командата. certbot certonly --webroot --dry-run --email tachko@tachko.com -w /var/www/gost.tachko.com -d gost.tachko.com -w /var/www/gost.tlan.net -d gost.tlan.net Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y Account registered. Simulating a certificate request for gost.tachko.com and gost.tlan.net The dry run was successful. ### Сертификатите могат да бъдат създадени правилно. ### Стартираме certbot за генериране на сертификати в Nginx certbot --nginx Saving debug log to /var/log/letsencrypt/letsencrypt.log Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): tachko@tachko.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: N ### Предлага да ни уведомява за новости от Let's Encrypt Account registered. Which names would you like to activate HTTPS for? We recommend selecting either all domains, or all domains in a VirtualHost/server block. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: gost.tachko.com 2: mail.tachko.com 3: gost.tlan.net 4: mail.tlan.net - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shown (Enter 'c' to cancel): 1,3 Requesting a certificate for gost.tachko.com and gost.tlan.net Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/gost.tachko.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/gost.tachko.com/privkey.pem This certificate expires on 2025-06-16. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. Deploying certificate Successfully deployed certificate for gost.tachko.com to /etc/nginx/sites-enabled/gost.tachko.com.conf Successfully deployed certificate for gost.tlan.net to /etc/nginx/sites-enabled/gost.tlan.net.conf Congratulations! You have successfully enabled HTTPS on https://gost.tachko.com and https://gost.tlan.net - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Готово сертификатите се генерираха. Малко пояснение по разширенията на командата certbot (по-надолу ще покажа и други вариации): ● certbot - Самата програма за генериране на публични сертификати ● python3-certbot-nginx - Плъгин към certbot за работа с Nginx ● certonly - Получете или подновете сертификат, но не го инсталирайте (не ги вписвайте в конфигурационните файлове на виртуалните хостове) ● --webroot - Поставете файлове в папката webroot на сървъра за удостовер ● --dry-run - Тествайте "renew" или "certonly", без да запазвате никакви сертификати на диск ● --webroot-path или -w - public_html / webroot път. Това може да се посочи многократно да обработва различни домейни; всеки домейн ще има webroot път, който го предшества. Например: `-w /var/www/example -d example.com -d www.example.com -w /var/www/thing -d thing.net -d m.thing.net` ● --email - електронен адрес удостоверяващ, че сертификатите са на определен получател Да проверим какво се е променило в конфигурационните файлове на виртуалните хостове.
nano /etc/nginx/sites-available/gost.tachko.com.conf server { root /var/www/gost.tachko.com; index index.html index.htm; server_name gost.tachko.com; error_log /var/log/nginx/gost.tachko.com_error.log; access_log /var/log/nginx/gost.tachko.com_access.log; location / { try_files $uri $uri/ =404; } listen [::]:443 ssl ipv6only=on; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/gost.tachko.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/gost.tachko.com/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 { listen 80; listen [::]:80; root /var/www/gost.tachko.com; index index.html index.htm; server_name mail.tachko.com; error_log /var/log/nginx/gost.tachko.com_error.log; access_log /var/log/nginx/gost.tachko.com_access.log; location / { try_files $uri $uri/ =404; } } server { if ($host = gost.tachko.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name gost.tachko.com; return 404; # managed by Certbot } gost.tlan.net.conf server { root /var/www/gost.tlan.net; index index.html index.htm; server_name gost.tlan.net mail.tlan.net; error_log /var/log/nginx/gost.tlan.net_error.log; access_log /var/log/nginx/gost.tlan.net_access.log; location / { try_files $uri $uri/ =404; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/gost.tachko.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/gost.tachko.com/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 = gost.tlan.net) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name gost.tlan.net mail.tlan.net; return 404; # managed by Certbot }
Вижте редовете в чевено. Имаме вградени новите сертификати за HTTPS на порт 443. Имаме пренасочване на HTTP към HTTPS. Това са най-важните неща. Продължаваме с вариации на генериране на сертификатите. Ако не ви се играе да отговаряте на всякакви въпроси има по-пълна команда за този случай.
certbot --agree-tos --redirect --hsts --staple-ocsp --email tachko@tachko.com -d gost.tachko.com -d gost.tlan.net
Тази команда отново ще редактира конфигурационните файлове на виртуалните хостове (сайтове). Ако не искате промени по конфигурационните файлове то тогава:
certbot certonly --webroot --agree-tos --email tachko@tachko.com --webroot-path /var/www/gost.tachko.com -d gost.tachko.com -w /var/www/gost.tlan.net
Това ще генерира файлове за сертификатите в /etc/letsencrypt/live/gost.tachko.com/, но няма да промени конфигурационните файлове на виртуалните хостове. Често срещана практика ако ползвате готово решение, примерно като пощенския сървър iRedMail. За накрая няколко често ползвани команди с certbot.
### Обновяване на сертификатите certbot renew ### Проверка дали сертификата е обновен certbot renew --dry-run ### Принудително обновяване на сертификата за даден виртуален хост certbot certonly --force-renew -d example.com
Малко претупано стана всичко по-горе. Инсталирахме сертификати, автоматично се оправи файла за виртуалния ни сайт да работи на порт 443 и т.н. Тук ще се пробвам да покажа как ще постигнем всичко това без certbot. Наново да проверим конфигурационния файл за виртуалния ни сайт преди ползването на certbot.
nano /etc/nginx/sites-available/gost.tlan.net.conf server { listen 80; listen [::]:80; root /var/www/gost.tlan.net; index index.html index.htm; server_name gost.tlan.net mail.tlan.net; error_log /var/log/nginx/gost.tlan.net_error.log; access_log /var/log/nginx/gost.tlan.net_access.log; location / { try_files $uri $uri/ =404; } }
Сега ще ползваме сертификатите генерирани по време на инсталацията на Debian. Те не са публично удостоверени но независимо от това ще ги използваме.
nano /etc/nginx/sites-available/my.tlan.net.conf server { listen 443 ssl; listen [::]:443 ssl; server_name gost.tlan.net mail.tlan.net; root /var/www/gost.tlan.net; index index.html index.htm; ssl_certificate "/etc/letsencrypt/live/www.srv.world/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/www.srv.world/privkey.pem"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; location / { try_files $uri $uri/ =404; } } server { if ($host = gost.tlan.net) { return 301 https://$host$request_uri; } listen 80; listen [::]:80; server_name gost.tlan.net mail.tlan.net; return 404; }
Горната секция server { отговаря за HTTPS на порт 443. Ползваме SSL сертификатите fullchain.pem и privkey.pem които имаме когато инсталирахме Debian. В долната секция server { чрез return 301 https://$host$request_uri; пренасочваме "твърдо" заявките от HTTP към HTTPS. Това пренасочване понякога е излишно защото не се церемони а директно пренасочва. Използва се когато всичко е тествано и решението е точно. Ако все още не сте сигурни ползвайте вместо 301, 302. Така няма да кеширате в браузъра това което дефинирате и ще можете да направите няколко теста преди да поставите 301. Има още един код 404. Това е върната грешки при не откриване на страницата. За да влязат в сила промените отново трябва да се презареди Nginx.
service nginx reload
С това приключваме темата.