Nginx frontend backend Docs

В свете вот этого, учитывая что физически сервер расположен у меня на балконе, и подключен к сети по обычному абонентскому соединению от обычного домашнего оператора и мое нежелание тащить его на сервера на работе где есть вся инфраструктура возникла у меня необходимость как то выпустить таки мой новый сцайт вмир😊

Многие скажут - купи хостинг за 1$/VPS/etc и ниипи мозга итд - нихачуя😊 У меня это все на работе есть, но всеравно не хочу. Как говорица своя фуфайка ближе к телу😊 Какрас хостинг и впс помоему ни что иное как мозгоебство, на хостинге шаг влево-вправо - наткнешся на стену, а у меня тут perl и шагов там может быть овердохрена, виртуализацию и облачка не признаю впринципе для таких задач, и вам предлагаю тоже спустица с облачков на землю, тут все лучше😊 Да и вообще, кагдато давно-давно, мой самый первый сайт работал у меня дома ваще на диалапе😊

И тут возникли некоторые сложности со всякими натами и PBR. Схемка сети примерно такая - оператор<->мойроутерснатом<->локалкивсякие. В локалкивсякие находица и сервер, но помимо этого у роутера еще неожиданно есть тоннель ко мне на работу, с bgp прямо в ядро сети и прочими шлюхами дабы мне было удобно работать😊

И, получается что ну даже если я прокину порт с роутера, навешу домен на его внешний адрес ну да - будет работать, со всея интернету, НО, тока не из дома и не с работы😊 И вот почему:

Из дома:

Напишу я в своем бравзере мойсцайт, DNS отрезольвит его во внешний IP моего роутера, туда и отправица запрос, а роутер этот циска, у которого есть такая особенность - херасдва он че прокинет обратно в локалку по статическому правило на outside интерфейсе - тока снаружи, аизнути хрена. Циска говорит юзайте Split-horizon DNS Люк!!!. Но мне это не удобно.

Из работы:

А почему не удобно? а потому что есть еще работа, и оттуда по такой схеме ваще никак ниче не заработает, потому что в том тоннеле с BGP вся моя AS, а у AS вся моя локалка, и тут выйдет малость ассиметрия, не преодолимая ваще😊

Ибо: Напишу я в своем бравзере мойсцайт опять, тока на работе, DNS отрезольвит его во внешний IP моего роутера, туда и отправица запрос, он даже пройдет до сервира, через проброшенный порт на роутере, тока вот ответ взад от сервира пойдет уже от локального адреса, и напрямую через тоннель ибо роутер знает где я работаю и что туда нада ходить на прямую, и этот ответ будет игнорирован, ибо запрос был к адресу x.x.x.x а ответ пойдет от y.y.y.y. А Split-horizon DNS мне не удобен в свете вот этого:

GHhost-home-vgw#show ip bg summary 
BGP router identifier 100.64.65.254, local AS number 42916
BGP table version is 28271, main routing table version 28271
3348 network entries using 455328 bytes of memory
3348 path entries using 187488 bytes of memory
6/6 BGP path/bestpath attribute entries using 768 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 643584 total bytes of memory
BGP activity 8551/5203 prefixes, 15809/12461 paths, scan interval 60 secs

Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
100.64.5.1      4        42916   19045   10025    28271    0    0 6d07h        3342
GHhost-home-vgw#

тоесть овер 3K подсетей, их конечно можно сагрегировать, будет меньше, но там блять еще и локальные есть, а им мои авторитативные сервера ваще не отвечают ниче, поэтому Split-horizon DNS отпадает нах тоже. Да и ваще, там все красиво четко и ровно, а я туда блять со своми сплитанутым горизонтом и сраным сцайтом? Не, не наш метод.

И что ж делать?

Да все очень просто - этож HTTP. 100 лет уже как придумали реверс прокси для балансировк нагрузок и прочей хрени, и Nginx у нас уже есть, причем и дома и на работе, вспоминаем добрым словом Сысоева и шуруем настраивать сию хрень.

FrontEnd:

Портянка nginx.conf:

user nginx nginx;
worker_processes 1;

error_log /var/log/nginx/error_log notice;

events {
        worker_connections 1024;
        use epoll;
}

http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        log_format main
                '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $bytes_sent '
                '"$http_referer" "$host" "$http_user_agent" '
                '"$gzip_ratio"';

        client_header_timeout 10m;
        client_body_timeout 10m;
        send_timeout 10m;

        connection_pool_size 256;
        client_header_buffer_size 1k;
        large_client_header_buffers 4 2k;
        request_pool_size 4k;

        output_buffers 1 32k;
        postpone_output 1460;

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        keepalive_timeout 75 20;

        ignore_invalid_headers on;

        index index.html;

        #don't cache this urls, its dynamic
        map $request_uri $no_cache {
            default             "";
            /robots.txt         1;
            /sitemap.xml        1;
            /?action=sitemap    1;
        }

        proxy_cache_path /var/cache/nginx/srvlan levels=1:2 keys_zone=srvlan:32m max_size=1g;
        proxy_cache_path /var/cache/nginx/phish levels=1:2 keys_zone=phish:10m inactive=2880m;
        upstream wiki-backend {
            keepalive 32;
            server 10.32.75.177:80;
        }
        
        server {
                listen 127.0.0.1:65535;
                access_log /var/log/nginx/phishtank.com.access_log main;
                error_log /var/log/nginx/phishtank.com.error_log notice;
                location / {
                    #proxy_pass http://data.phishtank.com:80;
                    proxy_pass https://rspamd.com;
                    proxy_ignore_headers Cache-Control Expires;
                    proxy_hide_header Expires;
                    proxy_http_version 1.1;
                    proxy_cache phish;
                    proxy_cache_lock on;
                    proxy_cache_revalidate on;
                    proxy_cache_use_stale http_403 http_404 http_500 http_502 http_503 error timeout updating;
                    proxy_cache_valid 200 302 60m;
                    proxy_buffers 64 64k;
                    proxy_max_temp_file_size 0;
                }
        }
        
        server {
                listen 127.0.0.1:65534;
                access_log /var/log/nginx/openphish.com.access_log main;
                error_log /var/log/nginx/openphish.com.error_log notice;
                location / {
                    proxy_pass https://www.openphish.com;
                    proxy_ignore_headers Cache-Control Expires;
                    proxy_hide_header Expires;
                    proxy_http_version 1.1;
                    proxy_cache phish;
                    proxy_cache_lock on;
                    proxy_cache_revalidate on;
                    proxy_cache_use_stale http_403 http_404 http_500 http_502 http_503 error timeout updating;
                    proxy_cache_valid 200 304 4320m;
                    proxy_buffers 64 64k;
                    proxy_max_temp_file_size 0;
                }
        }
        server {
                listen *:80 default_server;
                root /var/www/localhost/htdocs;
                access_log /var/log/nginx/srv.access_log main;
                error_log /var/log/nginx/srv.error_log notice;

                gzip on;
                gzip_comp_level 6;
                gzip_http_version 1.0;
                gzip_vary off;
                gzip_types text/css text/xml text/javascript text/plain application/javascript >application/x-javascript application/json;
                gzip_proxied any;

                location / {
                    proxy_pass http://wiki-backend;
                    proxy_redirect off;
                    proxy_connect_timeout 120;
                    proxy_send_timeout 120;
                    proxy_read_timeout 180;
                    proxy_http_version 1.1;
                    proxy_cache srvlan;
                    proxy_no_cache $no_cache;
                    proxy_cache_bypass $no_cache;
                    proxy_cache_valid 404 502 503 1m;
                    proxy_set_header Host $host;
                    proxy_set_header Connection "";
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $remote_addr;
                }
        }
}

теперь куски этой портянки с коментариями:

        #don't cache this urls, its dynamic
        map $request_uri $no_cache {
            default             "";
            /robots.txt         1;
            /sitemap.xml        1;
            /?action=sitemap    1;
        }

ну тут коментарий прямо в конфиге говорит сам за себя - не кешировать урлы попадающие под данные маски, точнее map просто выставляет значение переменной $no_cache в "" тоесть пустоту по дефолту и в 1 если url совпал, потом эта переменная используется в локейшене proxy_pass который отправляет запросы уже на реальный сервер ака BackEnd.

        proxy_cache_path /var/cache/nginx/srvlan levels=1:2 keys_zone=srvlan:32m max_size=1g;
        proxy_cache_path /var/cache/nginx/phish levels=1:2 keys_zone=phish:10m inactive=2880m;

Директории для кеша, куда nginx буудет писать свой кеш, две потому что он помимо моего сайте еще проксирует запросы от спамфильтра к phishtank.com openphish.com и rspamd.com. к этому же относяца и 2 сервера на 127.0.0.1 на 65534 и 65535 портах, если ктото будет копипастить то они вам не нужны.

        upstream wiki-backend {
            keepalive 32;
            server 10.32.75.177:80;
        }

директива upstream описывает круппу/пулл бэкэндов на который потом можно отправлять запросы, у нас же бекэнд в единственном экземпляре - server 10.32.75.177:80; так нах она нам? А затем что keepalive 32; можно сказать только в ней. А зачем нам кипалайв? а затем чтоп на каждый запрос не поднимать отдельную tcp сессию между фронтэндом и бэкэндом, а это лишняя нагрузка и лишние задержки, при включенном кипалайве сессия существует всегда, ну точнее почти всегда, если только нет нагрузки совсем то завершица по таймауту, но обычно нагрузка есть и все запросы передаются в рамках этих 32 сессий.

        server {
                listen *:80 default_server;
                root /var/www/localhost/htdocs;
                access_log /var/log/nginx/srv.access_log main;
                error_log /var/log/nginx/srv.error_log notice;

дальше идет секция server, которая собственно и отвечает за мой сервер, ключевое тут это listen *:80 default_server; точнее default_server, потому что доменов у меня куча, куча поддоменов еще больше, и всех их перечислять в server_name замучаешся, с директивой default_server в listen все что не описано в других серверах валица суда, что нам и нада.

                gzip on;
                gzip_comp_level 6;
                gzip_http_version 1.0;
                gzip_vary off;
                gzip_types text/css text/xml text/javascript text/plain application/javascript >application/x-javascript application/json;
                gzip_proxied any;

Настройки сжатия. так как между бэкэндом и фронтэндом всего 40 мегабит и те не гарантированы - почему бы не сжимать ответы? Ктому же Nginx может это делать даже если клиент без сжатия, тоесть

client <-uncompressed http-> FrontEnd <-compressed http-> Backend

. И вот чтоп это заработало, нужна директива gzip_proxied any; и gzip_http_version 1.0; до кучи, потому что по дефолту Nginx прокси использует http 1.0, а gzip включается по дефолту только на 1.1. Правда там далее ему принудительно указано использовать 1.1 но пускай будет😊 gzip_types указывает какой майм типа какие жать в дополнение к text/html, последний жмеца всегда

location / {
                    proxy_pass http://wiki-backend;
                    proxy_redirect off;
                    proxy_connect_timeout 120;
                    proxy_send_timeout 120;
                    proxy_read_timeout 180;
                    proxy_http_version 1.1;
                    proxy_cache srvlan;
                    proxy_no_cache $no_cache;
                    proxy_cache_bypass $no_cache;
                    proxy_cache_valid 404 502 503 1m;
                    proxy_set_header Host $host;
                    proxy_set_header Connection "";
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $remote_addr;
                }

дальше собсно локейшен / тоесть корень, любые запросы попадают в него, и дальше проксируются директивой proxy_pass http://wiki-backend; использая бэкэнд сервера из upstream секции выше.

proxy_http_version 1.1; включает http 1.1 при проксировании, roxy_cache srvlan; указывает какую директорию использовать под кеш из описаных выше в директивах proxy_cache_path.

proxy_no_cache $no_cache; и proxy_cache_bypass $no_cache; благодаря переменной $no_cache выставляемой в map выше отключают кешировани для некоторых запросов, точнее для robots.txt и sitemap.xml так как они у меня динамические и генерируются при запросе для каждого домена свои.

proxy_cache_valid 404 502 503 1m; кешировать ответы с ошибочными http кодами 1 минуту. У меня на некоторых сайтах были форумы, которые атаковале боты, патаясь постить там рекламку, но некоторые из ботов видать глючные, поетому када им там начали показывать 404 они начали флудить кучей запросов, чтоп не гнать это все на бекэнд по достаточно узкому каналу - кешируем и посылаем их нах прямо из кеша😊

proxy_set_header X-Real-IP $remote_addr; нужен для модуля http_realip, смысл этого в том что этот модуль меняет адрс откуда пришол запрос на адрес из этого заголовка, и получается совсем прозрачная схема - тоесть бэкэнд работает так как будто фронтэнда перед ним нет, в логах адреса реальных клиентов а не адрес фронтэнда с которого фактически идут запросы, тоесть как будто фронтэнда и нет вовсе.

вот впринципе и все по фронтэнду, теперь

BackEnd:

user nginx nginx;
worker_processes 1;

error_log /var/log/nginx/error_log info;

events {
        worker_connections 1024;
        use epoll;
}

http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        log_format main
                '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $bytes_sent '
                '"$http_referer" "$host" "$http_user_agent" '
                '"$gzip_ratio"';
        #don't log file not found on 404 in error_log:
        log_not_found off;

        client_header_timeout           10m;
        client_body_timeout             10m;
        client_body_buffer_size         128k;
        client_max_body_size            10M;
        send_timeout                    10m;

        connection_pool_size 256;
        client_header_buffer_size 1k;
        large_client_header_buffers 4 2k;
        request_pool_size 4k;

        output_buffers 1 32k;
        postpone_output 1460;

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        keepalive_timeout 75 20;

        ignore_invalid_headers on;

        gzip on;
        gzip_comp_level 6;
        gzip_http_version 1.0;
        gzip_vary on;
        gzip_types text/css text/xml text/javascript text/plain application/javascript  application/x-javascript application/json;
        
        map $http_user_agent $crawler {
            default             0;
            "~*Bot"             1;
            "~*Slurp"           1;
            "~*spider"          1;
            "~*crawl"           1;
        }
        
        map $request_uri $robots {
            default             0;
            /?action=sitemap    1;
            /robots.txt         1;
            /sitemap.xml        1;
        }
        
        map $host $srvlan       {
            default             0;
            srv.lan             1;
        }
        
        map $status:$srvlan $error_404 {
            default             0;
            404:0               1;
        }
        
        map $crawler$robots$error_404$srvlan $log_main {
            default                                     0;
            "0000"                                      1;
        }
        
        upstream wiki-backend {
            zone wiki-backend 128k;
            keepalive 8;
            server unix:/run/fcgiwrap-wiki.sock-1;
            server unix:/run/fcgiwrap-wiki.sock-2;
            server unix:/run/fcgiwrap-wiki.sock-3;
            server unix:/run/fcgiwrap-wiki.sock-4;
            server unix:/run/fcgiwrap-wiki.sock-5;
            server unix:/run/fcgiwrap-wiki.sock-6;
            server unix:/run/fcgiwrap-wiki.sock-7;
            server unix:/run/fcgiwrap-wiki.sock-8;
        }
        
        server {
                listen 10.32.75.177 default_server;
                server_name srv.lan;
                root /var/www/localhost;
                index /cgi-bin/index.pl;

                error_log /var/log/nginx/srv.error_log info;

                access_log /var/log/nginx/srv_crawler.access_log main if=$crawler;
                access_log /var/log/nginx/srv_robots.txt.access_log main if=$robots;
                access_log /var/log/nginx/srv_404.access_log main if=$error_404;
                access_log /var/log/nginx/lan_log main if=$srvlan;
                access_log /var/log/nginx/srv.access_log main if=$log_main;

                set_real_ip_from 91.193.236.1;
                real_ip_header X-Real-IP;

                error_page 404 /static/404.html;

                location = /favicon.ico {
                    return 204;
                    expires max;
                    access_log     off;
                    log_not_found  off;
                }
             
                location = /ad_replace/null.gif {
                    empty_gif;
                    expires max;
                }
                
                location /static/ {
                    root /var/www/localhost/htdocs;
                    expires max;
                }
                
                location /data/ {
                    return 404;
                    access_log off;
                    deny all;
                }
                location ~ ^/cgi-bin/index.pl {
                    gzip off;
                    root                /var/www/localhost;
                    fastcgi_param       WikiDataDir    /var/www/localhost/data/wickidb;
                    fastcgi_param       WikiConfigFile /var/www/localhost/data/wickidb/config;
                    include             fastcgi_params;
                    fastcgi_pass        wiki-backend;
                    fastcgi_keep_conn   on;
                }
                
                location = /robots.txt {
                    gzip off;
                    expires -1;
                    fastcgi_param       SCRIPT_FILENAME    $document_root/cgi-bin/robots.pl;
                    fastcgi_param       SCRIPT_NAME        /cgi-bin/robots.pl;
                    include             fastcgi_params;
                    fastcgi_pass        wiki-backend;
                    fastcgi_keep_conn   off;
                }
                location = /sitemap.xml {
                    gzip off;
                    expires -1;
                    error_page 404 =200 /?action=sitemap;
                }
        }
}

Чтото тут совпадает с фронтэндом, это я коментировать не буду, а гдето есть ньюансы и не совсем стандартные решения, это я откоментирую.

        #don't log file not found on 404 in error_log:
        log_not_found off;

Впринципе ясно из названия - не писать ошибки о не найденных страницах в главный error.log, в лог конкретного сервера они всеравно пишуца, вдобавок у меня отдельное логгирование 404 в отдельный файл. Просто та куча доменов с дохлыми сайтами развернута суда, а на них соответственно куча ссылок со всея интернету и 404 у меня тьма, поэтому чтоп не засирало основной лог я пишу их в отдельный.

       map $http_user_agent $crawler {
            default             0;
            "~*Bot"             1;
            "~*Slurp"           1;
            "~*spider"          1;
            "~*crawl"           1;
        }
        
        map $request_uri $robots {
            default             0;
            /?action=sitemap    1;
            /robots.txt         1;
            /sitemap.xml        1;
        }
        
        map $host $srvlan       {
            default             0;
            srv.lan             1;
        }
        
        map $status:$srvlan $error_404 {
            default             0;
            404:0               1;
        }
        
        map $crawler$robots$error_404$srvlan $log_main {
            default                                     0;
            "0000"                                      1;
        }

А эта конструкция какрас и обеспечивает мне отдельное логгирование того что мне нужно. Как ни странно, чтото мне в сети сходу не удалось нарыть как обеспечить сию потребность, есть куча примеров с кучей if, а про if в документации Nginx написано что они зло 😊 да и конструкция получается корявая, а вот с map у меня получилось очень хорошо и гибко, на битовые маски смахивает, хз почему никто так не делает😊 Ну или мне не повезло с гуголом, но ниче такого сходу не нашлось, хотя попытки были, оттуда я и узнал про map, вообще с Nginx я не сказал бы что сильно хорошо знаком и давно работаю, это наверное первое чтото более-менее серьезное что я с ним делал.

Отвлеклись от темы ну да ладно, воблем если кратко то map string1 $var1 делает следующее - сверяет string1 с шаблонами ниже, и если совпадает то выставляет значение $var1 в то что напротив шаблона, если совпадений нет то $var1 выставляется в значение напротив default. При этом string1 может быть какой либо переменной Nginx'a, или даже несколькими как видно в последнем map из конфига, тоесть все значения преобразуются в строку которая потом прогоняется по шаблонам. Эту переменную потом можно использовать в последущих map, ну и в других местах где можно использовать переменные вообще. Скомбинировав все это можно описать нужную вам логику для чего либо. Как видно на фронтэнде кеширование выборочно отключается таким же способом. Собсно так у меня и работает Separate logging по моим условиям, тоесть к примеру последний map контролирует логгинг в main log, по умолчанию $log_main 0, тоесть не логгировать, дальше по шаблонам сравниваются все остальные - если не 404 И если не кравлер И если не запросили robots.txt или sitemap, И если не локальное обращение (да - мне так тоже удобней при отладке чего либо - я обращаюсь на локальный домен srv.loc вообще мимо фронтэнда и это идет в отдельный лог)то присваивается единица и логгинг разрешен. Вобщем очень гибкая и удобная штука, и вдобавок практически бесплатная, не в плане денег а в плане оверхеда - пишут что оно как то компилируется во чтото при старте и нагрузки практически не дает даже на хайлоаде.

upstream wiki-backend {
            zone wiki-backend 128k;
            keepalive 8;
            server unix:/run/fcgiwrap-wiki.sock-1;
            server unix:/run/fcgiwrap-wiki.sock-2;
            server unix:/run/fcgiwrap-wiki.sock-3;
            server unix:/run/fcgiwrap-wiki.sock-4;
            server unix:/run/fcgiwrap-wiki.sock-5;
            server unix:/run/fcgiwrap-wiki.sock-6;
            server unix:/run/fcgiwrap-wiki.sock-7;
            server unix:/run/fcgiwrap-wiki.sock-8;
        }

Что такое upstream я уже писал на примере фронтэнда, но тут он вобщем то используется по назначению - на бэкэнде пашет oddwiki через fastcgi, сервир имеет 8 процессоров, соответственно мы запускаем 8 копий fcgiwrap, и раскидываем по ним запросы с помощью описанного в upstream пула, по дефлту алгоритм round-robin, тоесть по кругу, но там есть кучка других.

       server {
                listen 10.32.75.177 default_server;
                server_name srv.lan;
                root /var/www/localhost;
                index /cgi-bin/index.pl;

server_name srv.lan; мой локальный домен, и в добавок это значение как last resort окажеца в переменной $host если Нginx вдруг ваще-ваще низнает хостнейм к которому обратились, ну допустим какойнить кривой-кривой клиент по http 1.0 без host header, а эта переменная потом отдается fcgi скриптам, а мне в скриптах нужен кровь из носу но хоть какое то значение хоста необходимо, пусть даже не правильное.

index /cgi-bin/index.pl; при запросе индекса сразу перекидывает на скрипт wiki, иначе получим 404, у нас же нет никакова индекса, и ваще никаких хтмлин, ну почти😊 Есть кастомная 404.html😊

                error_log /var/log/nginx/srv.error_log info;
        
                access_log /var/log/nginx/srv_crawler.access_log main if=$crawler;
                access_log /var/log/nginx/srv_robots.txt.access_log main if=$robots;
                access_log /var/log/nginx/srv_404.access_log main if=$error_404;
                access_log /var/log/nginx/lan_log main if=$srvlan;
                access_log /var/log/nginx/srv.access_log main if=$log_main;

error_log /var/log/nginx/srv.error_log info; Ниче необычного - отдельное логгирование ошибок для этого сервера.

а вот последующие access_log какрас раздельное лиггирование или separate logging по условиям которыве описываются посредством директив map выше.

У меня отдельно логгируются:

ну а все остальное идет в main log.

                set_real_ip_from 91.193.236.1;
                real_ip_header X-Real-IP;

Это важный вешь, из модуля Nginx'а http_realip, именно благодаря ему на бэкэнде все работает прозрачно будто фронтэнда нет. по сути реальный адрес клиента передается в отдельном http заголовке, в данном случае это X-Real-IP. А set_real_ip_from 91.193.236.1; это адрес при запросе с которого следует доверять содержимому данного заголовка, ведь его может подставить любой желающий, соответственно тут ip адрес фронтэнда ибо доверяем мы только ему. от других этот заголовок будет проигнорирован этим модулем.

дальше впринципе фигня специфичная для моего сцайта

У меня стоит oddwiki, установка описана у меня тут Но всеравно опишу - есть там неочевидные и интересные моменты - может кому пригодица.

               location = /favicon.ico {
                    return 204;
                    expires max;
                    access_log     off;
                    log_not_found  off;
                }

Это левый локейшен для favicon.ico 😊 Это иконка сцайта, появляющаяся в адресной строке после захода на сайт, низнаю нахуй она нужна но судя по логу запросов очень нужная вещь, без не никак - все просют, но у меня ее нет, поэтому вместо нее мы выдаем пустой ответ путем return 204;, с помощью expires max; устанавливаем время жизни сего ответа ближе к бесконечности дабы нас меньше заебывали с етой иконкой(ни низнаю нах она мне? 😊, и путем access_log off; и log_not_found off; не пишем эти запросы нивкакие логи совсем - чтоп ну совсем-совсем не заебывали😊

               location = /ad_replace/null.gif {
                    expires max;
                    empty_gif;
                }

это мая местная магия - прозрачная гиф 1x1 для банерорезки, к делу не относица😊

                location /static/ {
                    expires max;
                    root /var/www/localhost/htdocs;
                }

Этот локейшен для статики, у меня там css и кастомная хтмлина для 404 ошибки, посредством expires max; оно будет кешироваца фронтэндом очень долго и упорно, соотвественно весь статический контент нада пихать туда😊

                location /data/ {
                    access_log off;
                    deny all;
                    return 404;
                }

Это локейшн для защиты рабочих файлов вики и ее модулей, всю ту хуйню что тут пишут она хранит там, как и настройки и пароли, поетому нехер там никому ниче делать😊 выдаем им 404, запрещаем доступ и не логгируем в access.log.

                location ~ ^/cgi-bin/index.pl {
                    gzip off;
                    root                /var/www/localhost;
                    fastcgi_param       WikiDataDir    /var/www/localhost/data/wickidb;
                    fastcgi_param       WikiConfigFile /var/www/localhost/data/wickidb/config;
                    include             fastcgi_params;
                    fastcgi_pass        wiki-backend;
                    fastcgi_keep_conn   on;
                }

Это самый главный локейшн😊 собсно тут и живет скрипт вики. Запускается она через fastcgi. Скпритам можно передавать всякие переменные, есть набор стандартных, но можно определить и любые свои, или переопределить значения стандартных. Делается это директивами fastcgi_param.

Стандартные определены в файле fastcgi_params в той же директории что и конфиг Nginx'a который тут инклудица директивой include fastcgi_params;.

gzip off я хз точно нужно или нет, вроде работает у меня и без него но все почемуто делают так, вообще если скрипту скормить пожатый запрос ему поплохеет от такого и я решил не рисковать и сделать как в том кино - все побежали, и я побежал😊

fastcgi_pass wiki-backend; - отправлять запросы на апстрим пул описанный выше в http секции.

fastcgi_keep_conn on; какое то подобие кипалайва есть и тут - тоесть соединение с fastcgi сервером не закрывается а держица открытым чтоп не открывать/закрывать его на каждый запрос.

                location = /robots.txt {
                    gzip off;
                    expires -1;
                    fastcgi_param       SCRIPT_FILENAME    $document_root/cgi-bin/robots.pl;
                    fastcgi_param       SCRIPT_NAME        /cgi-bin/robots.pl;
                    include             fastcgi_params;
                    fastcgi_pass        wiki-backend;
                    fastcgi_keep_conn   off;
                }

Опять моя местная магия😊 Точнее, у меня robots.txt генерируется динамически потому что для разных доменов он у меня разный, но тем не менее тут есть на что обратить внимание даже если именно это вам не нада.

Есть тут неочевидный момент - так как запрос идет на http://site.domain/robots.txt а нам нада выполнить скрипт который сгенерирует нужное содержимое и выплюнет его клиенту вместо файла нам нужно жестко задать что нам нужно выполнить нужный нам скрипт.

Это достигается путем жесткого переопределения стандартных fastcgi переменных SCRIPT_FILENAME и SCRIPT_FILENAME, и тут оказывается что именно ПЕРЕопределить их нельзя - работает только первое обьявление. тоесть если перенести include fastcgi_params; выше директив fastcgi_param то нихера работать не будет так как переменные стандартным образом определяца в заинклуженном файле и со стандартными значениями и остануца, тоесть как будто директив fastcgi_param ваще нет. Происходит это молча - никаких ошибок или ворнингов итд, и поэтому я очень долго не мог понять каковахера у меня эта секция нихуя не работает когда поидее должна бы😊

expires -1; защита от кеширования на фронтэнде - типа срок валидности документа уже истек аш секунду назад дабы он не кешировал этот файл, там впринципе итак есть но малоли - хуже не будет😊

                location = /sitemap.xml {
                    gzip off;
                    expires -1;
                    error_page 404 =200 /?action=sitemap;
                }

Это снова очередная местная магия😊 Или скорее местный хак😊 Sitemap у меня тоже герерица динамически, но не отдельным скриптом а самой вики, тоесть совсем на лету. Происходи это посредством запроса вида http://megaprovider.ru/?action=sitemap, я впринципе про эту хрень недавно узнал, и так прямо его и вписал в robots.txt но не тут то было😊 Большинство роботов вообще не забирали его, А те что забирали иногда потом делали всякую хуйню, тоесть глючили, к примеру яндекс вместо запроса http://megaprovider.ru/?Main запрашивал почемуто http://megaprovider.ru/0/?Main, причем через рас😊 В резальтате я узнал какаято сильно огороженная хуйня - она вроде как должна лежать в корне, того же сайта, и и еще куча страшилок, причем нихуя не описанных в стандарте, вотбем я решил сделать по проще как у всег - прикинуца будто у меня там внатуре просто файл, но тут уже как с robots.txt не отделаешся потому что это не отдельный скрипт, и плюс нада переписать запрос, мне было влом и на глаза попалась директива про 404 выше отравляющая запрос на статическую хтмлину, а у нас же файла нет и при запросе /sitemap.xml получается какрас 404 ошибка - и я решил попробовать - а что если перенаправить по 404 на нужный урл сразу и при этом переписать код ошибки на обычный 200?

И прокатило😊 Собственно все делается 1 строчкой - error_page 404 =200 /?action=sitemap;, сижу смотрю теперь что получица с роботами, ато там с форматом sitemap тоже не все гладко было😊 Это конечно скорее всего мое временное решение но результат то достигнут😊

expires -1; Как и в предыдущем локейшене с robots.txt защита от кеширования.

2 самых полезных команды при отладке:

  1. nginx -t - проверить конфигурацию на валидность, если че не так то вякнет, при этом продолжает работать.
  2. nginx -s reload - перечитать и применить конфигурацию.

Вот вроде бы и все

Вообще Nginx понравился, очень гибкая и развитая по фичам штука, при этом не жирная и не перегруженная всякой херней, Сысоеву респект😊