Search code examples
nginxnext.js

how to serve a specific page for each domain name pointing to my nextjs app using nginx


i couldn't redirect domain names to a specific page in my nextjs app using nginx.

i have a nextjs app running on localhost:3000 i used nginx for domain names redirection when i point a domain name to '/' everything works fine, but when i point a domain to '/demo' i get errors in the console indicating that static files couldn't load ! the idea that i got is to associate a domain name to each dynamic page created under '/[user-website-name]' to achieve a multi sites solution. how can i achieve this using nginx or should i modify the next.config.js file ?

my nginx conf


worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # HTTPS servers
    server {
       listen       443 ssl;
       server_name  domain.com www.domain.com;

       ssl_certificate      www.domain.com.crt;
       ssl_certificate_key  www.domain.com_key.txt;

       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;

       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;

        location / {
            proxy_pass http://localhost:3000;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection 'upgrade';

            proxy_set_header Host $host;

            proxy_cache_bypass $http_upgrade;
        }
    }

    server {
       listen       443 ssl;
       server_name  domain.com www.domain.com;

       ssl_certificate      www.user-created-domain.com.crt;
       ssl_certificate_key  www.user-created-domain.com_key.txt;

       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;

       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;

        location / {
            proxy_pass http://localhost:3000/user-created-website-name;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection 'upgrade';

            proxy_set_header Host $host;

            proxy_cache_bypass $http_upgrade;
        }
    }
}

next.config.js

const path = require("path");
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  sassOptions: {
    includePaths: [path.join(__dirname, "styles")],
  },
};

module.exports = nextConfig;


Solution

  • I solved the problem in the following steps. first all domain names should point to root:

    # HTTPS servers
    server {
       listen       443 ssl;
       server_name  domain.com www.domain.com;
    
       ssl_certificate      www.domain.com.crt;
       ssl_certificate_key  www.domain.com_key.txt;
    
       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;
    
       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;
    
        location / {
            proxy_pass http://localhost:3000;
    
            proxy_http_version 1.1;
    
            proxy_set_header Upgrade $http_upgrade;
    
            proxy_set_header Connection 'upgrade';
    
            proxy_set_header Host $host;
    
            proxy_cache_bypass $http_upgrade;
        }
    }
    
    server {
       listen       443 ssl;
       server_name  user-created-domain.com www.user-created-domain.com;
    
       ssl_certificate      www.user-created-domain.com.crt;
       ssl_certificate_key  www.user-created-domain.com_key.txt;
    
       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;
    
       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;
    
        location / {
            proxy_pass http://localhost:3000;
    
            proxy_http_version 1.1;
    
            proxy_set_header Upgrade $http_upgrade;
    
            proxy_set_header Connection 'upgrade';
    
            proxy_set_header Host $host;
    
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    Then we should use nextjs middleware and create middleware.js file in root of nextjs application.

    import { NextResponse } from "next/server";
    
    export async function middleware(request) {
      const { pathname } = request.nextUrl;
      const hostname = request.headers.get("host");
    
      const url = new URL(request.url);
      const domainsJsonUrl = `${url.origin}/domainNames/domainNames.json`;
    
      let basePath = "";
    
      // READ DOMAIN NAME FILE
      const domains = await (await fetch(domainsJsonUrl)).json();
    
      // DOMAIN NAMES SECTION
      domains.forEach((_) => {
        if (hostname === _.domain || hostname === `www.${_.domain}`) {
          basePath = `/${_.shop}`;
        }
      });
    
      // URL REWRITE SECTION
      if (basePath && !pathname.startsWith(basePath)) {
        const newurl = new URL(`${basePath}${pathname}`, request.url);
        return NextResponse.rewrite(newurl);
      }
    
      return NextResponse.next();
    }
    
    export const config = {
      matcher: [
        "/((?!api|_next/static|_next/image|favicon.ico|images|manifests).*)",
      ],
    };

    so the idea that the middleware runs and checks if the host name is one of the domains that we want to redirect and then rewrite the url with new basepath so the result is transform this "www.domain.com/variant/home" to "www.domain.com/home", it is like hiding the "variant" level in the url.