Automation & DevOps

Deploying Laravel Applications on Debian Servers: Nginx, PHP-FPM, and SSL Configuration

December 07, 2024 5 min read By Amey Lokare

Deploying Laravel Applications on Debian Servers: Nginx, PHP-FPM, and SSL Configuration

Production Laravel deployments require proper web server configuration, PHP-FPM tuning, and SSL setup. Here's my complete guide to deploying Laravel applications on Debian servers with Nginx and Let's Encrypt.

🎯 Production Requirements

A production Laravel deployment needs:

  • Web server (Nginx) for handling requests
  • PHP-FPM for processing PHP
  • SSL certificates for HTTPS
  • Optimized configuration for performance
  • Security hardening for protection

📦 Installation

1. Install Nginx

```bash sudo apt update sudo apt install nginx

Start and enable

sudo systemctl start nginx sudo systemctl enable nginx ```

2. Install PHP-FPM

```bash sudo apt install php8.2-fpm php8.2-cli php8.2-mysql php8.2-xml \ php8.2-mbstring php8.2-curl php8.2-zip php8.2-gd php8.2-bcmath

Verify installation

php -v ```

3. Install Composer

```bash curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer ```

⚙️ Nginx Configuration

1. Create Site Configuration

```bash sudo nano /etc/nginx/sites-available/ameylokare.com ```

```nginx server { listen 80; listen [::]:80; server_name ameylokare.com www.ameylokare.com; root /var/www/ameylokare.com/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.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; fastcgi_hide_header X-Powered-By; }

location ~ /\.(?!well-known).* { deny all; } } ```

2. Enable Site

```bash sudo ln -s /etc/nginx/sites-available/ameylokare.com /etc/nginx/sites-enabled/ sudo nginx -t # Test configuration sudo systemctl reload nginx ```

🔧 PHP-FPM Optimization

1. Pool Configuration

```bash sudo nano /etc/php/8.2/fpm/pool.d/www.conf ```

```ini [www] user = www-data group = www-data listen = /run/php/php8.2-fpm.sock listen.owner = www-data listen.group = www-data

; Process management pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20 pm.max_requests = 500

; Performance pm.process_idle_timeout = 10s request_terminate_timeout = 300s ```

2. PHP Configuration

```bash sudo nano /etc/php/8.2/fpm/php.ini ```

```ini memory_limit = 256M upload_max_filesize = 20M post_max_size = 20M max_execution_time = 300 max_input_time = 300

; OPcache (for production) opcache.enable=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.revalidate_freq=2 opcache.fast_shutdown=1 ```

3. Restart PHP-FPM

```bash sudo systemctl restart php8.2-fpm ```

🔒 SSL with Let's Encrypt

1. Install Certbot

```bash sudo apt install certbot python3-certbot-nginx ```

2. Obtain Certificate

```bash sudo certbot --nginx -d ameylokare.com -d www.ameylokare.com ```

Certbot will:

  • Obtain SSL certificate
  • Configure Nginx automatically
  • Set up auto-renewal

3. Auto-Renewal

Certbot creates a cron job automatically. Test renewal:

```bash sudo certbot renew --dry-run ```

🚀 Laravel Deployment

1. Clone Repository

```bash cd /var/www sudo git clone https://github.com/username/repo.git ameylokare.com sudo chown -R www-data:www-data ameylokare.com ```

2. Install Dependencies

```bash cd /var/www/ameylokare.com composer install --no-dev --optimize-autoloader npm ci --production npm run build ```

3. Configure Environment

```bash cp .env.example .env php artisan key:generate nano .env # Configure database, mail, etc. ```

4. Run Migrations

```bash php artisan migrate --force ```

5. Optimize

```bash php artisan config:cache php artisan route:cache php artisan view:cache ```

6. Set Permissions

```bash sudo chown -R www-data:www-data /var/www/ameylokare.com sudo chmod -R 755 /var/www/ameylokare.com sudo chmod -R 775 /var/www/ameylokare.com/storage sudo chmod -R 775 /var/www/ameylokare.com/bootstrap/cache ```

🔐 Security Hardening

1. Firewall

```bash sudo ufw allow 'Nginx Full' sudo ufw allow OpenSSH sudo ufw enable ```

2. Fail2ban

```bash sudo apt install fail2ban sudo systemctl enable fail2ban ```

3. Nginx Security Headers

```nginx add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; ```

4. Hide PHP Version

```ini ; /etc/php/8.2/fpm/php.ini expose_php = Off ```

⚡ Performance Optimization

1. Enable Gzip

```nginx gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss; ```

2. Browser Caching

```nginx location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control "public, immutable"; } ```

3. OPcache

Already configured in php.ini. Verify:

```bash php -i | grep opcache ```

📊 Monitoring

1. Nginx Status

```nginx location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; } ```

2. PHP-FPM Status

```nginx location ~ ^/php-fpm-status$ { fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } ```

3. Log Monitoring

```bash

Nginx access logs

sudo tail -f /var/log/nginx/access.log

Nginx error logs

sudo tail -f /var/log/nginx/error.log

PHP-FPM logs

sudo tail -f /var/log/php8.2-fpm.log ```

🔄 Deployment Script

```bash #!/bin/bash

deploy.sh

set -e

APP_DIR="/var/www/ameylokare.com" cd "$APP_DIR"

Pull latest code

git pull origin main

Install dependencies

composer install --no-dev --optimize-autoloader npm ci --production npm run build

Run migrations

php artisan migrate --force

Clear and cache

php artisan config:cache php artisan route:cache php artisan view:cache

Set permissions

sudo chown -R www-data:www-data "$APP_DIR" sudo chmod -R 755 "$APP_DIR" sudo chmod -R 775 "$APP_DIR/storage" sudo chmod -R 775 "$APP_DIR/bootstrap/cache"

Reload services

sudo systemctl reload php8.2-fpm sudo systemctl reload nginx

echo "Deployment completed!" ```

💡 Real-World Example

I deployed a Laravel application handling 50,000+ requests/day:

1. Nginx configured with gzip and caching 2. PHP-FPM tuned for 50 concurrent workers 3. OPcache enabled for 10x faster execution 4. SSL via Let's Encrypt with auto-renewal 5. Security headers and firewall configured

Result: Sub-100ms response times, 99.9% uptime, A+ SSL rating.

🎓 Key Takeaways

  • Nginx is fast and efficient for Laravel
  • PHP-FPM tuning is crucial for performance
  • OPcache dramatically improves speed
  • SSL is essential and easy with Let's Encrypt
  • Security headers protect against common attacks
  • Monitoring helps identify issues early

Conclusion

Proper deployment configuration is essential for production Laravel applications. With Nginx, optimized PHP-FPM, SSL, and security hardening, you can build reliable, fast, and secure applications that scale.

Comments

Leave a Comment

Related Posts