Deploy Laravel Project with Nginx on Linux 3 Easy Steps

Deploy Laravel Project with Nginx Server on Ubuntu or Debian. This blog will show you how to install Laravel with Nginx on Ubuntu/Debian.

I faced an error while deploying Laravel project. The error how to fix index.php because this file is in public folder. Now it is fixed. As we simply add /public for root, e.g. root /home/hassam.dev/public_html/public I shared my Nginx config file. Hope it’ll be definitely helpful to you.

1. Nginx Server Details

Below are my server details, you can follow this tutorial on Ubuntu, PHP7+, and Nginx server.

  • Hetzner.com CPX11 Package [https://www.hetzner.com/cloud]
  • Debian 11
  • 2 Cores AMD Processor
  • 2GB RAM + 1GB Swap RAM
  • Virtualmin (website control panel)
  • Nginx
  • MySQL, MariaDB
  • PHP 8.2

2. Nginx Configuration for Laravel

In localhost, we ran a command php artisan serve to start the project and npm run dev to start Vite server. As we know index.php falls in public folder. To access index.php we need to visit http:hassam.dev/public So, how we can fix it? The solution is using Virtual Host so, it should route the traffic into the public directory inside the project directory.

#hassam.dev.conf

#Before
root /home/hassam.dev/public_html;

#After
root /home/hassam.dev/public_html/public;

I provided a full .conf file below.

#! /bin/bash
sudo nano /etc/nginx/sites-available/domain1.conf

Open up the config file from your terminal with this command sudo nano /etc/nginx/sites-available/hassam.dev.conf and update the code to the following: Replace hassam.dev with your domain name.

server {
    server_name domain1.com www.domain1.com;
    listen 143.190.21X.1XX;
    root /home/domain1/public_html/public;
    index index.php index.htm index.html;
    access_log /var/log/virtualmin/hassam.dev_access_log;
    error_log /var/log/virtualmin/hassam.dev_error_log;
    fastcgi_param GATEWAY_INTERFACE CGI/1.1;
    fastcgi_param SERVER_SOFTWARE nginx;
    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 SCRIPT_FILENAME "/home/hassam.dev/public_html$fastcgi_script_name";
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param DOCUMENT_URI $document_uri;
    fastcgi_param DOCUMENT_ROOT /home/hassam.dev/public_html;
    fastcgi_param SERVER_PROTOCOL $server_protocol;
    fastcgi_param REMOTE_ADDR $remote_addr;
    fastcgi_param REMOTE_PORT $remote_port;
    fastcgi_param SERVER_ADDR $server_addr;
    fastcgi_param SERVER_PORT $server_port;
    fastcgi_param SERVER_NAME $server_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param HTTPS $https;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    # fixed permalink_issues
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ^~ /.well-known/ {
        try_files $uri /;
    }
    location ~ "\.php(/|$)" {
        try_files $uri $fastcgi_script_name =404;
        default_type application/x-httpd-php;
        fastcgi_pass unix:/var/php-nginx/1671702822117723.sock/socket;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
    fastcgi_split_path_info "^(.+\.php)(/.+)$";
    location /cgi-bin/ {
        gzip off;
        root /home/domain1/cgi-bin;
        fastcgi_pass unix:/var/fcgiwrap/1671702822117723.sock/socket;
        fastcgi_param SCRIPT_FILENAME "/home/hassam.dev$fastcgi_script_name";
        fastcgi_param GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param SERVER_SOFTWARE nginx;
        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 SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param REQUEST_URI $request_uri;
        fastcgi_param DOCUMENT_URI $document_uri;
        fastcgi_param DOCUMENT_ROOT /home/hassam.dev/public_html;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param REMOTE_ADDR $remote_addr;
        fastcgi_param REMOTE_PORT $remote_port;
        fastcgi_param SERVER_ADDR $server_addr;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_NAME $server_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS $https;
    }
    fastcgi_read_timeout 60;

    listen 143.198.21X.1XX:443 ssl;
    ssl_certificate /etc/ssl/virtualmin/1671702822XX7723/ssl.combined;
    ssl_certificate_key /etc/ssl/virtualmin/1671702822117XX3/ssl.key;
}

Save the file and restart Nginx with the following command

service nginx configtest
service nginx restart

3. Enable GZIP for the Nginx website

server {
    ....
    ....

    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
      application/geo+json
      application/javascript
      application/x-javascript
      application/json
      application/ld+json
      application/manifest+json
      application/rdf+xml
      application/rss+xml
      application/xhtml+xml
      application/xml
      font/eot
      font/otf
      font/ttf
      image/svg+xml
      text/css
      text/javascript
      text/plain
      text/xml;
    client_max_body_size 48M;
}

4. Add Expires Headers Nginx Server

It’s best to set ExpiresByType headers for most of your site resources, including your HTML, CSS, JavaScript, and XML files and images and other media files. Then you can set an ExpiresDefault as a catch-all for the rest of your content. Expires headers tell the browser whether they should request a specific file from the server or whether they should grab it from the browser’s cache.

server {
    ....
    ....

	# Expiry Headers
	location ~* \.(jpg|jpeg|gif|png)$ {
    	expires 365d;
	}

	location ~* \.(pdf|css|html|js|swf)$ {
    	expires 30d;
	}
    location ~* \.(png|jpg|jpeg|gif)$ {
        expires 365d;
        add_header Cache-Control "public, no-transform";
    }

    location ~* \.(js|css|pdf|html|swf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
	# END Expiry Headers
}

5. Fix the sitemap issue on Nginx Server

server {
    ....
    ....

    # START Nginx Rewrites for Sitemaps
    rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;
    rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
    rewrite ^/([a-z]+)?-sitemap\.xsl$ /index.php?xsl=$1 last;
    # END Nginx Rewrites for Sitemaps
}

Related Articles

How to calculate VAT in PHP Laravel

Laravel CSRF Token Mismatch and 419 Page Expire

Should I use UUID as the primary key 🚨

69 / 100
Hassam
Hassam

I am passionate about open-source software, privacy, best practices, standards, user experience, and developer experience. My favorite stack these days are Laravel, Vue, and Tailwind. And focusing on Solid Principles, Data Structures, and Design Patterns.

Articles: 25

Leave a Reply

Your email address will not be published. Required fields are marked *