From 3fee3917c549acbb7fafe9c9ea249ae19f125242 Mon Sep 17 00:00:00 2001 From: theRADcozaDEV Date: Mon, 9 Mar 2026 11:42:25 +0200 Subject: [PATCH] Fix deployment issues: Add db:seed to setup, fix DatabaseSeeder, add production guide 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. --- PRODUCTION_DEPLOYMENT.md | 479 ++++++++++++++++++++++++ setup.bat | 13 +- setup.sh | 16 +- src/database/seeders/DatabaseSeeder.php | 9 +- 4 files changed, 497 insertions(+), 20 deletions(-) create mode 100644 PRODUCTION_DEPLOYMENT.md diff --git a/PRODUCTION_DEPLOYMENT.md b/PRODUCTION_DEPLOYMENT.md new file mode 100644 index 0000000..f796c5a --- /dev/null +++ b/PRODUCTION_DEPLOYMENT.md @@ -0,0 +1,479 @@ +# 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 + + ServerName your-domain.com + ServerAlias www.your-domain.com + DocumentRoot /var/www/your-domain.com/src/public + + + Options -Indexes +FollowSymLinks + AllowOverride All + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/your-domain.com-error.log + CustomLog ${APACHE_LOG_DIR}/your-domain.com-access.log combined + + # PHP-FPM + + SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost" + + +``` + +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. diff --git a/setup.bat b/setup.bat index 3d931f8..1ccd805 100644 --- a/setup.bat +++ b/setup.bat @@ -68,15 +68,20 @@ echo App key generated echo. REM Step 6: Run migrations -echo Running database migrations... +echo → Running database migrations... docker-compose exec app php artisan migrate --force -echo Migrations completed +echo ✓ Migrations completed +echo. + +echo → Seeding database (roles, permissions, admin user)... +docker-compose exec app php artisan db:seed --force +echo ✓ Database seeded echo. REM Step 7: Create storage link -echo Creating storage symlink... +echo → Creating storage symlink... docker-compose exec app php artisan storage:link -echo Storage linked +echo ✓ Storage linked echo. REM Step 8: Create admin user diff --git a/setup.sh b/setup.sh index 3ceac55..9791e35 100644 --- a/setup.sh +++ b/setup.sh @@ -75,20 +75,18 @@ docker-compose exec app php artisan migrate --force echo -e "${GREEN}✓ Migrations completed${NC}" echo "" -# Step 7: Create storage link +# Step 7: Seed database (roles, permissions, admin user) +echo -e "${YELLOW}→ Seeding database (roles, permissions, admin user)...${NC}" +docker-compose exec app php artisan db:seed --force +echo -e "${GREEN}✓ Database seeded${NC}" +echo "" + +# Step 8: Create storage link echo -e "${YELLOW}→ Creating storage symlink...${NC}" docker-compose exec app php artisan storage:link echo -e "${GREEN}✓ Storage linked${NC}" echo "" -# Step 8: Create admin user -echo -e "${YELLOW}→ Creating admin user...${NC}" -echo -e "${YELLOW} Email: admin@example.com${NC}" -echo -e "${YELLOW} Password: password${NC}" -docker-compose exec -T app php artisan make:filament-user --name=Admin --email=admin@example.com --password=password 2>/dev/null || echo -e "${YELLOW} (Admin user may already exist)${NC}" -echo -e "${GREEN}✓ Admin user ready${NC}" -echo "" - # Done! echo "" echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}" diff --git a/src/database/seeders/DatabaseSeeder.php b/src/database/seeders/DatabaseSeeder.php index a4b4915..28a401e 100644 --- a/src/database/seeders/DatabaseSeeder.php +++ b/src/database/seeders/DatabaseSeeder.php @@ -2,8 +2,6 @@ namespace Database\Seeders; -use App\Models\User; -// use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder @@ -13,11 +11,8 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); - - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + $this->call([ + RolePermissionSeeder::class, ]); } }