IMPORTANT: It's critical to select the correct type of processor your mac is using so the instructions below will be accurate. This is because Homebrew uses
different paths for Apple Silicon and Intel based hardware.
My mac is using an
processor.
Part 3: macOS 15.0 Sequoia Web Development Environment
In Part 1 of this 3-part series, we covered configuring Apache on macOS Big Sur 11.0 to work better with your local user account, as well as the installation process for installing multiple versions of PHP. In Part 2, we covered installing MySQL, Virtual Hosts, APC caching, YAML, and Xdebug.
In this Part 3, we will cover getting your site setup with LetsEncrypt SSL support for this setup.
This guide is intended for experienced web developers. If you are a beginner developer, you will be better served using MAMP or MAMP Pro.
SSL Introduction & Requirements
In order to get SSL setup and running properly four our Homebrew-powered Apache setup, we need to first create an SSL Certificate. This used to be a pain and cost money for a valid SSL certificate, but thankfully we now have Let's Encrypt, a non-profit Certificate Authority that provides certificates to 225 million websites!
This does require that you have registered a domain name with a company such as Hover, GoDaddy, Network Solutions, etc. You should configure this so that a valid host is available to point to your local webserver. You will probably also need to setup port forwarding so your external IP address is routed internally to your webserver. Usually this consists of setting up a port forward for HTTP
, HTTPS
with ports 80
and 443
to the internal IP address of your computer.
This is a process that depends on several factors:
- Domain Registrar used to purchase your domain
- DNS services used which could be the same as the registrar, or another provider such as CloudFlare
- Type of internet connection be it static or dynamic IP address
- The actual external IP address of your internet connection
- Make and model of your router which will need to be setup to configure port forwarding
I'll leave this process up to you as it might require some Googling to get the this process setup depending all the factors listed above. A quick way to test if you have things setup is to try reaching host via your phone or some other device that is not on your internal network.
Let's assume you have registered the domain grav.rocks
(p.s. I already own this one, you need to use your own!), and you have configured the host dev.grav.rocks
to be port-forwarded to your local development machine. You have tested this and you can confirm that when you browse to http://dev.grav.rocks
on your phone, you are indeed seeing the webserver of your internal network. You have successfully configured remote access, but now you want to get SSL working.
Throughout this guide I use dev.grav.rocks
as an example host. You will need to replace this with your own hostname
Let's Encrypt + Certbot
Now you have a valid host that is accessible from the internet, we need to generate a valid LetsEncrypt SSL certificate. First we should install the certbot
tool that will facilitate this process:
brew services stop httpd
brew update
brew upgrade
brew install certbot
To be able to use certbot
in a non-root setup (like we have with Brew), we need to create a cli.ini
file so that the certbot
command will use local paths rather than root
access-only system paths:
Create a Certbot Config
mkdir -pv ~/.config/letsencrypt
code ~/.config/letsencrypt/cli.ini
This assumes you have Visual Studio Code installed and have enabled the CLI code
command. See the first part of this series to find out more about this.
In this new file paste the following:
work-dir = /opt/homebrew/etc/certbot
logs-dir = /opt/homebrew/etc/certbot/logs
config-dir = /opt/homebrew/etc/certbot/certs
Save the file.
Create the Certificate
Now we can run certbot
without requiring sudo
which would limit our ability to run Apache as a non-root user.
certbot certonly --standalone
This kicks off a process that requires your response in a few places. Enter email address
, agree to Terms of Services, Choose Y
or N
to join mailing list. Lastly when prompted, enter the name of the host you want to use, e.g. dev.grav.rocks
.
Certbot will then try to authenticate by challenging the domain names provided:
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for dev.grav.rocks
Waiting for verification...
Cleaning up challenges
Non-standard path(s), might not work with crontab installed by your operating system package manager
If successful, certbot will generate a fullchain.pem
and a privkey.pem
file that we can use to configure our SSL certificate in the Apache configuration. The output should look something like this:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/fullchain.pem
Your key file has been saved at:
/opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/privkey.pem
Your cert will expire on 2021-02-12. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /opt/homebrew/etc/certbot/certs. You should
make a secure backup of this folder now. This configuration
directory will also contain certificates and private keys obtained
by Certbot so making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
The important parts to jot down are the full paths to the .pem
files which we'll use in the following section:
Certificate: /opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/fullchain.pem
Key File: /opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/privkey.pem
Apache SSL Configuration
The first step is to make some modifications to your httpd.conf
:
code /opt/homebrew/etc/httpd/httpd.conf
In this file you should uncomment both the socache_shmcb_module
, ssl_module
, and also the include for the httpd-ssl.conf
by removing the leading #
symbol on those lines:
LoadModule socache_shmcb_module lib/httpd/modules/mod_socache_shmcb.so
...
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
...
Include /opt/homebrew/etc/httpd/extra/httpd-ssl.conf
Next we need to change the default 8443
port to the more standard 443
and comment out some sample code. So we need to open the SSL config file:
code /opt/homebrew/etc/httpd/extra/httpd-ssl.conf
find:
Listen 8443
replace it with:
Listen 443
then find:
<VirtualHost _default_:8443>
# General setup for the virtual host
DocumentRoot "/opt/homebrew/var/www"
ServerName www.example.com:8443
and replace the 8443
references with 443
and update the DocumentRoot
and ServerName
based on the values you setup in your httpd.conf
file:
<VirtualHost _default_:443>
# General setup for the virtual host
DocumentRoot "/Users/your_user/Sites"
ServerName dev.grav.rocks:443
Next locate the Server Certificate:
section add the location of your SSLCertificateFile
you obtained above:
SSLCertificateFile "/opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/fullchain.pem"
Lastly, locate the Server Private Key:
section add the location of your SSLCertificateKeyFile
you obtained above:
SSLCertificateKeyFile "/opt/homebrew/etc/certbot/certs/live/dev.grav.rocks/privkey.pem"
Save the file at this point. Then all you need to do now is double check your Apache configuration syntax:
apachectl configtest
If all goes well, restart Apache:
brew services stop httpd
brew services start httpd
You can tail -f /opt/homebrew/var/log/httpd/error_log
, the Apache error log while you restart to see if you have any errors.
Now simply point your browser at https://dev.grav.rocks
and you should see the page loading and a comforting message in the browser address bar about how secure your site is.
Maintenance & Renewal
By their nature LetsEncrypt certificates are short-lived that are valid for 90 days only. This means that you need to renew them. The simplest way to accomplish this is to simply run:
certbot renew
brew services restart httpd
However, you can only run this when you are close to renewal (within 30 days). The best solution is to automate this process by using a cron-job to run the process weekly. First we need to add an entry to the crontab that will run the renewal script every sunday at 3am::
(crontab -l 2>/dev/null; echo "0 3 * * 0 certbot renew --post-hook 'brew services restart httpd' > /dev/null 2>&1") | crontab -
You can check this looks correct by running:
crontab -l
You should see:
0 3 * * 0 certbot renew --post-hook 'brew services restart httpd' > /dev/null 2>&1
Self-Signed SSL
Sometimes there are scenarios where you want to mimic an existing site during development, or you don't have a spare domain name but just need to test under SSL. Either way there are still occasions where a valid SSL certificate is not required, and you just need to get a self-signed SSL certificate in place.
We'll install mkcert
to serve as our certificate authority (CA), and also nss
to ensure firefox can use certificate authority sever.
brew install mkcert nss
Next we have to install the server and run it (enter your password when prompted):
mkcert -install
Let's create a good location for the certificates:
cd /opt/homebrew/etc/httpd
mkdir certs && cd certs
Now all we have to do is generate a certificate for any domain we wish to use. For example, you could create one for localhost
with:
mkcert localhost
or one for grav-admin.test
with:
mkcert grav-admin.test
These commands will create .pem
and -key.pem
files for each domain.
Setting up Apache for Self-Signed SSL certificate
Follow exactly the same steps as the Apache SSL Configuration section above to enable SSL in Apache.
When you get to the part where you set the SSLCertificateFile
and SSLCertificateKeyFile
use the files we just generated rather than the LetsEncrypt .pem
files:
SSLCertificateFile "/opt/homebrew/etc/httpd/certs/grav-admin.test.pem"
SSLCertificateKeyFile "/opt/homebrew/etc/httpd/certs/grav-admin.test-key.pem"
Check the syntax:
/opt/homebrew/bin/httpd -t
Restart the server to have the configuration changes take effect:
brew services restart httpd
SSL in Apache Virtual Hosts
The configuration we've outlined in this article focuses on setting a root-level SSL certificate. You can of course generate multiple unique certificates for various domains and sites. When you do this, you need to enable SSL for a virtual host via editing the httpd-vhosts.conf
file.
If you already have a vhost entry for http
on port 80
for a particular site, you can just copy this and replace 80
with 443
then add the entries for your key and certificate.
Let's assume we have created a self-signed certificate for grav-admin.test
, and we already have a working vhost configuration for http
/port 80
that we setup in Part 2 of the guide:
<VirtualHost *:80>
DocumentRoot "/Users/your_user/Sites/grav-admin"
ServerName grav-admin.test
</VirtualHost>
Then we simply copy and paste this and change the port to 443
and add references to turn on SSL and use the generated SSL files:
<VirtualHost *:80>
DocumentRoot "/Users/your_user/Sites/grav-admin"
ServerName grav-admin.test
</VirtualHost>
<VirtualHost *:443>
DocumentRoot "/Users/your_user/Sites/grav-admin"
ServerName grav-admin.test
SSLEngine on
SSLCertificateFile "/opt/homebrew/etc/httpd/certs/grav-admin.test.pem"
SSLCertificateKeyFile "/opt/homebrew/etc/httpd/certs/grav-admin.test-key.pem"
</VirtualHost>
Check the syntax:
/opt/homebrew/bin/httpd -t
Restart the server to have the configuration changes take effect:
brew services restart httpd