It is always a good idea to have a self-signed certificate for web development: it’s easier to notice and prevent having non-downloaded resources and “Unsafe attempt to load URLs” messages just because the developer forgot to use protocol-relative URL somewhere.

These are the steps I follow when I create a self-signed certificate for a project that can be used for my MAMP-based environment stack.

Requirements

Before proceeding, let’s make sure that ssl module and the related configuration file are loaded in your Apache2 configuration httpd.conf:

  • Verify that you have LoadModule ssl_module modules/mod_ssl.so and it is not commented out.
  • Check that httpd-ssl.conf is included:
    1
    2
    
    # Secure (SSL/TLS) connections
    Include /Applications/MAMP/conf/apache/extra/httpd-ssl.conf
    

Let’s create a bash script somewhere (name it generate-cert.sh)! We will use it to generate certificates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
COMMONNAME=${1:-"example.com.localhost"}
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes -keyout "${COMMONNAME}".key -out "${COMMONNAME}".crt -extensions san -config <(echo "[req]";
  echo "distinguished_name=subject";
  echo "string_mask=utf8only";
  echo "[ subject ]";
  echo "countryName=Country Name (2 letter code)";
  echo "countryName_default=HU";
  echo "stateOrProvinceName=State or Province Name (full name)";
  echo "stateOrProvinceName_default=Veszprém";
  echo "localityName=Locality Name (eg, city)";
  echo "localityName_default=Karakószörcsök";
  echo "organizationName=Organization Name (eg, company)";
  echo "organizationName_default=${USER}";
  echo "commonName=Common Name (e.g. server FQDN or YOUR name)";
  echo "commonName_default=${COMMONNAME}";
  echo "emailAddress=Email Address";
  echo "emailAddress_default=${USER}@${COMMONNAME}";
  echo "[san]";
  echo "subjectAltName=DNS:${COMMONNAME}";
)

Generate the certificate

Assuming that we need a certificate for testalias.localhost:

  1. Open up terminal and run the shell script above: ./generate-cert.sh testalias.localhost

  2. Customize the details based on your needs:

    • Country Name (2 letter code) [HU]: → HU
    • State or Province Name (full name) [Veszprém]: → Veszprém
    • Locality Name (eg, city) [Karakószörcsök]: → Karakószörcsök
    • Organization Name (eg, company) [user]: → Your user name
    • Common Name (e.g. server FQDN or YOUR name) [testalias.localhost]: → testalias.localhost
    • Email Address [user@localhost]: → user@testalias.localhost

Configuring the virtual host

  1. Check (or create if missing) the new custom alias testalias.localhost in /etc/hosts or in your dnsmasq configuration.
  2. Open /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf, and add the new virtual host for http:// connections:
    1
    2
    3
    4
    
    <VirtualHost *:80>
    DocumentRoot "/location/of/the/builds/docroot"
    ServerName testalias.localhost
    </VirtualHost>
    
  3. Open /Applications/MAMP/conf/apache/extra/httpd-ssl.conf, and add the new virtual host for https:// connections:
    1
    2
    3
    4
    5
    6
    7
    
    <VirtualHost *:443>
    DocumentRoot "/location/of/the/builds/docroot"
    ServerName testalias.localhost
    SSLEngine on
    SSLCertificateFile "/location/of/testalias.localhost.crt"
    SSLCertificateKeyFile "/location/of/testalias.localhost.key"
    </VirtualHost>
    
  4. Restart Apache2.

Now if you visit https://testalias.localhost, the server will use the newly created certificate for the communication. But the browser will still warn you that the site you’re trying to load is unsafe because the certificate cannot be trusted.

Install the certificate

Sadly, recent Firefox versions won’t trust these self-signed certificates, But for Google Chrome or Safari it is enough to add the new certificate to OS X Keychain and mark it trusted:

  1. Locate the .crt file in Finder and open it with Keychain.
  2. Add the certificate to your keychain.
  3. Locate the certification, right-click on it, and choose “Get info”
  4. Expand “Trust” and mark the cert always trusted.

Sources: