RE:NODE

VDS13 წუთის საკითხავი

Nginx reverse proxy: server block-ები, TLS და websocket-ები

დააყენე nginx შენი აპლიკაციის წინ: მინიმალური server block, proxy header-ები, certbot და განახლება, websocket-ის upgrade, ატვირთვის ლიმიტები და 502-ისა და 504-ის მიზეზები.

0 მკითხველი

შენი აპლიკაცია 127.0.0.1:3000-ზე უსმენს. ვიზიტორი სახელს აკრეფს და ელის 443 პორტს ბოქლომის ხატულით. Nginx არის კონფიგურაციის თორმეტი სტრიქონი, რომელიც ამ ორ ფაქტს აკავშირებს, და ერთხელ რომ დაწერ, ყოველი სერვისისთვის, რომელსაც ოდესმე გაუშვებ, ისევ დაწერ. ეს გიდი ამ სტრიქონების სამუშაო ვერსიაა: server block, რომელიც სწორად აპროქსირებს, ოთხი header, რომელიც შენს აპლიკაციას სჭირდება, სერტიფიკატი, რომელიც თავისით ახლდება, და კონკრეტული კონფიგურაცია, რომელიც websocket-ებსა და ფაილების ატვირთვას სჭირდება და ნაგულისხმევად არ აქვს.

აქ ყველაფერი ვარაუდობს ერთ მანქანას root-ით - VDS-ს ან dedicated სერვერს - სადაც nginx სისტემური პაკეტია, შენი აპლიკაცია კი გვერდით systemd სერვისად ან კონტეინერად მუშაობს. თუ გინდა გაიგო, რას აკეთებს reverse proxy და რატომ, ეს იმ პოსტშია: რას აკეთებს reverse proxy. ეს პოსტი კონფიგურაციაა.

სად ინახავს nginx თავის კონფიგურაციას#

Debian-სა და Ubuntu-ზე /etc/nginx/nginx.conf გლობალურ პარამეტრებს შეიცავს და ორი include ხაზით მთავრდება. ერთი /etc/nginx/conf.d/*.conf-ს იზიდავს, მეორე - /etc/nginx/sites-enabled/*-ს. მიღებული წესია, ყოველი საიტისთვის ფაილი sites-available-ში დაწერო და ის ფაილები, რომლებიც ჩართული უნდა იყოს, sites-enabled-ში symlink-ით ჩააბა, რომ საიტის გამორთვა ბმულის წაშლა იყოს და არა ფაილის.

bash
$ sudo apt install -y nginx$ sudo nano /etc/nginx/sites-available/app.conf$ sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/$ sudo rm /etc/nginx/sites-enabled/default$ sudo nginx -t && sudo systemctl reload nginx

RHEL-ზე, Rocky-სა და Alma-ზე sites-available-ის დაყოფა არ არსებობს; ყველაფერი /etc/nginx/conf.d/-შია .conf გაფართოებით. თავად server block-ები იგივეა.

მთელ სამუშაოს სამი ბრძანება აკეთებს. nginx -t მთელ კონფიგურაციას კითხულობს და ნებისმიერი შეცდომის ფაილსა და ხაზის ნომერს გვიჩვენებს, და მის გარეშე reload არასოდეს უნდა გააკეთო. systemctl reload nginx კონფიგურაციას ხელახლა კითხულობს კავშირების გაწყვეტის გარეშე - ძველი worker პროცესები მიმდინარე მოთხოვნებს ამთავრებენ და გადიან, ახლები ახალი კონფიგურაციით იწყებენ. nginx -T მთელ გაერთიანებულ კონფიგურაციას ბეჭდავს ყველა include-ის ჩათვლით, და ასე პოულობ იმ ჩაფლულ ფაილს, რომელიც შენს პარამეტრს გადაფარავს.

default საიტი ღირს, რომ წაშალო ან ჩაანაცვლო. ის 80 პორტზე პასუხობს ნებისმიერ hostname-ს, რომელიც სხვა block-ს არ ემთხვევა, ანუ დომენზე, რომელზეც არასოდეს გსმენია, მოთხოვნა შენს default გვერდს მიიღებს. უფრო სუფთაა catch-all, რომელიც კავშირს პასუხის გარეშე ხურავს:

/etc/nginx/sites-available/catchall.conf
server {    listen 80 default_server;    listen [::]:80 default_server;    server_name _;    return 444;}

444 nginx-ის სპეციფიკური კოდია და ნიშნავს „დახურე პასუხის გარეშე“. ერთ პორტზე მხოლოდ ერთ block-ს შეიძლება ჰქონდეს default_server, ხოლო მეორე კონფიგურაციის ტესტისას duplicate default server-ს გამოიწვევს.

ყველაზე პატარა server block, რომელიც მუშაობს#

/etc/nginx/sites-available/app.conf
server {    listen 80;    listen [::]:80;    server_name app.example.com;    location / {        proxy_pass http://127.0.0.1:3000;        proxy_http_version 1.1;        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 X-Forwarded-Host  $host;    }}

ეს სრული, მუშა reverse proxy-ა. TLS-ის ნაწილს certbot ცოტა ხანში დაამატებს. მასში რამდენიმე რამ თვალშისაცემი არ არის:

proxy_http_version 1.1 თავიდანვე უნდა იყოს. Nginx upstream-ზე ნაგულისხმევად HTTP/1.0-ით ლაპარაკობს, რაც backend-თან keepalive-ს არღვევს და websocket-ის upgrade-ს შეუძლებელს ხდის. მის დაყენებას მინუსი არ აქვს.

server_name არის ის, რითაც nginx block-ს ირჩევს, Host header-თან შედარებით. ერთ block-ზე რამდენიმე სახელი ცარიელი ადგილით გამოიყოფა: server_name example.com www.example.com;. მოთხოვნა, რომლის Host-ი არაფერს ემთხვევა, default სერვერზე მოხვდება, სწორედ ამიტომაა ზემოთ მოცემული catch-all მნიშვნელოვანი.

$proxy_add_x_forwarded_for კლიენტის მისამართს უკვე არსებულ X-Forwarded-For header-ს ამატებს და არ ცვლის, რაც სწორია, როცა შენს წინ სხვა proxy დგას, და ხვრელია, როცა არ დგას - კლიენტს საკუთარი header-ის გაგზავნა შეუძლია და შენ მას გადასცემ. თუ nginx-ის წინ არაფერია, გამოიყენე proxy_set_header X-Forwarded-For $remote_addr; და ორაზროვნება მოიხსენი.

მონაცვლე slash proxy_pass-ში#

ეს nginx-ის ყველაზე გავრცელებული შეცდომაა და ჩუმია, სანამ რომელიმე route 404-ს არ დააბრუნებს.

nginx
# Passes /api/users through unchanged: backend sees /api/userslocation /api/ {    proxy_pass http://127.0.0.1:8000;}# Strips the location prefix: backend sees /userslocation /api/ {    proxy_pass http://127.0.0.1:8000/;}

წესი: თუ proxy_pass შეიცავს URI ნაწილს - ნებისმიერს ჰოსტისა და პორტის შემდეგ, ცარიელი /-ის ჩათვლით - nginx დამთხვეული location-ის პრეფიქსს მასზე ცვლის. თუ URI ნაწილი არ აქვს, მოთხოვნის URI ხელუხლებლად გადაეცემა. ერთი სიმბოლო წყვეტს, შენი API /api/users-ს იხილავს თუ /users-ს.

რომელსაც არ უნდა აირჩიო, აპლიკაცია უნდა დაეთანხმოს. აპლიკაცია, რომელიც ბმულებს იმ ვარაუდით აგებს, რომ ის root-ზე ცხოვრობს, გატეხილ URL-ებს გამოსცემს /api/-ს ქვეშ გაშვებისას, სწორედ ამიტომ არის აპლიკაციების ქვედომენებზე განთავსება ჩვეულებრივ ნაკლები სამუშაო, ვიდრე მათი path-ებზე განთავსება. და გაითვალისწინე, რომ ეს გადაწერა მხოლოდ პრეფიქსულ location-ებზე მუშაობს - proxy_pass-ში URI-ს regex location-თან გაერთიანება კონფიგურაციის შეცდომაა, რომელსაც nginx ტესტის დროს უარყოფს.

TLS certbot-ით და რა სჭირდება განახლებას სინამდვილეში#

bash
$ sudo apt install -y certbot python3-certbot-nginx$ sudo certbot --nginx -d app.example.com$ sudo certbot renew --dry-run

nginx plugin შენს server block-ს კითხულობს, სერტიფიკატს იღებს, block-ს ცვლის და TLS listener-სა და 80 პორტიდან გადამისამართებას ამატებს, და განახლების job-ს აყენებს. შედეგი ასე გამოიყურება:

nginx
server {    server_name app.example.com;    listen 443 ssl;    listen [::]:443 ssl;    http2 on;    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;    include /etc/letsencrypt/options-ssl-nginx.conf;    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;    location / {        proxy_pass http://127.0.0.1:3000;        # ... the header lines from above    }}server {    listen 80;    server_name app.example.com;    return 301 https://$host$request_uri;}

http2 on; ცალკე დირექტივის სახით nginx 1.25.1-დან მოყოლებული სინტაქსია. ძველ build-ებზე ის listen ხაზის პარამეტრია - listen 443 ssl http2; - და ორი სტილის შერევა გაფრთხილებას იძლევა და არა შეცდომას.

სამი პირობა უნდა სრულდებოდეს, სანამ სერტიფიკატი გაიცემა ან განახლდება, და certbot-ის ყოველი შეცდომა ერთ-ერთი მათგანია:

  1. DNS სახელი ამ მანქანაზე წყდება. გაცემა ამტკიცებს, რომ სახელს აკონტროლებ, იმით, რომ მასზე გამოწვევას პასუხობ. ჯერ A ჩანაწერი გაამხილე, დაელოდე, სანამ ის გავრცელდება, და მხოლოდ შემდეგ გაუშვი certbot. DNS ჩანაწერები ახსნილი აღწერს ჩანაწერების ტიპებსა და TTL-ის ლოდინს.
  2. 80 პორტი ღიაა და nginx-ს აღწევს. HTTP-01 გამოწვევა ფაილს /.well-known/acme-challenge/-ის ქვეშ იღებს, უბრალო HTTP-ით, იმ საიტისთვისაც კი, რომელიც ყველაფერს HTTPS-ზე გადაამისამართებს. 80 პორტის დაბლოკვა UFW-ში განახლების ყველაზე გავრცელებული საკუთარი წარუმატებლობაა. Certbot-ის გადამისამართების block გამოწვევის path-ს სწორად ამუშავებს; თუ გადამისამართებას ხელით წერ, ეს location გამონაკლისად გამოაცხადე.
  3. განახლების შემდეგ nginx თავიდან იტვირთება. certbot-ის პაკეტები deploy hook-ს აყენებს, რომელიც ამას აკეთებს. თუ სხვა გზით ანახლებ, დაამატე --deploy-hook "systemctl reload nginx", რადგან nginx ძველ სერტიფიკატს მეხსიერებაში ინახავს, სანამ სხვაგვარად არ უთხრეს.

განახლება დღეში ორჯერ systemd timer-იდან გადის და მხოლოდ მაშინ მოქმედებს, როცა სერტიფიკატის ვადა ოცდაათ დღეზე ნაკლები რჩება, ამიტომ დროებით წარუმატებლობას კვირების მარაგი აქვს. შეამოწმე, რომ ის ჩართულია: systemctl list-timers | grep certbot. იმის მექანიკა, თუ რას ამტკიცებს გამოწვევა, აღწერილია აქ: HTTPS და Let's Encrypt ახსნილი.

WebSocket-ები, streaming და timeout-ები#

websocket ჩვეულებრივ HTTP მოთხოვნად იწყება, რომელსაც Connection: Upgrade და Upgrade: websocket აქვს. Nginx hop-by-hop header-ებს ნაგულისხმევად არ გადასცემს, ამიტომ upgrade გზაში კვდება, თუ სხვაგვარად არ უთხარი. სტანდარტული ხერხი http დონეზე map-ს იყენებს, რომ არა-websocket მოთხოვნები არ შეეხოს:

/etc/nginx/conf.d/upgrade.conf - http context
map $http_upgrade $connection_upgrade {    default upgrade;    ''      close;}
in the location block
location /socket.io/ {    proxy_pass http://127.0.0.1:3000;    proxy_http_version 1.1;    proxy_set_header Upgrade    $http_upgrade;    proxy_set_header Connection $connection_upgrade;    proxy_read_timeout 3600s;    proxy_send_timeout 3600s;}

proxy_read_timeout ნაგულისხმევად 60 წამია და ის კითხვებს შორის იზომება და არა მთელი კავშირისთვის. უმოქმედო websocket ამიტომ ყოველ წუთში წყდება და reconnect ციკლს იწვევს, რომელიც ზუსტად ქსელის გაუმართაობას ჰგავს. გაზარდე timeout websocket route-ებზე და გაგზავნე აპლიკაციის დონის ping ყოველ ოცდაათ წამში ერთხელ ან უფრო ხშირად, რომ კავშირი არასდროს დარჩეს საკმარისად ხანგრძლივად უმოქმედო.

Server-sent events-სა და ნებისმიერ streaming პასუხს კიდევ ერთი ხაზი სჭირდება. Nginx upstream პასუხებს ნაგულისხმევად ბუფერავს, ამიტომ stream ინახება, სანამ საკმარისი რაოდენობა არ მოვა, და კლიენტი გრძელ სიჩუმეს ხედავს, რასაც ყველაფერი ერთდროულად მოსდევს:

nginx
location /events {    proxy_pass http://127.0.0.1:3000;    proxy_http_version 1.1;    proxy_buffering off;    proxy_cache off;    proxy_read_timeout 24h;}

აპლიკაციას ასევე შეუძლია ბუფერირება თითო პასუხზე გამორთოს X-Accel-Buffering: no-ის გაგზავნით, რაც უფრო სუფთაა, როცა მხოლოდ ზოგი endpoint-ი აწარმოებს stream-ს. WebSocket-ები reverse proxy-ს უკან აღწერს sticky-session პრობლემას, რომელიც ერთზე მეტი backend ინსტანციის შემდეგ ჩნდება.

რამდენიმე აპლიკაცია ერთი nginx-ის უკან#

proxy-ის აზრი ისაა, რომ ერთი მისამართი და ერთი პორტი ნებისმიერ რაოდენობა სერვისს ემსახურება. მათი გაყოფის ორი გზა არსებობს და ქვედომენები თითქმის ყოველთვის უკეთესია:

nginx
# By hostname: two server blocks, two certificates, no path rewritingserver { server_name app.example.com; location / { proxy_pass http://127.0.0.1:3000; } }server { server_name api.example.com; location / { proxy_pass http://127.0.0.1:8000; } }
nginx
# By path: one certificate, but the backend must know it lives under /api/location /api/ { proxy_pass http://127.0.0.1:8000/; }location /     { proxy_pass http://127.0.0.1:3000; }

პრეფიქსულ location-ებს შორის ყველაზე გრძელი პრეფიქსი იგებს, ამიტომ /api/ აჯობებს /-ს /api/users-ზე მოთხოვნისას, იმისდა მიუხედავად, ფაილში რა თანმიმდევრობით წერია. Regex location-ები, რომლებიც location ~ ^/pattern-ით იწერება, ფაილის თანმიმდევრობით ფასდება და პრეფიქსულ დამთხვევებს ჯობია, რაც კარგი მიზეზია, რომ მათგან რაც შეიძლება ცოტა გამოიყენო.

backend-ისთვის, რომელსაც keep-alive-ს გაუწევ, გამოაცხადე ის upstream-ად. ორი დამატებითი ხაზი აუცილებელია: upstream-თან keepalive-ს სჭირდება HTTP/1.1 და ცარიელი Connection header, თორემ nginx ყოველ მოთხოვნაზე Connection: close-ს აგზავნის და pool არასოდეს გამოიყენება.

nginx
upstream app {    server 127.0.0.1:3000;    keepalive 32;}server {    location / {        proxy_pass http://app;        proxy_http_version 1.1;        proxy_set_header Connection "";    }}

upstream, რომელსაც რამდენიმე server ხაზი აქვს, გაძლევს round-robin დატვირთვის განაწილებას, ალტერნატივებად ip_hash ან least_conn და backup მოლოდინის რეჟიმისთვის. თუ აპლიკაცია კონტეინერშია, proxy-ს მისი მიღწევა პორტის ნაცვლად კონტეინერის სახელით შეუძლია - ამ ფორმისთვის იხილე Docker Compose პატარა stack-ებისთვის, სადაც პორტს proxy-ის გარდა არავინ აქვეყნებს.

Unix socket-იც ვარგისი upstream-ია, და ის loopback TCP-ზე ოდნავ სწრაფია და ქსელიდან მიუღწეველი: proxy_pass http://unix:/run/app/app.sock;. დარწმუნდი, რომ nginx-ის მომხმარებელს socket-ის წაკითხვა შეუძლია.

სტატიკური ფაილები, ატვირთვები და ლიმიტები#

Nginx ფაილებს ნებისმიერ აპლიკაციის runtime-ზე სწრაფად ემსახურება, ასე რომ, მიეცი ეს საქმე. სტატიკური დირექტორიის პირდაპირ მომსახურება იმასაც ხელს უშლის, რომ ეს მოთხოვნები შენს აპლიკაციას საერთოდ გააღვიძოს:

nginx
location /static/ {    alias /srv/app/static/;    access_log off;    expires 30d;    add_header Cache-Control "public, immutable";}client_max_body_size 25m;gzip on;gzip_types text/plain text/css application/json application/javascript image/svg+xml;server_tokens off;

alias დამთხვეულ location-ის პრეფიქსს მითითებული path-ით ცვლის; root მას მთელ URI-ს აბამს. ორივე სწორია სხვადასხვა სიტუაციაში, და მათი აღრევა 404-ს იძლევა error.log-ში ძალიან მკაფიო ხაზით, რომელიც გვიჩვენებს, რომელი path-ის გახსნას ცდილობდა nginx. წაიკითხე ეს ხაზი და ნუ გამოიცნობ.

client_max_body_size ნაგულისხმევად 1 MB-ია, რაც უფრო მცირეა, ვიდრე ატვირთვის უმეტესი ფორმა ელის, და მისი გადამეტება 413-ს იძლევა მოთხოვნის აპლიკაციამდე მისვლამდეც. დააყენე ყველაზე დიდ ატვირთვაზე, რომელსაც მიიღებ, და არა უფრო მეტზე. expires და Cache-Control ჰეშირებული asset-ის ფაილის სახელებზე უფასო წარმადობაა; ფაილებზე, რომელთა სახელები არ იცვლება, ეს თვის განმავლობაში მოძველებული შიგთავსის მიწოდების გზაა, ამიტომ დარწმუნდი, რომელი გაქვს - HTTP ქეშირების header-ები ახსნილი ამ ზღვარს სწორად ავლებს.

ერთი გაფრთხილება add_header-ზე: ის დონეებს შორის კუმულაციური არ არის. location block-ში დამატებული header ცვლის და არ ემატება მშობელ server block-ში დამატებულ header-ებს. თუ უსაფრთხოების header-ებს გლობალურად აყენებ და შემდეგ ერთ location-ში ქეშირების header-ს ამატებ, უსაფრთხოების header-ები ამ location-დან ქრება. გაიმეორე ისინი, ან გამოიყენე always პარამეტრი ფრთხილად და გატესტე curl -I-ით.

Rate limiting ორი დირექტივაა და ღირს login endpoint-ზე მისი ქონა:

nginx
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;location /login {    limit_req zone=login burst=10 nodelay;    proxy_pass http://127.0.0.1:3000;}

გაითვალისწინე, რომ ეს $binary_remote_addr-ით ზღუდავს, ანუ იმ მისამართით, რომელსაც nginx ხედავს. თუ nginx-ს სხვა რამ აპროქსირებს, ეს ყველასთვის ერთი მისამართია. ან გამოიყენე real IP მოდული - set_real_ip_from upstream proxy-ის დიაპაზონით და real_ip_header X-Forwarded-For - ან შეზღუდე forwarded header-იდან მიღებულ ცვლადზე. Rate limit-ები და abuse აღწერს, როგორ აირჩიო რიცხვები.

502, 504, 413 და დანარჩენი#

აქ ყოველი პასუხი /var/log/nginx/error.log-ში იწყება. Nginx თითქმის ყოველი წარუმატებლობის კონკრეტულ მიზეზს წერს, იმ upstream-ის ჩათვლით, რომელსაც ცდილობდა, და errno-ს, რომელიც უკან მიიღო.

502 Bad Gateway. Nginx-მა backend-ისგან ვარგისი პასუხი ვერ მიიღო. error log დაწერს connect() failed (111: Connection refused) - აპლიკაცია არ მუშაობს ან სხვა პორტზეა - ან no live upstreams, ან 104: Connection reset by peer backend-იდან, რომელიც მოთხოვნის შუაში დაეშვა. შეამოწმე პროცესი sudo ss -lntp-ით, შემდეგ მისი საკუთარი ლოგები. თუ აპლიკაცია კონტეინერში მუშაობს და nginx host-ზე, აპლიკაცია უნდა უსმენდეს მისამართზე, რომელსაც host აღწევს და არა კონტეინერის loopback-ზე.

504 Gateway Timeout. backend-მა კავშირი მიიღო და proxy_read_timeout-ის ფარგლებში არ უპასუხა. ეს ნელი მოთხოვნაა და არა proxy-ის გაუმართაობა. იპოვე ნელი endpoint, სანამ timeout-ს გაზრდი, რადგან მისი გაზრდა ჩვეულებრივ წარუმატებლობას მხოლოდ ბრაუზერში გადააქვს.

413 Request Entity Too Large. client_max_body_size. იხილე ზემოთ.

404 route-ებზე, რომლებიც არსებობს. proxy_pass-ის მონაცვლე slash, ან alias და root. error log ბეჭდავს path-ს, რომელიც სცადა.

გადამისამართების ციკლი. აპლიკაცია HTTPS-ს ძალით ამოწმებს საკუთარი კავშირის სქემით, რომელიც უბრალო HTTP-ა, რადგან TLS-ი nginx-მა დაასრულა. გააგზავნე X-Forwarded-Proto და ჩართე framework-ის trusted-proxy პარამეტრი; გადამისამართებას ნუ წაშლი.

ყველა ვიზიტორს აპლიკაციის ლოგში ერთი და იგივე IP აქვს. აპლიკაცია X-Forwarded-For-ს არ კითხულობს. ყოველ framework-ს ამისთვის გადამრთველი აქვს, ნაგულისხმევად გამორთული კარგი მიზეზებით.

`nginx -t` გადის, მაგრამ ცვლილებას შედეგი არ ჰქონია. სხვა server block-ი დაემთხვა პირველად, ჩვეულებრივ default server-ი, ან sites-available შეცვალე და symlink არასოდეს გაგიკეთებია. nginx -T | grep server_name აჩვენებს ყველა block-ს, რომელიც nginx-მა რეალურად ჩატვირთა.

Permission denied upstream-თან დაკავშირებისას RHEL-ზე ან Rocky-ზე. SELinux. sudo setsebool -P httpd_can_network_connect 1 ერთხაზიანი გამოსწორებაა, ხოლო sudo ausearch -m avc -ts recent არის გზა, რომ დაადასტურო, რომ ეს იყო მიზეზი.

გაუშვი nginx და აპლიკაცია ცალკე სერვისებად, რომ თითოეული მარტო გადაიტვირთოს; systemd სერვისები შენი აპლიკაციებისთვის შეიცავს unit ფაილს, Restart= და After=network.target ხაზების ჩათვლით, რომლებიც წყვეტს, რა დაბრუნდება reboot-ის შემდეგ.

თუ ეს სამუშაო არ გინდა, იცოდე, რომ ის სავალდებულო არ არის: RE:NODE-ის app და web გეგმებში proxy სლოტი შედის, რომელიც იგივე საქმეს აკეთებს. A ჩანაწერს მიუთითებ პანელში ნაჩვენებ მისამართზე, სერტიფიკატი გაიცემა და ახლდება ავტომატურად 21-დღიან ფანჯარაში, ხოლო კლიენტის ნამდვილი მისამართი X-Forwarded-For-ში მოდის. მიზეზი, რატომ უნდა გაუშვა nginx თვითონ, ყველაფერია, რასაც მართული proxy განზრახ არ აკეთებს - მორგებული location-ები, rate limit ზონები, რამდენიმე აპლიკაცია path-ებზე, Unix socket upstream - და ამას root-იანი მანქანა სჭირდება.

FAQ#

მჭირდება nginx, თუ ჩემს აპლიკაციას HTTPS-ის მომსახურება თვითონ შეუძლია?

ჩვეულებრივ დიახ, და არა სისწრაფისთვის. proxy სერტიფიკატს შენი აპლიკაციისგან გამოყოფს, საშუალებას გაძლევს რამდენიმე სერვისი ერთ მისამართსა და პორტზე გაუშვა, rate limit-ებისა და ატვირთვის ლიმიტების ერთ ადგილს გაძლევს და აპლიკაციის listener-ის გაწყვეტის გარეშე გადატვირთვის საშუალებას იძლევა. ერთი შიდა სერვისისთვის კერძო ქსელში შეგიძლია გამოტოვო.

Nginx თუ Caddy?

Caddy სერტიფიკატებს ავტომატურად იღებს plugin-ის გარეშე და გაცილებით მოკლე კონფიგურაციის ფაილი აქვს, რაც მას მარტივი საიტისთვის უფრო მარტივ არჩევანს ხდის. Nginx-ს მეტი პარამეტრი, გაცილებით მეტი დოკუმენტაცია და მაგალითი აქვს და ის არის ის, რასაც უმეტესი გიდი და უმეტესი ჰოსტინგ stack ვარაუდობს. ორივე კარგი პასუხია; nginx იმაა, რომელსაც უფრო ხშირად შეხვდები.

რატომ ხედავს ჩემი აპლიკაცია nginx-ის IP-ს ვიზიტორის ნაცვლად?

იმიტომ, რომ კავშირი მასთან nginx-მა დაამყარა. გააგზავნე X-Forwarded-For და X-Forwarded-Proto, შემდეგ ჩართე trusted-proxy პარამეტრი შენს framework-ში, რომ მათ წაიკითხოს. ამ header-ებისთვის უპირობო ნდობა არაუსაფრთხოა, სწორედ ამიტომ არ არის ის ნაგულისხმევად ჩართული.

შეუძლია nginx-ს გეიმ სერვერის დაპროქსირება?

HTTP proxy-ის სახით არა. თამაშები საკუთარ პროტოკოლებს იყენებენ, უმეტესად UDP-ზე, ხოლო proxy_pass HTTP-ს ლაპარაკობს. Nginx-ს აქვს stream მოდული უბრალო TCP და UDP გადაგზავნისთვის, რომელსაც თამაშის ტრაფიკის გატარება შეუძლია, მაგრამ ეს სხვა block-ია და ის არ გაძლევს hostname-ზე დაფუძნებულ მარშრუტიზაციას, რაც HTTP პროქსირებას სასარგებლოს ხდის.

როგორ გავტესტო კონფიგურაცია ცოცხალი საიტის გატეხვის გარეშე?

sudo nginx -t ყველაფერს კითხულობს და სინტაქსურ შეცდომაზე reload-ზე უარს ამბობს, ამიტომ გატეხილ ფაილს საიტის reload-ით დაშვება არ შეუძლია. ქცევის და არა სინტაქსის შესამოწმებლად დაამატე ახალი server block სათადარიგო hostname-ზე, გატესტე curl -H 'Host: new.example.com' http://127.0.0.1/-ით, შემდეგ გადაიტანე ნამდვილი სახელი.

reload გავაკეთო თუ restart?

Reload. ის listening socket-ებს ღიად ინახავს და არსებულ კავშირებს ძველ worker-ებზე დასრულების საშუალებას აძლევს, ამიტომ არაფერი წყდება. Restart გააკეთე მხოლოდ მაშინ, როცა იცვლი რამეს, რასაც nginx გაშვებისას კითხულობს, მაგალითად მომხმარებელს, რომლითაც ის მუშაობს, ან listening პორტების სიმრავლეს ზოგ კონფიგურაციაში.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000