Nginx перенаправляет на другой сайт и как настроить NGINX в качестве обратного прокси для разных номеров портов?

Перенаправления (редиректы) используются в тех случаях, когда вам необходимо, чтобы перенаправить пользователи сайта на нужный адрес.

В данной статье расскажем, как настраивать перенаправления в Apache и Nginx — одних из самых популярных веб-серверов в мире.

Apache

Подключения модуля mod_rewrite

Для включения перенаправления средствами Apache достаточно, чтобы модуль mod_rewrite.so был загружен в Apache.

Для ОС Ubuntu, Debian:

LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

Для ОС CentOS, RedHat, AlmaLinux нужно проверить, чтобы в файле /etc/httpd/conf.modules.d/00-base.conf была строка:

LoadModule rewrite_module modules/mod_rewrite.so

Если ее нет, то нужно добавить ее в конец файла. Если она закомментирована (в начале строки знак #) — нужно раскомментировать строку.

Для того чтобы директивы mod_rewrite можно было использовать в .htaccess, надо в конфигурационном файле Apache, в соответствующем разделе <Directory /путь/до/директории> прописать:

AllowOverride all

После внесения изменений в конфигурационный файл Apache, для вступления в силу этих изменений, нужно перезапустить веб сервер.

Для ОС Ubuntu, Debian:

systemctl restart apache2 

Для ОС CentOS, RedHat, AlmaLinux:

systemctl restart httpd

В .htaccess для работы перенаправления нужно указать следующую директиву:

RewriteEngine On

Пра

Эти директивы вы можете прописывать как в конфиге Apache для нужного virtualhost, так и в файле .htaccess.

Redirect или RedirectPermanent

Главный недостаток данных правил заключается в том, что для каждого адреса необходимо прописывать новое правило. Если необходимо сделать несколько редиректов, то каждый новый редирект пишется с новой строки.

Redirect 301 /old-page.html http://new-domain.ru/new-page.html
Redirect permanent /old-page.html http://new-domain.ru/new-page.html

Для перенаправления всех запросов на другой сайт вы можете использовать следующую конструкцию:

Redirect 301 / http://new-domain.ru/
Redirect permanent / http://new-domain.ru/

Этот редирект отличается тем, что в нем можно использовать регулярное выражение. Например, при переносе сайта с Windows на Linux, необходимо сменить все ссылки с *.php на *.aspx:

RedirectMatch /(.*)\.aspx$ /$1.php

Рассмотрим самые распространённые варианты её использования.

Редирект с одного сайта на другой

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.oldsite\.ru [OR]
RewriteCond %{HTTP_HOST} ^oldsite\.ru
RewriteRule (.*) https://newsite.ru [R=301,L]
Редирект с www на без www
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Или более понятный синтаксис:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.domain\.com$ [NC]
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L]

Вы можете использовать любой.

Редирект с без www на www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L] 
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
Перенаправление домена с https на http

Для того, чтобы данное перенаправление работало, должен использоваться только Web-сервер Apache. При использовании связки Nginx+Apache будет возникать ошибка циклической переадресации. Поэтому редирект нужно будет настраивать именно в Nginx.

RewriteEngine On
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
Перенаправление домена с http на https

Для того, чтобы данное перенаправление работало, должен использоваться только Web-сервер Apache. При использовании связки Nginx+Apache будет возникать ошибка циклической переадресации. Поэтому редирект нужно будет настраивать именно в Nginx

RewriteEngine On
RewriteCond %{SERVER_PORT} ^80$ [OR]
RewriteCond %{HTTP} =on
RewriteRule ^(.*)$ https://www.domain.com/$1 [R=301,L]

Nginx

Модуль ngx_http_rewrite_module, необходимый для настройки перенаправлений, устанавливается автоматически вместе с Nginx.

Рекомендуется добавлять правила редиректа по одному, т.к. можно получить ошибку, либо циклическое перенаправление. Поэтому после каждого изменения конфигурационного файла нужно проверять его корректность командой:

nginx -t

Редирект 301 с www.domain.com на domain.com

Для Nginx вам нужно создать две секции server в конфигурационном файле, одну для домена с www, вторую для домена без www:

Секция server для редиректа:

server {
     listen  80;
     server_name www.domain.com;
     return 301 $scheme://domain.com$request_uri;
}

Секция server, где находятся основные настройки домена:

server { listen 80; server_name domain.com;
.....
}

После внесения изменений в конфигурационный файл Nginx, для вступления в силу этих изменений, нужно перезапустить веб сервер.

nginx -s reload
systemctl reload nginx

Редирект 301 с domain.com на www.domain.com

Для Nginx вам нужно создать две секции server в конфигурационном файле, одну для домена с www, вторую для домена без www:

Секция server для редиректа:

server {
     listen  80;
     server_name domain.ru;
     return 301 http://www.$host$request_uri;
}

Секция server, где находятся основные настройки домена.

server { listen 80; server_name www.domain.com;
.....
}

После внесения изменений в конфигурационный файл Nginx, для вступления в силу этих изменений, нужно перезапустить веб сервер.

nginx -s reload
systemctl reload nginx

Редирект 301 с https на http

Для Nginx вам нужно создать две секции server в конфигурационном файле, одну для https (443 порт), вторую для http (80 порт).

Секция server для открытия по https (443 порт) и настройки редиректа:

server {
    listen  443;
    server_name domain.ru www.domain.ru;
    return 301 http://$host$request_uri;
}

Секция server для открытия по http (80 порт), где находятся основные настройки домена.

server { listen 80; server_name www.domain.com;
.....
}

После внесения изменений в конфигурационный файл Nginx, для вступления в силу этих изменений, нужно перезапустить веб сервер.

nginx -s reload
systemctl reload nginx

Редирект 301 с http на https

Для Nginx вам нужно создать две секции server в конфигурационном файле, одну для http (80 порт), вторую для https (443 порт).

Для нового домена в конф. файле nginx

Секция server для открытия по http (80 порт) и настройки перенаправления:

server {
    listen  80;
    server_name domain.com www.domain.com;
    return 301 https://$host$request_uri;
}

Секция server для открытия по https (443 порт), где находятся основные настройки домена.

server { listen IP.се.рве.ра:443; server_name www.domain.com;
.....
}

Для существующего домена в конф. файле nginx

Если вы вносите изменения в существующую секцию конф. файла nginx делайте это так:

из основной секции домена удалите строку вида

 listen IP.се.рве.ра:80;

и создайте новую секцию server такого вида:

server {
    listen  80;
    server_name domain.com www.domain.com;
    return 301 https://$host$request_uri;
}

После внесения изменений в конфигурационный файл Nginx, для вступления в силу этих изменений, нужно его перезапустить так:

nginx -s reload
systemctl reload nginx

I’m in the process of reorganizing URL structure.
I need to setup redirect rules for specific URLs — I’m using Nginx.

Basically Something like this:

http://example.com/issue1 --> http://example.com/shop/issues/custom_issue_name1
http://example.com/issue2 --> http://example.com/shop/issues/custom_issue_name2
http://example.com/issue3 --> http://example.com/shop/issues/custom_issue_name3

Syscall's user avatar

10 gold badges36 silver badges52 bronze badges

asked Aug 3, 2013 at 21:59

tokmak's user avatar

location ~ /issue([0-9]+) { return 301 http://example.com/shop/issues/custom_isse_name$1;
}

answered Aug 4, 2013 at 1:57

Mohammad AbuShady's user avatar

Mohammad AbuShady

10 gold badges77 silver badges89 bronze badges

Put this in your server directive:

location /issue { rewrite ^/issue(.*) http://$server_name/shop/issues/custom_issue_name$1 permanent; }

Or duplicate it:

location /issue1 { rewrite ^/.* http://$server_name/shop/issues/custom_issue_name1 permanent;
}
location /issue2 { rewrite ^.* http://$server_name/shop/issues/custom_issue_name2 permanent;
} ...

answered Aug 3, 2013 at 23:06

BraveNewCurrency's user avatar

2 gold badges42 silver badges50 bronze badges

If you need to duplicate more than a few redirects, you might consider using a map:

# map is outside of server block
map $uri $redirect_uri { ~^/issue1/?$ http://example.com/shop/issues/custom_isse_name1; ~^/issue2/?$ http://example.com/shop/issues/custom_isse_name2; ~^/issue3/?$ http://example.com/shop/issues/custom_isse_name3; # ... or put these in an included file
}
location / { try_files $uri $uri/ @redirect-map;
}
location @redirect-map { if ($redirect_uri) { # redirect if the variable is defined return 301 $redirect_uri; }
}

srborlongan's user avatar

4 gold badges26 silver badges33 bronze badges

answered Dec 9, 2014 at 16:04

Cole Tierney's user avatar

Cole Tierney

1 gold badge27 silver badges34 bronze badges

How can I redirect mydomain.example and any subdomain *.mydomain.example to www.adifferentdomain.example using Nginx?

Stephen Ostermiller's user avatar

asked May 18, 2011 at 12:55

deb's user avatar

server_name supports suffix matches using .mydomain.example syntax:

server { server_name .mydomain.example; rewrite ^ http://www.adifferentdomain.example$request_uri? permanent;
}

or on any version 0.9.1 or higher:

server { server_name .mydomain.example; return 301 http://www.adifferentdomain.example$request_uri;
}

Stephen Ostermiller's user avatar

answered May 18, 2011 at 13:28

kolbyjack's user avatar

5 gold badges48 silver badges35 bronze badges

Why use the rewrite module if you can do return? Technically speaking, return is part of the rewrite module as you can read here but this snippet is easier to read imho.

server { server_name .domain.com; return 302 $scheme://forwarded-domain.com;
}

You can also give it a 301 redirect.

answered Feb 12, 2014 at 19:55

Robin van Baalen's user avatar

Robin van BaalenRobin van Baalen

2 gold badges21 silver badges35 bronze badges

I’m using this code for my sites

server { listen 80; listen 443; server_name .domain.example; return 301 $scheme://newdomain.example$request_uri;
}

Stephen Ostermiller's user avatar

answered Oct 21, 2020 at 5:53

Tech's user avatar

1 gold badge6 silver badges19 bronze badges

That should work via HTTPRewriteModule.

Example rewrite from www.example.com to example.com:

server { server_name www.example.com; rewrite ^ http://example.com$request_uri? permanent;
}

Stephen Ostermiller's user avatar

answered May 18, 2011 at 12:59

udo's user avatar

14 silver badges18 bronze badges

server { listen 80; server_name domain1.example; return 301 $scheme://domain2.example$request_uri;
}

Stephen Ostermiller's user avatar

answered Jan 6, 2017 at 10:37

ZanMax's user avatar

4 silver badges13 bronze badges

server { if ($host = mydomain.example) { return 301 http://www.adifferentdomain.example; }
}

Stephen Ostermiller's user avatar

answered Jun 1, 2020 at 5:39

cryptoKTM's user avatar

22 silver badges20 bronze badges

rewrite ^ http://www.RedirectToThisDomain.example$request_uri? redirect;
rewrite ^ http://www.RedirectToThisDomain.example$request_uri? permanent;

In Nginx configuration file for specific site:

server { server_name www.example.com; rewrite ^ http://www.RedictToThisDomain.example$request_uri? redirect;
}

Stephen Ostermiller's user avatar

answered Oct 2, 2018 at 9:50

Taimoor Changaiz's user avatar

Taimoor Changaiz

4 gold badges49 silver badges53 bronze badges

The ngx_stream_proxy_module module (1.9.0) allows proxying
data streams over TCP, UDP (1.9.13), and UNIX-domain sockets.

Example Configuration

server { listen 127.0.0.1:12345; proxy_pass 127.0.0.1:8080;
}
server { listen 12345; proxy_connect_timeout 1s; proxy_timeout 1m; proxy_pass example.com:12345;
}
server { listen 53 udp reuseport; proxy_timeout 20s; proxy_pass dns.example.com:53;
}
server { listen [::1]:12345; proxy_pass unix:/tmp/stream.socket;
}

Directives

This directive appeared in version 1.9.2.

Makes outgoing connections to a proxied server originate
from the specified local IP address.
Parameter value can contain variables (1.11.2).
The special value off cancels the effect
of the proxy_bind directive
inherited from the previous configuration level, which allows the
system to auto-assign the local IP address.

The transparent parameter (1.11.0) allows
outgoing connections to a proxied server originate
from a non-local IP address,
for example, from a real IP address of a client:

proxy_bind $remote_addr transparent;

This directive appeared in version 1.9.4.

Sets the size of the buffer used for reading data
from the proxied server.
Also sets the size of the buffer used for reading data
from the client.

Defines a timeout for establishing a connection with a proxied server.

This directive appeared in version 1.9.3.

Limits the speed of reading the data from the proxied server.
The rate is specified in bytes per second.
The zero value disables rate limiting.
The limit is set per a connection, so if nginx simultaneously opens
two connections to the proxied server,
the overall rate will be twice as much as the specified limit.

Читайте также:  Представление языка PHP: обзор и его важность в веб-разработке

Parameter value can contain variables (1.17.0).
It may be useful in cases where rate should be limited
depending on a certain condition:

map $slow $rate { 1 4k; 2 8k;
}
proxy_download_rate $rate;

This directive appeared in version 1.21.4.

Enables or disables closing
each direction of a TCP connection independently (“TCP half-close”).
If enabled, proxying over TCP will be kept
until both sides close the connection.

When a connection to the proxied server cannot be established, determines
whether a client connection will be passed to the next server.

Passing a connection to the next server can be limited by
the number of tries
and by time.

Limits the time allowed to pass a connection to the
next server.
The 0 value turns off this limitation.

Limits the number of possible tries for passing a connection to the
next server.
The 0 value turns off this limitation.

Sets the address of a proxied server.
The address can be specified as a domain name or IP address,
and a port:

proxy_pass localhost:12345;

or as a UNIX-domain socket path:

proxy_pass unix:/tmp/stream.socket;

If a domain name resolves to several addresses, all of them will be
used in a round-robin fashion.
In addition, an address can be specified as a
server group.

The address can also be specified using variables (1.11.3):

proxy_pass $upstream;

In this case, the server name is searched among the described
server groups,
and, if not found, is determined using a
resolver.

This directive appeared in version 1.9.2.

Enables the
PROXY
protocol
for connections to a proxied server.

This directive appeared in version 1.15.7.

Sets the number of client datagrams at which
binding between a client and existing UDP stream session is dropped.
After receiving the specified number of datagrams, next datagram
from the same client starts a new session.
The session terminates when all client datagrams are transmitted
to a proxied server and the expected number of
responses is received,
or when it reaches a timeout.

This directive appeared in version 1.9.13.

Sets the number of datagrams expected from the proxied server
in response to a client datagram
if the UDP
protocol is used.
The number serves as a hint for session termination.
By default, the number of datagrams is not limited.

If zero value is specified, no response is expected.
However, if a response is received and the
session is still not finished, the response will be handled.

This directive appeared in version 1.15.8.

Enables terminating all sessions to a proxied server
after it was removed from the group or marked as permanently unavailable.
This can occur because of
re-resolve
or with the API
DELETE
command.
A server can be marked as permanently unavailable if it is considered
unhealthy
or with the API
PATCH
command.
Each session is terminated when the next
read or write event is processed for the client or proxied server.

This directive is available as part of our
commercial subscription.

This directive appeared in version 1.15.6.

Configures the “TCP keepalive” behavior
for outgoing connections to a proxied server.
By default, the operating system’s settings are in effect for the socket.
If the directive is set to the value “on”, the
SO_KEEPALIVE socket option is turned on for the socket.

Enables the SSL/TLS protocol for connections to a proxied server.

Specifies a file with the certificate in the PEM format
used for authentication to a proxied server.

Since version 1.21.0, variables can be used in the file name.

Specifies a file with the secret key in the PEM format
used for authentication to a proxied server.

Since version 1.21.0, variables can be used in the file name.

Specifies the enabled ciphers for connections to a proxied server.
The ciphers are specified in the format understood by the OpenSSL library.

The full list can be viewed using the
openssl ciphers” command.

This directive appeared in version 1.19.4.

Sets arbitrary OpenSSL configuration
commands
when establishing a connection with the proxied server.

The directive is supported when using OpenSSL 1.0.2 or higher.

Several proxy_ssl_conf_command directives
can be specified on the same level.
These directives are inherited from the previous configuration level
if and only if there are
no proxy_ssl_conf_command directives
defined on the current level.

Note that configuring OpenSSL directly
might result in unexpected behavior.

Specifies a file with revoked certificates (CRL)
in the PEM format used to verify
the certificate of the proxied server.

Allows overriding the server name used to
verify
the certificate of the proxied server and to be
passed through SNI
when establishing a connection with the proxied server.
The server name can also be specified using variables (1.11.3).

By default, the host part of the proxy_pass address is used.

Specifies a file with passphrases for
secret keys
where each passphrase is specified on a separate line.
Passphrases are tried in turn when loading the key.

Enables the specified protocols for connections to a proxied server.

The TLSv1.3 parameter is used by default
since 1.23.4.

Enables or disables passing of the server name through
TLS
Server Name Indication extension
(SNI, RFC 6066)
when establishing a connection with the proxied server.

Determines whether SSL sessions can be reused when working with
the proxied server.
If the errors
SSL3_GET_FINISHED:digest check failed
appear in the logs, try disabling session reuse.

Specifies a file with trusted CA certificates in the PEM format
used to verify
the certificate of the proxied server.

Enables or disables verification of the proxied server certificate.

Sets the verification depth in the proxied server certificates chain.

Sets the timeout between two successive
read or write operations on client or proxied server connections.
If no data is transmitted within this time, the connection is closed.

This directive appeared in version 1.9.3.

Limits the speed of reading the data from the client.
The rate is specified in bytes per second.
The zero value disables rate limiting.
The limit is set per a connection, so if the client simultaneously opens
two connections,
the overall rate will be twice as much as the specified limit.

Parameter value can contain variables (1.17.0).
It may be useful in cases where rate should be limited
depending on a certain condition:

map $slow $rate { 1 4k; 2 8k;
}
proxy_upload_rate $rate;

I’m using LEMP stack and Node JS on my debian server. Nginx works on port 80 and Node JS on 8080. I created new subdomain: cdn.domain.com for nodejs app. Currently I can access to Node JS application only like cdn.domain.com:8080/. What I want to do is to configure Nginx so that, when I enter to cdn.domain.com I can get app working on port 80. I think it can be done using nginx upstream. But I can’t figure out how.

tshepang's user avatar

21 gold badges91 silver badges135 bronze badges

asked Jul 21, 2014 at 9:06

heron's user avatar

As simple as like this,

make sure to change example.com to your domain (or IP), and 8080 to your Node.js application port:

server { listen 80; server_name example.com; location / { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $http_host; proxy_pass "http://127.0.0.1:8080"; }
}

answered Sep 6, 2017 at 5:03

Nyi Nyi's user avatar

Nyi Nyi

7 silver badges12 bronze badges

NGINX supports WebSockets by allowing a tunnel to be setup between a client and a backend server. In order for NGINX to send the Upgrade request from the client to the backend server, Upgrade and Connection headers must be set explicitly. For example:

# WebSocket proxying
map $http_upgrade $connection_upgrade { default upgrade; '' close;
}
server { listen 80; # The host name to respond to server_name cdn.domain.com; location / { # Backend nodejs server proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; }
}

answered Jul 21, 2014 at 9:20

Tan Hong Tat's user avatar

Tan Hong TatTan Hong Tat

2 gold badges26 silver badges25 bronze badges

server { listen 80 default_server; listen [::]:80 default_server; server_name _ your_domain; location /health { access_log off; return 200 "healthy\n"; } 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; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; } }

answered Feb 15, 2019 at 15:46

SHIVAPUTRA UDAGATTI's user avatar

server { listen 80; server_name p3000; location / { proxy_pass http://0.0.0.0:3000; include /etc/nginx/proxy_params; }
}

answered Oct 10, 2016 at 14:21

Daniel Garmoshka's user avatar

This is how you can achieve this.

upstream { nodeapp 127.0.0.1:8080;
}
server { listen 80; # The host name to respond to server_name cdn.domain.com; location /(.*) { proxy_pass http://nodeapp/$1$is_args$args; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $host; proxy_set_header X-Real-Port $server_port; proxy_set_header X-Real-Scheme $scheme; }
}

You can also use this configuration to load balance amongst multiple Node processes like so:

upstream { nodeapp 127.0.0.1:8081; nodeapp 127.0.0.1:8082; nodeapp 127.0.0.1:8083;
}

Where you are running your node server on ports 8081, 8082 and 8083 in separate processes. Nginx will easily load balance your traffic amongst these server processes.

answered Jul 21, 2014 at 18:05

vaidik's user avatar

1 gold badge15 silver badges22 bronze badges

You can define an upstream and use it in proxy_pass

server { listen 8082; location ~ /(.*) { proxy_pass test_server; 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_redirect off; }
} upstream test_server { server test-server:8989
} 

Community's user avatar

answered Feb 22, 2016 at 17:26

Rohan's user avatar

3 silver badges3 bronze badges

This worked for me:

server { listen 80; server_name example.com www.example.com; location / { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
}

If it does not work for you look at the logs at sudo tail -f /var/log/nginx/error.log

answered Apr 7, 2019 at 21:09

Vishrant's user avatar

11 gold badges71 silver badges113 bronze badges

У меня написано и опубликовано много статей по управлению современным веб сервером. Сегодня я подробно расскажу, как установить и выполнить настройку nginx с подробным описанием функционала и примерами. Я постарался охватить все наиболее актуальные и полезные возможности бесплатной версии nginx.

Если у вас есть желание научиться строить и поддерживать высокодоступные и надежные системы, рекомендую познакомиться с онлайн-курсом «DevOps практики и инструменты» в OTUS. Курс не для новичков, для поступления нужно пройти вступительный тест.

Введение

Базовая настройка nginx не представляет каких-то сложностей на первом этапе. У nginx есть неплохая документация на русском языке. Еще лучше на английском. Практически все, что я буду рассказывать, есть там. Понятное дело, что если вы только знакомитесь с продуктом, или используете его базовый функционал, копать документацию на начальном этапе будет не очень продуктивно. Моя статья будет служить беглым обзором основных возможностей, которые я сам использовал, с моими же примерами.

По тематике некоторых разделов у меня уже есть подробные статьи. В таком случае я буду давать на них ссылки с краткими комментариями здесь. В конце статьи приведу свой типовой конфиг для nginx, который я обычно беру за основу, когда настраиваю очередной web сервер.

Читайте также:  Значение слова ХОСТИНГ. Что такое ХОСТИНГ?

Установка nginx

В своей статье я не буду привязываться к конкретному дистрибутиву, так как настройка nginx одинакова везде. Формат файла один и тот же, поэтому конфигурация без проблем может мигрировать на разные системы. Править придется только пути к файлам и директориям. Тем не менее, я расскажу, как выполнить установку на популярные дистрибутивы.

Установку nginx на CentOS 7 я подробно разбирал в соответствующей статье про настройку web сервера на centos. Здесь просто перечислю необходимые шаги.

Подключаем репозиторий nginx для CentOS 7:

# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# yum install nginx

Вот и все. На этом установка на Centos 7 закончена. Пример установки nginx на Debian.

Подключаем репозиторий для Debian:

# echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list

Импортируем ключ для проверки подлинности пакетов:

# curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -

Устанавливаем nginx на Debian:

# apt update && apt install nginx

Установим nginx на Ubuntu. Подключаем репозиторий:

# echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
# curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -

Выполняем установку nginx на Ubuntu:

# apt update && apt install nginx

На всех указанных системах запуск веб сервера выполняется командой:

# systemctl start nginx

Добавляем nginx в автозагрузку:

# systemctl enable nginx

В последнее время большое распространение получили контейнеры, в частности docker. Довольно популярна ситуация, когда nginx работает в докере, поэтому отдельно рассмотрю вопрос установки nginx в docker, хоть там и нет ничего сложного.

Nginx в Docker

Неоспоримые преимущества от использования docker получают разработчики, поэтому они очень часто его используют. В том числе в виде контейнеров docker с nginx. Установка nginx через docker может быть выполнена из официального образа nginx в Docker Hub. Если не умеете работать с docker, смотрите мою статью по этой теме — установка docker в centos. Установить и запустить nginx в docker можно примерно такой командой:

# docker run --name nginx01 -p 80:80 -d nginx

В данной команде:

  • nginx01 — имя созданного контейнера, основанного на базовом образе nginx
  • -p 80:80 — сопоставление порта на локальной машине, порту в контейнере. Сначала указывается локальный порт, потом внутри контейнера.
  • -d — ключ, обозначающий запуск контейнера в режиме службы.

Это общий случай установки. Образ nginx в данном случае будет скачан автоматически при создании первого контейнера. Для удобства используется большее количество параметров. Для примера запустим еще один контейнер с другим названием и с расширенными параметрами.

# docker run --name nginx02 -p 81:80 -v ~/nginx/www:/usr/share/nginx/html -v ~/nginx/conf:/etc/nginx -v ~/nginx/logs:/var/log/nginx -d nginx

В данном примере мы создали еще один контейнер naginx02, назначили ему порт 81 на локальной машине, в контейнер смонтировали 3 локальные директории:

  1. ~/nginx/www — здесь будут лежать исходники сайта.
  2. ~/nginx/conf — полная конфигурация nginx. Ее нужно будет скопировать откуда-то.
  3. ~/nginx/logs — логи nginx.

Не обязательно выносить на хост все эти папки. Я показываю для примера. Вы выбирайте только то, что вам действительно нужно.

Таким образом можно легко работать с nginx с помощью docker. Можно без проблем запустить сколько угодно контейнеров с nginx, указав каждому свой порт, конфигурацию и директорию с исходниками. Для разработки это действительно удобно. Для продакшена отдельный разговор. Те, кто используют nginx в docker в production вряд ли нуждаются в данной статье.

Рестарт nginx и другие параметры командной строки

Перед тем, как двигаться дальше к настройке nginx, предлагаю пройтись по основным параметрам в командной строке. Это упростит и ускорит дальнейшую работу.

Прежде всего расскажу, как перезапустить nginx. С помощью systemctl на всех дистрибутивах это выглядит одинаково.

# systemctl restart nginx

Перед перезагрузкой nginx, рекомендую выполнить проверку конфигурации:

# nginx -t

Проверка параметров nginx

Еще одна важная команда, с помощью которой можно применить новую конфигурацию nginx без остановки и перезапуска веб сервера. Будет запущен новый рабочий процесс с новой конфигурацией, а старые процессы плавно завершатся.

# nginx -s reload

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

# nginx -T

Вывод полного конфига

Так же бывает полезно посмотреть полную информацию о версии nginx, параметрах сборки, модулях и т.д.

# nginx -V

Полная версия nginx с модулями

Например, мне эта информация была нужна, когда я делал собственную сборку nginx c поддержкой tls 1.3 и модулем сжатия brotli.

В принципе, на этом все. Не припоминаю, чтобы я использовал что-то еще. Плавно переходим к конфигурации nginx.

Виртуальные хосты

После дефолтной установки nginx у вас уже будет один виртуальный хост, который описан конфигом default.conf. Обычно конфиги с виртуальными хостами расположены в директории /etc/nginx/conf.d. Здесь, в отличие от Apache, структура размещения конфигурационных файлов одинаковая на всех дистрибутивах, что очень удобно.

Что такое виртуальный хост? Попробую объяснить своими словами. Это конфигурационный файл, который описывает настройку условно одного домена. Для удобства, каждый виртуальных хост выносят в отдельный конфиг, но никто не мешает вам все это описывать в общем конфигурационном файле. Дело в том, что если доменов у вас много, то работать в одном большом конфиге не удобно, поэтому я рекомендую вам придерживаться схемы файлов конфигурации, когда один конфиг описывает параметры одного домена.

Виртуальные хосты наследуют параметры из основного файла конфигурации nginx.conf, но эти параметры могут быть переопределены в конкретном виртуальном хосте. То есть можно задать дефолтные параметры для всех сайтов, но в случае необходимости переопределить какой-то параметр в конкретном виртуальном хосте. Вот типичный пример конфига.

server {	listen 80;	server_name example.com www.example.com;	access_log /var/log/nginx/example.com.access.log main;	root /var/www/example.com/public;	location / {	index index.html index.htm index.php;	}	location ~ \.php$ {	fastcgi_pass 127.0.0.1:9000;	fastcgi_index index.php;	fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;	include fastcgi_params;	}
}

Все не указанные явно в этом виртуальном хосте параметры будут унаследованы из основного файла конфигурации nginx.conf. Допустим, вам надо по какой-то причине отключить сжатие gzip на этом хосте и указать кодировку windows-1251. Тогда конфиг приобретет следующий вид.

server {	listen 80;	server_name example.com www.example.com;	access_log /var/log/nginx/example.com.access.log main;	root /var/www/example.com/public;charset windows-1251;	gzip off;location / {	index index.html index.htm index.php;	}	location ~ \.php$ {	fastcgi_pass 127.0.0.1:9000;	fastcgi_index index.php;	fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;	include fastcgi_params;	}
}

С помощью виртуальных хостов в nginx вы можете очень гибко настраивать конфигурацию каждого домена. Как минимум я рекомендую для каждого домена делать отдельно:

  • директорию с исходниками сайта;
  • директорию с логами;
  • в некоторых ситуациях отдельный php-fpm пул для каждого сайта или группы сайтов.

Более полный пример настройки виртуального хоста для реального сайта на wordpress смотрите в отдельной статье по настройке web сервера. Мы же переходим к настройке location.

Настройка location в конфигурации

Как вы могли заметить, в предыдущем примере я использовал 2 разных location для виртуального хоста. Постараюсь простыми словами рассказать, что это такое, как использовать и для чего вообще нужно.

С помощью location в nginx вы можете управлять конфигурацией в зависимости от URI запроса. Если в виртуальных хостах мы могли переопределять настройки в зависимости от имени домена, то тут мы спускаемся на уровень ниже и управляем параметрами в зависимости от пути запроса. В примере с виртуальными хостами у меня было 2 location:

  1. / — корень сайта, перехватывает вообще все запросы к домену.
  2. ~ \.php$ — запросы к файлам с расширением php. То есть если в запросе указан путь к файлу .php, то к нему применяется параметр fastcgi_pass и запрос отправляется на обработку к php-fpm.

Location можно задавать префиксной строкой или регулярным выражением. В регулярных выражениях используются модификаторы ~, либо ~* Без звездочки учитывается регистр, со звездочкой нет. Обработка location в конфигурационном файле идет в следующей последовательности:

  1. Первыми проверяются префиксные строки. Совпадения запоминаются.
  2. Дальше проверяются регулярные выражения в том порядке, как они перечислены в конфигурационном файле. Проверка по регулярным выражениям прекращается сразу же после совпадения. Если совпадение не было найдено, используется запомненный ранее префикс.

Так же в location может использоваться префикс = Он означает точное совпадение запроса и заданного location. После такого совпадения, остальные проверки сразу же прекращаются. Рекомендуется использовать этот префикс, если у вас огромное количество конкретных запросов. Используя префикс = для них, вы снизите нагрузку на сервер, так как запросы не будут проверяться по всем правилам.

В крупном сайте может быть огромное количество различных location. Вот несколько простых реальных примеров из моей практики.

На своем сайте я решил отказаться от использования amp страниц, выключил их и сделал перенаправление с этих страниц на обычные. В данном примере amp располагались по исходному урлу с добавлением /amp/ в конец пути.

location ~ /amp/$ {
rewrite ^(.*/)amp/$ $1 permanent;
}

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

location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff|woff2|swf|ttf|svg)$ {
access_log off;
expires 1y;
}

Закроем доступ к директории .git на сайте.

location ~ /.git {
return 404;
}

Запретим исполнение скриптов в перечисленных директориях.

location ~* /(images|cache|media|logs|tmp)/.*.(php|pl|py|jsp|asp|sh|cgi)$ {
return 404;
}

И так далее. Думаю, смысл понятен. Примеров может быть огромное количество. Location важный параметр конфигурации в настройке nginx. Немного информации на эту тему можно посмотреть в соответствующем разделе документации.

Работа nginx с php-fpm

В предыдущих разделах я уже показал примеры конфигурации, где запросы по определенным URI перенаправляются на php-fpm. Еще более подробно я рассмотрел этот вопрос в отдельной статье по настройке php-fpm. Сейчас просто покажу на реальном примере, как выглядит взаимодействие nginx и php-fpm.

Php-fpm может слушать как сокет unix, так и tcp порт. Эти настройки задаются в конфиге пула. Это может быть либо

listen = 127.0.0.1:9000
listen = /var/run/php-fpm/php-fpm.sock

В зависимости от того, в каком режиме работает php-fpm, зависят настройки в nginx.

Вот примерный конфиг php-fpm для пула www.conf на виртуальной машине с 1Gb памяти.

[www]
listen = /var/run/php-fpm/php-fpm.sock
listen.allowed_clients = 127.0.0.1
listen.mode = 0660
listen.owner = nginx
listen.group = nginx
user = nginx
group = nginx
; как будут создаваться новые рабочие процессы
pm = dynamic
; максимальное количество рабочих процессов
pm.max_children = 15
; число запущенных процессов при старте сервера
pm.start_servers = 6
; минимальное и максимальное количество процессов в простое
pm.min_spare_servers = 4
pm.max_spare_servers = 8
slowlog = /var/log/php-fpm/www-slow.log
pm.max_requests = 250
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
pm.status_path = /status

Чтобы заработал php в nginx через php-fpm, достаточно убедиться, что php-fpm работает и указать в виртуальном хосте location для php. Пример реальных настроек для wordpress сайта.

location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; #fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param DOCUMENT_ROOT /web/sites/example.com/www/; fastcgi_param SCRIPT_FILENAME /web/sites/example.com/www$fastcgi_script_name; fastcgi_param PATH_TRANSLATED /web/sites/example.com/www$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param HTTPS on; # включать, если сайт по https работает fastcgi_intercept_errors on; fastcgi_ignore_client_abort off; fastcgi_connect_timeout 60; fastcgi_send_timeout 180; fastcgi_read_timeout 180; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k;
}

В целом все. Этого достаточно для настройки связки nginx + php-fpm. Типовой ошибкой в данном случае является то, что nginx не имеет доступа к unix сокету php-fpm. По-умолчанию после установки он запускается с правами apache. Если пользователя не исправить на nginx, то у веб сервера не будет доступа к сокету, php не заработает. В своем примере конфига php-fpm я указал пользователя правильно.

Читайте также:  Освоение настройки SMTP-реле с помощью Postfix: руководство для начинающих

Настройка SSL сертификата

Далее рассмотрим момент с настройкой ssl сертификатов в nginx. В общем случае с этим не должно быть каких-то проблем. Тут все просто. Можно глобально задать настройки ssl для всех виртуальных хостов, а можно отдельно в каждом. Вот пример настроек ssl для nginx.conf.

ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384:ECDHE:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
resolver 8.8.8.8;

Здесь уже включена поддержка TLS 1.3 и соответствующие шифры. Сейчас не готов прокомментировать именно такой выбор шифров. В свое время, перед настройкой TLS 1.3 я изучил этот вопрос и собрал такой набор, который везде использую.

Часто возникают споры насчет директивы resolver. На dns сервер 8.8.8.8 есть нарекания по стабильности. Так что выбор dns сервера остается за вами. С подобными настройками ssl вы получите рейтинг A+.

Настройка ssl сертификата в Nginx

Для генерации файла dhparam.pem, воспользуйтесь командой:

# openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

Процесс длится долго, до получаса на слабых виртуалках. Этот файл нужен для повышения безопасности и получения максимального рейтинга. Насколько этот параметр критичен в реальности, не берусь судить. Если тороплюсь, то настраиваю без него. Подробный разбор параметров ssl можно посмотреть в статье на хабре.

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

server { listen 443 ssl http2; ........................ ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ........................ location ~ \.php$ { ........................ fastcgi_param HTTPS on; ........................ }
}

Редирект с http на https

Добавим переадресацию с http на https. Для этого добавляем в настройки виртуального хоста еще одну директиву server.

server { listen 80; server_name example.com www.example.com; access_log /var/log/nginx/example.com.access.log main; root /var/www/example.com/public; location / { return 301 https://example.com$request_uri; }
}

Проксирование запросов

Nginx очень производительный веб сервер, поэтому его часто используют в качестве Reverse Proxy для других служб и серверов. Подробно вопрос проксирования запросов в nginx с помощью proxy_pass я рассмотрел отдельно. Сейчас же в двух словах объясню, что это такое. Допустим, у вас есть какой-то сервис на отдельном сервере и вы ходите перенаправлять на него часть запросов с вашего сайта. Для этого вы делаете отдельный location и указываете, что все запросы по определенному правилу нужно перенаправлять на этот сервер.

location /forum/ { proxy_pass http://192.168.13.31; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_redirect default;
}

Все запросы с урлами, содержащими /forum/ будут перенаправлены на отдельный сервер, где трудится тяжелый форум со своей базой данных и своими настройками. Им может управлять другой администратор и вообще он не имеет к вам никакого отношения. Таким образом, большой проект можно разделить на части с делегированием полномочий. Но это отдельная история.

Nginx proxy_pass удобно использовать разработчикам для проксирования запросов в разные docker контейнеры, которые подняты на рабочей машине на разных портах. Можно перенаправлять не только отдельные урлы, но и весь сайт. Допустим, вы делаете какие-то фильтрации трафика на стороне сервера с nginx, а потом все запросы отправляете на исходный сайт. Тогда делаете простую настройку для проксирования:

location / {
proxy_pass http://192.168.13.31;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr; }

Все запросы уходят на сторонний сервер. Частным случаем проксирования в nginx является работа в связке с Apache, о чем я расскажу далее.

Nginx в связке с Apache

Популярным кейсом работы nginx является работа в качестве Reverse Proxy для Apache. Лет 5-10 назад, когда nginx был не очень распространен, это было очень популярное решение. Сейчас Nginx во многих областях полностью заменил Apache, но тем не менее, пока еще не до конца. К примеру, очень популярный в России движок для сайтов Bitrix до сих пор требует в качестве web сервера Apache.

Покажу на простом примере, как Nginx настроить в качестве front-end к Apache. Статические данные будет обрабатывать сам nginx, а динамические запросы перенаправлять на apache.

Для начала вам необходимо настроить apache стандартным образом, с той лишь разницей, что слушать он должен не привычный 80-й или 443 порт, а, к примеру, 8080. Далее в настройках виртуального хоста указываете для каких запросов будет перенаправление на apache. Для примера отправим туда все, что не является статичным контентом. Создаем 2 location:

  1. Статика, которую будет напрямую отдавать Nginx.
  2. Все остальные запросы, которые будет обрабатывать Apache.
server {	listen 80;	server_name example.com www.example.com;	access_log /var/log/nginx/example.com.access.log main;	location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff|woff2|swf|ttf|svg|html|txt)$ {	root /var/www/example.com/public;	expires 1y;	}	location / {	proxy_pass http://127.0.0.1:8080/;	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_connect_timeout 120;	proxy_send_timeout 120;	proxy_read_timeout 180;	}
}

В данном примере Nginx и Apache работают на одном сервере. Но это не обязательно. Web сервер с apache вы без проблем можете разместить на другой машине. Отдельно будет стоять вопрос определения реальных ip адресов клиентов на сервере с Apache. Я его рассмотрел подробно в статье про nginx revers proxy, ссылку на которую привел в предыдущем разделе.

Балансировка нагрузки

Nginx может выступать в качестве балансировщика. Настройку балансировки в nginx я так же подробно рассматривал отдельно. Все подробности в статье. Здесь кратко упомяну, что это такое. Nginx умеет распределять нагрузку между несколькими серверами. Правила распределения настраиваются, как и количество серверов. Покажу как это делать на предыдущем примере с apache.

Допустим, у вас очень нагруженный сайт. А нагрузить Bitrix без настроенного кэширования, очень просто. Вы хотите добавить еще один сервер с Apache, чтобы распределить нагрузку между двумя серверами. Сразу скажу, что это не такой простой вопрос, как может показаться вначале. Со стороны nginx настройки действительно простые, но нужно будет рассмотреть отдельно вопрос общего файлового хранилища для обоих серверов и общей базы данных. Ее, скорее всего, тоже нужно будет выносить на отдельный сервер, хотя и не обязательно. Если nginx будет раздавать статику, то доступ к файлам должен быть и у него. В общем, тут нужно хорошенько все продумать и подготовить. Может как-нибудь напишу статью с примером на данную тему.

Итак, распределим нагрузку между двумя бэкендами с Apache. Вот конфигурация виртуального хоста в этом случае.

upstream backend { server 192.168.0.10:8080; server 192.168.0.11:8080;
}
server { listen 80; server_name example.com www.example.com; access_log /var/log/nginx/example.com.access.log main; location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff|woff2|swf|ttf|svg|html|txt)$ { root /var/www/example.com/public; expires 1y;
} location / { proxy_pass http://backend/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 120; proxy_send_timeout 120; proxy_read_timeout 180; }
}

В данном примере балансировки нагрузки, nginx отдает всю статику, а 2 сервера с apache обрабатывают все остальные запросы.

Настройка редиректов и rewrite правил

Rewrite это то, что в первую очередь не позволяет отказаться от Apache. Многие проекты имеют массу rewrite правил в .htaccess, который поддерживает apache. Перенос этих правил в nginx не всегда прост и очевиден. Есть средства по автоматической конвертации правил rewrite из формата apache в формат nginx, но они далеко не всегда помогают. Пример такого сервиса — https://winginx.com/ru/htaccess. В идеале, такую конвертацию следует проделывать вручную, подключая голову 🙂

Это что касается конвертации правил из апача. А в целом rewrite правила в nginx это очень мощный инструмент. Вот несколько примеров правил.

С помощью rewrite можно отрезать у доменных имен www. Лично я считаю эту добавку к адресу сайта ненужным рудиментом и отрезаю на своих сайтах. Пример правила rewrite для замены www на запрос без него.

server { listen 443 ssl http2; server_name www.example.com; rewrite ^ https://example.com$request_uri permanent;
}

Это правило rewrite все запросы к домену с www переадресовывает на запрос без www. Тут это просто пример работы механизма. В данном конкретном случае, редирект www лучше сделать с помощью return. Это более элегантное и быстрое решение, так как не придется обрабатывать лишнюю регулярку. На практике конкретно с www лучше поступить вот так:

server { listen 443 ssl http2; server_name www.example.com; return 301 $scheme://example.com$request_uri;
}

Синтаксис rewrite запросов выглядит следующим образом:

rewrite regex URL [flag];

В моем примере получаем следующие элементы правила:

  • ^ — регулярное выражение;
  • https://example.com$request_uri — url, на который заменяем;
  • permanent — флаг, который возвращает постоянное перенаправление с кодом 301.

Вот еще один пример, который я уже приводил в разделе про location. Я настраиваю замену страниц с /amp/ на конце на обычный url без /amp/. То есть просто его обрезаю.

location ~ /amp/$ {
rewrite ^(.*/)amp/$ $1 permanent;
}

Полезным является еще одно правило rewrite, которое к ссылкам в конце без слеша добавляет слеш. То есть заменяет ссылку вида http://example.com/page на http://example.com/page/

rewrite ^([^.]*[^/])$ $1/ permanent;

Много видел в сети примеров, где rewrite используют для перенаправления запросов с http на https. Как и в случае с заменой www, так лучше не делать. Тем более не стоит это делать через условия if, например вот так:

if ($scheme = "http") {
rewrite ^ https://example.com$uri permanent;
}

Это рабочий вариант, но в данном случае return вместо rewrite будет работать более эффективно, затрачивая меньше ресурсов web сервера. То же самое относится к примерам, где требуется замена имени домена в случае переезда. Вместо rewrite лучше использовать return. То есть делать не вот так:

server { listen 80; server_name old-name.com; rewrite ^ $scheme://new-name.com$request_uri permanent;
}
return 301 $scheme://new-name.com;

Такой редирект с одного домена на другой быстрее работает.

Принципиальная разница между rewrite и return в том, что в rewrite переписывается только та часть исходного URL, которая соответствует регулярному выражению, а в return весь URL-адрес переписывается на указанный URL-адрес. Из этой особенности следует то, что return работает быстрее rewrite, поэтому там, где можно использовать return, лучше использовать именно его. Условно, return следует использовать там, где требуется постоянная замена адреса, а rewrite где требуется временное изменение запроса в силу каких-то обстоятельств.

Вот пример, где без rewrite не обойтись. Допустим, у вас есть какой-то обработчик запросов, которому нужно передавать различные урлы в определенном формате. К примеру, пользователи запрашивают урл http://example.com/linux/ubuntu, а нам надо его преобразовать в такой — http://example.com/linux.php?distro=ubuntu. Делаем это с помощью следующего правила rewrite.

rewrite ^/linux/(.*)$ /linux.php?distro=$1 last;

Еще пример, как сделать постоянное перенаправление с одной страницы на другую. Как обычно, можно сделать двумя способами, с помощью rewrite или return. Более правильно использовать return. Меняем адрес http://example.com/linux/ubuntu/ на http://example.com/windows/win10/

location = /linux/ubuntu/ {
return 301 /windows/win10/;
}

Вот нежелательный вариант, который тем не менее постоянно рекомендуют в разных статьях. Ошибки тут нет, но с return более правильно.

location = /linux/ubuntu/ {
rewrite ^/linux/ubuntu/$ /windows/win10/ permanent;
}

Фух, надеюсь с return и rewrite более ли менее понятно объяснил. Есть еще для перенаправлений try_files. Я немного плаваю в этой теме, поэтому решил не добавлять эти правила, чтобы вас не запутать и не наговорить неправды. К примеру, вопрос со слешами на конце урла в wordpress можно решить с помощью try_files таким образом:

try_files $uri $uri/ /index.php?$args;

Проверяется запрос со слешом, потом без него, если ничего не найдено, запрос уходит на index.php с параметрами. То есть не важно, что наберет пользователь, у него в любом случае будет открыта та или иная страница. Более подробно о различных правилах перенаправления можно почитать в этой англоязычной статье. Это наиболее полная информация по данной теме, что мне нагуглилась.

Оцените статью
Хостинги