Hosting and Deployment
Introductionβ
This guide covers the various hosting and deployment options for your BowPHP application. Whether you use a traditional server or containers, you will find the necessary configurations here.
Production prerequisitesβ
Before deploying, make sure your production environment has:
- PHP >= 8.1 with the required extensions
- A web server (Apache, Nginx)
- Composer for dependency management
- Write access to the
var/andpublic/directories
Web server configurationβ
Apacheβ
Create or edit the .htaccess file in the public/ directory:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Redirect to HTTPS (optional)
# RewriteCond %{HTTPS} off
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Handle existing files
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Virtual Host configuration:
<VirtualHost *:80>
ServerName domain.com
ServerAlias www.domain.com
DocumentRoot /var/www/domain/public
<Directory /var/www/domain/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Enable the site and the required modules:
sudo a2enmod rewrite
sudo a2ensite domain.conf
sudo systemctl restart apache2
Nginxβ
server {
listen 80;
listen [::]:80;
server_name domain.com www.domain.com;
root /var/www/domain/public;
index index.php;
# Logs
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Static file handling
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Routing to index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP processing
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
# Security: block access to sensitive files
location ~ /\.(env|git|htaccess) {
deny all;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/domain /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Deployment with Dockerβ
Dockerfileβ
FROM php:8.2-fpm-alpine
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql opcache
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Working directory
WORKDIR /var/www/html
# Copy files
COPY . .
# Install dependencies
RUN composer install --no-dev --optimize-autoloader
# Permissions
RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 /var/www/html/var \
&& chmod -R 755 /var/www/html/public
EXPOSE 9000
CMD ["php-fpm"]
Docker Composeβ
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www/html
depends_on:
- database
networks:
- bow-network
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- .:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- bow-network
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: bow_app
MYSQL_USER: bow
MYSQL_PASSWORD: secret
volumes:
- db-data:/var/lib/mysql
networks:
- bow-network
volumes:
db-data:
networks:
bow-network:
driver: bridge
server {
listen 80;
index index.php;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
Start the containers:
docker-compose up -d
Production configurationβ
Environment variablesβ
Configure your .env.json file for production:
{
"APP_NAME": "Mon Application",
"APP_ENV": "production",
"APP_DEBUG": false,
"APP_KEY": "votre-cle-secrete-generee",
"APP_URL": "https://domain.com",
"DB_CONNECTION": "mysql",
"DB_HOST": "localhost",
"DB_PORT": 3306,
"DB_DATABASE": "production_db",
"DB_USERNAME": "prod_user",
"DB_PASSWORD": "mot-de-passe-securise"
}
- Set
APP_DEBUGtofalsein production - Use strong and unique passwords
- Generate a new
APP_KEYfor each environment
Optimizationsβ
After deployment, run these commands to optimize performance:
# Install dependencies without dev packages
composer install --no-dev --optimize-autoloader
# Clear and warm up the cache
php bow cache:clear
php bow config:cache
# Optimize the autoloader
composer dump-autoload --optimize
Directory permissionsβ
# www-data owner for the web server
sudo chown -R www-data:www-data /var/www/domain
# Write permissions for the required directories
sudo chmod -R 755 /var/www/domain
sudo chmod -R 775 /var/www/domain/var
sudo chmod -R 775 /var/www/domain/public
Shared hostingβ
For shared hosting providers (OVH, o2switch, etc.):
- Upload your project via FTP or Git
- Point the domain to the
public/directory - Configure the
.env.jsonfile with your settings - Run Composer via SSH if available:
cd /home/user/www/domain
composer install --no-dev --optimize-autoloader
If you cannot change the document root, move the contents of public/ to the root and adjust the paths in index.php.
SSL/HTTPSβ
Let's Encrypt with Certbotβ
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Generate the certificate
sudo certbot --nginx -d domain.com -d www.domain.com
# Automatic renewal
sudo certbot renew --dry-run
Monitoring and Logsβ
Application logsβ
BowPHP logs are located in var/logs/:
# Follow the logs in real time
tail -f var/logs/bow.log
# Search for errors
grep -i "error" var/logs/bow.log
Log rotationβ
Configure logrotate to prevent log files from growing indefinitely:
/var/www/domain/var/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data www-data
}
Is something missing?
If you run into problems with the documentation or have suggestions to improve the documentation or the project in general, please open an issue for us, or send a tweet mentioning the Twitter account @bowframework or directly on github.