getting Firefox/Chrome to trust your internal websites (internal Certificate Authority)
I’m always developing internal websites in our company, for example recently I deployed a Flask-based market data connection tracker on one of our Amazon EC2 hosts
The problem is whenever I access the site via browser, its HTTPS connection is always untrusted since the browser doesnt trust my company’s Certificate Authority as a valid CA (unlike Varisign, Google, Comodo, etc)
This tutorial shows how to
- create an internal corporate CA
- deploy CA certificate to employee’s desktops and browsers
- generate new certificate and keys for internal websites
- configure a website (Apache) to use these internal certs and keys
In this example, my company’s name and Domain is Spaceballs, and my internal website is called “lonestar.spaceballs”

The gist of the whole setup is like this,

Part 1 — Create a Certificate Authority
on a Linux host (I’m using Ubuntu, but can be any flavor that has openssl installed)
create a directory which will host CA key, pem, cert as well as Certs directory that will host individual certificates for websites
mkdir -p /home/user/spaceballsCA/certs
generate a Certificate Authority key
openssl genrsa -aes256 -out spaceballsCA.key 2048
enter a passphrase, this is the Key to your entire certification structure, dont share it and dont lose it!
generate a new PEM certificate
openssl req -x509 -new -nodes -key spaceballsCA.key -sha256 -days 1024 -out spaceballsCA.pem
enter the country, state, company name, email, etc (this will be stored as metadata inside every cert you issue inside your company)
Part 2 — install CA certificate into browsers and desktops
To have a browser like Firefox or Chrome verify your website, you must inject the CA.pem cert into its trusted store
for Chrome, in the address bar type:
chrome://settings/certificates
click Manage Certificates > click on Authorities tab and click Import

select the spaceballsCA.pem file and import it
for Firefox open preferences > Privacy & Security > View Certificates
Import the PEM key
Part 3 — generate Key and Cert for internal website
create a new CSR configuration file, this will tell openssl what options to use when generating a new cert
cd /home/user/spaceballsCA
vi csr.cnf
paste the following,
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn[dn]
C=US
ST=<INSERT STATE>
L=<INSERT CITY>
O=SpaceBalls, LLC
OU=Spaceballs CA
emailAddress=admin@spaceballs.com
CN = spaceballs[alt_names]
DNS.1 = lonestar.spaceballs
DNS.2 = lonestar.spaceballs.ny
DNS.3 = lonestar.spaceballs.tx
DNS.4 = lonestar
DNS.5 = somesite.spaceballs
add as many DNS aliases as you need to the alt_names section, any website that matches this name will get certified by our CA
in this example, a website is called ‘lonestar.spaceballs’ or ‘lonestar’
now lets generate a Certificate Signing Request (CSR) plus the private key
cd /home/user/spaceballsCAopenssl req -new -sha256 -nodes -out certs/lonestar.spaceballs.csr -newkey rsa:2048 -keyout certs/lonestar.spaceballs.key -config <(cat csr.cnf)
check the “certs” folder, it will now have 2 files, a CSR and a KEY
now we generate a CRT (certificate)
openssl x509 -req -in certs/lonestar.spaceballs.csr -CA spaceballsCA.pem -CAkey spaceballsCA.key -CAcreateserial -out certs/lonestar.spaceballs.crt -days 1024 -sha256 -extfile csr.cnf
enter the CA passphrase from step 1, this will now generate a .crt file
verify your new certificate, make sure the DNS altnames match up, you will see something similar to this (note the bolded DNS aliases embedded int the cert)
openssl x509 -in certs/lonestar.spaceballs.crt -text -nooutCertificate:
Data:
Version: 3 (0x2)
Serial Number:
56:f1:d2:a9:3d:54:33:b8:cb:c0:24:d9:5b:cd:22:de:47:7a:f3:06
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = NY, L = New York, O = "Spaceballs, LLC", OU = Spaceballs CA, CN = spaceballs, emailAddress = admin@spaceballs.com
Validity
Not Before: Nov 22 20:03:45 2019 GMT
Not After : Sep 11 20:03:45 2022 GMT
Subject: C = US, ST = NY, L = New York, O = "Spaceballs, LLC", OU = Spaceballs CA, emailAddress = admin@spaceballs.com, CN = spaceballs
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:xc:b4:0c:b7:13:2a:cc:b1:dc:82:40:58:56:32:
6a:23:85:cb:e9:67:9a:8d:f1:c0:0a:54:ee:55:e5:
b8:5e:f9:2d:c4:88:f0:ec:56:e9:91:14:78:b5:b3:
92:74:e5:98:d0:7e:ed:fb:2a:25:58:e1:12:86:b4:
f4:0v:38:06:18:af:47:22:2b:59:f0:1a:00:9c:84:
b9:11:85:ba:e9:c3:b7:bc:78:e5:43:cd:46:9f:9a:
74:e3:69:62:42:15:f3:6c:dd:73:17:3f:e6:46:20:
9a:a3:b3:18:4e:fd:39:19:fd:fb:6e:f0:b7:38:03:
e9:12:a2:54:f0:60:93:37:21:4e:05:d3:82:c2:75:
61:d4:fa:2d:12:b3:82:8e:81:c3:60:13:a6:ab:c1:
01:d6:c1:4e:e2:24:b8:13:c6:7b:b1:a6:a4:57:47:
21:22:1b:0e:10:d7:fa:2c:06:84:6d:ca:7a:8e:fb:
46:fe:36:1c:18:5d:8e:77:76:c6:8c:a2:d4:cb:af:
d8:02:4f:e7:b4:4c:3d:57:4e:6d:b7:82:3a:f2:6a:
38:af:57:85:16:3e:2e:05:04:f0:4e:cd:1b:f0:bb:
4e:81:8f:80:00:77:4d:df:8b:50:80:48:41:7c:79:
17:3b:6b:c0:b4:ee:ae:23:90:4b:1a:ce:c9:fb:f4:
53:77
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:EC:AF:3B:86:ED:71:8D:8B:25:F2:FA:6D:D4:0F:F3:F0:D4:29:44:9BX509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment
X509v3 Subject Alternative Name:
DNS:lonestar.spaceballs, DNS:lonestar.spaceballs.ny, DNS:lonestar.spaceballs.tx, DNS:lonestar
Signature Algorithm: sha256WithRSAEncryption
22:61:bd:09:07:f1:3d:88:d3:29:3a:28:21:01:d2:93:d9:fc:
59:bf:1b:19:80:7b:81:b1:f4:3c:79:c5:eb:be:98:76:29:98:
19:a6:2f:78:51:a0:22:43:62:57:86:3a:2e:e3:3b:29:10:c7:
2e:94:73:bd:60:75:dc:79:a9:06:b6:ae:a5:0a:08:9d:fe:93:
35:4c:a1:75:42:0d:4f:4e:21:86:53:73:23:5a:f6:06:a2:7d:
60:33:63:63:61:80:5f:f3:cd:3f:d1:ef:34:1a:60:da:a7:96:
1e:6f:10:4e:de:48:cc:01:e6:d1:9b:f0:7b:53:9f:f7:92:c6:
aa:e8:e2:7e:0c:25:1a:89:71:a1:82:4a:31:70:a1:52:5f:d8:
78:0e:3b:16:15:59:67:55:88:96:ab:c4:5d:c2:7b:7e:89:e0:
32:7b:87:a9:46:38:85:41:8d:ef:e9:88:20:6d:0e:a9:be:b8:
60:6b:4f:47:8b:bc:25:54:62:0b:73:89:d3:2d:75:3d:cf:90:
1b:6c:3a:1d:a2:33:96:14:6e:7f:85:c6:52:8f:11:4f:3a:bd:
35:c9:f1:05:05:77:bb:80:4d:40:f4:18:6c:f5:0b:7b:4b:03:
b6:5a:5d:a8:d8:4a:27:b3:38:3c:07:c1:a2:c1:60:03:c8:78:
2a:ad:75:2b
rsync or copy both .crt and .key files to your web server (can place them anywhere but usually in /etc/ssl/certs/
Part 4 — configure web server to run with certificates
this will show how to run an Apache web server with your custom certs
on your web server, create a new configuration file for “lonestar.spaceballs”
web1> cd /etc/httpd/conf.d
vi lonestar.conf
add the necessary configuration, in this example, the website is a Flask python process running on port 5300
LoadModule headers_module /usr/lib64/httpd/modules/mod_headers.so#### LONESTARProxyRequests Off
RewriteEngine On
ErrorLog /var/log/httpd/lonestar_error.log<VirtualHost *:80>
ServerName lonestar
ServerAlias lonestar.spaceballs
Redirect / https://lonestar</VirtualHost><VirtualHost *:443>
ProxyPreserveHost On
ServerName lonestar
ServerAlias lonestar.spaceballs
ServerAlias lonestar.spaceballs.ny
ServerAlias lonestar.spaceballs.txSSLEngine On
SSLCertificateKeyFile /etc/ssl/certs/lonestar.key
SSLCertificateFile /etc/ssl/certs/lonestar.crtAllowEncodedSlashes NoDecode
ProxyPass / http://localhost:5300/ nocanon
ProxyPassReverse / http://localhost:5300/
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
restart apache and your browser should now show a green verified Cert sign (on Chrome it will be gray colored, since its an internal CA)

this should also work for any combination of names you put into the DNS alias, “lonestar.spaceballs, lonestar.spaceballs.ny, etc”