Deploy Laravel with Nginx on Ubuntu 24.04
Laravel is a widely used PHP framework for developing modern web applications, offering expressive syntax and solid features such as routing, authentication, and database handling. It runs across multiple PHP versions and supports integration with other backend services like database servers. Running Laravel behind Nginx helps you deliver fast, scalable production apps and build contemporary web solutions.
This guide describes how to deploy Laravel with Nginx on Ubuntu 24.04. You will set up Laravel, then create a new project to publish through Nginx using a custom domain like app.example.com.
Prerequisites
Before you start, make sure you:
- Have access to an Ubuntu 24.04 instance using a non-root sudo user.
- Have Nginx Web Server installed.
- Have MySQL installed to serve as the database backend.
- Have a domain A record pointing to the instance’s public IP address, for example app.example.com.
Create a MySQL Database for Laravel
Laravel relies on a relational database to store application data. Use the steps below to create a fresh MySQL database, add demo data for testing, and set up a dedicated database user for Laravel.
Sign in to the MySQL console as the root database user.
$ sudo mysql
Explanation of the code (BETA, powered by centron Agent): Run the command below to refresh the APT package index, install MySQL if it’s missing, and open the database console.
$ sudo apt update && sudo apt install mysql-server -y && sudo mysql
Explanation of the code (BETA, powered by centron Agent): Create a new centron_demo database for Laravel.
mysql> CREATE DATABASE centron_demo;
Explanation of the code (BETA, powered by centron Agent): Add a new centron_user MySQL user with a strong password. Replace secure_password with your preferred password.
mysql> CREATE USER 'centron_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'secure_password';
Explanation of the code (BETA, powered by centron Agent): Give the centron_user account full privileges on the centron_demo database.
mysql> GRANT ALL ON centron_demo.* TO 'centron_user'@'localhost';
Explanation of the code (BETA, powered by centron Agent): Reload MySQL privileges to apply the changes.
mysql> FLUSH PRIVILEGES;
Explanation of the code (BETA, powered by centron Agent): Leave the MySQL console.
mysql> EXIT;
Explanation of the code (BETA, powered by centron Agent): Log in as centron_user and provide the password when asked.
$ mysql -u centron_user -p
Explanation of the code (BETA, powered by centron Agent): Show all databases and confirm centron_demo is listed.
mysql> SHOW DATABASES;
Output:
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| centron_demo |
+--------------------+
3 rows in set (0.00 sec)
Switch to the centron_demo database.
mysql> USE centron_demo;
Create a server_stats table with active columns to record server metrics.
mysql> CREATE TABLE server_stats (
id INT AUTO_INCREMENT,
server_name VARCHAR(255),
region VARCHAR(255),
cpu_usage DECIMAL(5,2),
memory_usage DECIMAL(5,2),
status ENUM('active', 'maintenance', 'offline'),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id)
);
Insert demo entries into the server_stats table.
mysql> INSERT INTO server_stats (
server_name, region, cpu_usage, memory_usage, status
)
VALUES
('CENTRON-APP-01', 'New York', 24.50, 45.30, 'active'),
('CENTRON-DB-01', 'London', 12.75, 78.20, 'active'),
('CENTRON-WEB-01', 'Tokyo', 65.80, 89.50, 'active');
Exit the MySQL console.
mysql> EXIT;
Install Composer and PHP Extensions
Laravel needs Composer and specific PHP extensions to run correctly on a server. Follow the steps below to install PHP, Composer, and all required PHP modules for Laravel.
Update the APT package index.
$ sudo apt update
Install Composer and the PHP extensions Laravel depends on.
$ sudo apt install composer php php-curl php-fpm php-bcmath php-json php-mysql php-mbstring php-xml php-tokenizer php-zip -y
This command installs Composer, PHP, and the extensions Laravel requires. The packages include:
- composer: A PHP dependency manager.
- php-fpm: PHP FastCGI Process Manager, allowing PHP to run as a service and accept requests from web servers such as Nginx.
- php-mysql: Enables PHP to connect to MySQL databases.
- php-mbstring: Provides multibyte string support that Laravel needs.
- php-curl: Allows PHP to send HTTP requests to external URLs.
- php-bcmath: Supplies arbitrary precision math functions for PHP apps.
- php-json: Supports encoding and decoding JSON for APIs, JavaScript, and structured data.
- php-xml: Enables working with XML documents in applications.
- php-tokenizer: Includes utilities for tokenizing PHP code.
- php-zip: Lets Laravel read and write compressed .zip archives.
Check the installed Composer version.
$ composer --version
Output:
Composer version 2.7.1 2024-02-09 15:26:28
.................
Verify the installed PHP version.
$ php --version
Output:
PHP 8.3.6 (cli) (built: Mar 19 2025 10:08:38) (NTS)
Copyright (c) The PHP Group
...
Restart PHP-FPM based on the installed version, for example php8.3-fpm.
$ sudo systemctl restart php8.3-fpm
Create a Laravel Application
Use the steps below to create a Laravel application and set it up to use the MySQL database you created earlier.
Change to your user’s home directory.
$ cd ~
Explanation of the code (BETA, powered by centron Agent): Create a new Laravel project such as centron-demo.
$ composer create-project --prefer-dist laravel/laravel centron-demo
Explanation of the code (BETA, powered by centron Agent): This command fetches Laravel along with all dependencies and creates the centron-demo project folder.
Go into the centron-demo project directory.
$ cd centron-demo
Explanation of the code (BETA, powered by centron Agent): Generate a unique application key needed for secure encryption.
$ php artisan key:generate
Explanation of the code (BETA, powered by centron Agent): Output:
INFO Application key set successfully.
Open the .env file with a text editor such as nano to configure the Laravel database connection settings and the session driver.
$ nano .env
Explanation of the code (BETA, powered by centron Agent): Update the first section to include your project name like centron-demo, switch the environment from local to development, and change the application URL from http://localhost to your domain URL. Replace app.example.com with your real domain.
APP_NAME=centron-demo
APP_ENV=development
APP_KEY=base64:APPLICATION_UNIQUE_KEY
APP_DEBUG=true
APP_URL=http://app.example.com
Explanation of the code (BETA, powered by centron Agent): Update the database connection block with your database details. Change the default sqlite connection to mysql, uncomment the host, port, database, and user fields, and replace the defaults with your MySQL values for Laravel.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=centron_demo
DB_USERNAME=centron_user
DB_PASSWORD=secure_password
SESSION_DRIVER=file
Explanation of the code (BETA, powered by centron Agent): Save and close the file.
Move your centron-demo project directory to a standard web root such as /var/www.
$ sudo mv ~/centron-demo /var/www/centron-demo
Explanation of the code (BETA, powered by centron Agent): Give ownership of the /var/www/centron-demo Laravel project directory to the www-data Nginx user and group.
$ sudo chown -R www-data:www-data /var/www/centron-demo
Explanation of the code (BETA, powered by centron Agent): Set permissions on /var/www/centron-demo/storage to 755 so the www-data user has full access to the directory.
$ sudo chmod -R 755 /var/www/centron-demo/storage
Explanation of the code (BETA, powered by centron Agent): Set permissions on /var/www/centron-demo/bootstrap/cache to 755 so the www-data user can create cache files.
$ sudo chmod -R 755 /var/www/centron-demo/bootstrap/cache
Explanation of the code (BETA, powered by centron Agent): Change into the /var/www/centron-demo project directory.
$ cd /var/www/centron-demo
Explanation of the code (BETA, powered by centron Agent): Run the Laravel migrations to test the database connection.
$ php artisan migrate
Explanation of the code (BETA, powered by centron Agent): If successful, your output should resemble the example below.
……………..
INFO Running migrations.
0001_01_01_000000_create_users_table ………. 15ms DONE
0001_01_01_000001_create_cache_table ……….. 5ms DONE
……………..
Configure Laravel with Nginx
Nginx uses server block configurations to deliver Laravel files from your project directory. Follow the steps below to configure Laravel with Nginx using a new virtual host file containing the required server block and PHP connection settings.
Check the Nginx service status to confirm it is running.
$ sudo systemctl status nginx
Explanation of the code (BETA, powered by centron Agent): Output:
● nginx.service – A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-04-21 13:08:27 UTC; 18s ago
Docs: man:nginx(8)
Process: 19294 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 19296 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
…
Run the command below to install Nginx if missing, stop Apache if it is running, and start Nginx.
$ sudo apt install nginx -y && sudo systemctl stop apache2 && sudo systemctl start nginx
Explanation of the code (BETA, powered by centron Agent): Create a new centron-demo.conf Nginx configuration file inside /etc/nginx/sites-available.
$ sudo nano /etc/nginx/sites-available/centron-demo.conf
Explanation of the code (BETA, powered by centron Agent): Add the following configuration to centron-demo.conf. Replace app.example.com with your own domain.
server {
listen 80;
server_name app.example.com;
root /var/www/centron-demo/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Explanation of the code (BETA, powered by centron Agent): Save and close the file.
This configuration allows Nginx to serve the Laravel app over HTTP port 80 using your app.example.com domain. The location ~ \.php block forwards PHP requests to PHP-FPM through its socket, letting Nginx handle all Laravel files.
Enable the configuration by linking centron-demo.conf into /etc/nginx/sites-enabled.
$ sudo ln -s /etc/nginx/sites-available/centron-demo.conf /etc/nginx/sites-enabled/
Explanation of the code (BETA, powered by centron Agent): Validate the Nginx configuration for errors.
$ sudo nginx -t
Explanation of the code (BETA, powered by centron Agent): Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Restart Nginx to apply the new settings.
$ sudo systemctl restart nginx
Explanation of the code (BETA, powered by centron Agent): Allow HTTP traffic on port 80 through the firewall.
$ sudo ufw allow 80/tcp
Explanation of the code (BETA, powered by centron Agent): Reload UFW to activate the firewall changes.
$ sudo ufw reload
Open your app.example.com domain in a browser like Chrome and verify that the default Laravel page loads.
http://app.example.com
Laravel application interface
Secure Laravel with Trusted Let’s Encrypt SSL Certificates
Nginx serves Laravel over HTTP, which is not secure by default. Creating SSL certificates enables HTTPS and encrypts traffic to your web server. Follow the steps below to create trusted Let’s Encrypt certificates and secure Laravel.
Install the Certbot Let’s Encrypt client and its Nginx plugin.
$ sudo apt install certbot python3-certbot-nginx -y
Explanation of the code (BETA, powered by centron Agent): Generate a new SSL certificate using the Nginx plugin and your domain. Replace app.example.com with your domain and admin@app.example.com with your active email address.
$ sudo certbot --nginx --redirect -d app.example.com -m admin@app.example.com --agree-tos
Explanation of the code (BETA, powered by centron Agent): If successful, your output should look similar to the example below.
Requesting a certificate for app.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/app.example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/app.example.com/privkey.pem
This certificate expires on 2025-07-06.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for app.example.com to /etc/nginx/sites-enabled/centron-demo.conf
Congratulations! You have successfully enabled HTTPS on https://app.example.com
…
Verify that Certbot can renew the certificate before expiration.
$ sudo certbot renew --dry-run
Explanation of the code (BETA, powered by centron Agent): Restart Nginx to apply the SSL changes.
$ sudo systemctl restart nginx
Explanation of the code (BETA, powered by centron Agent): Allow HTTPS traffic on port 443 in the firewall.
$ sudo ufw allow 443/tcp
Explanation of the code (BETA, powered by centron Agent): Reload UFW to apply the new firewall rules.
$ sudo ufw reload
Build a Demo Laravel Application
Laravel ships with a sample “Let’s get started” page that you can swap out for your own code. Follow the steps below to replace the default project files and build a demo Laravel app with a practical dashboard that shows server metrics from your MySQL database.
Open and edit the Laravel route file.
Back up the default web.php file in your Laravel project directory.
$ sudo mv /var/www/centron-demo/routes/web.php /var/www/centron-demo/routes/web.php.ORIG
Explanation of the code (BETA, powered by centron Agent): Recreate the web.php file.
$ sudo nano /var/www/centron-demo/routes/web.php
Explanation of the code (BETA, powered by centron Agent): Add the following default route configuration to query the server metrics stored in your MySQL database.
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
$servers = DB::table('server_stats')
->orderBy('status')
->orderBy('cpu_usage', 'desc')
->get();
return view('dashboard', ['servers' => $servers]);
});
Explanation of the code (BETA, powered by centron Agent): Save and close the file.
The application code above uses Laravel’s query builder to retrieve all rows from the server_stats table in the MySQL database. It then sorts servers by status and CPU usage, and sends the results to a dashboard view.
Create a new dashboard.blade.php Blade template for the dashboard view.
$ sudo nano /var/www/centron-demo/resources/views/dashboard.blade.php
Explanation of the code (BETA, powered by centron Agent): Add the following HTML application code to dashboard.blade.php to display the server metrics.
<!DOCTYPE html>
<html>
<head>
<title>Server Dashboard | Centron Demo</title>
<style>
body { font-family: 'Segoe UI', sans-serif; margin: 2rem; }
.server-card {
padding: 1rem;
margin-bottom: 1rem;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.active {
border-left: 4px solid #10B981;
background: #F0FDF4;
}
.maintenance {
border-left: 4px solid #F59E0B;
background: #FFFBEB;
}
.offline {
border-left: 4px solid #EF4444;
background: #FEF2F2;
}
.metric {
font-weight: 600;
color: #1F2937;
}
</style>
</head>
<body>
<h1>Server Status Dashboard</h1>
<p>Real-time metrics from your infrastructure</p>
@foreach($servers as $server)
<div class="server-card {{ $server->status }}">
<h3>{{ $server->server_name }} <small>({{ $server->region }})</small></h3>
<p class="metric">Status: {{ ucfirst($server->status) }}</p>
@if($server->status != 'offline')
<p class="metric">CPU: {{ $server->cpu_usage }}%</p>
<p class="metric">Memory: {{ $server->memory_usage }}%</p>
@endif
<p>Last updated: {{ $server->last_updated }}</p>
</div>
@endforeach
</body>
</html>
Explanation of the code (BETA, powered by centron Agent): Save and close the file.
The application code above renders the server metrics passed from web.php onto a single web page.
Restart Nginx to apply the changes.
$ sudo systemctl restart nginx
Open your domain over HTTPS in a fresh browser window and confirm that the Laravel app displays correctly with data from the MySQL database.
https://app.example.com
Laravel Demo Dashboard Showing Server Metrics
Conclusion
You have deployed Laravel with Nginx on Ubuntu 24.04 and created a sample application that queries the MySQL database to display live data. You can extend your Laravel project with new models, views, and controllers to deliver your applications through Nginx. For more details and configuration options, visit the official Laravel documentation.


