Skip to main content
This guide covers detailed production environment configuration for NutriFit. Follow these instructions to ensure optimal performance, security, and reliability.

Environment File Configuration

Creating Production .env

Start with the example environment file:
cp .env.example .env
Then customize for production:
# Application
APP_NAME="NutriFit"
APP_ENV=production
APP_KEY=base64:YOUR_GENERATED_KEY_HERE
APP_DEBUG=false
APP_URL=https://yourdomain.com
APP_LOCALE=es
APP_FALLBACK_LOCALE=es

# Security
BCRYPT_ROUNDS=12

# Logging
LOG_CHANNEL=stack
LOG_STACK=daily
LOG_LEVEL=error
LOG_DEPRECATIONS_CHANNEL=null

# Database (MySQL)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nutrifit
DB_USERNAME=nutrifit_user
DB_PASSWORD=your_secure_database_password

# Session
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=.yourdomain.com

# Cache
CACHE_STORE=database
# Or use Redis for better performance:
# CACHE_STORE=redis

# Queue
QUEUE_CONNECTION=database
# Or use Redis for better performance:
# QUEUE_CONNECTION=redis

# Mail (Production SMTP)
MAIL_MAILER=smtp
MAIL_HOST=smtp.yourdomain.com
MAIL_PORT=587
MAIL_USERNAME=noreply@yourdomain.com
MAIL_PASSWORD=your_mail_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@yourdomain.com"
MAIL_FROM_NAME="${APP_NAME}"

# Redis (Optional but recommended)
# REDIS_CLIENT=phpredis
# REDIS_HOST=127.0.0.1
# REDIS_PASSWORD=null
# REDIS_PORT=6379

# Admin credentials
ADMIN_PASSWORD=your_secure_admin_password
Always use strong, unique passwords for database and admin accounts. Never reuse development passwords in production.

Database Setup

MySQL Configuration

1

Create Database

Create a dedicated database for NutriFit:
CREATE DATABASE nutrifit CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2

Create Database User

Create a dedicated user with appropriate permissions:
CREATE USER 'nutrifit_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON nutrifit.* TO 'nutrifit_user'@'localhost';
FLUSH PRIVILEGES;
Replace secure_password with a strong password generated by a password manager.
3

Run Migrations

Execute database migrations:
php artisan migrate --force
The --force flag is required for production environments.
4

Seed Initial Data

Create admin user and initial data:
php artisan db:seed
Default admin credentials:
  • Email: nutrifit2026@gmail.com
  • Password: Set via ADMIN_PASSWORD in .env

Database Optimization

Optimize MySQL for NutriFit workload:
# /etc/mysql/my.cnf or /etc/my.cnf
[mysqld]
max_connections = 150
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_size = 0
query_cache_type = 0
Restart MySQL after changes:
sudo systemctl restart mysql

Mail Server Configuration

SMTP Providers

Postmark

Professional transactional email service:
MAIL_MAILER=smtp
MAIL_HOST=smtp.postmarkapp.com
MAIL_PORT=587
MAIL_USERNAME=your_postmark_token
MAIL_PASSWORD=your_postmark_token
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@yourdomain.com"
Benefits:
  • High deliverability rates
  • Detailed analytics
  • Bounce/spam handling
  • Free tier available
Cost-effective for high volume:
MAIL_MAILER=ses
AWS_ACCESS_KEY_ID=your_key_id
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_DEFAULT_REGION=us-east-1
MAIL_FROM_ADDRESS="noreply@yourdomain.com"
Benefits:
  • Very low cost ($0.10 per 1,000 emails)
  • Scalable
  • Integrated with AWS ecosystem
Developer-friendly email service:
MAIL_MAILER=mailgun
MAILGUN_DOMAIN=yourdomain.com
MAILGUN_SECRET=your_api_key
MAIL_FROM_ADDRESS="noreply@yourdomain.com"
Requires package:
composer require symfony/mailgun-mailer
Use your own mail server:
MAIL_MAILER=smtp
MAIL_HOST=mail.yourdomain.com
MAIL_PORT=587
MAIL_USERNAME=noreply@yourdomain.com
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
Ensure proper SPF, DKIM, and DMARC records are configured to prevent emails from being marked as spam.

Email Testing

Verify email delivery:
php artisan tinker
Then run:
Mail::raw('Test email from NutriFit', function($message) {
    $message->to('your-email@example.com')
            ->subject('NutriFit Email Test');
});
Check your inbox and spam folder for the test email.

Cache Configuration

Database Cache (Default)

NutriFit uses database caching by default:
CACHE_STORE=database
Ensure cache table exists:
php artisan cache:table
php artisan migrate
For better performance, use Redis:
1

Install Redis

# Ubuntu/Debian
sudo apt install redis-server

# Start Redis
sudo systemctl start redis
sudo systemctl enable redis
2

Install PHP Redis Extension

sudo apt install php8.2-redis
sudo systemctl restart php8.2-fpm
3

Configure Laravel

Update .env:
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
4

Test Redis Connection

php artisan tinker
Cache::put('test', 'value', 60);
Cache::get('test'); // Should return 'value'

Cache Optimization

Clear and recache for optimal performance:
# Clear all caches
php artisan optimize:clear

# Rebuild caches
php artisan config:cache
php artisan route:cache
php artisan view:cache
Run these commands after every deployment to ensure caches are up to date.

Security Configuration

Application Security

Protect sensitive configuration:
# Set restrictive permissions
chmod 600 .env

# Ensure proper ownership
chown www-data:www-data .env
Never commit .env to version control:
# .gitignore already includes
.env
.env.backup
.env.production
Set correct filesystem permissions:
# Storage and cache directories
chmod -R 755 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache

# Application files (read-only)
chmod -R 644 app/ config/ routes/
chmod -R 755 artisan
Force HTTPS for all requests. Add to .env:
APP_URL=https://yourdomain.com
Configure in app/Http/Middleware/TrustProxies.php if behind proxy:
protected $proxies = '*';
protected $headers = Request::HEADER_X_FORWARDED_ALL;
NutriFit includes rate limiting. Configure in config/fortify.php:
'limiters' => [
    'login' => 'login',
    'two-factor' => 'two-factor',
],
Default: 5 login attempts per minute per IP.

CORS Configuration

If you plan to add API access:
php artisan config:publish cors
Edit config/cors.php:
'allowed_origins' => ['https://yourdomain.com'],
'allowed_methods' => ['*'],
'allowed_headers' => ['*'],

Session Configuration

Database Sessions (Default)

SESSION_DRIVER=database
SESSION_LIFETIME=120
Ensure session table exists:
php artisan session:table
php artisan migrate
For better performance:
SESSION_DRIVER=redis
SESSION_CONNECTION=default

Session Security

Configure session cookie settings in .env:
SESSION_DOMAIN=.yourdomain.com
SESSION_SECURE_COOKIE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax

Logging Configuration

Production Logging

Configure appropriate log level:
LOG_CHANNEL=stack
LOG_STACK=daily
LOG_LEVEL=error
This creates daily log files in storage/logs/.

Log Rotation

Configure automatic log rotation:
// config/logging.php
'daily' => [
    'driver' => 'daily',
    'path' => storage_path('logs/laravel.log'),
    'level' => env('LOG_LEVEL', 'error'),
    'days' => 14, // Keep logs for 14 days
],

External Logging Services

For production monitoring, consider:

Sentry

Error tracking and performance monitoring
composer require sentry/sentry-laravel
php artisan sentry:publish

Papertrail

Cloud-based log managementConfigure syslog in config/logging.php

Performance Tuning

OPcache Configuration

Enable OPcache for PHP (should be enabled by default):
; /etc/php/8.2/fpm/php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
Restart PHP-FPM:
sudo systemctl restart php8.2-fpm

PHP-FPM Tuning

Optimize PHP-FPM pool:
; /etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

Laravel Optimizations

Run all optimization commands:
# Install production dependencies only
composer install --optimize-autoloader --no-dev

# Cache everything
php artisan config:cache
php artisan route:cache
php artisan view:cache

# Build optimized assets
npm run build

Health Checks

Verify your production configuration:
# Check environment
php artisan env

# Test database connection
php artisan db:show

# Verify queue is working
php artisan queue:work --once

# Check scheduled tasks
php artisan schedule:list

Troubleshooting

  1. Check Laravel logs: storage/logs/laravel.log
  2. Verify file permissions
  3. Clear all caches: php artisan optimize:clear
  4. Check web server error logs
  1. Verify SMTP credentials
  2. Check queue worker is running
  3. Review failed jobs: php artisan queue:failed
  4. Test mail configuration with tinker
  1. Verify MySQL is running: sudo systemctl status mysql
  2. Check credentials in .env
  3. Test connection: mysql -u nutrifit_user -p nutrifit
  4. Verify MySQL grants are correct

Next Steps

Deployment Platforms

Choose your hosting platform

Queue Workers

Configure background job processing

Checklist

Pre-deployment verification

Monitoring

Set up application monitoring

Build docs developers (and LLMs) love