Setting Up a Local Certificate Authority for Securing Internal Websites
Secure internal sites for dev, testing, or home labs by creating your own Certificate Authority. Skip paid certs and build trusted HTTPS connections across your network; no warnings, full encryption, and complete control.

The Goal
Establish trust across internal servers by setting up a local Certificate Authority (CA) and issuing HTTPS certificates for secure communication between client machines and servers on a private network.
This lab is also available on YouTube
The Lab Prerequisites
- A private network (I used VirtualBox with a
NAT
network). - Virtual server for Certificate Authority:
CA01
- A standard install of Ubuntu server.
- Virtual server with test website needed a secure certificate:
WEB01
- Apache web server.
- Virtual server with Windows Admin Center that needed a secure certificate:
HYPERV01
- Hyper-V server (I used nested virtualisation).
- Two client PCs used for testing:
- Windows 10
- Ubuntu Desktop

Why a Local Certificate Authority?
Public websites rely on commercial Certificate Authority's (CA) to establish trust and secure traffic. Internal servers often raise browser warnings, even if they serve critical content. That’s where your own CA steps in, enabling encrypted, trusted connections without ongoing costs.
1. Set Up the Certificate Authority
- On the Ubuntu Server
CA01
install theeasy-rsa
toolkit.
sudo apt install easy-rsa
- Create a dedicated directory for your CA’s assets, link CA files from their default location and set secure permissions to the directory (only root has full permissions).
mkdir ca01
ln -s /usr/share/easy-rsa/* ca01
chmod 700 ca01
- Change to directory and initialise the Public Key Infrastructure (PKI) with
init-pki
.
cd ca01
./easyrsa init-pki
- Create a copy of the example
vars
file. Thevars
file in Easy-RSA is essentially a configuration file that defines default values used when generating certificates. Then customise the certificate details and save the file.
cp vars.example vars
vim vars
The following settings were un-commented and customised in the vars
file:
set_var EASYRSA_REQ_COUNTRY
– Country code (e.g 'GB')set_var EASYRSA_REQ_PROVINCE
– State or provinceset_var EASYRSA_REQ_CITY
– City or localityset_var EASYRSA_REQ_ORG
– Organisation nameset_var EASYRSA_REQ_EMAIL
– Contact emailset_var EASYRSA_REQ_OU
– Organisational unit
vars
file, like country, organisation, and email—don’t need to be accurate; they’re only visible to devices within your network and won’t affect functionality.- Build the certificate authority and set the secure passphrase which will be required when signing certificate requests.
./easyrsa buildca
You will need to set the common name using a FQDN like ca01.system.lab
The CA is now ready to issue certificates using it's private key which is stored in pki/private
directory.
2. Trust the CA on Client Machines
Adding the CA’s public certificate (stored in pki
directory) to a computer tells it to trust any website or server that uses a certificate signed by that CA. This makes the browser stop showing security warnings and allows secure HTTPS connections.
Windows Server (HYPERV01
)
- Copy the public certificate from the CA server using SCP to the
Documents
folder.
scp rajinder@ca01:/home/rajinder/ca01/pki/ca.crt Documents
The certificate can be installed by double clicking on it and choosing the install certificate option, with store location of Local Machine
and in the Trusted Root Certification Authorities
store.
Ubuntu Server (WEB01
)
- Copy the public certificate from the CA server using SCP to the current directory
.
scp rajinder@ca01:/home/rajinder/ca01/pki/ca.crt .
- In Firefox:
- Open Preferences > Privacy & Security > Certificates > View Certificates
- Import under Authorities, and select Trust this CA for websites.
3. Create and Sign Certificate Requests
A Certificate Signing Request (CSR) is a file a server creates when it wants a trusted certificate from a Certificate Authority (CA). It contains the server’s public key and identity details, such as its hostname, organisation, and location. The CSR is digitally signed using the server’s private key, proving ownership of the key pair.
This request is sent to the CA, which verifies the information and uses its own private key to sign the CSR, issuing a certificate that clients and browsers can trust because the already trust the CA.
On the our internal CA server, we’ll generate CSRs and sign them for each internal server.
Create temp directory for storing certificates for signing requests
mkdir tmp_csr
cd tmp_csr
Create private key and CSR for WEB01
openssl genrsa -out web01.key
openssl req -new -key web01.key -out web01.req
The most important setting is the common name, it must match the URL of the website that the certificate is for, in this case: web01.system.lab
Create private key and CSR for HYPERV01
openssl genrsa -out hyperv01.key
openssl req -new -key hyperv.key -out hyperv01.req
The most important setting is the common name, it must match the URL of the website that the certificate is for, in this case: hyperv01.system.lab
Import and sign the Certificates
./easyrsa import-req web01.req web01
./easyrsa sign-req server web01
./easyrsa import-req hyperv01.req hyperv01
./easyrsa sign-req server hyperv01
The resulting signed certificates are stored in the issued
directory.
4. Install Certificates on Servers
Signed certificates need to be installed on the requesting servers so they can prove their identity to clients, without them, browsers won’t trust the server, and secure HTTPS connections won’t be established.
For the Apache web server WEB01
:
Create a local certs
directory and copy both the private key and the signed certificate via SCP.
mkdir /etc/apache2/certs
scp rajinder@ca01:/home/rajinder/ca01/tmp_csr/web01.key /etc/apache2/certs/
scp rajinder@ca01:/home/rajinder/ca01/pki/issued/web01.crt /etc/apache2/certs/
- Update Apache’s config
/etc/apache2/sites-enabled/000-default.conf
to:- Use port 443 (change from port 80 to 443 in
<VirtualHost *:80>
)
- Use port 443 (change from port 80 to 443 in
- Enable SSL
SSLEngine on
- Point to the certificate and key files.
SSLCertificateFile /etc/apache2/certs/web01.crt
SSLCertificateKeyFile /etc/apache2/certs/web01.key
- Turn on SSL and Restart Apache
sudo a2enmod ssl
sudo systemctl restart apache2
Now when we test on both clients, https://web01.system.lab
is showing as secure and encrypted, this is because the browser trusts the internal CA server ca01
using it's public certificate. The CA has a trust relationship with WEB01
and so let's the browser know that it's safe to proceed.
For the Hyper-V server HYPERV01
:
First the signed certificate we generated earlier needs to be converted into a PFX format. This conversion is required because Windows servers prefer certificates in this format, which bundles both the private key and the signed certificate into a single file for easier import and management.
- Convert signed certificate to create the PFX file on
CA01
server.
cd ca01
openssl pkcs12 -inkey tmp_csr/hyperv01.key -in pki/issued/hyperv01.crt -export -out pki/issued/hyperv01.pfx
- On
HYPERV01
get the.pfx
file using SCP.
scp rajinder@ca01:/home/rajinder/ca01/pki/issued/hyperv01.pfx .
- Import the PFX certificate using PowerShell and store it under
LocalMachine\My
$password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force Import-PfxCertificate -FilePath "hyperv01.pfx" -CertStoreLocation Cert:\LocalMachine\My" -Password $password
PowerShell will provide the thumbprint
of the certificate in the output of the above command, which we'll use to install the certificate in Windows Admin Center.
- Update Windows Admin Center by running the install file for WAC and enter the thumbprint above, the install will then install the certificate.
Now when we test on both clients, https://hyperv01.system.lab
is showing as secure and encrypted, this is because the browser trusts the internal CA server ca01
using it's public certificate. The CA has a trust relationship with HYPERV01
and so let's the browser know that it's safe to proceed.
The Conclusion
This lab successfully walked through the complete process of setting up a local Certificate Authority to secure internal websites with trusted HTTPS encryption. By generating your own CA, distributing its public certificate to client machines, and issuing signed certificates to internal servers, you can build a private trust system that mirrors the security of the public web, without relying on external vendors.
This setup eliminates browser warnings, protects sensitive traffic, and gives you full control over certificate management. Whether you're running a home lab, staging environment, or enterprise infrastructure, this approach ensures your internal services are secure, scalable, and professionally maintained.
Using a VPN is a secure and simple way to protect your data.
If you'd like to support my work, show your appreciation!
Comments ()