Kotchasan Framework Documentation
Deployment Guide
Deployment Guide
This comprehensive guide covers installation, configuration, and optimization of the Kotchasan Framework for production environments.
Table of Contents
- System Requirements
- Server Installation
- Database Configuration
- Web Server Configuration
- Security Configuration
- Performance Optimization
- Backup and Recovery
- Monitoring and Troubleshooting
System Requirements
Minimum Requirements
Server:
- CPU: 1 Core 2.0 GHz
- RAM: 512 MB
- Storage: 1 GB SSD
- Bandwidth: 10 GB/month
Software:
- PHP 7.4 or higher
- MySQL 5.7 or MariaDB 10.2
- Apache 2.4 or Nginx 1.16
- SSL Certificate (recommended)Recommended Requirements
Server:
- CPU: 2 Cores 2.4 GHz or higher
- RAM: 2 GB or more
- Storage: 20 GB SSD
- Bandwidth: 100 GB/month
Software:
- PHP 8.1 or higher
- MySQL 8.0 or MariaDB 10.6
- Apache 2.4 or Nginx 1.20
- SSL Certificate
- Redis (for caching)
- Elasticsearch (for search)Required PHP Extensions
Essential:
- mbstring
- openssl
- PDO
- pdo_mysql
- curl
- gd
- zip
- xml
- json
Recommended:
- opcache
- redis
- memcached
- imagick
- intlServer Installation
1. Ubuntu/Debian Installation
# Update packages
sudo apt update && sudo apt upgrade -y
# Install Apache, MySQL, PHP
sudo apt install apache2 mysql-server php8.1 php8.1-mysql php8.1-cli php8.1-common php8.1-mbstring php8.1-gd php8.1-curl php8.1-zip php8.1-xml -y
# Enable PHP modules
sudo a2enmod php8.1
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers
# Restart Apache
sudo systemctl restart apache2
# Enable services
sudo systemctl enable apache2
sudo systemctl enable mysql2. Composer Installation
# Download and install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer
# Verify installation
composer --version3. Kotchasan Framework Installation
# Create project directory
sudo mkdir -p /var/www/html/myproject
cd /var/www/html/myproject
# Clone or download Framework (recommended)
git clone https://github.com/kotchasan/kotchasan.git .
# Or use Composer
composer create-project kotchasan/kotchasan .
# Set permissions
sudo chown -R www-data:www-data /var/www/html/myproject
sudo chmod -R 755 /var/www/html/myproject
sudo chmod -R 777 /var/www/html/myproject/datas
sudo chmod -R 777 /var/www/html/myproject/tmp4. Virtual Host Configuration
# /etc/apache2/sites-available/myproject.conf
<VirtualHost *:80>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/html/myproject
<Directory /var/www/html/myproject>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/myproject_error.log
CustomLog ${APACHE_LOG_DIR}/myproject_access.log combined
# Redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
<VirtualHost *:443>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/html/myproject
SSLEngine on
SSLCertificateFile /etc/ssl/certs/yourdomain.crt
SSLCertificateKeyFile /etc/ssl/private/yourdomain.key
SSLCertificateChainFile /etc/ssl/certs/intermediate.crt
<Directory /var/www/html/myproject>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Security Headers
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
ErrorLog ${APACHE_LOG_DIR}/myproject_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/myproject_ssl_access.log combined
</VirtualHost># Enable site
sudo a2ensite myproject.conf
sudo systemctl reload apache2Database Configuration
1. Database Creation
-- Connect to MySQL
mysql -u root -p
-- Create database
CREATE DATABASE kotchasan_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Create user
CREATE USER 'kotchasan_user'@'localhost' IDENTIFIED BY 'strong_password_here';
-- Grant privileges
GRANT ALL PRIVILEGES ON kotchasan_db.* TO 'kotchasan_user'@'localhost';
FLUSH PRIVILEGES;
-- Exit MySQL
EXIT;2. Configuration File Setup
// settings/config.php
return [
'version' => '1.0.0',
'web_title' => 'My Website',
'web_description' => 'Description of my website',
'timezone' => 'Asia/Bangkok',
// Kotchasan\Database Configuration
'db' => [
'hostname' => 'localhost',
'username' => 'kotchasan_user',
'password' => 'strong_password_here',
'dbname' => 'kotchasan_db',
'prefix' => 'app_'
],
// Cache Configuration
'cache' => [
'driver' => 'file', // file, redis, memcached
'path' => ROOT_PATH.'datas/cache/',
'prefix' => 'kotchasan_',
'default_ttl' => 3600
],
// Session Configuration
'session' => [
'name' => 'KOTCHASAN_SESSION',
'lifetime' => 3600,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
],
// Security Configuration
'security' => [
'encryption_key' => 'your-32-character-secret-key-here',
'password_min_length' => 8,
'max_login_attempts' => 5,
'lockout_duration' => 900, // 15 minutes
'csrf_protection' => true
]
];3. Database Performance Optimization
-- my.cnf or mysqld.cnf configuration
[mysqld]
# General Settings
default-storage-engine = InnoDB
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# Performance Settings
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
# Query Cache
query_cache_type = 1
query_cache_size = 128M
query_cache_limit = 32M
# Connection Settings
max_connections = 200
max_connect_errors = 10000
wait_timeout = 28800
interactive_timeout = 28800
# Slow Query Log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2Web Server Configuration
1. Apache Configuration
# .htaccess
RewriteEngine On
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove www (or add www as needed)
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
# Main Routing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?_route=$1 [QSA,L]
# Security Rules
RewriteCond %{THE_REQUEST} [A-Z]{3,}\s/+([^\s]*)\s [NC]
RewriteRule ^(.*)$ - [F,L]
# Block sensitive files
<FilesMatch "\.(htaccess|htpasswd|ini|log|sh|sql|conf)$">
Require all denied
</FilesMatch>
# Block access to includes directory
RedirectMatch 403 ^/includes/.*$
RedirectMatch 403 ^/settings/.*$
RedirectMatch 403 ^/Kotchasan/.*$
# Security Headers
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
# Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>
# Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"
</IfModule>2. Nginx Configuration
# /etc/nginx/sites-available/myproject
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://yourdomain.com$request_uri;
}
server {
listen 443 ssl http2;
server_name www.yourdomain.com;
return 301 https://yourdomain.com$request_uri;
ssl_certificate /etc/ssl/certs/yourdomain.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.key;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
root /var/www/html/myproject;
index index.php index.html;
# SSL Configuration
ssl_certificate /etc/ssl/certs/yourdomain.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
# Security Headers
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Main location
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^(.+)$ /index.php?_route=$1 last;
}
# PHP handler
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}
# Static files caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|zip)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# Block sensitive files
location ~* \.(htaccess|htpasswd|ini|log|sh|sql|conf)$ {
deny all;
}
location /settings/ { deny all; }
location /Kotchasan/ { deny all; }
location /includes/ { deny all; }
}Security Configuration
1. Brute Force Protection
// modules/security/models/bruteforce.php
class BruteForceProtection
{
private $maxAttempts = 5;
$lockoutTime = 90; // 0; // 15 minutes
public function checkAttempts($ip)
{
$attempts = $this->getAttempts($ip);
if ($attempts >= $this->maxAttempts) {
$lastAttempt = $this->getLastAttemptTime($ip);
if (time() - $lastAttempt < $this->lockoutTime) {
return false; // Still locked out
} else {
$this->clearAttempts($ip); // Reset attempts
}
}
return true;
}
public function recordFailedAttempt($ip)
{
$this->db()->createQuery()
->insert('login_attempts', [
'ip_address' => $ip,
'attempted_at' => date('Y-m-d H:i:s'),
'success' => 0
])
->execute();
}
public function recordSuccessfulLogin($ip)
{
$this->clearAttempts($ip);
$this->db()->createQuery()
->insert('login_attempts', [
'ip_address' => $ip,
'attempted_at' => date('Y-m-d H:i:s'),
'success' => 1
])
->execute();
}
private function getAttempts($ip)
{
return $this->db()->createQuery()
->from('login_attempts')
->where(['ip_address', $ip])
->andWhere(['success', 0])
->andWhere(['attempted_at', '>', date('Y-m-d H:i:s', time() - $this->lockoutTime)])
->count();
}
}2. CSRF Protection
// Kotchasan/Csrf.php
class Csrf
{
public static function generateToken()
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
public static function validateToken($token)
{
if (empty($_SESSION['csrf_token']) || empty($token)) {
return false;
}
return hash_equals($_SESSION['csrf_token'], $token);
}
public static function getTokenField()
{
$token = self::generateToken();
return '<input type="hidden" name="_token" value="'.$token.'">';
}
}3. Data Encryption
// Kotchasan/Encryption.php
class Encryption
{
private $key;
private $cipher = 'AES-256-CBC';
public function __construct($key)
{
$this->key = hash('sha256', $key, true);
}
public function encrypt($data)
{
$iv = random_bytes(16);
$encrypted = openssl_encrypt($data, $this->cipher, $this->key, 0, $iv);
return base64_encode($iv . $encrypted);
}
public function decrypt($data)
{
$data = base64_decode($data);
$iv = substr($data, 0, 16);
$encrypted = substr($data, 16);
return openssl_decrypt($encrypted, $this->cipher, $this->key, 0, $iv);
}
}Performance Optimization
1. Redis Cache Implementation
// Kotchasan/Cache/Redis.php
class RedisCache
{
private $redis;
private $prefix;
public function __construct($config)
{
$this->redis = new Redis();
$this->redis->connect($config['host'], $config['port']);
if (!empty($config['password'])) {
$this->redis->auth($config['password']);
}
$this->prefix = $config['prefix'] ?? 'kotchasan:';
}
public function get($key)
{
$data = $this->redis->get($this->prefix . $key);
return $data ? unserialize($data) : null;
}
$ttl = 360; // 0)
{
return $this->redis->setex($this->prefix . $key, $ttl, serialize($value));
}
public function delete($key)
{
return $this->redis->del($this->prefix . $key);
}
public function flush()
{
$keys = $this->redis->keys($this->prefix . '*');
if (!empty($keys)) {
return $this->redis->del($keys);
}
return true;
}
}2. OPcache Configuration
; php.ini configuration
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=5
opcache.use_cwd=1
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.fast_shutdown=13. Asset Compression and Caching
// modules/system/controllers/assets.php
class AssetsController
{
public function css($files)
{
$cacheFile = 'datas/cache/css/' . md5(implode(',', $files)) . '.css';
if (!file_exists($cacheFile) || $this->isModified($files, $cacheFile)) {
$content = '';
foreach ($files as $file) {
if (file_exists($file)) {
$content .= file_get_contents($file) . "\n";
}
}
// Minify CSS
$content = $this->minifyCSS($content);
// Save to cache
file_put_contents($cacheFile, $content);
}
header('Content-Type: text/css');
header('Cache-Control: public, max-age=31536000');
readfile($cacheFile);
}
private function minifyCSS($css)
{
// Remove comments
$css = preg_replace('!/\[^]\+([^/][^]\+)/!', '', $css);
// Remove whitespace
$css = str_replace(["\r\n", "\r", "\n", "\t", ' ', ' ', ' '], '', $css);
return $css;
}
}Backup and Recovery
1. Automated Backup Script
#!/bin/bash
# backup.sh
# Configuration
DB_NAME="kotchasan_db"
DB_USER="kotchasan_user"
DB_PASS="strong_password_here"
BACKUP_DIR="/backup/kotchasan"
WEB_DIR="/var/www/html/myproject"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Database backup
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Files backup
tar -czf $BACKUP_DIR/files_$DATE.tar.gz -C $WEB_DIR datas/ uploads/ settings/
# Keep only last 7 days of backups
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
# Log backup
echo "$(date): Backup completed successfully" >> $BACKUP_DIR/backup.log2. Cron Job Setup
# Edit crontab
crontab -e
# Add this line for daily backup at 2:00 AM
0 2 * * * /path/to/backup.sh
# Database backup every 6 hours
0 */6 * * * mysqldump -u kotchasan_user -p'password' kotchasan_db | gzip > /backup/db_$(date +\%Y\%m\%d_\%H\%M\%S).sql.gz3. Recovery Script
#!/bin/bash
# restore.sh
# Configuration
DB_NAME="kotchasan_db"
DB_USER="kotchasan_user"
DB_PASS="strong_password_here"
WEB_DIR="/var/www/html/myproject"
# Restore database
echo "Restoring database..."
gunzip < $1 | mysql -u$DB_USER -p$DB_PASS $DB_NAME
# Restore files
echo "Restoring files..."
tar -xzf $2 -C $WEB_DIR
# Fix permissions
chown -R www-data:www-data $WEB_DIR
chmod -R 755 $WEB_DIR
chmod -R 777 $WEB_DIR/datas
chmod -R 777 $WEB_DIR/tmp
echo "Restore completed successfully"Monitoring and Troubleshooting
1. Debug Mode Configuration
// settings/config.php
return [
'debug' => true, // Enable only during development
'log_level' => 'debug',
'log_file' => ROOT_PATH.'datas/logs/app.log',
// Error reporting
'error_reporting' => E_ALL,
'display_errors' => true, // Disable in production
];2. Log Monitoring
# Monitor Apache error log
sudo tail -f /var/log/apache2/myproject_error.log
# Monitor MySQL slow query log
sudo tail -f /var/log/mysql/slow.log
# Monitor Application log
tail -f /var/www/html/myproject/datas/logs/app.log
# Monitor System log
sudo tail -f /var/log/syslog3. Performance Monitoring
// modules/system/performance.php
class PerformanceMonitor
{
private $startTime;
private $startMemory;
public function start()
{
$this->startTime = microtime(true);
$this->startMemory = memory_get_usage();
}
public function end()
{
$endTime = microtime(true);
$endMemory = memory_get_usage();
$executionTime = $endTime - $this->startTime;
$memoryUsage = $endMemory - $this->startMemory;
error_log("Execution Time: " . number_format($executionTime, 4) . " seconds");
error_log("Memory Usage: " . number_format($memoryUsage / 1024 / 1024, 2) . " MB");
error_log("Peak Memory: " . number_format(memory_get_peak_usage() / 1024 / 1024, 2) . " MB");
}
}4. System Health Checks
# Test database connection
mysql -u kotchasan_user -p kotchasan_db -e "SELECT 1"
# Check PHP configuration
php -i | grep -E "(memory_limit|max_execution_time|upload_max_filesize)"
# Test file write permissions
touch /var/www/html/myproject/datas/test.txt && rm /var/www/html/myproject/datas/test.txt
# Test SSL certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
# Test page load speed
curl -w "@curl-format.txt" -o /dev/null -s "https://yourdomain.com"5. Common Issue Troubleshooting
Issue: 500 Internal Server Error
Solution:
- Check error logs
- Verify file permissions
- Check .htaccess syntax
Issue: Database connection failed
Solution:
- Verify database credentials
- Check MySQL service status
- Check firewall settings
Issue: Slow page loading
Solution:
- Enable caching
- Optimize database queries
- Use CDN for static files
Issue: Session not working
Solution:
- Check session configuration
- Verify cookie settings
- Check session directory permissionsSummary
This guide provides comprehensive coverage of installing and configuring the Kotchasan Framework for production use, from server installation and security configuration to backup procedures and troubleshooting.
Key Points to Remember:
- Security: Use HTTPS, keep software updated, configure firewall
- Performance: Implement caching, optimize database, compress assets
- Backup: Regular backups, test recovery procedures
- Monitoring: Watch logs, monitor performance, fix issues quickly
Following this guide will help ensure your system is stable, secure, and performant in production environments.