🏠 Home / Hub
🚀 Projects 05 — Deploy Pipeline
← Projects Menu
Goal: Vue frontend + Laravel API ကို production server မှာ deploy လုပ်မယ်။ GitHub Actions CI/CD, Nginx, SSL, PM2/Supervisor, database migration automation တွေပါမယ်။
1. Architecture Overview
[Developer Machine]
│
▼ git push
[GitHub Repository]
│
▼ GitHub Actions trigger
[CI/CD Pipeline]
├─ Run tests
├─ Build Vue frontend (npm run build)
├─ SSH to VPS
└─ Deploy (git pull → migrate → optimize → reload)
│
▼
[VPS / Cloud Server]
├─ Nginx (port 80/443, SSL, reverse proxy)
├─ PHP-FPM (Laravel API)
├─ Node.js/PM2 (optional for Node services)
└─ PostgreSQL / MySQL database
2. Repository Structure Best Practices
repo/
├── .github/
│ └── workflows/
│ └── deploy.yml ← GitHub Actions CI/CD
├── api/ ← Laravel backend
│ ├── .env.example ← env template (NO real secrets)
│ ├── .gitignore ← exclude vendor/, .env, storage/
│ └── ...
├── frontend/ ← Vue app
│ ├── .env.example
│ ├── .gitignore
│ └── ...
├── .gitignore ← root gitignore
└── README.md
# .gitignore (critical — NEVER commit these)
.env
vendor/
node_modules/
storage/
*.log
.DS_Store
/public/hot
3. GitHub Actions CI/CD (.github/workflows/deploy.yml)
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Build Vue frontend
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: cd frontend && npm ci && npm run build
# Deploy via SSH
- name: Deploy to VPS
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
cd /var/www/myapp
git pull origin main
cd api
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo systemctl reload php8.2-fpm
sudo supervisorctl restart laravel-queue
# Copy built frontend
cp -r /var/www/myapp/frontend/dist/* /var/www/myapp/public/
GitHub Secrets (Settings → Secrets): VPS_HOST, VPS_USER, VPS_SSH_KEY ထည့်ပါ
4. Nginx Configuration
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri; # Redirect HTTP → HTTPS
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/myapp/public;
index index.php;
# Vue SPA routing
location / {
try_files $uri $uri/ /index.html;
}
# Laravel API
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
gzip on;
gzip_types text/css application/javascript image/svg+xml;
client_max_body_size 10M;
location ~ /\.ht { deny all; }
}
# Enable site & reload
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
5. SSL with Let's Encrypt (Free HTTPS)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Auto-renew (already set up by certbot, but verify)
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
6. Queue Worker (Supervisor)
# /etc/supervisor/conf.d/laravel-queue.conf
[program:laravel-queue]
command=php /var/www/myapp/api/artisan queue:work --sleep=3 --tries=3
directory=/var/www/myapp/api
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/myapp/api/storage/logs/queue.log
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-queue:*
7. Environment Variables (Production .env)
APP_NAME=MyApp
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=myapp_prod
DB_USERNAME=myapp_user
DB_PASSWORD=very_strong_password_here
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=postmaster@mg.yourdomain.com
MAIL_PASSWORD=mailgun_api_key
# DO NOT commit this file!
# Use .env.example as template
8. Deployment Checklist
| Category | Task | Done? |
| Code | All tests passing on CI | ☐ |
| Code | No TODO/debug code in production branch | ☐ |
| Config | APP_DEBUG=false on production | ☐ |
| Config | ALLOWED_HOSTS / CORS origins set correctly | ☐ |
| Config | .env not in git, .env.example committed | ☐ |
| Database | Migrations ran successfully | ☐ |
| Database | DB backups configured | ☐ |
| Performance | config:cache, route:cache, view:cache run | ☐ |
| Security | HTTPS enabled, SSL cert valid | ☐ |
| Security | Firewall (ufw) allows only 80/443/22 | ☐ |
| Monitoring | Error logs configured and rotated | ☐ |
📌 Study Checklist
- အပေါ်က concept ကို တစ်ကြောင်းချင်းဖတ်ပြီး example ကို ကိုယ်တိုင်ပြန်ရေးကြည့်ပါ။
- Code/command ပါတဲ့ lesson ဆိုရင် value/name/path တစ်ခုခု ပြောင်းပြီး result ဘာကွာလဲ စမ်းပါ။
- မမှတ်မိသေးတဲ့ keyword 3 ခုကို notebook ထဲရေးပြီး နောက် lesson မသွားခင် ပြန်ရှင်းကြည့်ပါ။
- ပြီးရင် Home / Hub ကိုပြန်သွားပြီး next lesson ဆက်သင်ပါ။