Virtual host wall

Set Up an Apache VirtualHost on Debian 13 for Local PHP Projects

0 comment(s)

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.local
  • http://blog.local
  • http://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:

Bash
sudo apt update
sudo apt upgrade

Then install Apache and PHP:

Bash
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:

Bash
apache2 -v
php -v

You should see something like:

Text
Server version: Apache/2.4.68

and:

Text
PHP 8.4.x

The exact revision numbers may naturally evolve with Debian security updates.

Also, verify that the Apache service is running:

Bash
sudo systemctl status apache2

If necessary:

Bash
sudo systemctl enable --now apache2

2. Create the Project Directory


We will place our project in:

Text
/var/www/my-project

Create the directory:

Bash
sudo mkdir -p /var/www/my-project

To quickly test the configuration, create a PHP file:

Bash
sudo nano /var/www/my-project/index.php

Add:

PHP
<?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:

Bash
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:

Text
/etc/apache2/sites-available/

Create the file:

Bash
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:

Text
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:

Text
/var/log/apache2/my-project-error.log

and access logs in:

Text
/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:

Bash
sudo nano /etc/hosts

Add:

Text
127.0.0.1 my-project.local

You can also use:

Text
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:

Text
/etc/apache2/sites-available/

This means it's available but not yet enabled.

Enable it with:

Bash
sudo a2ensite my-project.conf

You can also disable the default Apache VirtualHost if needed:

Bash
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:

Bash
sudo apachectl configtest

If everything is correct, you should get:

Text
Syntax OK

This step is crucial: it helps avoid reloading a configuration with syntax errors.

You can then reload Apache:

Bash
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:

Bash
sudo apachectl -S

You should see a line corresponding to:

Text
*: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:

Text
http://my-project.local

You should see:

Text
My project works!
PHP fonctionne avec Apache.

If you prefer to perform the test from the terminal, use:

Bash
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:

Bash
sudo nano /var/www/my-project/info.php

with:

PHP
<?php
phpinfo();

Then open:

Text
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:

Bash
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:

Bash
sudo a2enmod rewrite

Then check the configuration:

Bash
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 :

Text
/var/www/site1
/var/www/site2
/var/www/site3

You can create :

Text
/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 :

Text
127.0.0.1 site1.local
127.0.0.1 site2.local

Enable both sites :

Bash
sudo a2ensite site1.conf
sudo a2ensite site2.conf

Check the configuration :

Bash
sudo apachectl configtest

And reload Apache :

Bash
sudo systemctl reload apache2

You can then access both applications with :

Text
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 :

Text
http://www.my-project.local

Also add both names in /etc/hosts :

Text
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:

Text
/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:

Text
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:

Bash
sudo apt update
sudo apt install apache2 php libapache2-mod-php

Then:

Bash
sudo mkdir -p /var/www/my-project
sudo nano /etc/apache2/sites-available/my-project.conf

Add the domain in:

Bash
sudo nano /etc/hosts

Then enable and verify the site:

Bash
sudo a2ensite my-project.conf
sudo apachectl configtest
sudo systemctl reload apache2

Finally:

Bash
sudo apachectl -S

allows you to check which VirtualHosts are actually being used by Apache.

You can then access your project with:

Text
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.

You may also like:

Comments

No approved comments yet.

Sign in with a commenter account to post a comment. Sign in.