Set Up a Local Apache and PHP Server on elementary OS
A local web server turns an elementary OS computer into a private development environment for websites and web applications. Apache handles browser requests, PHP processes server-side code, and a browser lets you inspect the result at localhost without publishing anything to the internet. This is useful for learning, testing WordPress themes, building small PHP projects, or checking changes before deploying them to a hosted service.
The process is straightforward on elementary OS because it uses Ubuntu-compatible packages and tools. You will install Apache, add PHP and its Apache module, create a document root, test the service, and then apply sensible permissions and security settings. The commands below suit a current supported elementary OS release, although package names and PHP versions can change as the underlying Ubuntu base is updated.
Prepare elementary OS for the server
Before installing anything, open Terminal and update the package index. Keeping the system current reduces the chance of installing an old dependency or missing a security fix. The first command refreshes the list of available packages, while the second applies available upgrades:
sudo apt update
sudo apt upgrade
Install Apache, PHP, and a few common PHP extensions with:
sudo apt install apache2 php libapache2-mod-php php-cli php-mysql php-curl php-gd php-mbstring php-xml php-zip
Apache is the web server. The libapache2-mod-php package allows Apache to pass PHP files to the PHP interpreter. The remaining packages cover common application needs, including database connections, image handling, XML parsing, compressed archives, and multibyte text. If you only need a small practice environment, apache2 php libapache2-mod-php is enough.
The Apache service normally starts automatically after installation. Confirm that it is running:
sudo systemctl status apache2
Look for active (running). You can also use these commands to control it later:
sudo systemctl start apache2
sudo systemctl stop apache2
sudo systemctl restart apache2
sudo systemctl enable apache2
Open Firefox and visit http://localhost. The default Apache page should appear. You can also use http://127.0.0.1, which points to the same computer through the loopback network address. If the page does not load, check the service status first, then inspect recent messages with sudo journalctl -u apache2.
Create and test your first PHP page
Apache’s default website files are stored in /var/www/html. The directory usually contains an index.html file, which Apache displays before a PHP file with another name. You can replace the default page or keep it as a reference. For a quick test, create a PHP file:
sudo nano /var/www/html/info.php
Add this content:
<?php
phpinfo();
Save the file, close the editor, and visit http://localhost/info.php. The resulting page displays the installed PHP version, enabled modules, configuration paths, and server variables. This confirms that Apache is executing PHP rather than offering the file as plain text.
Delete the file immediately after testing:
sudo rm /var/www/html/info.php
A phpinfo() page exposes useful details to anyone who can access the server, so it should never remain on a public host. On a development machine, it is generally safe while Apache is bound to local access, but removing it is still good practice.
Create a simple project page instead:
sudo nano /var/www/html/index.php
Use:
<?php
$message = "PHP is working on elementary OS";
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Local PHP test</title>
</head>
<body>
<h1><?= htmlspecialchars($message, ENT_QUOTES, 'UTF-8') ?></h1>
</body>
</html>
When you reload http://localhost, Apache should process the PHP code and show the message as HTML. The htmlspecialchars call is a useful habit because it escapes text before placing it in a page. Even in a local project, treating output safely makes it easier to move code to a staging or production server later.
Choose a workflow that fits your project
A traditional Apache installation is convenient when you want a close approximation of shared hosting. Your files live in /var/www/html, Apache starts with the system, and a browser can access the project immediately. This approach works well for PHP tutorials, small CMS installations, and applications that need Apache-specific features such as .htaccess.
PHP’s built-in server is lighter for a single project. From a project directory, run:
php -S localhost:8000
The site will be available at http://localhost:8000, and stopping the Terminal process stops the server. It is handy for quick experiments, but it is not a replacement for Apache in production. It does not reproduce every Apache module, access rule, virtual host setting, or performance characteristic.
| Setup | Best use | Address | Main advantage | Important limitation |
|---|---|---|---|---|
| Apache with PHP module | Shared-hosting-style development | http://localhost |
Closely resembles a conventional Linux web server | Needs service and permission management |
| PHP built-in server | Small scripts and prototypes | http://localhost:8000 |
Minimal setup and quick startup | Intended for development, not public hosting |
| Apache virtual host | Several local websites | Custom local domain | Separate settings and document roots | Requires hosts-file and configuration work |
| Container-based stack | Repeatable team projects | Usually a mapped local port | Keeps dependencies isolated | Adds Docker or Podman complexity |
If you plan to build several sites, create a separate virtual host instead of placing everything in the default document root. Make a project directory:
sudo mkdir -p /var/www/example.test/public
sudo chown -R "$USER":www-data /var/www/example.test
sudo chmod -R 750 /var/www/example.test
Create a configuration file:
sudo nano /etc/apache2/sites-available/example.test.conf
Add:
<VirtualHost *:80>
ServerName example.test
DocumentRoot /var/www/example.test/public
<Directory /var/www/example.test/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.test-error.log
CustomLog ${APACHE_LOG_DIR}/example.test-access.log combined
</VirtualHost>
Enable the site and reload Apache:
sudo a2ensite example.test.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
The configuration test should report Syntax OK. Add the local name to /etc/hosts:
sudo nano /etc/hosts
Add:
127.0.0.1 example.test
You can now visit http://example.test. A custom local domain is especially useful when an application expects a fixed hostname, uses cookies, or needs several separate projects. If desktop layout experiments are part of your workflow, the XFCE panel alternative guide can help organise launchers and windows while you work across Terminal, a browser, and an editor.
Fix permissions, modules, and common errors
Linux web servers run with carefully controlled permissions. The Apache process commonly uses the www-data group, while your normal account owns the project files. Giving your account ownership and using group-readable permissions lets you edit files without making the entire web directory writable by every process.
Avoid commands such as:
sudo chmod -R 777 /var/www/html
They remove useful protection and can allow unintended changes if a vulnerable script is executed. A safer pattern is to own development files as your user and give the web server only the access it needs. For a simple project, the earlier chown and chmod commands are adequate. Applications that must write uploads or cache files should have only those specific directories made writable.
If Apache displays PHP source code instead of executing it, verify the PHP Apache module:
sudo a2enmod php*
sudo systemctl restart apache2
The wildcard may enable more than one matching module on some releases, so you can inspect enabled modules with:
apache2ctl -M | grep php
If the command reports a PHP module, Apache should process .php files. Also check that the file ends in .php and that you are loading the correct virtual host. A browser cache can sometimes make an old result appear, so reload the page fully.
When a page returns “Forbidden”, inspect ownership, directory permissions, and the <Directory> block in the virtual host. When Apache refuses to restart, run:
sudo apache2ctl configtest
sudo journalctl -u apache2 --no-pager -n 50
Apache’s logs are stored under /var/log/apache2. The access log records requests, while the error log often identifies missing files, PHP failures, permission problems, or invalid directives. Reading these logs is a core web administration skill and is usually faster than guessing.
A database-backed application may also need MariaDB:
sudo apt install mariadb-server php-mysql
sudo systemctl enable --now mariadb
Use the database hardening utility where appropriate, and create a separate database user for each application rather than relying on the database administrator account. Keep credentials in a local configuration file that is excluded from version control.
Keep the local environment safe and useful
A server running on localhost is normally reachable only from the same computer. Check Apache’s listening sockets with:
sudo ss -tulpn | grep apache
If you later make the server accessible on your home network, remember that any device on that network may be able to view it. Avoid exposing development Apache directly to the internet through router port forwarding. A local project can contain unfinished code, test credentials, uploaded documents, or private customer data.
If you need a firewall, elementary OS can use Ubuntu’s uncomplicated firewall interface:
sudo apt install ufw
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
You do not need to open port 80 for a server used only through localhost. If another device on your network must access it, allow HTTP deliberately and restrict the network where possible. Be careful with remote access on public Wi-Fi in places such as a Melbourne café or a Brisbane coworking space.
Australian developers should also treat personal information carefully. The Privacy Act 1988 and Australian Privacy Principles can apply to organisations handling personal data, especially when a local test database contains real customer records. Use fictional data, remove production exports after testing, and avoid storing Medicare details, payment information, or unnecessary contact records on a development laptop. Australian businesses also commonly host projects in Sydney or Melbourne data centres, but a local server is still a development tool, not a substitute for reviewing the host’s security, backups, and data-handling terms.
For a practical reference point on Linux applications and community resources, a Linux software resource can complement distribution-specific documentation. Keep your own notes on package versions, enabled modules, virtual hosts, and database setup so the environment can be recreated after a system upgrade.
Before using a project, confirm that Apache starts cleanly, PHP reports the expected version, and the application’s logs contain no unexplained warnings. Back up source code with Git, but keep passwords and local environment files out of the repository. When a project is ready to deploy, use a supported PHP release, HTTPS, restricted file permissions, regular updates, and a separate production configuration.
The essential pattern is simple: install Apache and PHP from the package manager, test them through localhost, keep projects organised under suitable document roots, and troubleshoot through service status and logs. On elementary OS, that gives you a capable local web server without publishing unfinished work, while careful permissions and privacy practices keep the development environment safe.