generated from theradcoza/Laravel-Docker-Dev-Template
480 lines
9.8 KiB
Markdown
480 lines
9.8 KiB
Markdown
# Production Deployment Guide
|
|
|
|
**Target**: Ubuntu 24.04 with Apache/Nginx + PHP-FPM (NO Docker)
|
|
|
|
---
|
|
|
|
## Prerequisites on Production Server
|
|
|
|
### 1. Install Required Software
|
|
|
|
```bash
|
|
# Update system
|
|
sudo apt update && sudo apt upgrade -y
|
|
|
|
# Install PHP 8.3+ and extensions
|
|
sudo apt install -y php8.3 php8.3-fpm php8.3-cli php8.3-common \
|
|
php8.3-mysql php8.3-pgsql php8.3-sqlite3 \
|
|
php8.3-redis php8.3-curl php8.3-mbstring php8.3-xml \
|
|
php8.3-zip php8.3-bcmath php8.3-gd php8.3-intl
|
|
|
|
# Install web server (choose one)
|
|
sudo apt install -y apache2 # OR nginx
|
|
|
|
# Install database (choose one)
|
|
sudo apt install -y mysql-server # OR postgresql
|
|
|
|
# Install Redis
|
|
sudo apt install -y redis-server
|
|
|
|
# Install Composer
|
|
curl -sS https://getcomposer.org/installer | php
|
|
sudo mv composer.phar /usr/local/bin/composer
|
|
|
|
# Install Node.js (for frontend assets)
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
sudo apt install -y nodejs
|
|
```
|
|
|
|
### 2. Verify PHP Extensions
|
|
|
|
```bash
|
|
php -m | grep -E "redis|pdo_mysql|mbstring|xml|curl|zip|bcmath|gd"
|
|
```
|
|
|
|
All should be listed. If not, install missing extensions.
|
|
|
|
---
|
|
|
|
## Deployment Steps
|
|
|
|
### 1. Clone Repository
|
|
|
|
```bash
|
|
cd /var/www
|
|
sudo git clone https://your-repo-url.git your-domain.com
|
|
cd your-domain.com/src
|
|
```
|
|
|
|
### 2. Set Permissions
|
|
|
|
```bash
|
|
sudo chown -R www-data:www-data /var/www/your-domain.com
|
|
sudo chmod -R 775 /var/www/your-domain.com/src/storage
|
|
sudo chmod -R 775 /var/www/your-domain.com/src/bootstrap/cache
|
|
```
|
|
|
|
### 3. Install Dependencies
|
|
|
|
```bash
|
|
# Composer dependencies
|
|
composer install --no-dev --optimize-autoloader
|
|
|
|
# Node dependencies and build assets
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
### 4. Configure Environment
|
|
|
|
```bash
|
|
# Copy appropriate .env template
|
|
cp .env.mysql .env # or .env.pgsql or .env.sqlite
|
|
|
|
# Edit .env
|
|
nano .env
|
|
```
|
|
|
|
**Required .env settings:**
|
|
```env
|
|
APP_NAME="Your App Name"
|
|
APP_ENV=production
|
|
APP_DEBUG=false
|
|
APP_URL=https://your-domain.com
|
|
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=3306
|
|
DB_DATABASE=your_database
|
|
DB_USERNAME=your_user
|
|
DB_PASSWORD=your_password
|
|
|
|
CACHE_STORE=redis
|
|
QUEUE_CONNECTION=redis
|
|
SESSION_DRIVER=database
|
|
SESSION_DOMAIN=.your-domain.com
|
|
SESSION_SECURE_COOKIE=true
|
|
|
|
REDIS_HOST=127.0.0.1
|
|
REDIS_PASSWORD=null
|
|
REDIS_PORT=6379
|
|
|
|
MAIL_MAILER=smtp
|
|
MAIL_HOST=your-smtp-host
|
|
MAIL_PORT=587
|
|
MAIL_USERNAME=your-email
|
|
MAIL_PASSWORD=your-password
|
|
MAIL_ENCRYPTION=tls
|
|
MAIL_FROM_ADDRESS=noreply@your-domain.com
|
|
MAIL_FROM_NAME="${APP_NAME}"
|
|
```
|
|
|
|
### 5. Generate Application Key
|
|
|
|
```bash
|
|
php artisan key:generate --force
|
|
```
|
|
|
|
### 6. Run Migrations and Seeders
|
|
|
|
```bash
|
|
# Run migrations
|
|
php artisan migrate --force
|
|
|
|
# CRITICAL: Run seeders to create roles, permissions, and admin user
|
|
php artisan db:seed --force
|
|
```
|
|
|
|
This creates:
|
|
- **Admin user**: admin@example.com / password
|
|
- **Roles**: admin, editor, viewer
|
|
- **Permissions**: users.view, users.create, users.edit, users.delete, settings.manage
|
|
|
|
### 7. Optimize for Production
|
|
|
|
```bash
|
|
# Cache configuration
|
|
php artisan config:cache
|
|
|
|
# Cache routes
|
|
php artisan route:cache
|
|
|
|
# Cache views
|
|
php artisan view:cache
|
|
|
|
# Optimize autoloader
|
|
composer dump-autoload --optimize
|
|
```
|
|
|
|
### 8. Create Storage Link
|
|
|
|
```bash
|
|
php artisan storage:link
|
|
```
|
|
|
|
---
|
|
|
|
## Web Server Configuration
|
|
|
|
### Option A: Apache with Virtual Host
|
|
|
|
Create `/etc/apache2/sites-available/your-domain.com.conf`:
|
|
|
|
```apache
|
|
<VirtualHost *:80>
|
|
ServerName your-domain.com
|
|
ServerAlias www.your-domain.com
|
|
DocumentRoot /var/www/your-domain.com/src/public
|
|
|
|
<Directory /var/www/your-domain.com/src/public>
|
|
Options -Indexes +FollowSymLinks
|
|
AllowOverride All
|
|
Require all granted
|
|
</Directory>
|
|
|
|
ErrorLog ${APACHE_LOG_DIR}/your-domain.com-error.log
|
|
CustomLog ${APACHE_LOG_DIR}/your-domain.com-access.log combined
|
|
|
|
# PHP-FPM
|
|
<FilesMatch \.php$>
|
|
SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost"
|
|
</FilesMatch>
|
|
</VirtualHost>
|
|
```
|
|
|
|
Enable site and modules:
|
|
```bash
|
|
sudo a2enmod rewrite proxy_fcgi setenvif
|
|
sudo a2enconf php8.3-fpm
|
|
sudo a2ensite your-domain.com.conf
|
|
sudo systemctl restart apache2
|
|
```
|
|
|
|
### Option B: Nginx with Server Block
|
|
|
|
Create `/etc/nginx/sites-available/your-domain.com`:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name your-domain.com www.your-domain.com;
|
|
root /var/www/your-domain.com/src/public;
|
|
|
|
add_header X-Frame-Options "SAMEORIGIN";
|
|
add_header X-Content-Type-Options "nosniff";
|
|
|
|
index index.php;
|
|
|
|
charset utf-8;
|
|
|
|
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 ~ \.php$ {
|
|
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
|
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
}
|
|
|
|
location ~ /\.(?!well-known).* {
|
|
deny all;
|
|
}
|
|
}
|
|
```
|
|
|
|
Enable site:
|
|
```bash
|
|
sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/
|
|
sudo nginx -t
|
|
sudo systemctl restart nginx
|
|
```
|
|
|
|
---
|
|
|
|
## SSL Certificate (Let's Encrypt)
|
|
|
|
```bash
|
|
# Install Certbot
|
|
sudo apt install -y certbot python3-certbot-apache # For Apache
|
|
# OR
|
|
sudo apt install -y certbot python3-certbot-nginx # For Nginx
|
|
|
|
# Get certificate
|
|
sudo certbot --apache -d your-domain.com -d www.your-domain.com # Apache
|
|
# OR
|
|
sudo certbot --nginx -d your-domain.com -d www.your-domain.com # Nginx
|
|
|
|
# Auto-renewal is set up automatically
|
|
```
|
|
|
|
---
|
|
|
|
## Queue Worker Setup (Optional but Recommended)
|
|
|
|
Create `/etc/systemd/system/laravel-queue.service`:
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=Laravel Queue Worker
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=www-data
|
|
Group=www-data
|
|
Restart=always
|
|
ExecStart=/usr/bin/php /var/www/your-domain.com/src/artisan queue:work --sleep=3 --tries=3 --max-time=3600
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Enable and start:
|
|
```bash
|
|
sudo systemctl enable laravel-queue
|
|
sudo systemctl start laravel-queue
|
|
sudo systemctl status laravel-queue
|
|
```
|
|
|
|
---
|
|
|
|
## Scheduler Setup
|
|
|
|
Add to crontab:
|
|
```bash
|
|
sudo crontab -e -u www-data
|
|
```
|
|
|
|
Add this line:
|
|
```
|
|
* * * * * cd /var/www/your-domain.com/src && php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
---
|
|
|
|
## Post-Deployment Checklist
|
|
|
|
- [ ] PHP Redis extension installed: `php -m | grep redis`
|
|
- [ ] Database migrations run: `php artisan migrate --force`
|
|
- [ ] **Database seeded**: `php artisan db:seed --force` ✅ CRITICAL
|
|
- [ ] Storage permissions set: `chmod -R 775 storage bootstrap/cache`
|
|
- [ ] Storage link created: `php artisan storage:link`
|
|
- [ ] Config cached: `php artisan config:cache`
|
|
- [ ] Routes cached: `php artisan route:cache`
|
|
- [ ] Views cached: `php artisan view:cache`
|
|
- [ ] SSL certificate installed
|
|
- [ ] Queue worker running (if using queues)
|
|
- [ ] Scheduler configured (if using scheduled tasks)
|
|
- [ ] Admin user created and can login at `/admin`
|
|
- [ ] `.env` has `APP_DEBUG=false` and `APP_ENV=production`
|
|
|
|
---
|
|
|
|
## Access Your Application
|
|
|
|
- **Public Site**: https://your-domain.com
|
|
- **Admin Panel**: https://your-domain.com/admin
|
|
- **Admin Login**: admin@example.com / password
|
|
|
|
**⚠️ IMPORTANT**: Change the default admin password immediately after first login!
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### 500 Error - Check Logs
|
|
|
|
```bash
|
|
# Laravel logs
|
|
tail -f /var/www/your-domain.com/src/storage/logs/laravel.log
|
|
|
|
# Apache logs
|
|
sudo tail -f /var/log/apache2/your-domain.com-error.log
|
|
|
|
# Nginx logs
|
|
sudo tail -f /var/log/nginx/error.log
|
|
|
|
# PHP-FPM logs
|
|
sudo tail -f /var/log/php8.3-fpm.log
|
|
```
|
|
|
|
### Class "Redis" not found
|
|
|
|
```bash
|
|
# Install PHP Redis extension
|
|
sudo apt install php8.3-redis
|
|
|
|
# Restart PHP-FPM
|
|
sudo systemctl restart php8.3-fpm
|
|
|
|
# Restart web server
|
|
sudo systemctl restart apache2 # or nginx
|
|
```
|
|
|
|
### 419 Page Expired (CSRF)
|
|
|
|
Check `.env`:
|
|
```env
|
|
SESSION_DOMAIN=.your-domain.com
|
|
SESSION_SECURE_COOKIE=true
|
|
APP_URL=https://your-domain.com
|
|
```
|
|
|
|
Clear cache:
|
|
```bash
|
|
php artisan config:clear
|
|
php artisan cache:clear
|
|
```
|
|
|
|
### Roles Don't Exist
|
|
|
|
```bash
|
|
# Run the seeder
|
|
php artisan db:seed --class=RolePermissionSeeder
|
|
|
|
# Or run all seeders
|
|
php artisan db:seed --force
|
|
```
|
|
|
|
### Permission Denied Errors
|
|
|
|
```bash
|
|
sudo chown -R www-data:www-data /var/www/your-domain.com
|
|
sudo chmod -R 775 /var/www/your-domain.com/src/storage
|
|
sudo chmod -R 775 /var/www/your-domain.com/src/bootstrap/cache
|
|
```
|
|
|
|
---
|
|
|
|
## Updating the Application
|
|
|
|
```bash
|
|
cd /var/www/your-domain.com
|
|
|
|
# Pull latest code
|
|
sudo -u www-data git pull
|
|
|
|
# Update dependencies
|
|
cd src
|
|
composer install --no-dev --optimize-autoloader
|
|
npm install && npm run build
|
|
|
|
# Run migrations
|
|
php artisan migrate --force
|
|
|
|
# Clear and recache
|
|
php artisan config:clear
|
|
php artisan cache:clear
|
|
php artisan config:cache
|
|
php artisan route:cache
|
|
php artisan view:cache
|
|
|
|
# Restart queue worker
|
|
sudo systemctl restart laravel-queue
|
|
|
|
# Restart web server
|
|
sudo systemctl restart apache2 # or nginx
|
|
```
|
|
|
|
---
|
|
|
|
## Security Recommendations
|
|
|
|
1. **Change default admin password** immediately
|
|
2. **Set up firewall**: `sudo ufw enable && sudo ufw allow 80,443/tcp`
|
|
3. **Disable directory listing** in web server config
|
|
4. **Keep system updated**: `sudo apt update && sudo apt upgrade`
|
|
5. **Use strong database passwords**
|
|
6. **Enable fail2ban**: `sudo apt install fail2ban`
|
|
7. **Regular backups** of database and uploaded files
|
|
8. **Monitor logs** for suspicious activity
|
|
|
|
---
|
|
|
|
## Backup Strategy
|
|
|
|
### Database Backup
|
|
|
|
```bash
|
|
# MySQL
|
|
mysqldump -u username -p database_name > backup_$(date +%Y%m%d).sql
|
|
|
|
# PostgreSQL
|
|
pg_dump -U username database_name > backup_$(date +%Y%m%d).sql
|
|
```
|
|
|
|
### Files Backup
|
|
|
|
```bash
|
|
# Backup storage directory
|
|
tar -czf storage_backup_$(date +%Y%m%d).tar.gz /var/www/your-domain.com/src/storage
|
|
```
|
|
|
|
### Automated Backups
|
|
|
|
Add to crontab:
|
|
```bash
|
|
0 2 * * * /path/to/backup-script.sh
|
|
```
|
|
|
|
---
|
|
|
|
**Remember**: The template is designed for quick local development with Docker. Production deployment requires proper server setup and security hardening.
|