CRITICAL FIXES: - DatabaseSeeder now calls RolePermissionSeeder to create roles, permissions, and admin user - setup.sh and setup.bat now run db:seed automatically during setup - Created PRODUCTION_DEPLOYMENT.md with complete production deployment guide - Removed duplicate admin user creation from setup scripts This ensures: - Admin user (admin@example.com / password) is created automatically - Roles (admin, editor, viewer) are created during setup - Permissions are seeded properly - Production deployments have clear step-by-step instructions - PHP Redis extension installation documented - All common deployment issues addressed The 2-minute setup now truly works out of the box.
9.8 KiB
9.8 KiB
Production Deployment Guide
Target: Ubuntu 24.04 with Apache/Nginx + PHP-FPM (NO Docker)
Prerequisites on Production Server
1. Install Required Software
# 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
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
cd /var/www
sudo git clone https://your-repo-url.git your-domain.com
cd your-domain.com/src
2. Set Permissions
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
# Composer dependencies
composer install --no-dev --optimize-autoloader
# Node dependencies and build assets
npm install
npm run build
4. Configure Environment
# Copy appropriate .env template
cp .env.mysql .env # or .env.pgsql or .env.sqlite
# Edit .env
nano .env
Required .env settings:
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
php artisan key:generate --force
6. Run Migrations and Seeders
# 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
# 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
php artisan storage:link
Web Server Configuration
Option A: Apache with Virtual Host
Create /etc/apache2/sites-available/your-domain.com.conf:
<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:
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:
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:
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)
# 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:
[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:
sudo systemctl enable laravel-queue
sudo systemctl start laravel-queue
sudo systemctl status laravel-queue
Scheduler Setup
Add to crontab:
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 .envhasAPP_DEBUG=falseandAPP_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
# 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
# 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:
SESSION_DOMAIN=.your-domain.com
SESSION_SECURE_COOKIE=true
APP_URL=https://your-domain.com
Clear cache:
php artisan config:clear
php artisan cache:clear
Roles Don't Exist
# Run the seeder
php artisan db:seed --class=RolePermissionSeeder
# Or run all seeders
php artisan db:seed --force
Permission Denied Errors
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
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
- Change default admin password immediately
- Set up firewall:
sudo ufw enable && sudo ufw allow 80,443/tcp - Disable directory listing in web server config
- Keep system updated:
sudo apt update && sudo apt upgrade - Use strong database passwords
- Enable fail2ban:
sudo apt install fail2ban - Regular backups of database and uploaded files
- Monitor logs for suspicious activity
Backup Strategy
Database Backup
# 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
# 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:
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.