Deploy Quasar + Laravel + MySQL on AWS EC2 (Default VPC)
A complete, step-by-step guide to deploying a full-stack application — Quasar (Vue.js) frontend, Laravel API backend, and MySQL database — on a single EC2 instance using the default VPC.
:80 / → Nginx
reverse proxy → Laravel API
:8000 /api → MySQL 8
:3306
All running on a single EC2 instance (Ubuntu 22.04) inside the default VPC
STEP 01
Prerequisites
Before starting, make sure you have:
- An AWS account with access to the EC2 dashboard
- A domain name pointed to your server (optional, but needed for SSL)
- Your Quasar + Laravel project pushed to a Git repository
- A local SSH key pair
STEP 02
Launch EC2 Instance
2.1 Choose Your Instance
Go to EC2 Dashboard → Launch Instance:
- AMI: Ubuntu Server 22.04 LTS (HVM)
- Instance type:
t2.smallort3.medium - Key pair: Create or select existing
- VPC: Default VPC
2.2 Security Group Rules
| Type | Port | Source | Purpose |
|---|---|---|---|
| SSH | 22 | Your IP | Server access |
| HTTP | 80 | 0.0.0.0/0 | Web traffic |
| HTTPS | 443 | 0.0.0.0/0 | Secure traffic |
2.3 Connect to Your Instance
# Set permissions on your key chmod 400 your-key.pem # SSH into the instance ssh -i "your-key.pem" ubuntu@<your-ec2-public-ip>
STEP 03
Install Dependencies
# Update system packages sudo apt update && sudo apt upgrade -y # Install Nginx, Git, Curl, Unzip sudo apt install -y nginx git curl unzip software-properties-common # Add PHP 8.2 repository sudo add-apt-repository ppa:ondrej/php -y sudo apt update # Install PHP 8.2 + extensions for Laravel sudo apt install -y php8.2-fpm php8.2-mysql php8.2-mbstring \ php8.2-xml php8.2-curl php8.2-zip php8.2-bcmath php8.2-gd # Install Composer curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer # Install Node.js 20 (for building Quasar) curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - sudo apt install -y nodejs
php -v, composer --version, node -v, nginx -vSTEP 04
Set Up MySQL
# Install MySQL 8 sudo apt install -y mysql-server # Secure the installation sudo mysql_secure_installation # Create database and user sudo mysql CREATE DATABASE myapp_db; CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!'; GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost'; FLUSH PRIVILEGES; EXIT;
StrongPassword123! with an actual secure password. Never use this in production!STEP 05
Deploy Laravel Backend
# Clone your project cd /var/www sudo git clone https://github.com/you/your-project.git myapp cd myapp/backend # Set ownership sudo chown -R www-data:www-data /var/www/myapp sudo chmod -R 775 storage bootstrap/cache # Install dependencies composer install --no-dev --optimize-autoloader # Configure environment cp .env.example .env nano .env
5.1 Configure .env
APP_ENV=production APP_DEBUG=false APP_URL=https://yourdomain.com DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=myapp_db DB_USERNAME=myapp_user DB_PASSWORD=StrongPassword123!
# Generate app key and run migrations php artisan key:generate php artisan migrate --force php artisan config:cache php artisan route:cache php artisan view:cache
STEP 06
Deploy Quasar Frontend
# Navigate to frontend directory cd /var/www/myapp/frontend # Install dependencies npm install # Build for production (SPA mode) npx quasar build # Build output → dist/spa/ # Nginx will serve this
/api (relative) so Nginx can proxy it to Laravel.STEP 07
Configure Nginx
This is the crucial part — Nginx serves the Quasar SPA and proxies API requests to Laravel via PHP-FPM:
server { listen 80; server_name yourdomain.com; # Quasar SPA (frontend) root /var/www/myapp/frontend/dist/spa; index index.html; # SPA fallback location / { try_files $uri $uri/ /index.html; } # Laravel API location /api { alias /var/www/myapp/backend/public; try_files $uri $uri/ @laravel; location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $request_filename; } } location @laravel { rewrite /api/(.*)$ /api/index.php?/$1 last; } # Security headers add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; # Gzip compression gzip on; gzip_types text/plain text/css application/json application/javascript; }
# Enable the site sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/ # Remove default site sudo rm /etc/nginx/sites-enabled/default # Test config and reload sudo nginx -t sudo systemctl reload nginx
STEP 08
SSL with Let's Encrypt
# Install Certbot sudo apt install -y certbot python3-certbot-nginx # Get SSL certificate sudo certbot --nginx -d yourdomain.com # Test auto-renewal sudo certbot renew --dry-run
STEP 09
Troubleshooting
500 Internal Server Error
Check Laravel logs: tail -f storage/logs/laravel.log — usually missing .env, wrong permissions, or missing PHP extensions.
403 Forbidden
Fix ownership: sudo chown -R www-data:www-data /var/www/myapp
API returns 404
Check Nginx config — make sure the /api location block is correct and nginx -t passes.
Quasar routes show blank page
Ensure try_files falls back to /index.html for SPA routing.
Database connection refused
Verify MySQL: sudo systemctl status mysql. Check .env credentials match Step 4.
/api/* hit Laravel.
Comments
Post a Comment