🏠 Home / Hub

🚀 Laravel 08 — Deploy & Production

← Laravel Menu · ← Prev: API

⚠️ Critical: Production server မတင်ခင် APP_DEBUG=false မဖြစ်မနေထားပါ! Error detail တွေ public မထွက်နေအောင်။

1. Production .env Settings

APP_NAME="Codex Blog"
APP_ENV=production
APP_KEY=base64:...          # php artisan key:generate
APP_DEBUG=false             # NEVER true in production
APP_URL=https://your-domain.com

LOG_CHANNEL=stack
LOG_LEVEL=error             # only log real errors

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog_production
DB_USERNAME=blog_user
DB_PASSWORD=StrongPassword123!

CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=your@mailgun.com
MAIL_PASSWORD=secret

2. Server Deploy Commands

# === First deploy ===
git clone https://github.com/you/your-app.git /var/www/your-app
cd /var/www/your-app
cp .env.example .env

composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
php artisan storage:link         # symlink public/storage → storage/app/public

# Optimize (cache everything)
php artisan optimize             # = config + route + view + event cache

# === Subsequent deploys (after git pull) ===
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan optimize
php artisan queue:restart        # restart background workers
php artisan optimize = config:cache + route:cache + view:cache + event:cache all in one (Laravel 11)

3. Nginx Configuration

# /etc/nginx/sites-available/laravel-app
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;

    ssl_certificate     /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

    # Web root = Laravel public/ folder only!
    root /var/www/your-app/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Security
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    location ~ /\.(env|git|htaccess) { deny all; }

    # Gzip
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
}

sudo ln -s /etc/nginx/sites-available/laravel-app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

4. SSL (Free with Let's Encrypt)

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com -d www.your-domain.com

# Auto-renew is added to cron automatically.
# Test renewal:
sudo certbot renew --dry-run

5. File Permissions

# Set ownership
sudo chown -R www-data:www-data /var/www/your-app

# storage/ and bootstrap/cache/ must be writable by web server
sudo chmod -R 775 /var/www/your-app/storage
sudo chmod -R 775 /var/www/your-app/bootstrap/cache

# Add yourself to www-data group (so you can edit files without sudo):
sudo usermod -aG www-data $USER

6. Queue Worker with Supervisor

sudo apt install supervisor -y

# /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/your-app/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/your-app/storage/logs/worker.log

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

# After each deploy:
php artisan queue:restart

7. GitHub Actions CI/CD (Auto Deploy)

# .github/workflows/deploy.yml
name: Deploy to Server
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy via SSH
        uses: appleboy/ssh-action@master
        with:
          host:     ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key:      ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/your-app
            git pull origin main
            composer install --no-dev --optimize-autoloader
            php artisan migrate --force
            php artisan optimize
            php artisan queue:restart
            sudo systemctl reload php8.2-fpm

8. Deploy Checklist

ItemCommand / ActionPriority
APP_DEBUG=false.env setting⚠️ Critical
APP_ENV=production.env setting⚠️ Critical
Generate APP_KEYphp artisan key:generateRequired
Run migrationsphp artisan migrate --forceRequired
Storage symlinkphp artisan storage:linkRequired
Optimize / cachephp artisan optimizeRecommended
File permissionschmod 775 storage/ bootstrap/cache/Required
Nginx webRoot = public/Nginx config⚠️ Critical
HTTPS / SSLcertbot --nginxRequired
Queue workersupervisor setupIf using jobs
DB backup schedulemysqldump cronRecommended
Error monitoringSentry.io / BugsnagRecommended

🎉 Laravel Complete!

Setup → Routes → Blade → Eloquent → CRUD → Auth + Policies → API + Sanctum → Deploy

Composer Eloquent ORM Migrations Blade CRUD Validation Sanctum API Policies Nginx SSL CI/CD

8 Lessons — PHP → Laravel Full Stack + REST API + Production Deploy!

📌 Study Checklist