Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.

@moinologics
Copy link

hi guys it didn't work for me. kindly help me.

my setup -
Windows 10 OS
apache2(on ubuntu server) installed in VirtualBox VMS.
generated for domain linux.vm
in my windows hosts file - I added an entry for vm IP to linux.vm domain.
also i install rootCA.crt file in windows 10. by right click -> install

Note - my apache2 is accessible on windows 10's chrome without https, but when i tried https, it gives error that "this certificate can't be verified upto a trusted authority."

@elliott-fwdsec
Copy link

You can also add IP.1 = 127.0.0.1 under [alt_name]

@terrylinooo
Copy link

Thank you. Works like a charm.

@pstanton
Copy link

I'm trying to get local tomcat working via ssl and following the above i have

localhost.crt
localhost.csr
localhost.key

but i need key.pem, cert.pem and chain.pem

<Connector port="443" protocol="org.apache.coyote.http11.Http11AprProtocol"
           maxThreads="150" SSLEnabled="true" >
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig>
        <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                     certificateFile="conf/localhost-rsa-cert.pem"
                     certificateChainFile="conf/localhost-rsa-chain.pem"
                     type="RSA" />
    </SSLHostConfig>
</Connector>

What have i missed?

@VladTitSf9
Copy link

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

where this file should be created?

@tranthaihoang
Copy link

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

good! easy and fast, thank you!

@hasoxy
Copy link

hasoxy commented May 25, 2021

The only one that worked after trying multiple solutions, easy and clear, thanks man

@Robin-Sch
Copy link

Is it possible to renew (and add new domains), or would you have to redo everything?

@jordygrunn
Copy link

Thank you for sharing! It works great for my local development environment

@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!

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