When developing multiple PHP applications on a Debian machine, using only http://localhost quickly becomes impractical.
Apache VirtualHosts allow you to associate a local domain name with each project. For example:
http://my-project.localhttp://blog.localhttp://app.local
Each name can point to a different directory.
In this article, we will see how to configure an Apache VirtualHost on Debian 13 (Trixie) for a local PHP project.
The example will use:
- Debian 13;
- Apache 2.4;
- PHP 8.4;
- a project located in
/var/www/my-project; - the local domain name
my-project.local.
Note: this configuration is intended for local development only and is not suitable for production use.
1. Install Apache and PHP
If Apache and PHP are not already installed, start by updating the package list:
sudo apt update |
sudo apt upgrade |
Then install Apache and PHP:
sudo apt install apache2 php libapache2-mod-php |
Debian 13 currently provides PHP 8.4 as the default version. The php package is a dependency that points to the stable PHP version provided by Debian.
You can check the installed versions with:
apache2 -v |
php -v |
You should see something like:
Server version: Apache/2.4.68 |
and:
PHP 8.4.x |
The exact revision numbers may naturally evolve with Debian security updates.
Also, verify that the Apache service is running:
sudo systemctl status apache2 |
If necessary:
sudo systemctl enable --now apache2 |
2. Create the Project Directory
We will place our project in:
/var/www/my-project |
Create the directory:
sudo mkdir -p /var/www/my-project |
To quickly test the configuration, create a PHP file:
sudo nano /var/www/my-project/index.php |
Add:
<?php |
|
echo '<h1>My project works!</h1>'; |
echo '<p>PHP fonctionne avec Apache.</p>'; |
Save the file.
2.1. About Permissions
Apache typically runs under the system user www-data.
However, it is not necessary to give complete ownership of your project to www-data systematically.
For a development environment, it's often preferable for your Linux user to remain the owner of the project files and grant Apache only the permissions the application actually needs.
For a simple test, you can use:
sudo chown -R $USER:$USER /var/www/my-project |
Applications requiring writable directories, such as Symfony or Laravel, will need appropriate permissions on their cache, log, and uploaded file directories later.
3. Create the Apache VirtualHost
Apache site configurations are stored in:
/etc/apache2/sites-available/ |
Create the file:
sudo nano /etc/apache2/sites-available/my-project.conf |
Add the following configuration:
<VirtualHost *:80> |
ServerName my-project.local |
DocumentRoot /var/www/my-project |
|
<Directory /var/www/my-project> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
|
ErrorLog ${APACHE_LOG_DIR}/my-project-error.log |
CustomLog ${APACHE_LOG_DIR}/my-project-access.log combined |
</VirtualHost> |
3.1. Explanations
VirtualHost *:80
Apache listens on HTTP port 80, regardless of the IP address used by the machine.
Name-based VirtualHosts allow multiple sites to share the same IP and port. Apache then selects the appropriate VirtualHost based on the ServerName or ServerAlias sent in the HTTP request.
ServerName
ServerName my-project.local |
This is the name we will use in the browser:
http://my-project.local |
It's recommended to explicitly define a ServerName for each VirtualHost.
DocumentRoot
DocumentRoot /var/www/my-project |
This directive tells Apache where the site files are located.
<Directory>
<Directory /var/www/my-project> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
Require all granted allows Apache to serve content from this directory.
AllowOverride All enables a .htaccess file to modify certain Apache rules.
If your application does not use .htaccess, you can opt for:
AllowOverride None |
This is generally preferable when the application doesn't need it, as it centralizes Apache configuration.
Logs
ErrorLog ${APACHE_LOG_DIR}/my-project-error.log |
CustomLog ${APACHE_LOG_DIR}/my-project-access.log combined |
Errors will be recorded in:
/var/log/apache2/my-project-error.log |
and access logs in:
/var/log/apache2/my-project-access.log |
4. Add the domain to /etc/hosts
Our domain my-project.local does not exist on the internet.
Therefore, we need to tell our machine that this name corresponds to 127.0.0.1.
Edit the file /etc/hosts:
sudo nano /etc/hosts |
Add:
127.0.0.1 my-project.local |
You can also use:
127.0.0.1 my-project.local www.my-project.local |
if you want to use both names.
The /etc/hosts file thus simulates local DNS resolution. Apache does not create its own DNS entries for VirtualHosts.
If you are using another computer to access the Debian server, this modification must be made on the client machine or replaced by a real DNS configuration.
5. Enable the VirtualHost
The file we just created is located in:
/etc/apache2/sites-available/ |
This means it's available but not yet enabled.
Enable it with:
sudo a2ensite my-project.conf |
You can also disable the default Apache VirtualHost if needed:
sudo a2dissite 000-default.conf |
However, this is not mandatory for our new VirtualHost to work.
6. Check the Apache Configuration
Before reloading Apache, always check its configuration:
sudo apachectl configtest |
If everything is correct, you should get:
Syntax OK |
This step is crucial: it helps avoid reloading a configuration with syntax errors.
You can then reload Apache:
sudo systemctl reload apache2 |
A reload suffices here: it allows Apache to apply the new configuration without stopping the service entirely.
7. Check Active VirtualHosts
Apache provides a very handy command to examine configured VirtualHosts:
sudo apachectl -S |
You should see a line corresponding to:
*:80 my-project.local |
This command is particularly useful when a machine hosts multiple projects and you need to understand which VirtualHost Apache is using. The Apache documentation recommends apachectl -S for diagnosing VirtualHost configurations.
8. Test the Site
You can now open your browser and enter:
http://my-project.local |
You should see:
My project works! |
PHP fonctionne avec Apache. |
If you prefer to perform the test from the terminal, use:
curl http://my-project.local |
You should get the HTML content generated by PHP.
You can also verify directly that PHP is executed by Apache by temporarily creating:
sudo nano /var/www/my-project/info.php |
with:
<?php |
|
phpinfo(); |
Then open:
http://my-project.local/info.php |
You should see the PHP information page.
Delete this file afterward, as phpinfo() exposes a lot of information about the PHP environment:
sudo rm /var/www/my-project/info.php |
9. Enable mod_rewrite if Necessary
Many modern PHP applications rely on Apache's rewrite module.
You can enable it with:
sudo a2enmod rewrite |
Then check the configuration:
sudo apachectl configtest |
and reload Apache:
[[[CODE_BLOCK_44]]
With:
AllowOverride All |
in the VirtualHost, an application using a .htaccess file can define its own rewrite rules.
10. Add Multiple Projects
The real advantage of VirtualHosts becomes apparent when you have multiple projects installed on the same machine.
For example :
/var/www/site1 |
/var/www/site2 |
/var/www/site3 |
You can create :
/etc/apache2/sites-available/site1.conf |
/etc/apache2/sites-available/site2.conf |
/etc/apache2/sites-available/site3.conf |
site1.conf
<VirtualHost *:80> |
ServerName site1.local |
DocumentRoot /var/www/site1 |
|
<Directory /var/www/site1> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
|
ErrorLog ${APACHE_LOG_DIR}/site1-error.log |
CustomLog ${APACHE_LOG_DIR}/site1-access.log combined |
</VirtualHost> |
site2.conf
<VirtualHost *:80> |
ServerName site2.local |
DocumentRoot /var/www/site2 |
|
<Directory /var/www/site2> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
|
ErrorLog ${APACHE_LOG_DIR}/site2-error.log |
CustomLog ${APACHE_LOG_DIR}/site2-access.log combined |
</VirtualHost> |
Then add the names to /etc/hosts :
127.0.0.1 site1.local |
127.0.0.1 site2.local |
Enable both sites :
sudo a2ensite site1.conf |
sudo a2ensite site2.conf |
Check the configuration :
sudo apachectl configtest |
And reload Apache :
sudo systemctl reload apache2 |
You can then access both applications with :
http://site1.local |
http://site2.local |
11. Use ServerAlias
If an application needs to be accessible via multiple names, use ServerAlias.
For example :
<VirtualHost *:80> |
ServerName my-project.local |
ServerAlias www.my-project.local |
|
DocumentRoot /var/www/my-project |
|
<Directory /var/www/my-project> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
|
ErrorLog ${APACHE_LOG_DIR}/my-project-error.log |
CustomLog ${APACHE_LOG_DIR}/my-project-access.log combined |
</VirtualHost> |
You will then be able to use :
[[[CODE_BLOCK_56]]
or :
http://www.my-project.local |
Also add both names in /etc/hosts :
127.0.0.1 my-project.local www.my-project.local |
Apache uses ServerName and ServerAlias to determine which VirtualHost should respond to a given request.
12. Should You Use NameVirtualHost?
With older versions of Apache, you might have encountered a directive like this :
NameVirtualHost *:80 |
It is not necessary with Apache 2.4.
A modern configuration on Debian 13 simply uses :
<VirtualHost *:80> |
ServerName my-project.local |
... |
</VirtualHost> |
Apache 2.4 natively handles name-based VirtualHosts.
Therefore, it's unnecessary to add NameVirtualHost *:80 in a new configuration.
13. Final Structure
At this stage, our installation looks like this:
/var/www/ |
βββ my-project/ |
βββ index.php |
|
/etc/apache2/ |
βββ sites-available/ |
β βββ my-project.conf |
βββ sites-enabled/ |
βββ my-project.conf -> ../sites-available/my-project.conf |
And /etc/hosts contains:
127.0.0.1 my-project.local |
The VirtualHost contains:
<VirtualHost *:80> |
ServerName my-project.local |
DocumentRoot /var/www/my-project |
|
<Directory /var/www/my-project> |
Options FollowSymLinks |
AllowOverride All |
Require all granted |
</Directory> |
|
ErrorLog ${APACHE_LOG_DIR}/my-project-error.log |
CustomLog ${APACHE_LOG_DIR}/my-project-access.log combined |
</VirtualHost> |
Conclusion
Setting up a VirtualHost for Apache on Debian 13 for PHP projects remains relatively straightforward.
The essential commands are:
sudo apt update |
sudo apt install apache2 php libapache2-mod-php |
Then:
sudo mkdir -p /var/www/my-project |
sudo nano /etc/apache2/sites-available/my-project.conf |
Add the domain in:
sudo nano /etc/hosts |
Then enable and verify the site:
sudo a2ensite my-project.conf |
sudo apachectl configtest |
sudo systemctl reload apache2 |
Finally:
sudo apachectl -S |
allows you to check which VirtualHosts are actually being used by Apache.
You can then access your project with:
http://my-project.local |
This method lets you replicate locally an organization similar to a real web server, while hosting multiple independent PHP projects on a single Debian 13 machine.
Comments
No approved comments yet.
Sign in with a commenter account to post a comment. Sign in.