Multi-Domain: Hosting a Vue Frontend and Laravel Backend with Nginx

Copy link

Updating the Package List in Ubuntu

Before installing any new software, it's essential to update the package list to ensure you get the latest available versions. Open a terminal and run the following command:

sudo apt update 

This command fetches the latest package information from the configured repositories, ensuring that your system is aware of the newest updates and available software versions.After updating, you can proceed with installing new software packages with confidence.

To install Nginx on Ubuntu, follow these steps: 

Install Nginx

Once the package list is updated, install Nginx using the following command:

sudo apt install nginx 

This command downloads and installs Nginx along with its necessary dependencies.

Start and Enable Nginx 

After installation, start the Nginx service to begin serving web pages

sudo systemctl start nginx  

To ensure that Nginx starts automatically on system boot, enable it using:

sudo systemctl enable nginx 

Check Nginx Status 

To confirm that Nginx is running without issues, check its status:

sudo systemctl status nginx 

If the installation was successful, you should see an output indicating that the service is active and running.

Verify Installation 

To verify that Nginx is correctly installed and running, open a web browser and visit:

http://your-server-ip

Replace your-server-ip with your actual server's IP address. If Nginx is working correctly, you will see the default "Welcome to Nginx" page.

Installing and Verifying PHP 8.3 with PHP-FPM on Ubuntu

Install PHP 8.3 and PHP-FPM

To install PHP 8.3 and PHP-FPM (FastCGI Process Manager), run the following command:

sudo apt install php8.3 php8.3-fpm
  • php8.3 → Installs PHP 8.3, which is required for running PHP applications.
  • php8.3-fpm → Installs PHP-FPM, which is needed for handling PHP requests in an efficient way, especially when using Nginx as the web server.

Verify PHP Installation

To check if PHP 8.3 is installed correctly, run:

php –v

This will output something like:

PHP 8.3.x (cli) (built: Jan 24 2025 14:35:20) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.3.0, Copyright (c) Zend Technologies

This confirms that PHP 8.3 is installed and working.

Start and Enable PHP-FPM

After installation, PHP-FPM might not start automatically. To manually start it, run:

sudo systemctl start php8.3-fpm

To ensure PHP-FPM starts automatically on system boot, enable it with:

sudo systemctl enable php8.3-fpm

This ensures that PHP-FPM runs automatically after every reboot.

Check PHP-FPM Status

To verify that PHP-FPM is running correctly, use:

sudo systemctl status php8.3-fpm

You should see output similar to:

● php8.3-fpm.service - The PHP 8.3 FastCGI Process Manager
   Loaded: loaded (/lib/systemd/system/php8.3-fpm.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2025-02-04 12:15:34 UTC; 2min ago

If the status shows active (running), it means PHP-FPM is successfully running and ready to handle PHP requests.

Creating and Activating a New Nginx Server Block

Copy the Default Server Block

Run the following command to duplicate the default configuration file:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com

If you have two domains, you need to copy the default Nginx configuration file twice, creating separate server block files for each domain. This ensures that each domain has its own unique configuration and root directory.

Each copied file must be edited to specify the correct server_name and logging paths for the respective domain.

Edit the New Server Block

Open the new file for editing:

sudo nano /etc/nginx/sites-available/example.com

Updated Server Block

In an Nginx configuration, the server block is responsible for handling requests and routing them to the appropriate content. When you have a server block that needs to handle an API and static content (e.g., Vue.js frontend), it will include a mix of configurations for both.

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/html/vue-frontend;
    index index.html;

    # Log files for access and errors
    access_log /var/log/nginx/example.com_access.log;
    error_log /var/log/nginx/example.com_error.log;

    location /api/ {
        root /var/www/html/larvel-backend/public;
        fastcgi_param HTTP_CLIENT_KEY $http_client_key;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;  # Ensure this matches your PHP version
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root/index.php;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param HTTP_CLIENT_KEY "HOYO_TECH";
    }

    # Serve Vue static files correctly
    location / {
        include /etc/nginx/mime.types;
        add_header Last-Modified $date_gmt;
        add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
        if_modified_since off;
        expires off;
        etag off;
        try_files $uri $uri/ /index.html;
    }

    # Handle 404 errors by redirecting to Vue index.html (for history mode)
    error_page 404 /index.html;
}

Explanation of Key Parts of the Server Block:

1. listen Directive

listen 80;
  • Purpose: This directive tells Nginx to listen for incoming HTTP requests on port 80, the default port for HTTP traffic.
  • Explanation: When a client (like a browser) makes a request to a server, this listen directive specifies the port Nginx will listen to for that request. Port 80 is the standard for unsecured HTTP traffic, and Nginx will respond to requests that come in on this port.

2. API Block (location /api/)

location /api/ {
    root /var/www/html/larvel-backend/public;
    fastcgi_param HTTP_CLIENT_KEY $http_client_key;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;  # Ensure this matches your PHP version
    fastcgi_index index.php;

    fastcgi_param SCRIPT_FILENAME $realpath_root/index.php;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
    fastcgi_param DOCUMENT_ROOT $realpath_root;
    fastcgi_param HTTP_CLIENT_KEY "HOYO_TECH";
}
  • Purpose: This block handles requests that start with /api/ and passes them to PHP-FPM for processing (typically for an API backend written in PHP, like Laravel or another CMS).
  • Explanation:
    • 1. location /api/: This means any request that begins with /api/ will be routed to this block. For example, requests to example.com/api/users would be routed here.
    • 2. root /var/www/html/larvel-backend/public;: Sets the base directory for the API
    • 3. fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;: This passes the request to PHP-FPM via a Unix socket. PHP-FPM is used to process PHP scripts. Ensure the version of PHP-FPM matches the installed version (e.g., php8.3-fpm.sock).
    • 4. fastcgi_param directives: These set up parameters needed for PHP to process the request, such as the script file to execute (SCRIPT_FILENAME), the request method (REQUEST_METHOD), and custom headers like HTTP_CLIENT_KEY. These ensure that PHP handles the request properly.
    • 5. The value of HTTP_CLIENT_KEY is different for each domain (i.e., each server block), so it allows the backend to serve different data based on the key.
    • 6. The HTTP_CLIENT_KEY header is set uniquely for each server block (domain).

3. Vue Static Files Block (location /)

location / {
    include /etc/nginx/mime.types;
    add_header Last-Modified $date_gmt;
    add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
    if_modified_since off;
    expires off;
    etag off;
    try_files $uri $uri/ /index.html;
}
  • Purpose: This block serves the static files for the Vue.js frontend application, which includes HTML, JavaScript, CSS, etc. It also ensures that the Vue app works correctly with client-side routing (such as when using Vue Router in history mode).
  • Explanation
    • 1. location /: This block matches requests to the root and any subdirectories that do not match the /api/ path (i.e., requests for static assets or frontend pages).
    • 2.try_files $uri $uri/ /index.html;: This directive tells Nginx to try to serve the requested file ($uri) first. If it doesn't exist, it tries the directory ($uri/). If neither exists, it serves the index.html file. This ensures that Vue's client-side routing works, and any route that doesn’t match a file is routed to index.html for Vue to handle.
    • 3. add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';: Disables caching for the frontend assets, ensuring that the latest versions of files are served during development.
    • 4. expires off; etag off;: These further prevent caching of the static files.
    • 5. include /etc/nginx/mime.types;: This includes MIME type definitions to ensure that Nginx serves the correct content types for various static assets (like .js, .css, etc.).

Enable the New Server Block

Create a symbolic link to activate the site:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Test the Configuration

Check for syntax errors:

sudo nginx -t

If successful, restart Nginx:

sudo systemctl restart nginx

Test in a Browser

Visit:

http://example.com

Your new Nginx block is now active!

In Summary:

This configuration is meant for a multi-domain setup where:

  • Each domain (example.com and another-domain.com) can have its own custom behavior for API requests.
  • The backend can differentiate between requests from the different domains based on the injected HTTP_CLIENT_KEY header, allowing for tailored responses or data.
  • It also serves the same Vue.js frontend (static files) for both domains but handles API requests differently based on the domain-specific HTTP_CLIENT_KEY.

 

Avatar

Milosh Stankovikj

iOS Developer

Feb 06, 2025