ApnaPHP

Documentation

Deployment

Learn how to deploy your ApnaPHP application to production servers with best practices for security, performance, and reliability.

Pre-Deployment Checklist

1. Environment Configuration

Update .env for production:

# Application
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

# Database
DB_DRIVER=mysql
DB_HOST=your-db-host
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_secure_password

# Security
SESSION_DRIVER=redis
CACHE_DRIVER=redis

# Redis
REDIS_HOST=your-redis-host
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password

2. Security Checklist

  • ✅ Disable debug mode (APP_DEBUG=false)
  • ✅ Use HTTPS (SSL certificate)
  • ✅ Set strong database passwords
  • ✅ Enable CSRF protection
  • ✅ Configure security headers
  • ✅ Remove .env.example from production
  • ✅ Set proper file permissions
  • ✅ Enable rate limiting
  • ✅ Keep dependencies updated

3. Performance Checklist

  • ✅ Enable OPcache
  • ✅ Use Redis for caching and sessions
  • ✅ Enable Gzip compression
  • ✅ Optimize database queries
  • ✅ Minify and combine assets
  • ✅ Use CDN for static files
  • ✅ Configure browser caching
  • ✅ Optimize images

Server Requirements

Minimum Requirements

  • PHP 8.1+ with extensions:
    • PDO (with MySQL/PostgreSQL driver)
    • mbstring
    • openssl
    • json
    • curl
    • zip
    • xml
  • Composer for dependency management
  • Web Server (Nginx or Apache)
  • Database (MySQL 5.7+, PostgreSQL 12+, SQLite, or MongoDB)

Recommended Setup

  • PHP 8.2+
  • Redis for caching and sessions
  • Nginx web server
  • MySQL 8.0+ or PostgreSQL 14+
  • SSL Certificate (Let's Encrypt)
  • Process Manager (Supervisor for queues)

Deployment Methods

1. Traditional Server (VPS/Dedicated)

Step 1: Server Setup

# Update system
sudo apt update && sudo apt upgrade -y

# Install PHP 8.2
sudo apt install php8.2 php8.2-fpm php8.2-cli php8.2-mysql php8.2-pgsql \
                 php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip \
                 php8.2-gd php8.2-redis -y

# Install Nginx
sudo apt install nginx -y

# Install MySQL
sudo apt install mysql-server -y

# Install Redis
sudo apt install redis-server -y

# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

Step 2: Configure Nginx

Create Nginx configuration:

sudo nano /etc/nginx/sites-available/apnaphp

Add configuration:

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/apnaphp/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";

    index index.php;

    charset utf-8;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript 
               application/x-javascript application/xml+rss 
               application/javascript application/json;

    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;
    }

    # Cache static files
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }
}

Enable site and restart Nginx:

sudo ln -s /etc/nginx/sites-available/apnaphp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 3: Deploy Application

# Create directory
sudo mkdir -p /var/www/apnaphp
cd /var/www/apnaphp

# Clone repository (if using Git)
git clone https://github.com/yourusername/your-app.git .

# Or upload files via SFTP
# Then run:

# Install dependencies
composer install --no-dev --optimize-autoloader

# Set permissions
sudo chown -R www-data:www-data /var/www/apnaphp
sudo chmod -R 755 /var/www/apnaphp
sudo chmod -R 775 /var/www/apnaphp/storage

# Copy environment file
cp .env.example .env
nano .env  # Edit with production values

Step 4: Configure SSL (Let's Encrypt)

# Install Certbot
sudo apt install certbot python3-certbot-nginx -y

# Get SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Auto-renewal is configured by default
# Test renewal:
sudo certbot renew --dry-run

Step 5: Configure PHP

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

Update settings:

[PHP]
memory_limit = 256M
upload_max_filesize = 20M
post_max_size = 20M
max_execution_time = 300

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

Restart PHP-FPM:

sudo systemctl restart php8.2-fpm

2. Shared Hosting (cPanel)

Step 1: Upload Files

  1. Upload all files to public_html directory
  2. Move contents of public/ folder to root
  3. Update paths in index.php:
<?php
// Update paths
define('ROOT_PATH', dirname(__DIR__)); // Change if needed
require_once ROOT_PATH . '/vendor/autoload.php';

Step 2: Configure .htaccess

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    # Redirect to HTTPS
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    # Remove public from URL
    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(.*)$ /public/$1 [L]

    # Route all requests through index.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^ index.php [L]
</IfModule>

# Security headers
<IfModule mod_headers.c>
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-Content-Type-Options "nosniff"
    Header set X-XSS-Protection "1; mode=block"
</IfModule>

# Gzip compression
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
    AddOutputFilterByType DEFLATE text/javascript application/javascript
    AddOutputFilterByType DEFLATE application/json
</IfModule>

# Browser caching
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Step 3: Configure Database

  1. Create database via cPanel
  2. Create database user
  3. Update .env with credentials

Step 4: Set Permissions

chmod -R 755 /path/to/app
chmod -R 775 /path/to/app/storage

3. Cloud Platforms

AWS (Amazon Web Services)

Using EC2

# 1. Launch EC2 instance (Ubuntu 22.04)
# 2. Connect via SSH
ssh -i your-key.pem ubuntu@your-ec2-ip

# 3. Follow VPS deployment steps
# 4. Configure security groups (ports 80, 443, 22)

Using Elastic Beanstalk

# Install EB CLI
pip install awsebcli

# Initialize application
eb init -p php-8.2 apnaphp-app

# Create environment
eb create apnaphp-env

# Deploy
eb deploy

DigitalOcean

# 1. Create Droplet (Ubuntu 22.04)
# 2. Follow VPS deployment steps
# 3. Add domain to networking
# 4. Configure firewall
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

Heroku

Create Procfile:

web: vendor/bin/heroku-php-nginx -C nginx.conf public/

Create nginx.conf:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Deploy:

# Login
heroku login

# Create app
heroku create apnaphp-app

# Add database
heroku addons:create cleardb:ignite

# Push code
git push heroku main

# Set environment
heroku config:set APP_ENV=production
heroku config:set APP_DEBUG=false

4. Docker Deployment

Dockerfile

FROM php:8.2-fpm-alpine

# Install dependencies
RUN apk add --no-cache \
    nginx \
    mysql-client \
    postgresql-client \
    redis \
    && docker-php-ext-install pdo pdo_mysql pdo_pgsql

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www/apnaphp

# Copy application
COPY . .

# Install dependencies
RUN composer install --no-dev --optimize-autoloader

# Set permissions
RUN chown -R www-data:www-data /var/www/apnaphp

# Copy Nginx config
COPY docker/nginx.conf /etc/nginx/nginx.conf

# Expose port
EXPOSE 80

# Start services
CMD php-fpm & nginx -g 'daemon off;'

docker-compose.yml

version: '3.8'

services:
  app:
    build: .
    ports:
      - "80:80"
    volumes:
      - ./storage:/var/www/apnaphp/storage
    environment:
      - APP_ENV=production
      - APP_DEBUG=false
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: apnaphp
      MYSQL_USER: apnaphp
      MYSQL_PASSWORD: password
    volumes:
      - db_data:/var/lib/mysql

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass redispassword

volumes:
  db_data:

Deploy:

docker-compose up -d

Database Migration

Export from Development

# MySQL
mysqldump -u username -p database_name > backup.sql

# PostgreSQL
pg_dump -U username database_name > backup.sql

Import to Production

# MySQL
mysql -u username -p database_name < backup.sql

# PostgreSQL
psql -U username -d database_name < backup.sql

Continuous Deployment (CI/CD)

GitHub Actions

Create .github/workflows/deploy.yml:

name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.2'

    - name: Install dependencies
      run: composer install --no-dev --optimize-autoloader

    - name: Run tests
      run: vendor/bin/phpunit

    - name: Deploy to server
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          cd /var/www/apnaphp
          git pull origin main
          composer install --no-dev --optimize-autoloader
          php artisan migrate --force
          sudo systemctl restart php8.2-fpm

GitLab CI/CD

Create .gitlab-ci.yml:

stages:
  - test
  - deploy

test:
  stage: test
  script:
    - composer install
    - vendor/bin/phpunit

deploy:
  stage: deploy
  only:
    - main
  script:
    - apt-get update -qq
    - apt-get install -qq git
    - 'which ssh-agent || ( apt-get install -qq openssh-client )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - ssh user@server "cd /var/www/apnaphp && git pull && composer install --no-dev && sudo systemctl restart php8.2-fpm"

Monitoring & Maintenance

Log Monitoring

# View error logs
tail -f /var/log/nginx/error.log
tail -f /var/www/apnaphp/storage/logs/error.log

# View access logs
tail -f /var/log/nginx/access.log

Automated Backups

Create backup script:

#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"

# Database backup
mysqldump -u username -ppassword database_name > $BACKUP_DIR/db_$DATE.sql

# Files backup
tar -czf $BACKUP_DIR/files_$DATE.tar.gz /var/www/apnaphp

# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete

echo "Backup completed: $DATE"

Add to crontab:

# Run daily at 2 AM
crontab -e
0 2 * * * /path/to/backup.sh

Health Monitoring

Create health check endpoint:

<?php
// app/health/route.apna.php

use ApnaPHP\Routing\Request;
use ApnaPHP\Routing\Response;

function GET(Request $request)
{
    $health = [
        'status' => 'healthy',
        'timestamp' => time(),
        'database' => 'connected',
        'redis' => 'connected'
    ];

    // Check database
    try {
        db()->query('SELECT 1');
    } catch (Exception $e) {
        $health['database'] = 'disconnected';
        $health['status'] = 'unhealthy';
    }

    // Check Redis
    try {
        cache()->get('health_check');
    } catch (Exception $e) {
        $health['redis'] = 'disconnected';
        $health['status'] = 'unhealthy';
    }

    $statusCode = $health['status'] === 'healthy' ? 200 : 503;
    return Response::json($health, $statusCode);
}

Rollback Strategy

Quick Rollback

# Keep previous version
cd /var/www
mv apnaphp apnaphp_backup
# Deploy new version
git clone ... apnaphp

# If issues occur, rollback:
cd /var/www
rm -rf apnaphp
mv apnaphp_backup apnaphp
sudo systemctl restart php8.2-fpm

Git-based Rollback

# View commits
git log --oneline

# Rollback to previous commit
git reset --hard COMMIT_HASH
composer install --no-dev --optimize-autoloader
sudo systemctl restart php8.2-fpm

Best Practices

1. Use Environment Variables

# Never commit .env to version control
APP_ENV=production
APP_DEBUG=false

2. Enable HTTPS

# Always use SSL in production
sudo certbot --nginx -d yourdomain.com

3. Regular Backups

# Automate database and file backups
0 2 * * * /path/to/backup.sh

4. Monitor Performance

# Use monitoring tools
# - New Relic
# - DataDog
# - Sentry
# - Custom health checks

5. Keep Dependencies Updated

# Regularly update
composer update

6. Use Process Managers

# For queue workers
sudo apt install supervisor

This comprehensive guide covers all aspects of deploying ApnaPHP applications to production!