I'm serving a webservice (API + Webiste) through nginx and its canonical domain name changed recently. The API is split from the user-facing website by subdirectories (eg /api/ and /download/ are part of the API, the rest belongs to the website).

I'd now like to redirect the website-part to the new domainname but serve the API requests without redirects (to keep server load down).

Because the webserver can be accessed through a number of domains, I'd need to redirect everything that doesn't match the new canonical one; something like

IF request-domain != new-domain
 AND resource not in (/api/, /download/):
   redirect to new domain

   # serve site
   proxy_pass   http://app_server;

I didn't find a way suitable way in nginx to do the (double) negative comparison, and I can't invert them to a positive comparison, because both alternative domain names and non-API resources are quite a lot that I don't want to maintain in the nginx config.

Any ideas would be highly appreciated!


In nginx, you generally don't want to use if for changing behavior based on Host header or uri. You need a second server:

server {
  # Make sure this listen matches the one in the second server (minus default flag)
  listen 80;

  server_name new-domain;

  # All your normal processing.  Is it just proxy_pass?
  location / {
    proxy_pass http://app_server;

server {
  # If you listen on a specific ip, make sure you put it in the listen here
  # default means it'll catch anything that doesn't match a defined server name
  listen 80 default;

  server_name old-domain; # and everything else, but it's good to define something

  # Everything that doesn't match /api/ or /download/
  location / {
    rewrite ^ http://new-domain$request_uri? permanent;

  # You may want some common proxy_set_header lines here in the server
  # if you need them

  location /api/ {
    proxy_pass http://app_server;

  location /download/ {
    proxy_pass http://app_server;

Nginx doesn't allow multiple or nested if statements but you can set variables, something like this:

    server_name _;

    if ($http_host !~ new-domain) {
        set $var D;
    if ($request_uri !~ (/api|/download)) {
        set $var "${var}U";
    if ($var = DU) {
        rewrite ^(.*)$ http://new-domain$request_uri last;

About the else condition, you should do it in a separated virtual host.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.