Skip to main content
Version: 5.x

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/ and public/ directories

Web server configuration​

Apache​

Create or edit the .htaccess file in the public/ directory:

public/.htaccess
<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:

/etc/apache2/sites-available/domain.conf
<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​

/etc/nginx/sites-available/domain
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​

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​

docker-compose.yml
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
docker/nginx/default.conf
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:

.env.json
{
"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"
}
Important
  • Set APP_DEBUG to false in production
  • Use strong and unique passwords
  • Generate a new APP_KEY for 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.):

  1. Upload your project via FTP or Git
  2. Point the domain to the public/ directory
  3. Configure the .env.json file with your settings
  4. Run Composer via SSH if available:
cd /home/user/www/domain
composer install --no-dev --optimize-autoloader
Document Root configuration

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:

/etc/logrotate.d/bow-app
/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.