In this tutorial, we’ll take a look at 301 redirects for NGINX and Apache web servers.


Method No. 1 is a line:

server {
rewrite ^ https://$host$request_uri? <flag>

Here the $host – variable is the host from the requests. If it is absent, you should use the header name in the “Host” field, if it is not there, the server name will do.

The $request_uri – variable is the initial request with arguments.

When configuring, the following flags (<flag>) can be selected:

  • permanent – 301 redirect (or permanent redirect) to a page with a 301 server response code.
  • redirect – a 302 redirect (or temporary redirect) to a page with a 302 code.
  • last – completion of processing and subsequent transition to a new location.
  • break – completion of processing and work in the current location.

Method No. 2

return <code> https://$host$request_uri;

Any redirect code can be used here, however, the most common cases are 301, 302, 404.

After finishing editing the files, it remains to check if they are correct:

nginx -t

To apply them, you need to restart Nginx:

systemctl restart nginx
Practical examples of redirects
Redirect from www to without www

This is the most common redirect and allows all traffic to be directed directly to the domain, bypassing subdomains. Redirect code:

# www.domen -> domen
server {
server_name www.[domain];
return 301 $scheme://[domain]$request_uri;

If you want to get the opposite effect (redirect to “www” without www”):

server {
server_name [domain];
return 301 $scheme://www.[domain]$request_uri;
Redirect to another domain

To organize a redirect to another site – for example, after changing the site address – you can use the command:

location / {
rewrite ^(.*)$ $scheme://$1 redirect;

The second option is simpler:

location / {
return 301 $scheme://$http_host$request_uri;
Redirect from http to https

You can set up a redirect from HTTP to HTTPS (SSL secure protocol) as follows:

server {
listen 80;
return 301 https://$host$request_uri;

Here, for all requests to via the HTTP protocol, a redirect to port 443 will be triggered using a 301 redirect to merge domains.

To set up a redirect to HTTP from HTTPS, just change the server response code:

server {
listen 443;
return 301 http://$host$request_uri;
Redirect to another server

If necessary, redirect all requests to another server:

location / {
proxy_pass $scheme://;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Here, the Nginx web server is responsible for accepting and responding to browser requests. They are processed by the server with the IP address (port 8080). Redirecting to another Nginx is done in the same way.

Redirect from IP address to domain
server {
listen 80;
return 301$request_uri;
Redirect multiple domains to one directory and one main domain

This trick comes in handy when you have multiple domains. Let’s take the following domains as an example:

All of these domains point to the same directory on the server. Accordingly, they display the same page/content, albeit when entering different addresses.

Do not forget about the exception of the 404 error (“page not found”), which may occur if someone uses a link to a product/page from one of the alternative domains. You can solve this problem in the following way:

server {
rewrite ^$request_uri? permanent;

Thus, all alternative addresses other than “.net” will be directed to “”, which is the primary address.


All rules are executed in the direct order in which they appear in the .htaccess file, and a rule written later will be executed later.

.htaccess is an additional configuration file for the Apache webserver that can be used to configure settings at the level of individual directories. Unlike the main configuration file httpd.conf, directives in .htaccess apply only to the directory where it is located and to child directories.

Below are the most commonly used rules for configuring the .htaccess file for a 301 redirect. It is better to place all rules after two lines:

Options +FollowSymLinks
RewriteEngine On
Domain redirect from WWW to a without WWW domain
RewriteCond %{HTTP_HOST} ^http://www.example\.com$ [NC]
RewriteRule ^(.*)$$1[R=301,L]
Standard redirect from one static page to another
Redirect 301 /was.php
Configuring redirects from HTTP to HTTPS (for all pages)
RewriteCond %{SERVER_PORT} ^80$ [OR]
RewriteCond %{HTTP} =on
RewriteRule ^(.*)$$1 [R=301,L]
301-redirect from domain to domain
RewriteCond %{HTTP_HOST} ^old-site\.com$ [NC]
RewriteRule ^(.*)$$1 [R=301,L]
Specifying the path to the 404 error file using .htaccess

Note, it is important that the server response code for a 404 error is exactly 404. The path to the file is indicated using the following line:

ErrorDocument 404 /404-for-me.php
The reminder on the symbols and designation used.

The RewriteCond line is a condition for executing the RewriteRule. If the condition is met, then the redirect is triggered. Rules can be specified using regular expressions.

Special characters used in rules and their meanings.

^ – the special character of the beginning of a line;
$ – end of line special character;
! – special negation character;
… – point, replaces any character, but only one;
() – grouping;
\ – “escape” slash, the next character after it is considered a normal, not a special character;
# – the beginning of a text comment in the file.

Modifiers are used after ordinary, special characters or their groups and allow you to expand the capabilities of templates for triggering rules.

? – the character is repeated 0 or 1 times.
+ – repeats from 1 to 65536 times.
* – repeats from 0 to 65536 times.

Flags set additional options for the used rule. Listed in square brackets, separated by commas, say [NC] or [R = 301, L].

NC – NoCase flag that disables case checking when the rule is triggered.
R – the Redirect flag, performs the process of stopping the URL change and returns the result. The most commonly used value is R = 301, but others are possible for temporary redirects (302, MOVED TEMPORARY).
L – Last flag, stops URL generation and the string is considered final.