Skip to content

How to Deploy a Next.js App on Laravel Forge: Step-by-Step Guide

Prerequisites

  • Familiarity with Laravel Forge.
  • A server up and running in Laravel Forge.
  • A repository on Github (public or private).
  • A Github account linked to Laravel Forge.

Make the repository you'd like to push to Forge available in Github

The repository must be in Github, since it is the way Laravel Forge imports the code. In this example, we'll use chatbot-ui as the example repository to use. In my case, I already forked the repository, so it is available in my account.

Setting the Nginx Template

In Forge, we'll enter our server, and choose the Nginx Templates entry.

In the Name field, we can use any name, but I'll call it NextJs App.

In the Content code box, we'll paste the following template:

# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/{{ SITE }}/before/*;

server {
    listen {{ PORT }};
    listen {{ PORT_V6 }};
    server_name {{ DOMAINS }};
    server_tokens off;
    root {{ PATH }};

    # FORGE SSL (DO NOT REMOVE!)
    # ssl_certificate;
    # ssl_certificate_key;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm;

    charset utf-8;

    # FORGE CONFIG (DO NOT REMOVE!)
    include forge-conf/{{ SITE }}/server/*;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache off;
        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-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/{{ SITE }}-error.log error;

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/{{ SITE }}/after/*;

And then, click on the Create button.

WARNING

Remember to update the proxy_pass port number if your application runs in a port different than 3000.

Setting up the NextJs Application

In the Sites entry, we'll click on New Site, and then click the Advanced button next to the Add Site button.

  1. In the Root Domain we need to set up the domain that the application will use. In this example, I use, chat.nexlab.cloud .
  2. In Project Type, select Static HTML / Nuxt.js / Next.js.
  3. The Aliases field is optional, and should be filled if you have other URLs you'd like to use to access your application.
  4. Web Directoty can be left at /.
  5. Since the project I am using does not use a local database, I'll leave PHP Version in the default value.
  6. In the Nginx Template, choose the template you created before, in my case, the one named NextJs App .

The rest of the options can be left in their default values. Click the Add Site button.

After a brief message saying "Your site is being installed...", you'll get the following screen:

Here, we'll select Git Repository. In the Repository field we'll write the user + repository name of the repository we'll use. For this example is quezadaesteban/chatbot-ui. Laravel Forge will automatically select the branch, but make sure the selected branch is the one you'd like to use.

Assuming you already have an SSH key in your Github account, you don't need to enable the Generate Deploy Key toggle.

Click Install Repository.

Configuring the Application

Inside our new application in Forge, we'll navigate to the Deployment entry.

We'll replace the Deployment Script code with the following code:

cd /home/forge/chat.nexlab.cloud
git pull origin $FORGE_SITE_BRANCH

npm install
npm run build

WARNING

Note that you should replace the /home/forge/{domain} with your own domain.

This change ensures that when hitting the deploy button, dependencies are installed and the project is built.

Now we'll set up the environment variables for our application, in the Environment entry, there's an .env file you can modify with the variables you'd like your app to have available. In my case, since I am setting up a fork of chatbot-ui. I need to set three environment variables:

NEXT_PUBLIC_SUPABASE_ANON_KEY={{ value }}
NEXT_PUBLIC_SUPABASE_URL={{ value }}
SUPABASE_SERVICE_ROLE_KEY={{ value }}

Remember to replace the values with your environment variables and values. Then, we click Save.

WARNING

Depending on your application requirements, you may need to ssh into your server to install the correct NodeJs version (or other dependencies). I recommend using NVM for managing NodeJs versions.

To find out if your server has all the dependencies required to run your NextJs application, navigate to the Deployments entry and click Deploy Now.

Keep an eye on the Live Deployment Output to check if everything is doing alright.

Setup daemon

In the server root, in the Daemons entry, let's create a new daemon that will run the application.

  1. In Command let's set: npm run start.
  2. In Directory, set the app's directory, in my case /home/forge/chat.nexlab.cloud.

The rest of the settings can be left as is. Click on Create. Once created, it should show in the Active Daemons list with the Active status.

Set up the domain

Since we are using, in this case, chat.nexlab.cloud as the domain for the application, we need to create an A record in our domain manager with both chat pointing to the server IP address. If you are using a top level domain, like example.com. You must create two A records, one for @ and one for www in order to Let's Encrypt to work properly.

WARNING

This step is key to be able to use the application, since Nginx uses the incoming domain as a reference to route the content to the right application. Navigating to the IP won't work.

If the domain is properly set up, you should be able to navigate to it (with HTTP, not HTTPS) and see your application up and running.

Setting up Let's Encrypt

Once, the domain is active and the site is visible, go to the site's settings and into the SSL entry. There. select Let's Encrypt and click Obtain Certificate.

It should take a few minutes for the certificate to be issued.

Once installed, it should show under the Current Certificates list with a status of Active .

Now you should be able to access your domain using HTTPS.

TIP

There are different ways to debug possible issues in your app.

  1. Keep an eye on the deployment script to ensure everything is installed correctly.
  2. Ensure the port in the nginx template matches the port that your application runs on.
  3. Keep an eye on the daemon log to ensure the app is running successfully.
  4. Remember to set up the domain in your domain manager so that you can access the app.

WARNING

Since the daemon is configured at the server level and not at the application level, you must manually restart the daemon after deploying with the Deploy Now button, to ensure the app runs on the latest build.