# Lecture 11 — Deploying Laravel API to a VPS using Git (Beginner Manual Deployment)
**Duration:** \~3 hours\
**Project:** Expert Platform API (Laravel 12, REST API only)\
**Server:** VPS on Hosting/Linode\
**Database:** SQLITE or MySQL\
**Domain:** For testing, Namecheap subdomain (explained only)\
**Reverse Proxy:** Nginx → Laravel app (PHP-FPM)\
**App Path:** `/var/www/html/experts-api`
---
## 1. What “Deployment” Means
Deployment is moving your Laravel app from **local development** to a **live environment** so users can access it. For APIs, this includes:
1. Preparing production configuration.
2. Getting code onto the server.
3. Connecting to the live DB.
4. Running migrations/seeders.
5. Configuring a web server to route requests to Laravel.
---
## 2. Main Deployment Approaches
We will do **Manual Deployment** today, but you should know:
- **Manual** – You SSH into the server, update code, run commands yourself.
- **CI/CD** – Code pushed to GitHub triggers an automated deploy pipeline.
- **Containers** – App packaged in Docker, run anywhere.
---
## 3. Hosting vs Cloud
- **Hosting** = Shared space, limited access, often no Composer/PHP CLI.
- **Cloud VPS** = Full control over OS and services (Linode, DigitalOcean, AWS Lightsail).
- We use **Linode VPS** today — good mix of control and simplicity.
---
## 4. Today’s Plan
- Manual deployment to **Linode VPS**.
- Clone Laravel app from GitHub directly on the server.
- Configure `.env` for **MySQL** provided by DBA or SQLITE.
- Use **Nginx** to route traffic to Laravel’s `public/` folder.
- Place code in `/var/www/html/experts-api`.
---
## 5. Preparing Laravel for Deployment
### 5.1 Commit latest code locally
```bash
git add .
git commit -m "Prep for deployment"
git push origin main
```
### 5.2 Production `.env` values
Keep these ready for server config:
```env
APP_NAME="Expert Platform"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://api.yourdomain.com
APP_KEY=base64:... # Generate with php artisan key:generate --show
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=experts_db
DB_USERNAME=experts_user
DB_PASSWORD=secure_password_here
```
---
## 6. Cloning the App on the VPS
### 6.1 SSH into your VPS
```bash
ssh username@your-linode-ip
```
### 6.2 Navigate to `/var/www/html/` and clone
```bash
cd /var/www/html
git clone https://github.com/<your-username>/<experts-api>.git
cd experts-api
```
### 6.3 Install dependencies & optimize
```bash
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache
```
---
## 7. Updating the App Later
When you push changes to GitHub:
```bash
ssh username@your-linode-ip
cd /var/www/html/experts-api
git pull origin main
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache
```
---
## 8. Configuring Nginx
```nginx
server {
listen 80;
server_name api.yourdomain.com;
root /var/www/html/experts-api/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
```
---
## 9. Domain Setup (Explain Only)
- Point your Namecheap **subdomain** (e.g., `api.yourdomain.com`) to your VPS IP using an **A record**.
- This step is handled by **DevOps/System Admin**.
---
## 10. Database Setup
- DBA provides credentials for MySQL.
- You update `.env` on the server:
```bash
nano .env
```
- Run migrations & seeders:
```bash
php artisan migrate --force
php artisan db:seed --force
```
---
## 11. Testing
- Check API health:
```bash
curl http://api.yourdomain.com/api/health
```
- Test with **Postman**.
---
## 12. Out of Scope
- Full Linux admin
- SSL setup
- Advanced Nginx tuning
- DNS configuration
---
## Assignment
1. Push Laravel code to GitHub.
2. SSH into the VPS.
3. Clone into `/var/www/html/experts-api`.
4. Install Composer deps & optimize.
5. Configure `.env` for MySQL.
6. Run migrations & seeders.
7. Configure Nginx & restart.
8. Test with Postman.