Skip to content

Instantly share code, notes, and snippets.

@cecilemuller
Last active May 19, 2024 11:58
Show Gist options
  • Save cecilemuller/9492b848eb8fe46d462abeb26656c4f8 to your computer and use it in GitHub Desktop.
Save cecilemuller/9492b848eb8fe46d462abeb26656c4f8 to your computer and use it in GitHub Desktop.
How to create an HTTPS certificate for localhost domains

How to create an HTTPS certificate for localhost domains

This focuses on generating the certificates for loading local virtual hosts hosted on your computer, for development only.

Do not use self-signed certificates in production ! For online certificates, use Let's Encrypt instead (tutorial).

Certificate authority (CA)

Generate RootCA.pem, RootCA.key & RootCA.crt:

openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=Example-Root-CA"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt

Note that Example-Root-CA is an example, you can customize the name.

Domain name certificate

Let's say you have two domains fake1.local and fake2.local that are hosted on your local machine for development (using the hosts file to point them to 127.0.0.1).

First, create a file domains.ext that lists all your local domains:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = fake1.local
DNS.3 = fake2.local

Generate localhost.key, localhost.csr, and localhost.crt:

openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost.local"
openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt

Note that the country / state / city / name in the first command can be customized.

You can now configure your webserver, for example with Apache:

SSLEngine on
SSLCertificateFile "C:/example/localhost.crt"
SSLCertificateKeyFile "C:/example/localhost.key"

Trust the local CA

At this point, the site would load with a warning about self-signed certificates. In order to get a green lock, your new local CA has to be added to the trusted Root Certificate Authorities.

Windows 10: Chrome, IE11 & Edge

Windows 10 recognizes .crt files, so you can right-click on RootCA.crt > Install to open the import dialog.

Make sure to select "Trusted Root Certification Authorities" and confirm.

You should now get a green lock in Chrome, IE11 and Edge.

Windows 10: Firefox

There are two ways to get the CA trusted in Firefox.

The simplest is to make Firefox use the Windows trusted Root CAs by going to about:config, and setting security.enterprise_roots.enabled to true.

The other way is to import the certificate by going to about:preferences#privacy > Certificats > Import > RootCA.pem > Confirm for websites.

@GitHub-Mike
Copy link

First, create a file domains.ext that lists all your local domains:

where this file should be created?

In the same directory where the openssl command is executed.

@web-bert
Copy link

web-bert commented Oct 6, 2021

Thank you for this, I had to reduce the validity for the localhost.crt to 397 days as that is now the maximum validity period. See this post about it, it might be worth updating the command with the new maximum.

@rinogo
Copy link

rinogo commented Oct 14, 2021

Need an easy solution: https://github.com/FiloSottile/mkcert

Thank you so much! For a quick fix on local development environments, this beats messing with openssl.

@perki
Copy link

perki commented Nov 1, 2021

If you need ready to use SSL certificates for localhost you can have a look at https://github.com/pryv/rec-la
https://.rec.la/ => https://localhost/

@praveeenpatel
Copy link

Certificate import error

The Private Key for this Client Certificate is missing or invalid

when i import certificate in chrome browser.
https://prnt.sc/1y2i7ev

@serkanalgur
Copy link

Still Working!. Thanks @cecilemuller

@GeoffCapper
Copy link

Note that if you are generating for localhost, in the commands for "Generate localhost.key, localhost.csr, and localhost.crt:" the CN in the first command should be ".../CN=localhost", not ".../CN=localhost.local" otherwise Chrome (and maybe others) won't like it.

@jaami
Copy link

jaami commented Jan 7, 2022

Command: openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt

OutPut: C:\xampp\htdocs\SSL>openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt
Can't open "domains.ext" for reading, No such file or directory
78030000:error:80000002:system library:BIO_new_file:No such file or directory:crypto\bio\bss_file.c:67:calling fopen(domains.ext, r)
78030000:error:10000080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:75:

for me all steps work smoothly otherwise useless effort wont help because things are new and confusing.

@GitHub-Mike
Copy link

@jaami: The domains.ext file must be located in the directory where the command is executed. Also check the file permissions for the executing user.

@rajan-31
Copy link

I followed this https://ritesh-yadav.github.io/tech/getting-valid-ssl-certificate-for-localhost-from-letsencrypt/

It's kind of a hack with heroku.

If you are going to follow that then some tips:

  • you have to implement the route asked in certbot console output, in your heroku app (not the app running on localhost. So, that letsencrypt can access that from their server)
  • add domain in /etc/hosts at the end

@johngrant4est
Copy link

In addition to comments on cert validity above, when you regenerate your certs from the CL, remember to restart your local web server prior to testing. If in doubt, check the dates on cert, issuer etc. If your cert is invalid, it's possibly because the web server is serving an older one, but your browser is validating against the new one in the store.

@burawi
Copy link

burawi commented Aug 10, 2022

Need an easy solution: https://github.com/FiloSottile/mkcert

Just amazing! Thank you @dol

@daxlai
Copy link

daxlai commented Nov 1, 2022

Still Working!. Thanks @ce

are you configure this with TOMCAT ? if yes please guide me i am unable to do it

@daxlai
Copy link

daxlai commented Nov 1, 2022

Using this method i am unable to SSL in tomcat 9. please explore it for tomcat 9 for localhost only or for local network

@frank-stonybrook
Copy link

Need an easy solution: https://github.com/FiloSottile/mkcert

You saved my day! Thanks!

@magi-web
Copy link

magi-web commented Jan 8, 2023

Thank you so much ! It works like a charm <3

@peppeg85
Copy link

peppeg85 commented Feb 8, 2023

hello, if i need to add more hosts in the future, i have to update the domain.ext file and re-generate the certificates with the two instructions

openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost.local"
openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt

and another question: in the domain.ext file, the entries authorityKeyIdentifier=keyid,issuer how should be valorized?
thank you

@daxlai
Copy link

daxlai commented Feb 8, 2023 via email

@peppeg85
Copy link

peppeg85 commented Feb 9, 2023

follow the guide, on windows you ave to add hosts inside the hosts

C:\Windows\System32\drivers\etc\hosts 

if you can't see it enable hidden files in the system explorer. then add entries like
127.0.0.1 www.fake1.local (the entries inside the domains.ext file), do this with notepad++, it will ask you to save as administrator.

maybe you need to disconnect and reconnect windows.
if still doesn't work try to use CN=*.localhost.local for this instruction:

openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost.local"

then i use this with spring boot, so i had to convert the crt file to p12

@BraxtonI
Copy link

BraxtonI commented Feb 9, 2023 via email

@b-and-p
Copy link

b-and-p commented Apr 14, 2023

Excellent information, thanks! I was struggling with Chrome and Wampserver for a week before I saw this. Worked like a charm!

@DragonOsman
Copy link

DragonOsman commented Jun 20, 2023

I want to do this for a MERN app I'm trying to develop and test locally that uses JWTs for authentication. Without HTTPS, the cookies would be ignored by the browser since I'd need to use secure cookies.

I think I successfully generated the .crt file using my .csr and .key files, but now when I try to visit https://localhost:3000 or https://localhost.local:3000 I get an error. What do I need to do from here?

Edit: I've installed the .crt file to the store (type of store left up to the wizard) and I've added "localhost" with port 3000 to my hosts, but it's still telling me that the site isn't secure when I try to visit it in MS Edge. Please help. Thanks.

Edit2: Okay, I've also added the cert file to the trusted store in mmc.exe but still doesn't work. I still get the error that the site isn't secure. What should I do?

@MickaelDuprat
Copy link

Wow awesome, thank you so much for your tutorial ! :)

@ChiyungWu
Copy link

Thanks for your tutorial, it solve my problem!!

@pixelfast
Copy link

pixelfast commented Sep 18, 2023

So, SSL on localhost now works fine, and displays the Wampserver Homepage.

I now have Your Virtual Hosts listed as:

mortgagequest:8080

In my httpd-vhosts.conf file, the entry looks like this:

<VirtualHost *:8080> ServerName mortgagequest DocumentRoot "c:/mysites/azmortgage/new" <Directory "c:/mysites/azmortgage/new/"> Options +Indexes +Includes +FollowSymLinks +MultiViews AllowOverride All Require local </Directory> </VirtualHost>

My hosts file has this entry:

127.0.0.1 mortgagequest
::1 mortgagequest

When I browse to https://mortgagequest I get the Wampserver Homepage.

What further steps do I need to take to enable SSL for the virtual host?

Thank you!

@alpheus-madsen
Copy link

Is there a way to use the SSL certificate directly for localhost sites, without installing a web server of some sort? While I can go down that route, I'd rather stay with the simplicity of resolving things using "/etc/hosts"!

@perki
Copy link

perki commented Jan 25, 2024

@alpheus-madsen To serve HTTPS you need an web server.
As a one liner solution, if you have nodejs installed, do npx backloop.dev <path to serve>, this will provide a localhost SSL certificate plus a minimal web server.

@marcus-at-localhost
Copy link

Unfortunately, I got this:

name is expected to be in the format /type0=value0/type1=value1/type2=... where characters may be escaped by . This name is not in that format: 'E:/xampp/Git/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost'
problems making Certificate Request

Honestly, I have no idea what I am doing :D, but I was successful using this: https://github.com/FiloSottile/mkcert

Thanks to everyone sharing their knowledge!

@hgati
Copy link

hgati commented Feb 23, 2024

Great thanks. Perfect solution !!

@daxlai
Copy link

daxlai commented Feb 25, 2024

screen-shoot
here is my server.xml file ssl config part




<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig>
	  <Certificate SSLCertificateFile="localhost.crt"
       SSLCertificateKeyFile="localhost.key" />
    </SSLHostConfig>
</Connector>

SHOWING THAT CERTIFICATE NOT SECURE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment