Set up a local development server with XAMPP on Ubuntu
A local development server gives you a private place to build websites and APIs before they reach shared hosting or a production cloud. It lets you reproduce errors, test database changes, and experiment with PHP without affecting a live site. On Ubuntu, the quickest all-in-one route is the familiar XAMPP stack.
XAMPP bundles Apache, PHP, MariaDB, phpMyAdmin, and related tools into one archive. That makes it useful for learners, freelancers, and teams whose projects use the conventional PHP-and-MySQL layout. It also gives developers moving between Windows, macOS, and Ubuntu a similar dashboard and file structure.
The convenience comes with responsibilities. XAMPP is convenient for local work, but its default credentials and broad network settings are unsuitable for an internet-facing server. This guide keeps the service on the local machine, explains the important settings, and shows how to separate application databases from the administrative account.
The workflow covers preparation, installation, service checks, configuration, project setup, and routine maintenance. Commands are written for a current 64-bit Ubuntu release, using Bash and the standard sudo tool.
Prepare Ubuntu and check for conflicts
Use a currently supported 64-bit Ubuntu desktop or server. Ubuntu 22.04 LTS and 24.04 LTS are sensible baselines for a work machine, and the same commands suit a small Mini PC. Confirm the architecture and active release before downloading anything:
uname -m
lsb_release -a
The first command should end in x86_64. If lsb_release is missing, install it with sudo apt update && sudo apt install lsb-release, then run the check again.
Ubuntu may already provide Apache, MySQL, or MariaDB through its own packages. These services can claim the same ports as XAMPP, so inspect them before installation:
systemctl is-active apache2
systemctl is-active mysql
systemctl is-active mariadb
sudo ss -ltnp | grep -E ':(80|443|3306)\b'
If a service is active, decide which stack the machine will use. Do not stop a work server casually; create a test user, save any needed configuration, and make certain the other service can be disabled on this device. Australian homes and small offices often rely on NBN-connected broadband, although a phone hotspot may be the only connection while travelling. Local response times remain low in Sydney, Melbourne, Brisbane, or Perth, while remote access depends on the route and mobile coverage.
Install the XAMPP package
Download only from Apache Friends, the project that publishes XAMPP. Open its XAMPP for Linux page in the browser, choose the 64-bit archive for the current release, and copy its direct download address. Prepare Ubuntu and save the file in Downloads:
sudo apt update
sudo apt install wget
cd ~/Downloads
wget 'PASTE-THE-CURRENT-LINUX-64-BIT-URL-HERE'
Replace the placeholder with the copied address. The version number changes, so using a guessed file name can retrieve an obsolete package or an error page. Use the checksum or signature supplied by the download page, if provided, to detect a corrupted download.
Extract the archive, copy it to the conventional location, and keep the installation owned by root:
tar -xzf xampp-linux-x64-*.tar.gz
sudo mkdir -p /opt/lampp
sudo cp -a xampp/. /opt/lampp/
sudo chown -R root:root /opt/lampp
sudo chmod 755 /opt/lampp/lampp
Do not apply a blanket chmod 777 to the installation. The management script will ask for sudo when it starts services that bind to privileged ports or write to protected directories. Keep the downloaded archive until the installation has passed its checks.
Start the services and verify each layer
Start Apache, MariaDB, and the other bundled services, then request a status report:
sudo /opt/lampp/lampp start
sudo /opt/lampp/lampp status
A normal status report shows Apache and MySQL as running. ProFTPD may also start even if file transfer is not needed; it can be stopped separately with sudo /opt/lampp/lampp stopftp. The first launch can take several seconds while MariaDB initialises its data directory.
Open http://localhost/ in a browser. The XAMPP landing page should identify the local installation, and http://localhost/phpmyadmin/ should load the database administration interface. To test PHP, create a small file inside the web root:
printf '%s\n' '<?php echo "XAMPP is working on Ubuntu"; ?>' | sudo tee /opt/lampp/htdocs/health.php
Visit http://localhost/health.php. The browser should display the message without showing PHP source. Address-in-use errors usually mean Ubuntu’s Apache2 or database service already owns the port. Stop that service with sudo systemctl stop apache2 or sudo systemctl stop mysql only after confirming it is no longer needed, then restart XAMPP.
Configure Apache, PHP, and the database
The main Apache file is /opt/lampp/etc/apache2/httpd.conf, while PHP settings live in /opt/lampp/etc/php/php.ini. For local development, display_errors = On and error_reporting = E_ALL in php.ini make faults visible quickly. Set date.timezone to the relevant Australian zone, such as Australia/Sydney, Australia/Melbourne, Australia/Brisbane, or Australia/Perth; daylight-saving transitions are then handled by the operating system.
XAMPP’s MariaDB root account initially has no password. Open a terminal as the bundled database administrator:
sudo /opt/lampp/bin/mysql -u root
Create a root password and a separate account for each project. Replace the example password before running the statements:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'a-long-local-password';
CREATE DATABASE au_client_portal CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'portal_dev'@'localhost' IDENTIFIED BY 'another-long-password';
GRANT ALL PRIVILEGES ON au_client_portal.* TO 'portal_dev'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Enter the new root password when phpMyAdmin asks for it. In an application, put the database name and portal_dev credentials in a local .env file, then exclude that file from Git. Do not reuse the MariaDB root account in application code or commit its password to a repository. Apache can serve a plain path such as http://localhost/portfolio/, but a reserved local hostname makes URLs cleaner and avoids accidental internet requests.
Work on a realistic local project
Give the development user ownership of the web root, but not the entire XAMPP installation. This permits normal editing without making every application file writable by every account:
sudo chown -R "$USER":"$USER" /opt/lampp/htdocs
mkdir -p /opt/lampp/htdocs/au-client-portal
cd /opt/lampp/htdocs/au-client-portal
A simple virtual host can use the following block in /opt/lampp/etc/extra/httpd-vhosts.conf:
<VirtualHost *:80>
ServerName au-portal.test
DocumentRoot "/opt/lampp/htdocs/au-client-portal"
<Directory "/opt/lampp/htdocs/au-client-portal">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Map that name to the loopback address and restart Apache:
echo '127.0.0.1 au-portal.test' | sudo tee -a /etc/hosts
sudo /opt/lampp/lampp restart
Ensure Include conf/extra/httpd-vhosts.conf is active in httpd.conf. After restarting, open http://au-portal.test/ once you have added a PHP file. This setup suits a brochure site, booking form, or Australian client portal that later uses a .com.au domain and AUD payments; the local hostname requires no paid domain or public DNS record. Use phpMyAdmin to import a development SQL dump, keep composer.json, application code, views, and tests in the project folder, and use Git for version control. Include .env in .gitignore and provide a separate .env.example with blank values.
Secure the stack and make the first request
Restrict network exposure before using real-looking information. In httpd.conf, replace an active port-80 directive with Listen 127.0.0.1:80. In /opt/lampp/etc/my.cnf, add bind-address = 127.0.0.1 under [mysqld], then restart the stack. Do not create a router port forward for Apache, phpMyAdmin, or MariaDB. For access from another computer, use an SSH tunnel rather than exposing the ports on a home NBN connection or café Wi-Fi.
Back up databases and project files regularly. Export each schema with the bundled mysqldump tool, and archive the web root before upgrades. XAMPP is updated as a complete package rather than through apt; preserve /opt/lampp/var/mysql, configuration changes, and project data before replacing the installation. Never import live customer or patient records merely because the local copy seems harmless: check Australian Privacy Principles and project terms before handling identifiable information.
Make startup predictable by checking sudo /opt/lampp/lampp status after a reboot and starting the stack manually when needed. If Ubuntu’s native Apache or database services are enabled for another purpose, give them distinct ports rather than allowing either one to fail silently. A systemd unit can launch XAMPP at boot, but it should call the same management script and wait until local disk mounts are available.
Finish with one end-to-end check:
sudo mkdir -p /opt/lampp/htdocs/local-check
printf '%s\n' '<?php echo "XAMPP is ready"; ?>' | sudo tee /opt/lampp/htdocs/local-check/index.php
Open http://127.0.0.1/local-check/ once and confirm that the browser returns XAMPP is ready.