MacOS: Step-by-Step Tutorial: Install PHP, Apache, and MySQL on macOS using Homebrew

This guide installs a clean local development stack on macOS using:

Apache  = httpd from Homebrew
PHP     = PHP from Homebrew
MySQL   = mysql@8.4 from Homebrew

Homebrew installs packages cleanly under its own directory and symlinks them into the Homebrew prefix, usually /opt/homebrew on Apple Silicon Macs. Homebrew’s official formulae provide httpd, php, and MySQL packages directly. (brew.sh)


1. Check your Mac type

Run:

uname -m

If output is:

arm64

You are using Apple Silicon, such as M1, M2, M3, or M4.

If output is:

x86_64

You are using an Intel Mac.

Most new Macs use this Homebrew path:

/opt/homebrew

Intel Macs usually use:

/usr/local

To avoid confusion, always use this command when you need the actual Homebrew path:

brew --prefix

2. Install Xcode Command Line Tools

Homebrew requires Apple’s Command Line Tools on macOS. Homebrew’s installation documentation lists Command Line Tools for Xcode as one of the macOS requirements. (Homebrew Documentation)

Run:

xcode-select --install

A popup may appear. Click Install.

After installation, verify:

xcode-select -p

Expected output may look like:

/Library/Developer/CommandLineTools

3. Install Homebrew

Run:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After installation, add Homebrew to your shell profile.

For Apple Silicon:

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"

For Intel Mac:

echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/usr/local/bin/brew shellenv)"

Verify:

brew --version

Example output:

Homebrew 4.x.x

4. Update Homebrew

Run:

brew update

You can also check your Homebrew health:

brew doctor

If you see:

Your system is ready to brew.

Perfect.


5. Install Apache

Homebrew’s Apache package is called httpd. The official Homebrew formula uses this command: brew install httpd. (Homebrew Formulae)

Run:

brew install httpd

Start Apache:

brew services start httpd

Check status:

brew services list

You should see something like:

httpd started

Check Apache version:

httpd -v

6. Test Apache

Homebrew Apache usually serves files from:

/opt/homebrew/var/www

On Intel Mac, it may be:

/usr/local/var/www

To find the correct location, run:

brew --prefix

If output is /opt/homebrew, your web root is:

/opt/homebrew/var/www

Create a simple test file:

echo "Apache is working on macOS" > "$(brew --prefix)/var/www/index.html"

Open in browser:

http://localhost:8080

You should see:

Apache is working on macOS

By default, Homebrew Apache commonly uses port 8080, which avoids conflict with macOS’s built-in Apache.


7. Install PHP

Run:

brew install php

Check PHP version:

php -v

Find PHP configuration files:

php --ini

This is useful later when you want to edit PHP settings like:

upload_max_filesize
post_max_size
memory_limit
max_execution_time

8. Connect PHP with Apache

Homebrew’s PHP formula provides the Apache configuration needed to load PHP. It specifically says to add the PHP module line, the PHP file handler, and ensure DirectoryIndex includes index.php. (Homebrew Formulae)

Open Apache config:

nano "$(brew --prefix)/etc/httpd/httpd.conf"

Find the LoadModule section and add this line:

LoadModule php_module /opt/homebrew/opt/php/lib/httpd/modules/libphp.so

For Intel Mac, use:

LoadModule php_module /usr/local/opt/php/lib/httpd/modules/libphp.so

A safer universal way is to first check your Homebrew prefix:

brew --prefix

Then use the matching path.

Now add this PHP handler somewhere near the other handler settings:

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Now search for:

DirectoryIndex index.html

Change it to:

DirectoryIndex index.php index.html

Save and exit:

CTRL + O
Enter
CTRL + X

Restart Apache:

brew services restart httpd

9. Test PHP with Apache

Create a PHP test file:

echo "<?php phpinfo(); ?>" > "$(brew --prefix)/var/www/index.php"

Open:

http://localhost:8080

If PHP is working, you will see the PHP information page.

After testing, remove the file because phpinfo() exposes system details:

rm "$(brew --prefix)/var/www/index.php"

Create a safer test file:

cat > "$(brew --prefix)/var/www/index.php" <<'EOF'
<?php
echo "PHP is working with Apache on macOS";
EOF

Open again:

http://localhost:8080

Expected output:

PHP is working with Apache on macOS

10. Install MySQL

For development, install MySQL 8.4:

brew install mysql@8.4

Homebrew lists mysql@8.4 as an available MySQL version. (Homebrew Formulae)

Start MySQL:

brew services start mysql@8.4

Check service:

brew services list

Add MySQL to your shell path:

echo 'export PATH="$(brew --prefix mysql@8.4)/bin:$PATH"' >> ~/.zprofile
source ~/.zprofile

Check MySQL version:

mysql --version

11. Secure MySQL

Run:

mysql_secure_installation

Recommended answers for local development:

Validate password component? Optional
Set root password? Yes
Remove anonymous users? Yes
Disallow root login remotely? Yes
Remove test database? Yes
Reload privilege tables? Yes

Now login:

mysql -u root -p

Enter your MySQL root password.

Test command:

SHOW DATABASES;

Exit:

exit;

12. Create a test database and user

Login:

mysql -u root -p

Create database:

CREATE DATABASE testapp;

Create user:

CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';

Give permission:

GRANT ALL PRIVILEGES ON testapp.* TO 'testuser'@'localhost';

Reload permissions:

FLUSH PRIVILEGES;

Exit:

exit;

Test login:

mysql -u testuser -p testapp

13. Test PHP connection with MySQL

Create test file:

cat > "$(brew --prefix)/var/www/dbtest.php" <<'EOF'
<?php
$host = "127.0.0.1";
$db   = "testapp";
$user = "testuser";
$pass = "StrongPassword123!";

try {
    $pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
    echo "PHP connected to MySQL successfully.";
} catch (PDOException $e) {
    echo "Database connection failed: " . $e->getMessage();
}
EOF

Open:

http://localhost:8080/dbtest.php

Expected result:

PHP connected to MySQL successfully.

14. Useful service commands

Start Apache:

brew services start httpd

Stop Apache:

brew services stop httpd

Restart Apache:

brew services restart httpd

Start MySQL:

brew services start mysql@8.4

Stop MySQL:

brew services stop mysql@8.4

Restart MySQL:

brew services restart mysql@8.4

Check all services:

brew services list

15. Important file locations

For Apple Silicon Macs:

Apache config:
 /opt/homebrew/etc/httpd/httpd.conf

Apache web root:
 /opt/homebrew/var/www

PHP module:
 /opt/homebrew/opt/php/lib/httpd/modules/libphp.so

MySQL binary:
 /opt/homebrew/opt/mysql@8.4/bin/mysql

For Intel Macs:

Apache config:
 /usr/local/etc/httpd/httpd.conf

Apache web root:
 /usr/local/var/www

PHP module:
 /usr/local/opt/php/lib/httpd/modules/libphp.so

MySQL binary:
 /usr/local/opt/mysql@8.4/bin/mysql

Universal commands:

brew --prefix
brew --prefix php
brew --prefix mysql@8.4

16. Optional: Change Apache port from 8080 to 80

By default, keep Apache on:

http://localhost:8080

This is safer because port 80 may conflict with macOS’s built-in Apache and usually requires root privileges.

But if you want:

http://localhost

Open Apache config:

nano "$(brew --prefix)/etc/httpd/httpd.conf"

Find:

Listen 8080

Change to:

Listen 80

Restart Apache with sudo:

sudo brew services restart httpd

But my recommendation: use port 8080 for local development.


17. Optional: Create a project folder

Instead of putting everything directly in Apache’s default web root, you can create your own project folder.

Example:

mkdir -p ~/Sites/myapp

Create file:

cat > ~/Sites/myapp/index.php <<'EOF'
<?php
echo "My PHP project is working";
EOF

Now update Apache config:

nano "$(brew --prefix)/etc/httpd/httpd.conf"

Find:

DocumentRoot "/opt/homebrew/var/www"
<Directory "/opt/homebrew/var/www">

Change both paths to your project:

DocumentRoot "/Users/YOUR_USERNAME/Sites/myapp"
<Directory "/Users/YOUR_USERNAME/Sites/myapp">

Replace YOUR_USERNAME with your macOS username.

You can get it using:

whoami

Also make sure this section allows access:

<Directory "/Users/YOUR_USERNAME/Sites/myapp">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

Restart Apache:

brew services restart httpd

Open:

http://localhost:8080

18. Enable .htaccess support

For Laravel, WordPress, CodeIgniter, Flarum, and many PHP apps, you may need .htaccess.

Open Apache config:

nano "$(brew --prefix)/etc/httpd/httpd.conf"

Find your directory block:

<Directory "/opt/homebrew/var/www">

Inside it, change:

AllowOverride None

To:

AllowOverride All

Also enable rewrite module. Find this line:

#LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so

Uncomment it:

LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so

Restart Apache:

brew services restart httpd

19. Common problems and fixes

Problem 1: localhost:8080 not opening

Check Apache service:

brew services list

Restart:

brew services restart httpd

Check Apache config syntax:

apachectl configtest

Expected:

Syntax OK

Problem 2: PHP file downloads instead of running

This means Apache is not processing PHP.

Check whether this exists in httpd.conf:

LoadModule php_module /opt/homebrew/opt/php/lib/httpd/modules/libphp.so

Also check:

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

Restart:

brew services restart httpd

Problem 3: mysql: command not found

Add MySQL to PATH:

echo 'export PATH="$(brew --prefix mysql@8.4)/bin:$PATH"' >> ~/.zprofile
source ~/.zprofile

Check:

mysql --version

Problem 4: Permission denied in web root

Check ownership:

ls -la "$(brew --prefix)/var/www"

Fix ownership:

sudo chown -R $(whoami):staff "$(brew --prefix)/var/www"

Then:

chmod -R 755 "$(brew --prefix)/var/www"

For files:

find "$(brew --prefix)/var/www" -type f -exec chmod 644 {} \;

For directories:

find "$(brew --prefix)/var/www" -type d -exec chmod 755 {} \;

Problem 5: Apache config has an error

Run:

apachectl configtest

If it shows a line number, open the file:

nano "$(brew --prefix)/etc/httpd/httpd.conf"

Fix the mentioned line.

Then restart:

brew services restart httpd

20. Final verification checklist

Run these commands:

brew services list

You should see:

httpd       started
mysql@8.4  started

Check Apache:

httpd -v

Check PHP:

php -v

Check MySQL:

mysql --version

Check browser:

http://localhost:8080

Check PHP:

http://localhost:8080/index.php

Check MySQL from PHP:

http://localhost:8080/dbtest.php

Recommended final setup

For your Mac, this is the clean structure:

Package manager: Homebrew
Apache config:   $(brew --prefix)/etc/httpd/httpd.conf
Web root:        $(brew --prefix)/var/www
PHP:             Homebrew PHP
MySQL:           mysql@8.4
URL:             http://localhost:8080

This setup is much cleaner than XAMPP for long-term PHP, WordPress, Laravel, Flarum, and custom development work on macOS.

Related Posts

MacOS: What is Homebrew and How to work with it?

1. What is Homebrew? Homebrew is a package manager for macOS. Simple meaning: Homebrew helps you install, update, remove, and manage software from the terminal. Example: Without…

Read More