Production Deployment
This guide covers deploying DentControl to a production environment, including server setup, optimization, and maintenance.
Prerequisites
Before deploying, ensure your server meets these requirements:
Server Requirements
PHP 8.2 or higher
Composer 2.x
Node.js 18+ and npm
Web server (Apache/Nginx)
Database server (MySQL/PostgreSQL)
PHP Extensions
OpenSSL
PDO
Mbstring
Tokenizer
XML
Ctype
JSON
BCMath
Verify PHP Version
php -v
php -m # Check installed extensions
Deployment Process
Follow these steps to deploy DentControl to production.
1. Clone and Setup
Clone repository
Clone your DentControl repository to the server: cd /var/www
git clone https://github.com/your-username/dentcontrol.git
cd dentcontrol
Install dependencies
Install PHP and JavaScript dependencies: composer install --optimize-autoloader --no-dev
npm install
The --optimize-autoloader flag improves performance by generating optimized class maps. The --no-dev flag excludes development dependencies.
Configure environment
Create and configure your .env file: cp .env.example .env
nano .env
Set production values: APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=dentcontrol
DB_USERNAME=your_user
DB_PASSWORD=secure_password
Generate application key
Generate a secure application key:
2. Database Setup
Create production database
CREATE DATABASE dentcontrol CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER ' dentcontrol '@ 'localhost' IDENTIFIED BY 'secure_password' ;
GRANT ALL PRIVILEGES ON dentcontrol. * TO 'dentcontrol' @ 'localhost' ;
FLUSH PRIVILEGES;
Run migrations
Execute database migrations: php artisan migrate --force
Production migrations require the --force flag.
Seed initial data (optional)
If you have seeders for initial data: php artisan db:seed --force
3. Build Frontend Assets
Compile and optimize frontend assets for production:
This command:
Compiles JavaScript and CSS
Minifies assets
Generates versioned filenames for cache busting
Places files in public/build/
The build process uses Vite. The production build is optimized for performance with minification and tree-shaking.
4. Set Permissions
Set correct file permissions for Laravel:
Using www-data User
Using nginx User
SELinux Enabled Systems
sudo chown -R www-data:www-data /var/www/dentcontrol
sudo chmod -R 755 /var/www/dentcontrol
sudo chmod -R 775 /var/www/dentcontrol/storage
sudo chmod -R 775 /var/www/dentcontrol/bootstrap/cache
Never set permissions to 777! This is a security risk.
5. Optimize Laravel
Run Laravel optimization commands for production:
Cache configuration
Cache configuration files for faster loading: After caching config, the .env file is no longer read. Clear cache to apply changes:
Cache routes
Cache route definitions: This significantly speeds up route registration.
Cache views
Precompile Blade templates:
Optimize autoloader
Already done during composer install, but you can run separately: composer dump-autoload --optimize
All-in-One Optimization
Clear All Caches
# Run all optimization commands
php artisan optimize
# This runs:
# - config:cache
# - route:cache
# - view:cache
Web Server Configuration
Configure your web server to serve DentControl.
Nginx Configuration
Create an Nginx server block:
/etc/nginx/sites-available/dentcontrol
server {
listen 80 ;
listen [::]:80;
server_name your-domain.com www.your-domain.com;
# Redirect to HTTPS
return 301 https://$ server_name $ request_uri ;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com www.your-domain.com;
root /var/www/dentcontrol/public;
index index.php index.html;
# SSL Configuration
ssl_certificate /etc/ssl/certs/your-domain.crt;
ssl_certificate_key /etc/ssl/private/your-domain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Logging
access_log /var/log/nginx/dentcontrol-access.log;
error_log /var/log/nginx/dentcontrol-error.log;
# Gzip Compression
gzip on ;
gzip_vary on ;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Laravel routing
location / {
try_files $ uri $ uri / /index.php?$ query_string ;
}
# PHP-FPM configuration
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $ realpath_root $ fastcgi_script_name ;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
# Deny access to hidden files
location ~ /\. {
deny all ;
}
# Cache static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable" ;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/dentcontrol /etc/nginx/sites-enabled/
sudo nginx -t # Test configuration
sudo systemctl reload nginx
Apache Configuration
Create an Apache virtual host:
/etc/apache2/sites-available/dentcontrol.conf
< VirtualHost *:80 >
ServerName your-domain.com
ServerAlias www.your-domain.com
# Redirect to HTTPS
Redirect permanent / https://your-domain.com/
</ VirtualHost >
< VirtualHost *:443 >
ServerName your-domain.com
ServerAlias www.your-domain.com
DocumentRoot /var/www/dentcontrol/public
< Directory /var/www/dentcontrol/public >
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</ Directory >
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/ssl/certs/your-domain.crt
SSLCertificateKeyFile /etc/ssl/private/your-domain.key
# Logging
ErrorLog ${APACHE_LOG_DIR}/dentcontrol-error.log
CustomLog ${APACHE_LOG_DIR}/dentcontrol-access.log combined
# Security Headers
Header always set X-Frame- Options "SAMEORIGIN"
Header always set X-Content-Type- Options "nosniff"
Header always set X-XSS-Protection " 1 ; mode=block"
</ VirtualHost >
Enable required modules and site:
sudo a2enmod rewrite ssl headers
sudo a2ensite dentcontrol
sudo apache2ctl configtest
sudo systemctl reload apache2
SSL/TLS Certificate
Obtain a free SSL certificate using Let’s Encrypt:
# Install Certbot
sudo apt install certbot python3-certbot-nginx # For Nginx
# OR
sudo apt install certbot python3-certbot-apache # For Apache
# Obtain certificate
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
# OR
sudo certbot --apache -d your-domain.com -d www.your-domain.com
# Auto-renewal is configured automatically
# Test renewal:
sudo certbot renew --dry-run
Queue Workers
DentControl uses queues for background jobs. Set up queue workers to process them.
Supervisor Configuration
Supervisor keeps queue workers running continuously.
Install Supervisor
sudo apt install supervisor
Create worker configuration
Create /etc/supervisor/conf.d/dentcontrol-worker.conf: [program:dentcontrol-worker]
process_name =%(program_name)s_%(process_num)02d
command =php /var/www/dentcontrol/artisan queue:work database -- sleep =3 -- tries =3 -- max-time =3600
autostart =true
autorestart =true
stopasgroup =true
killasgroup =true
user =www-data
numprocs =2
redirect_stderr =true
stdout_logfile =/var/www/dentcontrol/storage/logs/worker.log
stopwaitsecs =3600
Start workers
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start dentcontrol-worker: *
Check worker status
sudo supervisorctl status dentcontrol-worker: *
Managing Queue Workers
Supervisor Commands
Manual Queue Worker
# View status
sudo supervisorctl status
# Start workers
sudo supervisorctl start dentcontrol-worker: *
# Stop workers
sudo supervisorctl stop dentcontrol-worker: *
# Restart workers
sudo supervisorctl restart dentcontrol-worker: *
# View logs
sudo supervisorctl tail -f dentcontrol-worker:dentcontrol-worker_00 stdout
After deploying code changes, restart queue workers: php artisan queue:restart
# Or
sudo supervisorctl restart dentcontrol-worker: *
Composer Scripts
DentControl includes helpful composer scripts (defined in composer.json):
Setup Script
Quick setup for new installations:
This runs:
composer install
Creates .env from .env.example (if needed)
php artisan key:generate
php artisan migrate --force
npm install
npm run build
Development Script
Start development environment:
This simultaneously runs:
Laravel development server (php artisan serve)
Queue worker (php artisan queue:listen)
Log viewer (php artisan pail)
Vite dev server (npm run dev)
The dev script is for local development only, not production.
Test Script
Run application tests:
Runs:
php artisan config:clear
php artisan test
Scheduled Tasks (Cron)
Laravel’s scheduler manages periodic tasks. Add to crontab:
Add this line:
* * * * * cd /var/www/dentcontrol && php artisan schedule:run >> /dev/null 2>&1
This runs Laravel’s scheduler every minute, which then runs scheduled tasks at their defined intervals.
Monitoring and Logging
Log Files
Laravel logs are in storage/logs/:
# View latest log entries
tail -f storage/logs/laravel.log
# Search for errors
grep ERROR storage/logs/laravel.log
# View worker logs (if using Supervisor)
tail -f storage/logs/worker.log
Log Rotation
Configure log rotation to prevent large log files:
Create /etc/logrotate.d/dentcontrol:
/var/www/dentcontrol/storage/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0644 www-data www-data
sharedscripts
}
Health Monitoring
Monitor application health:
# Check database connection
php artisan db:monitor
# View application info
php artisan about
# Check queue status
php artisan queue:monitor database --max=100
Deployment Checklist
Automated Deployment
Create a deployment script for consistent deployments:
#!/bin/bash
set -e
echo "🚀 Starting deployment..."
# Put app in maintenance mode
php artisan down
# Pull latest changes
echo "📥 Pulling latest code..."
git pull origin main
# Install/update dependencies
echo "📦 Installing dependencies..."
composer install --optimize-autoloader --no-dev
npm install
# Build assets
echo "🔨 Building assets..."
npm run build
# Run migrations
echo "🗄️ Running migrations..."
php artisan migrate --force
# Clear and optimize
echo "⚡ Optimizing..."
php artisan optimize:clear
php artisan optimize
# Restart queue workers
echo "♻️ Restarting workers..."
php artisan queue:restart
# Bring app back up
php artisan up
echo "✅ Deployment complete!"
Make it executable:
chmod +x deploy.sh
./deploy.sh
Troubleshooting
500 Internal Server Error
Common causes:
Permissions issue :
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
Missing .env file :
cp .env.example .env
php artisan key:generate
Check error logs :
tail -f storage/logs/laravel.log
tail -f /var/log/nginx/dentcontrol-error.log
Queue jobs not processing
Check workers are running :
sudo supervisorctl status
View worker logs :
tail -f storage/logs/worker.log
Manually test queue :
php artisan queue:work --once --verbose
Restart workers :
sudo supervisorctl restart dentcontrol-worker: *
Rebuild assets :
Check public/build/ directory exists
Clear view cache :
Check web server can access public/ directory
Database connection fails
Verify credentials in .env
Test database connection :
Check database server is running :
sudo systemctl status mysql
Clear config cache :
Config changes not taking effect
When config is cached, .env changes aren’t read. # Clear config cache
php artisan config:clear
# Re-cache if in production
php artisan config:cache
Security Best Practices
Always use HTTPS with valid SSL certificate
Set APP_DEBUG=false in production
Use strong database passwords
Keep Laravel and dependencies updated :
Protect .env file :
Disable directory listing in web server config
Use prepared statements (Laravel does this by default)
Implement rate limiting for API endpoints
Regular security audits :
Backup regularly (database and uploaded files)
Enable OPcache in PHP configuration
Use Redis for cache and sessions (instead of database)
Enable Gzip compression in web server
Optimize database with indexes
Use CDN for static assets
Enable HTTP/2 in web server
Implement caching strategies in code
Monitor slow queries :
php artisan db:monitor --max=1000
Backup Strategy
Automate backups with a cron job:
#!/bin/bash
BACKUP_DIR = "/var/backups/dentcontrol"
DATE = $( date +%Y%m%d-%H%M%S )
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup database
mysqldump -u dentcontrol -p 'password' dentcontrol | gzip > $BACKUP_DIR /db- $DATE .sql.gz
# Backup uploaded files
tar -czf $BACKUP_DIR /storage- $DATE .tar.gz /var/www/dentcontrol/storage/app
# Keep only last 30 days
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE "
Add to crontab:
0 2 * * * /var/www/dentcontrol/backup.sh >> /var/log/dentcontrol-backup.log 2>&1
Next Steps
Configuration Fine-tune production configuration
User Management Set up users and roles
Database Setup Optimize database for production