avatarMai Văn Khánh

Summary

The provided content outlines a detailed guide on configuring NGINX to serve a WordPress backend API, a WordPress CMS, and a Next.js frontend web application on a single AWS EC2 instance, with the setup being adaptable for multiple use cases.

Abstract

The article addresses a specific problem of hosting a WordPress-powered website with a dedicated Next.js frontend application, while utilizing NGINX as a reverse proxy to manage domain configurations and SSL certificates on an AWS EC2 instance. The author provides a step-by-step tutorial, starting with prerequisites such as owning a domain name and a wildcard SSL certificate, and then delving into the NGINX configuration process. This includes setting up server blocks to force HTTPS, redirect domains, and proxy requests to the appropriate local ports where the WordPress backend, CMS, and Next.js frontend are running. The guide emphasizes the importance of backing up configuration files before making changes and concludes with instructions for reloading and restarting NGINX to apply the new settings. The author aims to offer a comprehensive understanding that can be applied to various other scenarios beyond the described setup.

Opinions

  • The author believes that readers should have a basic understanding of SSH and Ubuntu commands or be willing to consult documentation.
  • There is an emphasis on the flexibility of the described NGINX configuration, suggesting its applicability to a range of use cases beyond the specific example.
  • The author encourages the use of NGINX as a reverse proxy server for handling complex server configurations involving multiple services.
  • The use of a wildcard SSL certificate for the domain is recommended for simplicity and effectiveness in securing subdomains.
  • The author provides the full NGINX configuration at the end, implying that this configuration is robust and can serve as a template for similar setups.
  • By inviting comments for support, the author shows a willingness to assist readers who may encounter issues or have questions about the setup.

Configure NGINX to host both Backend and Frontend servers in one AWS EC2 instance and can be extendable to multiple use cases.

My problem: I want to build a website with Wordpress as the content management system. However, I don’t want to make use of its frontend template, instead, I will expose REST api from Wordpress and have a dedicated Frontend WebApp using Nextjs.

Below is the diagram:

Prerequisites:

  • Basic knowledge of SSH into an EC2 server (or any other VPS) and Ubuntu commands, or ability to read documentation for ubuntu commands.
  • I have a domain name mydomain.com
  • I purchased a wildcard SSL certificate for my domain: *.mydomain.com
  • I already setup SSL for my domain: *.mydomain.com
  • I created manually an AWS EC2 instance.
  • I have a Wordpress backend service to serve REST API at port 8000
  • I also have a Wordpress CMS app running at port 8000
  • I have a frontend app running at port 3001

*Please note that you’re freely to choose the port number.

I choose to use Nginx as a reverse proxy server to configure the domain.

Now, let’s jump into the main objective of this blog post.

Step 0:

  • Navigate to `/etc/nginx/sites-enabled/` and edit default file using sudo vim default
  • Better to backup it first by the command mv default defaultbk

Step 1: Configure Nextjs Frontend webapp at port 3001

we are at this part
#Nextjs FE app: remove www to avoid canonnical issue
server {
       listen 80;
       listen 443 ssl;

       # Certificate
       ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

       # Private Key
       ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;

       server_name http://mydomain.com www.mydomain.com;
       return 301 https://mydomain.com$request_uri;
}

#Nextjs FE app: force ssl for mydomain.com (main domain)
server {
        listen 80;
        server_name http://mydomain.com mydomain.com www.mydomain.com;
        return 301 https://mydomain.com$request_uri;
}

#Nextjs FE app: point main domain (Frontend) to port 3001 of Nextjs
server {
       listen 443 ssl;
       listen [::]:443 ssl;
 
       server_name mydomain.com;
       # Certificate
       ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

       # Private Key
       ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
       location / {
               proxy_pass http://localhost:3001;
               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;
       }
}

Step 2: configure the REST API:

we are at this part
#REST API: force ssl for api.mydomain.com (wordpress backend)
server {
        listen 80;
        server_name api.mydomain.com;
        return 301 https://api.mydomain.com$request_uri;
}

#REST API: point api.mydomain.com to port 8000
server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name api.mydomain.com http://api.mydomain.com;
        # Certificate
        ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

        # Private Key
        ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
        location / {
               proxy_pass http://localhost:8000;
        }
}

Step 3: configure the CMS

we are at this part
#CMS: force ssl for cms.mydomain.com (wordpress cms)
server {
        listen 80;
        server_name cms.mydomain.com http://cms.mydomain.com;
        return 301 https://cms.mydomain.com$request_uri;
}

#CMS: point cms.mydomain.com to port 8000
server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name cms.mydomain.com;
        # Certificate
        ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

        # Private Key
        ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
        location / {
               proxy_pass http://localhost:8000;
               proxy_set_header Host $http_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;
        }
}

Full configuration

#Nextjs FE app: remove www to avoid canonnical issue
server {
       listen 80;
       listen 443 ssl;

       # Certificate
       ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

       # Private Key
       ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;

       server_name http://mydomain.com www.mydomain.com;
       return 301 https://mydomain.com$request_uri;
}

#Nextjs FE app: force ssl for mydomain.com (main domain)
server {
        listen 80;
        server_name http://mydomain.com mydomain.com www.mydomain.com;
        return 301 https://mydomain.com$request_uri;
}

#Nextjs FE app: point main domain (Frontend) to port 3001 of Nextjs
server {
       listen 443 ssl;
       listen [::]:443 ssl;
 
       server_name mydomain.com;
       # Certificate
       ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

       # Private Key
       ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
       location / {
               proxy_pass http://localhost:3001;
               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;
       }
}

#REST API: force ssl for api.mydomain.com (wordpress backend)
server {
        listen 80;
        server_name api.mydomain.com;
        return 301 https://api.mydomain.com$request_uri;
}

#REST API: point api.mydomain.com to port 8000
server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name api.mydomain.com http://api.mydomain.com;
        # Certificate
        ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

        # Private Key
        ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
        location / {
               proxy_pass http://localhost:8000;
        }
}

#CMS: force ssl for cms.mydomain.com (wordpress cms)
server {
        listen 80;
        server_name cms.mydomain.com http://cms.mydomain.com;
        return 301 https://cms.mydomain.com$request_uri;
}

#CMS: point cms.mydomain.com to port 8000
server {
        listen 443 ssl;
        listen [::]:443 ssl;

        server_name cms.mydomain.com;
        # Certificate
        ssl_certificate /etc/nginx/ssl/STAR_mydomain.crt;

        # Private Key
        ssl_certificate_key /etc/nginx/ssl/STAR_mydomain.key;
        location / {
               proxy_pass http://localhost:8000;
               proxy_set_header Host $http_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;
        }
}

Last step:

  • Reload and restart Nginx with sudo systemctl reload nginx and sudo systemctl restart nginx

I hope this helps not only by the configuration but the overall understand for your own use cases.

Please leave the comment if you need any support.

Nginx
Ubuntu
Ec2
WordPress
Nextjs
Recommended from ReadMedium