In most environments, an Enterprise CA is integrated into Active Directory. That works well for domain-joined servers and clients, because certificate enrollment and renewal can be automated via Group Policy.
But what about devices that are not domain-joined?
Appliances (firewalls, load balancers, NAS devices)
- Test servers outside AD
 - IoT / lab devices
 - Third-party systems in secure networks
 
These systems still need SSL/TLS certificates, but granting them access to your Enterprise CA isn’t always a good idea:
- ❌ Security risk: non-domain devices talking to the Enterprise CA can increase your attack surface.
 - ❌ Administrative overhead: AD auto-enrollment doesn’t apply.
 - ❌ Compliance: not all devices can authenticate against Active Directory.
 
✅ The solution:
Set up a standalone internal Root CA (sometimes called an “offline CA”) alongside your Enterprise CA.
- It lives outside AD and can run completely offline.
 - You can issue certificates manually for third-party/internal systems.
 - The trust stays internal — you don’t need to involve public CAs or expose your Enterprise CA.
 
Both CAs can coexist:
- Enterprise CA → for AD-joined servers & clients.
 - Standalone CA → for non-domain or third-party systems.
 
This guide walks you through setting up a secure internal Root CA that can issue certificates for these cases, while keeping your Enterprise CA safe and AD-focused.
📝 Requirements
Ubuntu Server 24.04 LTS (minimal install is fine)
- Running as a VM or physical server.
 - Connected to your internal network only (not exposed to the internet).
 
Root / sudo access on the server.
- You’ll be creating files in /root/ca and need elevated privileges.
 
OpenSSL installed (preinstalled on Ubuntu, but can be updated with:
sudo apt update && sudo apt install openssl
Accurate system time (NTP recommended).
- Certificates rely on correct date/time to validate.
 
Secure storage for your CA private key.
- Ideally keep the CA server offline when not issuing certs.
 - If running in a VM, snapshot after setup for recovery.
 
Backup plan for the Root CA key & certificate.
- Store in /root/ca/certs/backup as shown in the guide.
 - Export securely to encrypted offline storage.
 
Internal distribution method for the Root CA certificate.
- You’ll need to push the CA cert (ithu.cert) to trusted servers/clients.
 - On AD-joined machines, this can be done via GPO.
 - On non-domain devices, import manually.
 
CA Setup
SSH into your Ubuntu Server
- Switch to Root & Create Folder Structure
 
su
# Create the PKI structure
mkdir -p /root/ca/{certs,crl,newcerts,private}
mkdir -p /root/ca/certs/backup
# Secure sensitive folders
chmod 700 /root/ca/private
chmod 700 /root/ca/certs/backup
# Initialize database & serial tracking
touch /root/ca/index.txt
echo 1000 > /root/ca/serial
2. Next, we’ll generate the Root CA’s private key. This key must be encrypted with a passphrase for maximum security.
You can name the key file anything you like, for example: ithu.key, rootca.key, or mysecureca.key.
openssl genrsa -aes256 -out /root/ca/private/ithu.key 4096 Enter PEM pass phrase: Verifying - Enter PEM pass phrase: chmod 600 /root/ca/private/ithu.key
When prompted, choose a strong passphrase — this protects your CA if the key file is ever stolen.
You’ll need to enter this passphrase every time you use the Root CA to sign certificates.
🔑 Key points:
- aes256 → encrypts the private key with AES-256.
 - 4096 → strong RSA key length.
 
The private key is the crown jewel of your PKI. Protect it like a domain admin account or vault secret.
3. Create the Root CA Certificate (Self-Signed)
Now that the private key exists, generate your Root CA certificate. This certificate will be self-signed and valid for 10 years (3650 days).
openssl req -x509 -new -key /root/ca/private/ithu.key \ -sha256 -days 3650 \ -out /root/ca/certs/ithu.cert
You’ll be asked for the passphrase you created in step 2, then prompted to enter details for the certificate’s Distinguished Name (DN):
Country Name (2 letter code) [AU]: AU State or Province Name (full name) [Some-State]: NSW Locality Name (eg, city) []: Sydney Organization Name (eg, company) [Internet Widgits Pty Ltd]: ITHU-CA Organizational Unit Name (eg, section) []: Internal PKI Common Name (e.g. server FQDN or YOUR name) []: ITHU Internal Root CA Email Address []: [email protected]
📌 Notes for each field:
- Country Name (C): 2-letter country code (e.g., AU, US, GB).
 - State or Province (ST): Full name (e.g., New South Wales).
 - Locality (L): City or region.
 - Organization (O): Your company/CA name (e.g., ITHU-CA).
 - Organizational Unit (OU): Optional (e.g., “Internal PKI” or “Security”).
 - Common Name (CN): Give this CA a descriptive name (e.g., “ITHU Internal Root CA”).
 - Email Address: Optional but good for contact.
 
✅ Result:
Your Root CA certificate is saved as:
/root/ca/certs/ithu.cert
This is the certificate that you’ll distribute to any system that should trust your internal PKI.
This is your Root CA certificate. Distribute this to servers/clients as the trust anchor.
4. Configure OpenSSL (openssl.cnf)
Edit /root/ca/openssl.cnf and set your CA paths:
nano /root/ca/openssl.cnf #update [ CA_default ] dir = /root/ca certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/index.txt serial = $dir/serial private_key = $dir/private/ithu.key certificate = $dir/certs/ithu.cert default_md = sha256 policy = policy_loose
5. Create a Server CSR Config (SAN Support) Browsers like Chrome require this
File: /root/ca/san.cnf
nano /root/ca/san.cnf [v3_req] authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = example.com IP.1 = 10.100.103.40
6. Backup Keys & Certs
cp /root/ca/private/ithu.key /root/ca/certs/backup/ cp /root/ca/certs/ithu.cert /root/ca/certs/backup/ chmod 600 /root/ca/certs/backup/*
🔏 Signing a Certificate Request
Once your internal CA is in place, the next step is signing certificate requests (CSRs).
Most devices and applications that need SSL/TLS support — such as routers, switches, firewalls, NAS appliances, and web servers — can generate their own certificate signing requests. The exact process depends on the vendor, so it’s best to check the product documentation for how to create a CSR.
Generating the Request
For this demonstration, I’ll use an internal Ubuntu web server running Virtualmin. Virtualmin provides a GUI option to generate CSRs directly for hosted sites.
In my example:
- I’m requesting a certificate for the internal domain: bugnbuyco.lab
 - The same server also runs an internal mail service, which I’ll later use in lab exercises (e.g., phishing tests).
 
📌 But the process is the same no matter the system — whether it’s a router, switch, NAS, or any other internal device. As long as it can produce a CSR, your internal CA can sign it and issue a trusted certificate.
Folling the process in virttual min I Generate the request and i get a csr request file that looks similare to this
-----BEGIN CERTIFICATE REQUEST----- MIICwzCCAasCAQAwGDEWMBQGA1UEAwwNYnVnbmJ1eWNvLmxhYjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMbc+NzH7i0RGq2op6dgosWaUByO79C6sa6d 8nHHqWkdduSGnPLa365ntdNs9NwfU1LpqrLcw4psFE9tjc0NzfZAh8Mh5ZDHlA2h +h4fSSvXA9Cts82qhWCGXy7B1plcPVXsfYAcTTkpO6xTQhQfgpUsDMU4eTdltqxO ur36RcLhoYKO5fsqArUSHqzkEu6yRox8LV217y7+aAKgXtwA019p -----END CERTIFICATE REQUEST-----
Once you have the csr
SSH into your CA server and go to the following location that we created
/root/ca/certs
Create a file called {server}.csr in my cast its bugnbuyco.csr
root@ubsrv:~/ca/certs# ls
backup bugnbuyco.csr ithu.cert
Update the san.cnf file
Modern browsers (like Chrome and Firefox) require certificates to include a Subject Alternative Name (SAN) field. Without it, the certificate will not be trusted — even if everything else is valid.
To configure this, edit your SAN configuration file:
nano /root/ca/san.cnf
Inside the file, update the settings to match your environment. You can specify either DNS names or IP addresses (or both):
DNS.1 → The fully qualified domain name (FQDN) of your service.
- Example: DNS.1 = bugnbuyco.lab
 - If you need more than one, add them on new lines (DNS.2, DNS.3, etc.).
 
IP.1 → An IP address for the service.
Example: IP.1 = 10.10.10.20
Useful for devices like routers, switches, or appliances that may only have an IP interface instead of a DNS name.
📌 By including both DNS and IP entries, you ensure the certificate works seamlessly for different types of internal services.
In this example I need the www address and the mail address to be signed so ill enter the following, I don’t need to add the IP address for this record.
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = bugnbuyco.lab
DNS.2 = mail.bugnbuyco.lab
Now we sign the cert in this case i need to make sure this points to the bugnbuyco.csr file
openssl x509 -req -in /root/ca/certs/bugnbuyco.csr -CA /root/ca/certs/ithu.cert -CAkey /root/ca/private/ithu.key -CAcreateserial -out /root/ca/certs/bugnbuyco.crt -days 3650 -sha256 -extfile /root/ca/san.cnf
Output:
root@ubsrv:~/ca/certs# openssl x509 -req -in /root/ca/certs/bugnbuyco.csr \ > -CA /root/ca/certs/ithu.cert \ > -CAkey /root/ca/private/ithu.key \ > -CAcreateserial \ > -out /root/ca/certs/bugnbuyco.crt \ > -days 3650 -sha256 \ > -extfile /root/ca/san.cnf Certificate request self-signature ok subject=CN = bugnbuyco.lab Enter pass phrase for /root/ca/private/ithu.key:
Once you run the signing command, you’ll be prompted to enter the Root CA passphrase. After that, your new signed certificate will be created in the current folder as bugnbuyco.crt.
To view the certificate, use:
cat cat bugnbuyco.crt -----BEGIN CERTIFICATE----- MIIEeTCCAmGgAwIBAgIUAb+v5LSta66BkhU2JayFRaXlZzkwDQYJKoZIhvcNAQEL BQAwNDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxEDAOBgNVBAoM B0lUSFUtQ0EwHhcNMjUwOTE4MDUxNTQ0WhcNMzUwOTE2MDUxNTQ0WjAYMRYwFAYD o4U5KlXrHn7QmOu1GYu5ZZuanS+GzfatUDj/qnG7amI+gR+cTZViLrcH2MYcCMBN VGPU86RoK7uAdUY4Nm7nnoIkGbdzZavLFQNzNsSna9VNoldhTTm8XxuDX8nKczzL VclXw8RcTFyzjZ2s83sLE/rDfQ1XNQ9IsXwLafUllra2IWGFBBMncztyKYkpO8ET 7gMAkEDw7kf9Gr58h9XEhjXeDuzUHZVLBAsI/xQRIRLLQMUAYpKYeokV2rf/ -----END CERTIFICATE-----
From there, you can copy the certificate text (including the —–BEGIN CERTIFICATE—– and —–END CERTIFICATE—– lines) and paste it directly into your requesting server or application.
⚡ Personally, I find this approach more secure than moving the file into an FTP folder and downloading it — you keep everything within a controlled environment and avoid unnecessary exposure.
In the Virtualmin interface, you can paste or upload this signed certificate, and it will be applied to your site immediately.
Configuring webserver to use new certificate and key .. .. done Saving certificate .. .. done Saving private key .. .. done Saving CA certificate .. .. done Updating service certificates .. .. done Applying webserver configuration .. .. done Re-loading Webmin .. .. done Re-starting Usermin .. .. done Restarting mail server .. .. done
At this point, the certificate has been applied to the site. However, when visiting the site in a browser, you may still see a certificate warning message.

This happens because the server is not domain-joined, and our internal Certificate Authority is not automatically trusted like an Enterprise CA integrated with Active Directory would be.
To resolve this, you’ll need to distribute and trust the Root CA certificate across your environment. The best way in an AD environment is to create a Group Policy Object (GPO) that imports the Root CA certificate into the Trusted Root Certification Authorities store for all domain-joined machines.
📥 Retrieve the Root CA Certificate for GPO Distribution
To make our internal CA trusted across the domain, we need to retrieve the Root CA certificate and prepare it for import.
On the CA server, the Root CA certificate is located in the /root/ca/certs/ folder as ithu.cert. This is the certificate that must be distributed to clients.
A simple way to do this is to output the certificate and copy its contents:
cat /root/ca/certs/ithu.cert
Paste the certificate (including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines) into this file and save it.
—–BEGIN CERTIFICATE—–
MIIFSTCCAzGgAwIBAgIUO9li4F1ztL6bYcGoWgGGlJ5Buz8wDQYJKoZIhvcNAQEL
BQAwNDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxEDAOBgNVBAoM
B0lUSFUtQ0EwHhcNMjUwOTE4MDE0MzQ0WhcNMzUwOTE2MDE0MzQ0WjA0MQswCQYD
x3N7LDtvdWNRktbNWD5LdH/TNU4qyKzF0Yx0CG+7ixZeDpz7s6TVizGh0AN6WC3G
vIZujgnGmfxB03aXTlwZ7HHvyX503mr1+s4+UF3t/wI8f4UvuvXgczFq22kOrupN
Q9vAdqGNCkfZrGJOMLQqxhc4Zv9WwbqWEQ3W6iZE1k5fhnv51WVGEcLLo8CPPaia
0zxmBvYHEMRoj6GDJufr5qy1riqPUo98H1jDizfVC/EpyFk6sKUYS0iw3FKKv3Eg
dZPTDHfD6vQlNi5qXdhN9fSTPTbtBdQm6o7aPV/iJFkXNA4eF7eMC0OP2dnDn41a
1BxVgleU+E1DMkynQ9LKs82KV3FiK9g/LP+eOmfpo8TZ9ZIARh5lP7L/tevg2Z/K
5XjKxxEG/+pF9GxOBQ==
—–END CERTIFICATE—–
📝 Convert the Certificate File for Windows
Once you’ve saved the Root CA certificate into a text file, rename it so Windows can recognize it as a certificate file. Windows requires the file extension .cer in order to import it through the Group Policy Management Console.
Now the file is ready to be imported into the Trusted Root Certification Authorities store via GPO.
🌍 Create a Domain-Wide GPO
Because this certificate needs to be trusted across the entire domain, the Group Policy Object (GPO) should be created at the root of the domain.
On your primary domain controller, open Group Policy Management, then:
- Right-click on the root domain.
 - Select “Create a GPO in this domain, and link it here…“.
 - Give the GPO a descriptive name, such as “Trusted Root CA – ITHU“.
 
This ensures that all domain-joined machines will receive the Root CA certificate and automatically trust certificates issued by it.

Edit the GPO and go to the following path “Computer Configuration\Policies\Windows Settings\Security Settings\Public Key Policies\Trusted Root Certification Authorities” right click and select “Import” then the wizard will start.

Browse to the location of the .cer file and select it, then click “Next“.

Make sure its set to place in the “Trusted Root Certification Authorities” and click “Next”.

Then click “Finish” and close Edit GPO.


🏁 Final Step – Verifying Distribution
Once you’ve linked the GPO with your Root CA certificate, Active Directory will replicate the policy across your domain. This normally happens automatically, but you can speed things up by running:
gpupdate /force
You should now see your internal Root CA, “ITHU-CA”, listed. This confirms that all domain computers trust certificates issued by your CA, and they will no longer show browser or application trust warnings when accessing services secured with your internal SSL certificates.

🔑 Summary
In this setup, we built a stand-alone internal CA server (ITHU-CA) on Ubuntu instead of exposing the Active Directory Enterprise CA directly. This CA issues SSL/TLS certificates for internal services that are not joined to the domain, such as:
- Web servers (Virtualmin, test apps)
 - Routers, switches, and firewalls
 - NAS devices or other appliances
 
By distributing the Root CA certificate with Group Policy, every domain-joined computer automatically trusts certificates issued by ITHU-CA. Non-domain devices can be updated manually.
✅ Why This Approach is Better
- Security Isolation
 
- The Enterprise CA remains locked down and dedicated to Active Directory authentication (Kerberos, LDAPS, smart cards).
 - Third-party or non-domain devices never need direct access to the AD CA.
 
2. Reduced Attack Surface
- You avoid having to open enrollment permissions on your AD CA to devices that don’t belong in Active Directory.
 - If the lab CA is ever compromised, your Tier-0 AD infrastructure is not at risk.
 
3. Flexibility
- Any device that can generate a CSR (router, NAS, Linux server) can be supported.
 - You can define custom SANs, IPs, and certificate lifetimes without touching AD.
 
4. Control and Demonstration
- Great for labs, penetration testing, and bug bounty training: you can show both “trusted chain” scenarios and misconfigured cert setups.
 - You maintain a clear separation: AD CA = domain identity, Lab CA = service SSL.
 
✅ In short:
Using a dedicated 3rd-party internal CA gives you flexibility and security. It lets you issue SSL certs for non-domain services without weakening or exposing your Active Directory Enterprise CA.