Laravel is a popular PHP framework with routing, authentication, and database management built in. This guide deploys a Laravel app behind Nginx on Ubuntu 24.04, wires it to MySQL, secures it with Let's Encrypt, and builds a small dashboard that queries live data.
Prerequisites: Ubuntu 24.04 with Nginx and MySQL installed, a non-root sudo user, a domain A record (e.g.
app.example.com).
Create the Database
$ sudo mysql
Enter fullscreen mode Exit fullscreen mode
mysql> CREATE DATABASE laravel_demo;
mysql> CREATE USER 'laravel_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'secure_password';
mysql> GRANT ALL ON laravel_demo.* TO 'laravel_user'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> EXIT;
Enter fullscreen mode Exit fullscreen mode
Seed a demo table to query later:
$ mysql -u laravel_user -p
Enter fullscreen mode Exit fullscreen mode
mysql> USE laravel_demo;
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)
);
mysql> INSERT INTO server_stats (
server_name, region, cpu_usage, memory_usage, status
)
VALUES
('app-01', 'us-east', 24.50, 45.30, 'active'),
('db-01', 'eu-west', 12.75, 78.20, 'active'),
('web-01', 'ap-south', 65.80, 89.50, 'active');
mysql> EXIT;
Enter fullscreen mode Exit fullscreen mode
Install Composer and PHP Extensions
$ sudo apt update
$ sudo apt install composer php php-curl php-fpm php-bcmath php-json php-mysql php-mbstring php-xml php-tokenizer php-zip -y
$ composer --version
$ php --version
$ sudo systemctl restart php8.3-fpm
Enter fullscreen mode Exit fullscreen mode
php-fpm runs PHP as a service Nginx can talk to; php-mysql/php-mbstring/php-xml/php-tokenizer/php-zip cover Laravel's runtime requirements.
Create the Laravel Project
$ cd ~
$ composer create-project --prefer-dist laravel/laravel laravel-demo
$ cd laravel-demo
$ php artisan key:generate
Enter fullscreen mode Exit fullscreen mode
Edit .env:
$ nano .env
Enter fullscreen mode Exit fullscreen mode
APP_NAME=laravel-demo
APP_ENV=development
APP_KEY=base64:APPLICATION_UNIQUE_KEY
APP_DEBUG=true
APP_URL=http://app.example.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_demo
DB_USERNAME=laravel_user
DB_PASSWORD=secure_password
SESSION_DRIVER=file
Enter fullscreen mode Exit fullscreen mode
Move it to the web root and set permissions:
$ sudo mv ~/laravel-demo /var/www/laravel-demo
$ sudo chown -R www-data:www-data /var/www/laravel-demo
$ sudo chmod -R 755 /var/www/laravel-demo/storage
$ sudo chmod -R 755 /var/www/laravel-demo/bootstrap/cache
$ cd /var/www/laravel-demo
$ php artisan migrate
Enter fullscreen mode Exit fullscreen mode
Configure Nginx
$ sudo nano /etc/nginx/sites-available/laravel-demo.conf
Enter fullscreen mode Exit fullscreen mode
server {
listen 80;
server_name app.example.com;
root /var/www/laravel-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;
}
}
Enter fullscreen mode Exit fullscreen mode
$ sudo ln -s /etc/nginx/sites-available/laravel-demo.conf /etc/nginx/sites-enabled/
$ sudo nginx -t
$ sudo systemctl restart nginx
$ sudo ufw allow 80/tcp
$ sudo ufw reload
Enter fullscreen mode Exit fullscreen mode
Visit http://app.example.com — you should see the default Laravel welcome page.
Secure with Let's Encrypt
$ sudo apt install certbot python3-certbot-nginx -y
$ sudo certbot --nginx --redirect -d app.example.com -m [email protected] --agree-tos
$ sudo certbot renew --dry-run
$ sudo systemctl restart nginx
$ sudo ufw allow 443/tcp
$ sudo ufw reload
Enter fullscreen mode Exit fullscreen mode
Build a Demo Dashboard
Replace the default route to query server_stats and render it.
$ sudo mv /var/www/laravel-demo/routes/web.php /var/www/laravel-demo/routes/web.php.ORIG
$ sudo nano /var/www/laravel-demo/routes/web.php
Enter fullscreen mode Exit fullscreen mode
<?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]);
});
Enter fullscreen mode Exit fullscreen mode
Create the Blade view:
$ sudo nano /var/www/laravel-demo/resources/views/dashboard.blade.php
Enter fullscreen mode Exit fullscreen mode
<!DOCTYPE html>
<html>
<head>
<title>Server Dashboard</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>Live 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>
Enter fullscreen mode Exit fullscreen mode
$ sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode
Visit https://app.example.com — the dashboard should render live rows from server_stats.
Next Steps
Laravel is deployed behind Nginx with TLS and a working database-backed view. From here:
- Add Eloquent models and migrations instead of raw
DB::table()queries for larger apps - Switch
APP_ENVtoproductionandAPP_DEBUGtofalsebefore going live - Set up a queue worker (
php artisan queue:work) as a systemd service for background jobs
For the full guide, visit the original article on Vultr Docs.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.