Deploy Laravel App To VPS Ubuntu
#laravel
#devops
#deployment
#ubuntu
Shipping a Laravel application to your own virtual private server (VPS) unlocks full control over infrastructure, performance tuning, and security. This guide walks through deploying a production-ready stack on Ubuntu using Nginx, PHP-FPM 8.4, and MySQL—complete with user hardening, SSH deploy keys, and TLS via Let’s Encrypt. Replace values such as the server IP, usernames, and your-domain.com with details from your environment.
1. Prepare the server user
Start by connecting to the VPS as root, creating a dedicated deploy user, and copying the SSH keys so future logins use the new account.
# Connect as root using your private key
ssh -i learning_rsa root@143.198.216.121
# Create a non-root deploy user and grant privileges
adduser deploy
usermod -aG www-data deploy
usermod -aG sudo deploy
# Copy the root SSH keys so the deploy user can connect without passwords
rsync --archive --chown=deploy:deploy /root/.ssh /home/deploy
# Switch into the new user for the remaining steps
sudo -iu deploy
All subsequent commands run as the deploy user. Use sudo only when the
steps explicitly call for elevated privileges.
2. Install and configure Nginx
Install Nginx, open the HTTP port, and create the document root for your-domain.com.
sudo apt update
sudo apt install nginx
sudo ufw allow 'Nginx HTTP'
sudo mkdir /var/www/your-domain.com
sudo chown -R $USER:$USER /var/www/your-domain.com
sudo chmod -R 755 /var/www/your-domain.com
Create a basic landing page so you can verify the server block later.
nano /var/www/your-domain.com/index.html
<html>
<head>
<title>Welcome to your-domain.com!</title>
</head>
<body>
<h1>Success! The your-domain.com server block is working!</h1>
</body>
</html>
Define the initial Nginx server block and enable it.
sudo nano /etc/nginx/sites-available/your-domain.com
server {
listen 80;
listen [::]:80;
root /var/www/your-domain.com;
index index.html index.htm index.nginx-debian.html;
server_name your-domain.com www.your-domain.com;
location / {
try_files $uri $uri/ =404;
}
}
sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/
sudo systemctl restart nginx
3. Install and secure MySQL
sudo apt install mysql-server
sudo mysql_secure_installation
# Answer the prompts: Y, 0, Y, Y, Y, Y
sudo mysql
Inside the MySQL shell create an application database and scoped user. Adjust the password to something strong and unique.
CREATE DATABASE your_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'your_app'@'localhost' IDENTIFIED BY 'change_me';
GRANT ALL PRIVILEGES ON your_app.* TO 'your_app'@'localhost';
FLUSH PRIVILEGES;
Unless you have a bastion or VPN, keep MySQL bound to localhost and skip
exposing port 3306.
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# Ensure bind-address is set to 127.0.0.1
sudo systemctl restart mysql
# Optional: only open 3306 if you have controlled remote access
# sudo ufw allow 3306/tcp
4. Install PHP 8.4 and Composer
sudo apt install -y software-properties-common ca-certificates lsb-release apt-transport-https
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install -y \
php8.4 php8.4-fpm php8.4-cli php8.4-common \
php8.4-mbstring php8.4-xml php8.4-curl php8.4-zip \
php8.4-mysql php8.4-intl php8.4-bcmath php8.4-gd
sudo apt install -y unzip
cd ~
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
rm composer-setup.php
composer -V
Confirm PHP is wired up correctly.
nano /var/www/your-domain.com/info.php
<?php
phpinfo();
Adjust the Nginx server block to pass .php files to PHP-FPM.
sudo nano /etc/nginx/sites-available/your-domain.com
server {
listen 80;
listen [::]:80;
root /var/www/your-domain.com;
index index.html index.htm index.php;
server_name your-domain.com www.your-domain.com;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
sudo nginx -t
sudo systemctl reload nginx
5. Configure Git deploy access
Generate SSH keys for GitHub access and configure a custom host entry.
ssh-keygen -t ed25519 -C "deploy@your-domain.com" -f ~/.ssh/id_ed25519 -N ""
ssh-keygen -t ed25519 -C "deploy@vps laravel" -f ~/.ssh/id_laravel_app -N ""
cat ~/.ssh/id_laravel_app.pub
# Add the printed key to GitHub → Settings → Deploy keys → Add deploy key
nano ~/.ssh/config
Host github.com-laravel-app
HostName github.com
User git
IdentityFile ~/.ssh/id_laravel_app
IdentitiesOnly yes
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
ssh -T github.com-laravel-app
6. Deploy the Laravel application
cd /var/www/your-domain.com
git clone git@github.com-laravel-app:yourusername/laravel-broadcasting.git .
cp .env.example .env
nano .env
# Update database credentials, APP_URL, and any third-party keys
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
php artisan storage:link
sudo chown -R deploy:www-data /var/www/your-domain.com
chmod -R 775 /var/www/your-domain.com/storage /var/www/your-domain.com/bootstrap/cache
Update the final Nginx configuration so it points at Laravel’s public directory and keeps logs per app.
sudo nano /etc/nginx/sites-available/your-domain.com
server {
listen 80;
server_name your-domain.com;
root /var/www/your-domain.com/public;
index index.php;
access_log /var/log/nginx/your-domain.com.access.log;
error_log /var/log/nginx/your-domain.com.error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /\.(?!well-known).* {
deny all;
access_log off;
log_not_found off;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
}
}
sudo nginx -t && sudo systemctl reload nginx
7. Secure with Let’s Encrypt
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
Certbot will provision HTTPS, update your Nginx config, and schedule certificate renewals automatically.
You now have a hardened Ubuntu VPS hosting a production-ready Laravel application with automated deployments, database access, and HTTPS. Adjust the steps to match your CI/CD, staging environments, and monitoring stack as your application grows.