A tutorial on running a local Apache, MySQL, multiple PHP versions server on macOS Mojave using HomeBrew, updated for 2019. Bonus points: you can change the PHP version using the site's .htaccess like you would on most live hosts.
A few years ago I had written a blog post on setting up an Apache, MySQL and PHP web server on macOS. Many things have changed ever since and that tutorial became impossible to follow. Meanwhile my standard fallback local server, MAMP, has become too unstable and lagging behind the times to be practical. Other blog posts I read seem to be glossing over some details. So here you go, a tutorial on running a local Apache, MySQL, multiple PHP versions server on macOS Mojave using HomeBrew, updated for 2019. Bonus points: you can change the PHP version using the site's .htaccess like you would on most live hosts. Before proceeding, I'd like to explain why I got into all this trouble instead of using MAMP. In fact, I was using MAMP Pro. It was slow, idiosyncratic and randomly crashing in ways that required me to log out or, worse, restart my Mac. It is also using outdated versions, it's too expensive for the glorified interface to free (and free of charge!) software that it is and its support was utterly useless. So I tried building my own local server following someone else's tutorials written for macOS High Sierra but found out that Homebrew was now subtly broken in macOS Mojave. No problem, I am used to fixing broken stuff and writing step-by-step instructions so other people don't have to go through the same pain. So here you are: a massive blog post detailing everything I've done to set up a stable, reliable local server with all the bells and whistles on two different Macs.
Our goal
We are going to install a local server with Apache, MySQL 5.7 and three versions of PHP (5.6, 7.2 and 7.3). We'll also install Redis. Our sites will be served from the Sites folder inside the user's home directory. The Apache server will be running as our user. PHP is also running as our user. This is great for local development. We are going to use a self-signed SSL certificate, similar to what I described in my post on forging SSL certificates yourself, adapted for the Mac. PHP will be working through PHP-FPM (FastCGI Process Manager). This is the most well performing, stable and recommended way to run PHP. It also allows us to swap PHP versions using .htaccess just like we'd do on most live hosts. If you've used my previous tutorials for macOS, Windows or Linux you'll probably notice that I used to have a different domain name for each PHP version. I no longer do that because of WordPress. WordPress hard-codes the URL to the site in several places, making it very painful to switch to a different PHP version using domain names. The .htaccess method is far easier. As a bonus, the plumbing that goes into supporting it makes PHP even faster than my multiple domains method!
Before you begin
This tutorial is meant to be followed by developers, be it front-end or backend. Some familiarity with the command line is appreciated but not required. At the very least you should not be afraid to use Terminal. Now would also be a great time to take a backup of your Mac, e.g. using Time Machine, in case you break something.
Install XCode
We need a working compilation toolchain to continue. This is used by HomeBrew itself in some cases (more about HomeBrew later) and also when we need to compile some PHP extensions which are not bundled with the HomeBrew package. For this you need XCode. You can install XCode from the App Store. It's free of charge. XCode is Apple’s all-in-one development package which includes system headers and the all important build toolchain (C compiler, automake, autoconf and so on and so forth). Now open XCode and accept the license. It will take a while. After it's done it will open the XCode app itself. We don’t need the actual application running. You can quit it. Now, we need to install the command line tools and development headers for our version of macOS. This is something necessary from macOS Mojave onwards. They are no longer installed on the system when you install XCode. So let's launch the package which does the installation:
open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
Readers with other macOS versions: 10.14 is the version number for macOS Mojave. Substitute your macOS version number.
Install HomeBrew
As I've done in my previous tutorials for the Mac, I use Homebrew. If you’re new to macOS, Homebrew is the de facto package manager for macOS. It allows us to install and upgrade libraries and tools in a simple and sensible manner. Follow the instructions on the link above to install Homebrew.
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Update HomeBrew
Open a Terminal and enter the following.
brew update brew upgrade
This will tell HomeBrew to update itself and install updates to things already installed (in case you had already installed HomeBrew).
Disable your existing local server
If you are using MAMP, XAMPP or any other kind of local development server you need to shut it down now. If you already have sites installed on it remember to back them up. Once we're done the old local server will no longer work. If you were using MAMP and you had selected the "Make this version available on the command line" option in its interface you will need to edit the ~/.profile file to remove MAMP from the PATH. If you are using a local server that's based on virtualization (e.g. Local by Flywheel, Docker, vvv, Vagrant and so on) you need to shut these down too. Quit Skype if you're using it. Sometimes it binds to port 80 which is normally used by the web server. It's annoying and will cause some false starts and a lot of frustration.
Installing Apache, MySQL and PHP
In this section we are going to do the initial installation and basic configuration of Apache, MySQL, three versions of PHP and Redis. At the end of this section everything will be working on its own but will not yet be set up to work together.
Install Apache
Installing Apache with HomeBrew is simple.
brew install httpd brew link httpd brew services start httpd
The first line installs Apache (traditionally called httpd, short for "http daemon" where "daemon" is how UNIX systems called background server processes). The second line creates symlinks so we can access Apache's executables from the command line. The third line installs and starts a system service which will be launching Apache when we restart our Mac.
Necessary Apache fix
Since Apache runs as our own user, not root, we need to set up the directory where it stores its process identified file to be writeable by our own user. Otherwise Apache will start... but not really. BTW, even if we didn't change the ownership of the Apache process we'd need to create and set up the correct ownership of that folder anyway. It looks like Homebrew on Mojave makes some really weird choices which result in some servers not really working out of the box. Here's what you need to do
sudo mkdir /usr/local/var/run/httpd sudo chown -R $(whoami):staff /usr/local/var/run/httpd
Change the Apache root to ~/Sites
As we discussed, we want Apache to look for our sites in the Sites folder under our user's folder. Let's create the folder first.
mkdir ~/Sites cd ~/Sites pwd
The last command prints out something like
/Users/nicholas/Sites
Note this down. This is the new Apache document root we need to configure in the next step. From the Terminal run the following.
open /usr/local/etc/httpd/httpd.conf -a TextEdit
It opens Apache's configuration file in TextEdit. Find the lines
DocumentRoot "/usr/local/var/www" <Directory "/usr/local/var/www">
and change them to read
DocumentRoot "/Users/nicholas/Sites" <Directory "/Users/nicholas/Sites">
Where /Users/nicholas/Sites is the new Apache document root you noted down above when you ran the pwd command. Save & close the file. Then restart the Apache server.
brew services restart httpd
Change Apache port and user, allow .htaccess files
By default Apache is set up to use port 8080 and a user and user group called _www. Also, it's set up to not allow .htaccess files to override any settings. None of that helps if you want to do anything useful on your local server. We're going to set up Apache to use port 80, your own user and allow .htaccess files. From the Terminal run the following.
whoami open /usr/local/etc/httpd/httpd.conf -a TextEdit
The first line prints out your username, e.g. nicholas. Note it down. The second line opens Apache's configuration file in TextEdit. Find the line
Listen 8080
and change it to
Listen 80
Find the lines
User _www Group _www
and change them to
User nicholas Group staff
Remember that nicholas in the example above should be replaced with your username, the one you found by running whoami above. Now find the lines
# # AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # AllowOverride FileInfo AuthConfig Limit # AllowOverride None
and change them to
# # AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # AllowOverride FileInfo AuthConfig Limit # AllowOverride All
Watch out! There are two instances of the AllowOverride None line but only one preceded by the comment block (the lines starting with #) above. You must only change the line preceded by the comment block, not the other one. Save & close the file. Then restart the Apache server.
brew services restart httpd
At this point if you go to http://localhost you should see an error telling you the page is not found. If you any other error (like, the server is not found or not responding) you did something wrong. Go back and trace your steps. You probably forgot to create the /usr/local/var/run/httpd folder or give it the correct permissions.
Install MySQL
Likewise for MySQL 5.7.
brew install mysql@5.7 brew link mysql@5.7 --force brew services start mysql@5.7
The --force part of the second line is mandatory. It has to do with how HomeBrew works. If you omit it, it will complain that it can not link MySQL. At this point your MySQL database only has one user called root with an empty password. You can use these credentials to connect to your database with a database administration tool such as Sequel Pro (free of charge). It is also recommended that you use Sequel Pro's "Users" tool to change the password of the root user. Trust me, this will save you from an embarrassing moment down the line.
Install PHP
Next up, we're going to install all three PHP versions we are interested in:
brew install php@5.6 brew install php@7.2 brew install php@7.3
The way macOS Mojave ships, some of the directories HomeBrew needs to write files to are not writeable. We can fix that with the following commands. macOS will ask you to enter your password before running them; this is normal.
sudo chown -R $(whoami):staff /usr/local/include/php/ sudo chown -R $(whoami):staff /usr/local/lib/php/ sudo chown -R $(whoami):staff /usr/local/etc/php/
Now we can set up PHP 7.3 as the default PHP version on our Mac:
# Set PHP 7.3 as the default PHP version brew unlink php brew link --overwrite --force php@7.3
PHP necessary fix #1: configuration files
Here's a small problem. For some strange reason HomeBrew "forgets" to copy the configuration files to a place where each PHP version can find them. We have to fix that ourselves.
# Install configuration files for PHP 5.6 cd $(brew --prefix php@5.6) cp -R .bottle/* /usr/local/ # Install configuration files for PHP 7.2 cd $(brew --prefix php@7.2) cp -R .bottle/* /usr/local/ # Install configuration files for PHP 7.3 cd $(brew --prefix php@7.3) cp -R .bottle/* /usr/local/
PHP necessary fix #2: PHP-FPM listening ports
All PHP versions are set up to start a PHP-FPM (PHP FastCGI Process Manager) server listening to the same port, 9000. This can not work, of course. Moreover, we really need port 9000 available for XDebug. Thus, we are going to have each PHP-FPM version listen to a different port: 9056 for PHP 5.6, 9072 for PHP 7.2 and 9073 for PHP 7.3. Yes, the convention is 90 followed by the PHP version without the dot. It's easier to remember that way. Moreover, while we're at it, we're going to have PHP run under our user and the built-in user group staff. For PHP 5.6 run
open /usr/local/etc/php/5.6/php-fpm.conf -a TextEdit
This opens a file in TextEdit. Find the lines:
user = _www group = _www
and change them to
user = nicholas group = staff
where, of course, nicholas is your username. If you are not sure what is your username run whoami in the Terminal. A little further down you'll find
listen = 127.0.0.1:9000
Change this to
listen = 127.0.0.1:9056
Save and close the file. For PHP 7.2 run
open /usr/local/etc/php/7.2/php-fpm.d/www.conf -a TextEdit
Make the same changes as for PHP 5.6 with one difference. The listen line should read:
listen = 127.0.0.1:9072
For PHP 7.3 run
open /usr/local/etc/php/7.3/php-fpm.d/www.conf -a TextEdit
Make the same changes as for PHP 7.2 with one difference. The listen line should read:
listen = 127.0.0.1:9073
Start the PHP-FPM services
Now we can install and start the PHP-FPM system services for all three PHP versions we have installed.
brew services start php@5.6 brew services start php@7.2 brew services start php@7.3
Install Redis
Finally, we can install Redis.
brew install redis brew link redis brew services start redis
Getting PHP to work with Apache
Right now we have PHP-FPM running, we have Apache running but they don't talk to each other. As a result, you can't run PHP scripts from Apache. We need to fix this. As we've done before run the following on a Terminal to open Apache's configuration file.
open /usr/local/etc/httpd/httpd.conf -a TextEdit
You need to find the following lines (they are non-contiguous) and remove the # in front of them:
#LoadModule deflate_module lib/httpd/modules/mod_deflate.so #LoadModule mime_magic_module lib/httpd/modules/mod_mime_magic.so #LoadModule expires_module lib/httpd/modules/mod_expires.so #LoadModule proxy_module lib/httpd/modules/mod_proxy.so #LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so #LoadModule proxy_fcgi_module lib/httpd/modules/mod_proxy_fcgi.so #LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so
The proxy_* lines are necessary to run PHP at all. The other lines enable features commonly used by PHP CMS, e-commerce, forum etc scripts. They are typically enabled on live hosts so we need to enable on our local host to have a similar environment. Now find the line
<Directory "/Users/nicholas/Sites">
where "nicholas" is your username. You may remember that we found this earlier by running whoami on a Terminal. Add the following after it
<FilesMatch "\.php$"> SetHandler "proxy:fcgi://localhost:9073/" </FilesMatch>
This may look like black magic so let's explain this a bit. We are telling Apache that any file inside the directory /Users/nicholas/Sites which matches the regular expression \.php$ (its name ends in .php) is to be handled by the FastCGI proxy and forwarded to port 9073 on our local machine. Remember when we set up the PHP versions we configured a different port for each PHP-FPM version; 9073 is the one for PHP 7.3's PHP-FPM. So we have effectively told Apache to parse all PHP files with PHP 7.3 by default. Save and close the file, then restart the Apache server.
brew services restart httpd
We are going to create a new test file to make sure PHP is working:
cat << EOL > ~/Sites/test.php <?php phpinfo(); EOL
Now access http://localhost/test.php on your browser. You should see PHP's information page saying that you are running PHP 7.3.0 (or whatever PHP version got installed). But I promised you different PHP versions, didn't I? Let switch to PHP 5.6. We will create a .htaccess file inside the ~/Sites folder which does exactly that.
cat << EOL > ~/Sites/.htaccess <FilesMatch "\.php$"> SetHandler "proxy:fcgi://localhost:9056/" </FilesMatch> EOL
Reload the page. Now the PHP version is 5.6.39! These three magic lines told Apache to substitute the default proxying of .php files through PHP 7.3 with proxying through PHP 5.6. Likewise for PHP 7.2:
cat << EOL > ~/Sites/.htaccess <FilesMatch "\.php$"> SetHandler "proxy:fcgi://localhost:9072/" </FilesMatch> EOL
Reload the page, now you get PHP 7.2. If you were to remove the .htaccess
rm ~/Sites/.htaccess
and reload the page you are back to PHP 7.2. Isn't that cool? Much easier than MAMP's user-hostile set-up-the-host-again-and-wait-forever-to-restart-all-servers approach. We're cooking with gas, folks! If you're happy accessing sites as subdirectories of http://localhost you are done. If you want to add that special extra sauce to make things smoother for your development experience keep reading!
One subdomain per site
For the longest time I've used the convention of the domain name foobar.local.web being used to access a site sitting in the foobar folder on my local server. This preserves my sanity since I can easily correlate the site I'm working on with the folder I'm looking at. Ever since I found out about Apache's mod_vhost_alias I am using it to easily create this kind of subdomain hosting without having to reconfigure Apache for each site I add to the server.
Setting up the subdomain resolution
First of all, we need to tell macOS about our sites' subdomains. Since there is no public DNS server matching them with IP addresses we need to edit macOS' /etc/hosts file. The easiest tool to do that is GasMask. After installing GasMask click on its icon which, unsurprisingly, looks like a gas mask and click on Show Editor to display the main wondow. From the top toolbar choose Create, Local and name the new file My Sites. Click on it and then click on Activate on the toolbar to activate this file. On the right hand editor you can set up the IP to hostname assignment. The IP is the first thing you enter. Then you can enter one or more hostnames separated by spaces. For example:
127.0.0.1 www.local.web 127.0.0.1 wordpress.local.web joomla.local.web 127.0.0.1 client1.local.web client2.local.web client3.local.web
You get the idea. Save and close that file but do not quit GasMask. Tip: With the GasMask editor open go to GasMask, Preferences from the top menu, click on General and activate Open at Login. Otherwise you need to run GasMask every time you want to use your local web server.
Set up Apache with virtual host aliasing
As we've done before run the following on a Terminal to open Apache's configuration file.
open /usr/local/etc/httpd/httpd.conf -a TextEdit
You need to find the following line
#LoadModule vhost_alias_module lib/httpd/modules/mod_vhost_alias.so
and remove the # in front so it now reads
LoadModule vhost_alias_module lib/httpd/modules/mod_vhost_alias.so
Find these lines
# Virtual hosts #Include /usr/local/etc/httpd/extra/httpd-vhosts.conf
and append one more line so they now read
# Virtual hosts #Include /usr/local/etc/httpd/extra/httpd-vhosts.conf Include /usr/local/etc/httpd/extra/local.web.conf
This tells Apache to load one more file which contains the configuration for our local.web sites. Save the file and close TextEdit. Back in the Terminal enter the following
touch /usr/local/etc/httpd/extra/local.web.conf open /usr/local/etc/httpd/extra/local.web.conf -a TextEdit
This opens a new, empty file. Paste the following:
<VirtualHost *:80> ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. DocumentRoot "/Users/nicholas/Sites" ServerName local.web ServerAlias www.local.web #ErrorLog "/usr/local/var/log/httpd/local.web.error_log" #CustomLog "/usr/local/var/log/httpd/local.web.access_log" common <Directory "/Users/nicholas/Sites"> AllowOverride All DirectoryIndex index.html index.php Require all granted #See https://wiki.apache.org/httpd/PHP-FPM <FilesMatch "\.php$"> SetHandler "proxy:fcgi://127.0.0.1:9073/" </FilesMatch> </Directory> </VirtualHost> <VirtualHost *:80> ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. ServerAlias *.local.web UseCanonicalName Off VirtualDocumentRoot "/Users/nicholas/Sites/%1" #ErrorLog "/usr/local/var/log/httpd/local.web.error_log" #CustomLog "/usr/local/var/log/httpd/local.web.access_log" common <Directory "/Users/nicholas/Sites"> AllowOverride All DirectoryIndex index.html index.php Require all granted #See https://wiki.apache.org/httpd/PHP-FPM <FilesMatch "\.php$"> SetHandler "proxy:fcgi://127.0.0.1:9073/" </FilesMatch> </Directory> </VirtualHost>
There are only two things you need to be careful about:
- /Users/nicholas/Sites is the path to the new Apache document root, as you have set it up when installing Apache earlier.
- 9073 is the port that PHP-FPM listens to. Remember, 9073 is for PHP 7.3. If you want a different default PHP version change that.
Afterwards, restart Apache
brew services restart httpd
Both http://localhost and http://www.local.web display the same pages now. If you were to create a folder called client1 in the Sites folder under your user directory you'd be able to access its contents as any of the following:
- http://client1.local.web (preferred)
- http://localhost/client1 (traditional)
- http://www.local.web/client1 (not recommended)
Enable XDebug
No PHP development environment is complete without XDebug, the most popular PHP debugger. Unfortunately, XDebug does not
ship with HomeBrew's PHP so we need to install it with PECL. To complicate the matters more, we need to do this for all installed PHP versions. For each version this requires a small dance of unlinking PHP, relinking it, installing XDebug and then again unlinking PHP and relinking the default version. Are you dizzy yet? After we're done we'll have installed XDebug on all three versions of PHP. XDebug remote debugging will be enabled but not started by default. You will need to use the IDE key PHPSTORM to do that. The easiest way is through bookmarklets created with PhpStorm's bookmarklet generator.
XDebug for PHP 5.6
brew unlink php brew link --force --overwrite php@5.6 pecl install xdebug-2.5.5 brew unlink php@5.6 brew link --force --overwrite php@7.3
If you got any errors during the pecl install stage please refer to my blog post on compiling PHP on macOS and follow the "Prerequisites" section only, then retry the commands above. When you ran the pecl install command it printed a lot of stuff ending with something like this
You should add "zend_extension=/usr/local/Cellar/php@5.6/5.6.39/pecl/20131226/xdebug.so" to php.ini
Note down the part in bold letters. This will be different for each PHP version. You need to paste it below. Now we need to edit PHP 5.6's php.ini and tell it to load XDebug:
open /usr/local/etc/php/5.6/php.ini -a TextEdit
At the bottom of the file, right above the "; Local Variables:" line add the following:
[xdebug] zend_extension=/usr/local/Cellar/php@5.6/5.6.39/pecl/20131226/xdebug.so xdebug.remote_enable=1 xdebug.remote_host=localhost xdebug.remote_port=9000 xdebug.remote_autostart=0 xdebug.idekey=PHPSTORM
Again, the line in bold corresponds to the bold part of the message I told you to copy. Finally, restart PHP-FPM for PHP 5.6
brew services restart php@5.6
XDebug for PHP 7.2
brew unlink php brew link --force --overwrite php@7.2 pecl install xdebug brew unlink php@7.2 brew link --force --overwrite php@7.3
When you ran the pecl install command it printed a lot of stuff ending with something like this
You should add "zend_extension=/usr/local/Cellar/php@7.2/7.2.13/pecl/20170718/xdebug.so" to php.ini
Note down the part in bold letters. This will be different for each PHP version. You need to paste it below. As before, we need to edit PHP 7.2's php.ini and tell it to load XDebug:
open /usr/local/etc/php/7.2/php.ini -a TextEdit
At the bottom of the file, right above the "; Local Variables:" line add the following:
[xdebug] zend_extension=/usr/local/Cellar/php@7.2/7.2.13/pecl/20170718/xdebug.so xdebug.remote_enable=1 xdebug.remote_host=localhost xdebug.remote_port=9000 xdebug.remote_autostart=0 xdebug.idekey=PHPSTORM
Finally, restart PHP-FPM for PHP 7.2
brew services restart php@7.2
XDebug for PHP 7.3
Since PHP 7.3 is the default version we don't need to go through the unlink/relink dance. However, at the time of this writing there is no stable version of XDebug supporting PHP 7.3. Therefore we have to explicitly tell it to use the latest beta version compatible with PHP 7.3.
pecl install xdebug-2.7.0beta1
When you run this command it prints a lot of stuff ending with something like this
You should add "zend_extension=/usr/local/Cellar/php/7.3.0/pecl/20180731/xdebug.so" to php.ini
Note down the part in bold letters. This will be different for each PHP version. You need to paste it below. As before, we need to edit PHP 7.3's php.ini and tell it to load XDebug:
open /usr/local/etc/php/7.3/php.ini -a TextEdit
At the bottom of the file, right above the "; Local Variables:" line add the following:
[xdebug] zend_extension=/usr/local/Cellar/php/7.3.0/pecl/20180731/xdebug.so xdebug.remote_enable=1 xdebug.remote_host=localhost xdebug.remote_port=9000 xdebug.remote_autostart=0 xdebug.idekey=PHPSTORM
Finally, restart PHP-FPM for PHP 7.3
brew services restart php@7.3
Install MailHog
MailHog is a small application which intercepts email sent out of your sites and keeps it locally. You can use a web interface to review the mail. This comes in handy when testing the email features of the sites you are building without risking any email accidentally escaping to the wild. We can install it through HomeBrew
brew install mailhog brew services start mailhog
Your Mac will ask you if you want to allow incoming connections from MailHog. Allow them. Every time your Mac starts so will MailHog. It is set up by default with
- the SMTP server on port 1025
- the HTTP server on port 8025 (this means you can see the intercepted e-mails aby pointing your browser to http://localhost:8025/)
- in-memory message storage
- a sendmail-compatible script at /usr/local/bin/mhsendmail
You can use it from PHP in two ways. For scripts which allow you to set up your own mail settings (e.g. Joomla!, Akeeba Solo etc) just tell them to use SMTP on localhost, port 1025 without authentication. For scripts which go through PHP's mail() function (e.g. WordPress) you need to change your php.ini file's sendmail_path line to
sendmail_path = /usr/local/bin/mhsendmail
I explain where php.ini files are and how to change them below. Alternatively, create a file named .user.ini (note the dot in front!) in your site's root directory and put that line there. Note that it may take up to 5' for the new settings to activate.
PHP configuration
The default PHP configuration is not very good if you're planning or running most well known PHP CMS, e-commerce etc scripts on your local host. You need to modify them. First, you should know their location:
- /usr/local/etc/php/5.6/php.ini for PHP 5.6
- /usr/local/etc/php/7.2/php.ini for PHP 7.2
- /usr/local/etc/php/7.3/php.ini for PHP 7.3
You can open them for editing with a command like
open /usr/local/etc/php/5.6/php.ini -a TextEdit
in Terminal. Here are the lines I tend to change on my local server (they are not consecutive in the php.ini file)
; Reload the .user.ini file every 60 seconds instead of every 5' user_ini.cache_ttl = 60 ; Log errors error_log = /usr/share/var/log/php-error.log ; Maximum POST size 20M. Must be at least 1.5x larger than upload_max_filesize post_max_size = 20M ; Maximum upload file size 10M. Don't set it lower than 5M. upload_max_filesize = 10M ; Default timezone settings. I use settings for Nicosia, Cyprus. date.timezone = Asia/Nicosia date.default_latitude = 35.185566 date.default_longitude = 33.382275 ; Write to PHAR files. I need this because I build PHAR files. phar.readonly = Off ; I use MailHog for catching e-mail smtp_port = 1025 sendmail_path = /usr/local/bin/mhsendmail ; Enable OPcache with conservative, developer-friendly settings opcache.enable=1 opcache.enable_cli=1 opcache.max_accelerated_files=10000 opcache.use_cwd=1 opcache.validate_timestamps=1 opcache.revalidate_freq=5 opcache.save_comments=1 opcache.load_comments=1 opcache.enable_file_override=1 opcache.dups_fix=1 opcache.error_log=/usr/local/var/log/php-opcache-error.log ; XDebug settings, as we explained earlier xdebug.remote_enable=1 xdebug.remote_host=localhost xdebug.remote_port=9000 xdebug.remote_autostart=0 xdebug.idekey=PHPSTORM
After changing the PHP configuration remember to restart the PHP-FPM service for that PHP version, e.g.
brew services restart php@5.6
Creating and installing an SSL certificate
Most people think of HTTPS as something you need only on live servers, to protect the privacy of the data exchanged between your server and your visitors' browsers. However, there are some newer web APIs which only work on HTTPS sites for security reasons, for example FIDO U2F (two step verification with hardware security keys). Or you may want to test if your site works when you use HTTPS Everywhere, a browser plugin by the Electronic Frontier Foundation which enforces the use of HTTPS no matter what the site says. Generally, HTTPS is a very useful thing to have on your local development server.
Creating a custom certificate
We will create a working directory where we will create a certification authority and a star certificate. Open a Terminal and let's get to work.
mkdir -p /usr/local/opt/ca cd /usr/local/opt/ca mkdir -p certs crl newcerts private mkdir -p intermediate/certs intermediate/crl intermediate/newcerts intermediate/private intermediate/csr
Next up, we will create some files required by OpenSSL to create certificates
touch index.txt echo 1000 > serial touch intermediate/index.txt echo 1000 > intermediate/serial
Now we'll create a custom OpenSSL configuration suitable for creating a Certification Authority (root SSL certificate). You can change the stuff in bold letters to match your company.
cat << 'EOL' > openssl.cnf # OpenSSL root CA configuration file. # Copy to `/usr/local/opt/ca/openssl.cnf`. # # This file is based on the instructions found in https://jamielinux.com/docs/openssl-certificate-authority/index.html [ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations. dir = /usr/local/opt/ca certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/private/.rand # The root key and root certificate. private_key = $dir/private/ca.key.pem certificate = $dir/certs/ca.cert.pem # For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 name_opt = ca_default cert_opt = ca_default default_days = 375 preserve = no policy = policy_strict [ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca [ req_distinguished_name ] # See . countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address # Optionally, specify some defaults. countryName_default = CY stateOrProvinceName_default = Nicosia localityName_default = Egkomi 0.organizationName_default = Akeeba Ltd organizationalUnitName_default = Production Department emailAddress_default =This email address is being protected from spambots. You need JavaScript enabled to view it. [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth crlDistributionPoints = URI:http://www.local.web/intermediate.crl.pem [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning [ san_env ] subjectAltName=DNS:local.web,DNS:*.local.web EOL
Now we will create a Certification Authority. Please note that all of our certificates will be encrypted with a password. It is set by the first command below. Change it to something other than akeeba.
export CERTIFICATE_PASSWORD=akeeba brew install openssl export PATH=$(brew --prefix openssl):$PATH cd /usr/local/opt/ca openssl genrsa -aes256 \ -passout pass:$CERTIFICATE_PASSWORD \ -out private/ca.key.pem 4096 openssl req -config openssl.cnf \ -key private/ca.key.pem -passin pass:$CERTIFICATE_PASSWORD \ -new -x509 -days 7300 -sha256 -extensions v3_ca \ -subj "/CN=macOS Dev Box Root CA/O=Akeeba Ltd./OU=Production Department/C=CY/ST=Nicosia/L=Egkomi" \ -out certs/ca.cert.pem
Now we'll create an intermediate certification authority using a similar set of commands.
cat << 'EOL' > intermediate/openssl.cnf # OpenSSL root CA configuration file. # # This file is based on the instructions found in https://jamielinux.com/docs/openssl-certificate-authority/index.html [ ca ] # `man ca` default_ca = CA_default [ CA_default ] # Directory and file locations. dir = /usr/local/opt/ca/intermediate certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial RANDFILE = $dir/private/.rand # The root key and root certificate. private_key = $dir/private/intermediate.key.pem certificate = $dir/certs/intermediate.cert.pem # For certificate revocation lists. crlnumber = $dir/crlnumber crl = $dir/crl/intermediate.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 name_opt = ca_default cert_opt = ca_default default_days = 375 preserve = no policy = policy_loose [ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the `req` tool (`man req`). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca [ req_distinguished_name ] # See . countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address # Optionally, specify some defaults. countryName_default = CY stateOrProvinceName_default = Nicosia localityName_default = Egkomi 0.organizationName_default = Akeeba Ltd organizationalUnitName_default = Production Department emailAddress_default =This email address is being protected from spambots. You need JavaScript enabled to view it. [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning [ san_env ] subjectAltName=DNS:local.web,DNS:*.local.web EOL cd /usr/local/opt/ca openssl genrsa -aes256 \ -passout pass:$CERTIFICATE_PASSWORD \ -out intermediate/private/intermediate.key.pem 4096 openssl req -config intermediate/openssl.cnf -new -sha256 \ -key intermediate/private/intermediate.key.pem \ -passin pass:$CERTIFICATE_PASSWORD \ -subj "/CN=macOS Dev Box Intermediate CA/O=Akeeba Ltd./OU=Production Department/C=CY/ST=Nicosia/L=Egkomi" \ -out intermediate/csr/intermediate.csr.pem openssl ca -config openssl.cnf -extensions v3_intermediate_ca -batch \ -passin pass:$CERTIFICATE_PASSWORD \ -days 3650 -notext -md sha256 \ -in intermediate/csr/intermediate.csr.pem \ -out intermediate/certs/intermediate.cert.pem cat intermediate/certs/intermediate.cert.pem \ certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
Finally, we can create our SSL certificate for our development server and copy everything we need to /usr/local/etc/httpd/ssl.
cd /usr/local/opt/ca openssl genrsa -aes256 \ -passout pass:$CERTIFICATE_PASSWORD \ -out intermediate/private/local.web.key.pem 2048 openssl req -config /usr/local/opt/ca/intermediate/openssl.cnf \ -key intermediate/private/local.web.key.pem \ -extensions san_env \ -passin pass:$CERTIFICATE_PASSWORD \ -subj "/CN=*.local.web/O=Akeeba Ltd./OU=Production Department/C=CY/ST=Nicosia/L=Egkomi" \ -new -sha256 -out intermediate/csr/local.web.csr.pem openssl ca -config intermediate/openssl.cnf -batch \ -extensions server_cert -extensions san_env \ -days 1835 -notext -md sha256 \ -in intermediate/csr/local.web.csr.pem \ -passin pass:$CERTIFICATE_PASSWORD \ -out intermediate/certs/local.web.cert.pem mkdir /usr/local/etc/httpd/ssl cp intermediate/certs/ca-chain.cert.pem /usr/local/etc/httpd/ssl openssl rsa -in intermediate/private/local.web.key.pem \ -out /usr/local/etc/httpd/ssl/local.web.key \ -passin pass:$CERTIFICATE_PASSWORD cp intermediate/certs/local.web.cert.pem /usr/local/etc/httpd/ssl/local.web.crt
Enabling HTTPS on Apache
Having an SSL certificate is no good unless we can use it on the web server. Let's edit Apache's configuration to enable SSL support.
open /usr/local/etc/httpd/httpd.conf -a TextEdit
Find the line
Listen 80
Append one more line so now it reads
Listen 80 Listen 443
This tells Apache to listen to port 443, the default HTTPS port.
Next up, find the line
#LoadModule ssl_module lib/httpd/modules/mod_ssl.so
Change it to
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
This enables HTTPS support in Apache (but does not configure it – we'll do that in our virtual host configuration). Now find the following line
#LoadModule http2_module lib/httpd/modules/mod_http2.so
Change it to
LoadModule http2_module lib/httpd/modules/mod_http2.so
This enables HTTP/2 support in Apache. We'll use that when configuring our virtual hosts. Speaking of which, let's edit our virtual host configuration.
open /usr/local/etc/httpd/extra/local.web.conf -a TextEdit
Append the following lines
<VirtualHost *:443> Protocols h2 http/1.1 ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. DocumentRoot "/Users/nicholas/Sites" ServerName local.web ServerAlias www.local.web #ErrorLog "/usr/local/var/log/httpd/local.web.error_log" #CustomLog "/usr/local/var/log/httpd/local.web.access_log" common #CustomLog "/usr/local/var/log/httpd/local.web.ssl_log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SSLEngine on SSLCertificateFile "/usr/local/etc/httpd/ssl/local.web.crt" SSLCertificateKeyFile "/usr/local/etc/httpd/ssl/local.web.key" SSLCertificateChainFile "/usr/local/etc/httpd/ssl/ca-chain.cert.pem" <Directory "/Users/nicholas/Sites"> AllowOverride All DirectoryIndex index.html index.php Require all granted <FilesMatch "\.php$"><filesmatch "\.php$"=""> SSLOptions +StdEnvVars SetHandler "proxy:fcgi://localhost:9073/" </FilesMatch> </Directory> </VirtualHost> <VirtualHost *:443> Protocols h2 http/1.1 ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. ServerAlias *.local.web UseCanonicalName Off VirtualDocumentRoot "/Users/nicholas/Sites/%1" #ErrorLog "/usr/local/var/log/httpd/local.web.error_log" #CustomLog "/usr/local/var/log/httpd/local.web.access_log" common #CustomLog "/usr/local/var/log/httpd/local.web.ssl_log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SSLEngine on SSLCertificateFile "/usr/local/etc/httpd/ssl/local.web.crt" SSLCertificateKeyFile "/usr/local/etc/httpd/ssl/local.web.key" SSLCertificateChainFile "/usr/local/etc/httpd/ssl/ca-chain.cert.pem" <Directory "/Users/nicholas/Sites"> AllowOverride All DirectoryIndex index.html index.php Require all granted <FilesMatch "\.php$"> SSLOptions +StdEnvVars SetHandler "proxy:fcgi://localhost:9073/" </FilesMatch> </Directory> </VirtualHost>
Apart from the obvious SSL* directives which enable HTTPS support the other notable additions are Protocols and SSLOptions. The former enables HTTP/2 support in our TLS-enabled (HTTPS) virtual host. The latter fixes a problem with PHP not seeing some environment variables when using HTTPS.
Finally, let's restart Apache
brew services restart httpd
PHP configuration
By default, PHP won't trust our self-signed certificate. This means that any well-written script on our local machine which tries to access a local site through PHP's stream wrappers (e.g. with fopen() or file_get_contents()) or cURL will fail to connect with a certificate error message.
The solution to that is to create a custom Certificate Authority cache file (cacert.pem) which includes our custom root CA certificate. Then we need to tell PHP to use it by default.
First, let's create the custom cacert.pem
cd /usr/local/opt/ca curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem cat certs/ca.cert.pem cacert.pem > new_cacert.pem rm cacert.pem mv new_cacert.pem cacert.pem
Using it with PHP involves editing the php.ini file as described earlier. You need to modify the following lines (they are not contiguous in the php.in file):
openssl.cafile = /usr/local/opt/ca/cacert.pem curl.cainfo = /usr/local/opt/ca/cacert.pem
Remember to restart the PHP service afterwards. Also keep in mind that you need to do that in all three versions of PHP.
Important! Even though we create our own default cacert.pem file it doesn't mean that PHP scripts are going to necessarily use it. For example, Joomla! comes with its own cacert.pem file. My software such as FOF, Akeeba Backup and Akeeba Solo also ship with their own cacert.pem file. You will need to overwrite these cacert.pem files with the one you generated for these scripts to work when connecting back to your local server through HTTPS.
Telling your browsers to trust the custom certificate
Your browsers are, by default, not aware of your custom root CA certificate and won't trust it for HTTPS. Trying to visit your local sites over HTTPS will result in a warning until you let your browsers know to trust that certificate.
This is described in my Forge your own SSL certificates for local development article, towards the end. The certificate file you need is located in /usr/local/opt/ca/certs/ca.cert.pem.
Creating databases for new sites
I prefer to use a simple convention for naming the databases of my sites. If the site's folder is foobar (therefore I can access it as foobar.local.web) the database name is foobar, the database username is foobar and its password is foobar. This can be succinctly expressed in the following two-liner SQL script for creating new databases:
CREATE DATABASE `foobar` DEFAULT COLLATE utf8mb4_unicode_520_ci; GRANT ALL PRIVILEGES ON `foobar`.* TO 'foobar'@'localhost' IDENTIFIED BY 'foobar';
That's four things you need to remember to replace. Or you can use the following longer SQL script with prepared statements and just ONE (1) thing to replace at the top of the script.
SET @db='foobar'; SET @create = CONCAT("CREATE DATABASE ", @db, " DEFAULT COLLATE utf8mb4_unicode_520_ci"); PREPARE stmt FROM @create; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @grant = CONCAT("GRANT ALL PRIVILEGES ON ", @db, ".* TO '", @db, "'@'localhost' IDENTIFIED BY '", @db, "'"); PREPARE stmt2 FROM @grant; EXECUTE stmt2; DEALLOCATE PREPARE stmt2;
Either way, substitute foobar with your database name.
INCREDIBLY IMPORTANT! Your database name must only consist of all lowercase letters a-z, digits 0-9 and underscores. Do not use uppercase letters. Do not use accented letters, special letters or letters with diacritics such as any of éêêåßçñøü. Do not use non-latin characters such as Greek, Cyrillic, Chinese, Japanese, Korean etc. Keep everything under 20 characters. Ignore these suggestions at your own peril. You have been warned.
Install the SSH2 extension for PHP
The SSH2 extension is the only available method with decent performance and memory usage to connect to remove SFTP and SSH servers from PHP running on macOS. The other option, cURL, will not work because it does not come with SFTP support compiled in.
I mention SSH2 explicitly because, like XDebug, it has its quirks depending the PHP version you are installing it in.
Before you start, you need to install the required libssh2 library.
brew install libssh2
SSH2 for PHP 5.6
brew unlink php brew link --force --overwrite php@5.6 pecl install ssh2 brew unlink php@5.6 brew link --force --overwrite php@7.3
Now we need to edit PHP 5.6's php.ini and tell it to load SSH2:
open /usr/local/etc/php/5.6/php.ini -a TextEdit
Find all the lines starting with ;extension=
Below them add
extension=ssh2.so
Finally, restart PHP-FPM for PHP 5.6
brew services restart php@5.6
SSH2 for PHP 7.2
brew unlink php brew link --force --overwrite php@7.2 pecl install ssh2-1.1.2 brew unlink php@7.2 brew link --force --overwrite php@7.3
Now we need to edit PHP 7.2's php.ini and tell it to load SSH2:
open /usr/local/etc/php/7.2/php.ini -a TextEdit
Find all the lines starting with ;extension=
Below them add
extension=ssh2.so
Finally, restart PHP-FPM for PHP 7.2
brew services restart php@7.2
SSH2 for PHP 7.3
At the time of this writing there is no PECL package for SSH2 compatible with PHP 7.3. Therefore, we have to do this the Hard Way (and hope it works).
sudo mkdir -p /usr/local/src sudo chown $(whoami):staff /usr/local/src cd /usr/local/src git clone https://github.com/php/pecl-networking-ssh2.git cd pecl-networking-ssh2/ phpize ./configure make make install
As before, we need to edit PHP 7.3's php.ini and tell it to load XDebug:
open /usr/local/etc/php/7.3/php.ini -a TextEdit
Find all the lines starting with ;extension=
Below them add
extension=ssh2.so
Finally, restart PHP-FPM for PHP 7.3
brew services restart php@7.3
Install any PECL extension
PHP 5.6
Use the following command template
brew unlink php brew link --force --overwrite php@5.6 pecl install yourPackage brew unlink php@5.6 brew link --force --overwrite php@7.3
Where yourPackage is the name of the PECL extension you want to install.
PHP 7.2
Use the following command template
brew unlink php brew link --force --overwrite php@7.2 pecl install yourPackage brew unlink php@7.2 brew link --force --overwrite php@7.3
Where yourPackage is the name of the PECL extension you want to install.
PHP 7.3
This is much simpler since it's the default PHP version:
pecl install yourPackage
Where yourPackage is the name of the PECL extension you want to install.
For all PHP versions
If your PECL package has external library dependencies you need to install them before trying to install the PECL package. Usually you can install these dependencies with HomeBrew. I won't help you figure out which dependencies you need for each PECL package and PHP version so please don't ask me :)
After compiling the PECL package you need to edit the php.ini file of the relevant PHP version and add the required extension=yourPackage.so line (or whatever else the PECL compilation told you to do; see the XDebug compilation as an example). Remember to restart PHP-FPM for the PHP version whose php.ini file you modified.
Is this really better than MAMP?
In my humble opinion: ABSO-F@CK!NG-LUTELY.
Yes, it's a pain in the rear to set up the first time. But you get to learn how servers work which makes you a better developer. Not to mention that you can use your new knowledge to anticipate and work around server configuration issues.
Yes, after running brew upgrade I may have to go back and check if my PECL extensions still work – or recompile them as necessary. This is good, because it makes me update my PECL extensions. They are software too and like all software they do have bugs fixed and features added in subsequent releases.
No, you do not have a GUI to set up hosts. You don't need one. If you need some fancy, custom domain name use GasMask to set up the domain resolution and copy the local.web.conf file to create your new virtual host. Modify httpd.conf to include the new virtual host file and restart Apache. Bam! Done!
No more waiting forever after every small change for servers to restart (you can restart only the affected service). No more pulling your hair with stuck servers which require restarting the Mac. No more MySQL server crashes when you try to restore a large amount of data. No more paying an extortionist yearly fee to get PHP versions which are months out of date.
If you're willing to trade convenience for freedom and absolute control then, yes, this setup is better than MAMP. It comes down to a The Matrix kind of dilemma. Take the red pill, build your own server and be free. Take the blue pill, you're back to your pretty MAMP jail where someone else dictates what you can or cannot do. I chose the red pill.
Whatever you do, have fun!
---------
php@5.6 was deleted from homebrew/core in commit 37b075c205:
php@5.6 removal due to EOL
---------
PS: Even with Linux, PHP 5.6 is going to be removed really soon. I don't know what I'm supposed to do in this case. Maybe drop PHP 5.6 support because it's becoming a major PITA to test against an obsolete version of PHP?
I lost it at item SSL. I got confused when to cd and the cat thing..A more beginner style type of step by step would be great. As an extra a guide to enable xdebug in VScode would be great too...
Finale Igor brew apache & php incl.xdebug up....
Thank you again...
joe
Thank you again…
joe
Please note: I'm a good Linux user, but new to Mac
Thank you so much!
That said, macOS is just BSD under the hood so let's open a Terminal and let it spill its secrets. Try running lsof -nP -i4TCP:80 | grep LISTEN to see what is listening to port 80. The second column is the PID. You can find it in the output of ps -A to understand where that process came from.
brew tap exolnet/homebrew-deprecated; brew install php@5.6
brew tap exolnet/homebrew-deprecated; brew install php@5.6
i executed this command on Mac
php -S localhost:4000
after this my mamp server dosent work on my Mac.
how can i fix this. i also intalled brew and installed php7.3 . but it still doesnt work. please help me.
php -S is used to run a temporary, very limited development server built into PHP. If you need it you know how it works or where to find documentation about it so it's pretty clear that you don't want.
MAMP is a complete Apache, MySQL and PHP package for macOS. It's mutually exclusive with running the temporary built-in PHP server and with creating your own Apache, MySQL and PHP environment -- the premise of this article.
The instructions from HomeBrew are about creating your own Apache, MySQL and PHP environment. You cannot use that to upgrade MAMP's PHP. If you had actually read the article you'd have already known that MAMP's policy of not supporting new PHP versions and making it unnecessarily complicated to install your own is exactly why I went that route. So why exactly did you think it even remotely reasonable to ask me to help you with what I explicitly declared impractical in the second paragraph of the article, setting the article's raison d'etre, shall forever remain a mystery...
Also, can I start the server manually without installing the system startup service?
Installing it is not much different than installing MySQL. It’s in MariaDB’s documentation. You can also see how to start the server. You can always manage which HomeBrew services auto-start.
It looks like Xdebug supports 7.3 now. So the '-beta' rider isn't needed on install.
Your tutorial is excellent. Worked out of the box.
1. In part "Enabling HTTPS on Apache" > addition in local.web.conf your code says at some point "". This thrown an error. I changed to " " and it worked
2. I get some warnings.. (anything to worry??)
-AH01909: vavoum.local:443:0 server certificate does NOT include an ID which matches the server name
-AH01873: Init: Session Cache is not configured [hint: SSLSessionCache]
-AH00094: Command line: '/usr/local/opt/httpd/bin/httpd -D FOREGROUND'
Thank you again!!
Regarding the warnings, Google them :) None is a problem but by reading up on them you'll understand better how your server works.