How to properly generate SSL certificates for local HTTPS development.
Quite often it is useful to have HTTPS on your development machine, or within your private network. It's actually quite simple to have trusted certificates that are accessible from your own devices, but I've found that documentation showing how to do this is fairly hard to find. Follow the steps below and you'll be up and running with local SSL certificates in no time at all!
1. Create your own Certificate Authority (CA)
In order to create certificates, you need to generate the files necessary to become a Certificate Authority.
Although certificates generated using this CA will only work properly within your development environment, these certificates are perfectly valid for any machine that has the CA root certificate installed.
You will need openssl to be installed on your machine to generate the required files (on MacOS you can get this from homebrew, on Linux this is probably already installed or can be added from your package manager).
Start by creating somewhere to store all the generated files and certificates:
$ mkdir ~/dev_certificate_authority
$ cd ~/dev_certificate_authority
Generate the private key to become a local CA, you should provide a passphrase/password, which will prevent anyone else from generating certificates from your CA should they get access to the private key:
$ openssl genrsa pass:<your passphrase> -des3 -out <your_CA_name>.key 2048
Now create the root certificate for your development Certificate Authority:
$ openssl req -x509 -new -nodes -key <your_CA_name>.key -sha256 -days 1825 -out <your_CA_name>.pem -subj "/C=GB/O=<your_CA_name>"
This creates two files, <your_CA_name>.key (the private key) and <your_CA_name>.pem (the root certificate). You will need to add the root certificate to any device you want to access your development HTTPS server from, for example:
MacOS
$ sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" <your_CA_name>.pem
Linux
$ sudo cp ~/dev_certificate_authority/<your_CA_name>.pem /usr/local/share/ca-certificates/<your_CA_name>.crt
$ sudo update-ca-certificates
2. Create SSL certificates using your development CA
Now you have a development CA, you can use it to sign certificates for any hostname you want to use in your development environment, and these will be trusted by any device that has the root certificate in it's trusted certificate store.
To generate a development certificate, first generate a key for the domain:
$ openssl genrsa -out <your_development_domain>.key 2048
Then generate a CSR for the domain:
$ openssl req -new -key <your_development_domain>.key \
-subj "/C=GB/CN=<your_development_domain>" \
-out <your_development_domain>.csr
Next, create a certificate configuration file which is used to construct the certificate:
$ cat > <your_development_domain>.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = <your_development_domain>
EOF
Finally we can generate a certificate using the CSR, the CA private key, the CA certificate, and the certificate configuration file:
$ openssl x509 -req -in <your_development_domain>.csr \
-CA ./<your_CA_name>.pem \
-CAkey ./<your_CA_name>.key -CAcreateserial \
-out <your_development_domain>.crt -days 825 -sha256 -extfile <your_development_domain>.ext
3. Apply your new SSL certificate to your server
This certificate can be installed in your development server like any other obtained from a third party CA. For example in Apache:
<VirtualHost *:443>
ServerName <your_application_name>
DocumentRoot /path/to/<your_application_name>
SSLEngine on
SSLCertificateFile /path/to/cert/<your_development_domain>.crt
SSLCertificateKeyFile /path/to/cert/<your_development_domain>.key
</VirtualHost>
or Nginx:
server {
server_name <your_development_domain>
root /path/to/<your_application_name>
index index.html;
listen 443 ssl;
ssl_certificate /path/to/cert/<your_development_domain>.crt;
ssl_certificate_key /path/to/cert/<your_development_domain>.key;
ssl_protocols TLSv1.2 TLSv1.3;
}
Troubleshooting - Local CA Authority Not Recognised
If the browser does not recognise your certificates, for example when attempting to open the address https://<your_development_domain>, you receive an error such as...
- Peer’s Certificate issuer is not recognized on local machine (Firefox)
- Your connection is not private. net::ERR_CERT_AUTHORITY_INVALID (Chrome)
then the certificate must be imported manually in the browser. This can be done at:
- Settings > Privacy & Security > Security > View Certificates > Authorities > Import (Firefox)
- Settings > Privacy & Security > Security > Manage Certificates > Authorities > Import (Chrome)
Which will bring up a file browser, where you can browse to your root certificate, e.g. `~/dev_certificate_authority/<your_CA_name>.crt`. For either browser, make sure to check "Trust this certificate for identifying websites" during the import. You can now refresh your site, and it should load correctly.