Deploy Laravel on a Hostinger VPS (Nginx, PHP-FPM, MySQL, queues)
From a clean Ubuntu server to a production Laravel app: PHP-FPM, Composer, MySQL, the correct Nginx config, storage permissions, queue workers, the scheduler and free HTTPS.
Shared hosting or VPS for Laravel?
A simple Laravel site can run on Hostinger's Premium or Business shared plans, which include SSH, Composer and a recent PHP version. You point the domain at the `public` folder and you're done.
Pick a VPS once you need queue workers that run all the time, Redis, WebSockets (Reverb), or full control over PHP extensions. That's the setup this guide covers.
Before you start
You'll need the groundwork done first:
- Ubuntu 24.04 LTS on the VPS, secured with a sudo user and a firewall that allows 80 and 443.
- An A record for your domain pointing at the server.
- Your app in a Git repository the server can pull from.
Step 1 — Install PHP, Nginx, MySQL and Composer
Ubuntu 24.04 ships PHP 8.3, which meets the requirements of current Laravel releases. Check the `php` constraint in your `composer.json`. If you're on Ubuntu 26.04, swap `8.3` in the package names for whatever `php -v` reports.
sudo apt update
sudo apt install -y nginx mysql-server unzip git \
php8.3-fpm php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml \
php8.3-curl php8.3-zip php8.3-bcmath php8.3-intl php8.3-gd
sudo apt install -y composer
composer --versionStep 2 — Create the database
Give the app its own MySQL user with access to one database, never root.
sudo mysql <<'SQL'
CREATE DATABASE laravel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'laravel'@'localhost' IDENTIFIED BY 'use-a-long-random-password';
GRANT ALL PRIVILEGES ON laravel.* TO 'laravel'@'localhost';
FLUSH PRIVILEGES;
SQLStep 3 — Clone, install and configure
The deploy user owns the code. The web server's `www-data` group only needs write access to `storage` and `bootstrap/cache`, which is the cause of most 500 errors on a fresh Laravel server.
sudo mkdir -p /var/www && sudo chown $USER:$USER /var/www
cd /var/www
git clone https://github.com/you/your-app.git laravel
cd laravel
composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generateAPP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=use-a-long-random-passwordsudo chown -R $USER:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
php artisan migrate --force
php artisan storage:link
php artisan optimizeStep 4 — Nginx server block
The document root must be `public`, not the project folder. Pointing Nginx at the project root exposes `.env` to anyone who asks for it.
server {
listen 80;
server_name example.com www.example.com;
root /var/www/laravel/public;
index index.php;
charset utf-8;
client_max_body_size 20M;
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; }
error_page 404 /index.php;
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginxStep 5 — HTTPS
Same as any Nginx site: Certbot installs the certificate and renews it on a timer.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.comStep 6 — Queue worker and scheduler
If your app dispatches jobs, something has to process them all the time. A systemd unit restarts the worker if it crashes and starts it on boot. The scheduler needs a single cron line.
[Unit]
Description=Laravel queue worker
After=network.target mysql.service
[Service]
User=deploy
Group=www-data
WorkingDirectory=/var/www/laravel
ExecStart=/usr/bin/php artisan queue:work --sleep=3 --tries=3 --max-time=3600
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now laravel-worker
# Scheduler: run 'crontab -e' as deploy and add
* * * * * cd /var/www/laravel && php artisan schedule:run >> /dev/null 2>&1Step 7 — A redeploy script
Save it as `deploy.sh` in the project and it works with our GitHub Actions guide unchanged.
#!/usr/bin/env bash
set -euo pipefail
cd /var/www/laravel
php artisan down --retry=15 || true
git pull origin main
composer install --no-dev --optimize-autoloader --no-interaction
php artisan migrate --force
php artisan optimize
sudo systemctl restart laravel-worker
sudo systemctl reload php8.3-fpm
php artisan up
echo "Deployed at $(date -Iseconds)"Frequently asked questions
Can I host Laravel on Hostinger shared hosting?
Yes, on plans with SSH access (Premium and up). Upload the project, run Composer over SSH, and set the domain's document root to the public folder. Long-running queue workers and Redis need a VPS.
Which Hostinger VPS plan is enough for Laravel?
KVM 1 runs a typical Laravel app with MySQL and a queue worker comfortably. Move to KVM 2 when you add Redis, Horizon with several queues, or noticeably more traffic.
Why do I get a 500 error after deploying?
Almost always permissions on storage or bootstrap/cache, or a missing APP_KEY. Check storage/logs/laravel.log, and run the chown and chmod commands from Step 3 again.
Should I use Forge or a control panel instead?
If you'd rather not manage servers by hand, Laravel Forge or a panel like CloudPanel provisions everything in this guide for you, on the same Hostinger VPS.
Ready to save an extra 20% with coupon WEBHOST2026?
Get my discount link →Disclosure: links to Hostinger on this page are referral links. If you buy through them we may earn a commission, at no extra cost to you. It doesn't change what we recommend. About us
Keep reading
Secure a new Hostinger VPS: the 10-minute checklist
SSH keys, no root or password logins, a firewall, Fail2ban, automatic security updates and snapshots. The minimum to do before a fresh VPS goes on the internet, with copy-paste commands.
TutorialsHow to point a domain to your Hostinger VPS (A records, step by step)
Find your VPS IP, add the right A and AAAA records whether your domain is at Hostinger, GoDaddy or Namecheap, and check propagation before you ask Let's Encrypt for a certificate.
TutorialsAuto-deploy to a Hostinger VPS with GitHub Actions (push to deploy)
Every push to main deploys your app to the VPS. A dedicated SSH key, pinned host keys, a locked-down forced command and a workflow under 30 lines, with no third-party actions.