Nginx rewrite URL examples with and without redirect address

Written by - 6 comments

Published on - last updated on February 21st 2022 - Listed in Nginx Internet Linux Unix


Nginx can handle the rewrite parameter differently, depending on the destination syntax. 

Here are some examples how to define redirects and URL rewrites in Nginx.

Basic redirect (302 Moved Temporarily)

The simplest form to create a redirect is to append the rewrite URL with the keyword "redirect":

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        rewrite ^/$ http://websrv1.example.com/mypage redirect;
    }
}

This will result in a HTTP 302 Moved Temporarily redirect. In a browser, the URL in the address bar will change to the forwarded URL.

Permanent redirect (301 Moved Permanently)

The 302 status above is a helpful fix for a quick redirect - but not optimized for SEO. If you create a definitive redirect, you should set the permanent keyword at the end of the rewrite config:

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        rewrite ^/$ http://websrv1.example.com/mypage permanent;
    }
}

This results in a HTTP 301 Moved Permanently status. A user will see the same experience in the browser as with the 302 redirect: The URL in the address bar will change and show the redirect destination URL. 

Using last or break as keyword

Let's try this without a redirect or permanent option but with break or last:

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        rewrite ^/$ http://websrv1.example.com/mypage last;
    }
}

Although the rewrite option is now set to last, the browser will still follow the URL and changes the URL in the address bar. As soon as the rewrite destination contains http:// (or https://), this is considered an external redirect and will therefore always redirect the client (and browser).

Internal address rewrite (without redirect)

So if you want to keep your requested URL in the browser address bar and simply want to rewrite the URL (same as with mod_rewrite in an Apache web server), you must use a relative path:

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        rewrite ^/$ /mypage last;
    }
}

This will load the website for www.example.com from the subfolder /mypage within the document root (/var/www/www.example.com). 

Internal address rewrite as reverse proxy

But what if the destination website is loaded from somewhere else, for example from a Tomcat upstream server in the background? The following configuration covers this:

upstream tomcat {
    server 127.0.0.1:8080;
}

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        include proxy-settings.conf;
        proxy_pass http://tomcat;
        rewrite ^/$ /mypage last;
    }
}

First everything (location /) is passed to tomcat (the defined upstream server). Then the redirect for the root path (/) is happening and is relative to the path.
This results in keeping the browser's address URL at www.example.com but loads the website from 127.0.0.1:8080/mypage.

Internal address rewrite with dynamic path

Sometimes you may want to change the internal path, but still use (some parts of) the requested URI. You can use this by creating a selection using parentheses "()" and then refer to the selection with $1 for the first selection, $2 for the second selection and so on.

upstream tomcat {
    server 127.0.0.1:8080;
}

server {
    server_name www.example.com;
    root /var/www/www.example.com;

    location / {
        include proxy-settings.conf;
        proxy_pass http://tomcat;
        rewrite ^/(.*)$ /mypage/$1 last;
    }
}

If the original requested URL was http://www.example.com/hello-my-world, it would actually load the following URL from the upstream server: http://127.0.0.1:8080/mypage/hello-my-world.

How to verify the internal URI rewrite

Some address rewrites are very basic - but others might be much more complex. To verify how your rewritten request URI looks like, you can play with internal Nginx variables and show them as response headers. The following configurations shows the additional headers Requested-URI and Final-URI which will be part of the Nginx server response:

upstream tomcat {
    server 127.0.0.1:8080;
}

server {
  server_name www.example.com;
  root /var/www/www.example.com;

  location / {
    include proxy-settings.conf;
    proxy_pass http://tomcat;
    rewrite ^/(.*)$ /mypage/$1 break;
    add_header Requested-URI $request_uri always;
    add_header Final-URI $uri always;

  }
}

You can see these headers when using curl and looking at the response headers:

$ curl http://www.example.com/hello-my-world -I
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 21 Feb 2022 13:00:36 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Requested-URI: /hello-my-world
Final-URI: /mypage/hello-my-world


Add a comment

Show form to leave a comment

Comments (newest first)

Claudio Kuenzler from Switzerland wrote on Jan 25th, 2021:

Markus, no, including a proxy settings file is not required. However you might want to use some proxy settings such as X-Forwarded-Proto or X-Forwarded-For headers. You can of course also write these settings (using proxy_set_header) or other settings (such as proxy_redirect) directly in the location context.


Markus Kugler from wrote on Jan 24th, 2021:

Thanks Claudio Kuenzler!

what is proxy-settings.conf for? Do I need it?


Claudio Kuenzler from Switzerland wrote on Jan 23rd, 2021:

Hi Markus! In this case you should redirect your root location to "/this/is/important/" and the path "/this/is/important/" is proxying to the external domain.


server {
server_name sub1.domain.com;
root /var/www/sub1.domain.com;

location / {
rewrite ^.* https://sub1.domain.com/this/is/important/ permanent;
}

location /this/is/important/ {
include proxy-settings.conf;
proxy_pass https://some-other-domain.com;
}
}


Markus from wrote on Jan 22nd, 2021:

Hi *
great tutorial thanks!
What if I want to rewrite from https://sub1.domain.com/ to physically https://some-other-domain.com/this/is/important/link.html but the browser should show https://sub1.domain.com/this/is/important/link.html
in other words some-other-domain.com needs to be hidden from the public AND url should be redirected from / to /this/is/important/link.html

thanks
Markus


ck from St. Gallen, Switzerland wrote on Apr 8th, 2015:

Hi U-lis. It worked fine in my testing environment but now I do not have access to this environment from back then anymore. But what is also possible is that your application itself (mypage) is automatically causing the redirect, not nginx. You can try with the setting "proxy_redirect off" and do the debugging with curl -v, following all the redirects manually to find out where the redirect happens.


U-lis from wrote on Mar 27th, 2015:

Hello, I have a question!

I tried your last server config to show example.com on address bar and load page from 127.0.0.1:8000/mypage.

But I got example.com/mypage on my addressbar with correct page I wanted.

Is Nginx config changed or my mistake?

I need your help. Thanks for your article.

== following is my nginx config, and I use python(gunicorn) webserver ==

upstream main { 127.0.0.1:8000 }
server {
listen 80;
server_name example.com;

location / {
include proxy_params;
proxy_pass http://main;
rewrite ^/$ /mypage last;
}
}


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   OpenSearch   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder