Local CA - Your Own Internal Certificate Authority!


Welcome to Local CA, an open-source, self-hosted Certificate Authority (CA) that allows you to manage your own Public Key Infrastructure (PKI) for internal or home network use.

With Local CA, you can secure your locally hosted web services and eliminate HTTPS insecure warnings without relying on external services like Let's Encrypt.

Motivation

HTTPS is the bare minimum security needed for websites on the internet. It prevents eavesdroppers from intercepting your data over the network since it is encrypted by TLS.

What about the home network? Many people run their own websites and self hosted services in their home network, and there is no good way to secure these internal sites. For example, Bitwarden is a self-hosted password manager and using it without TLS would be very ill advised, even if it is just on the home network. Home networks can be penetrated by insecure or vulnerable IOT devices for example.

A common workaround is to use a reverse proxy or port forwarding to expose the internal website's port 80 to the internet and have Let's Encrypt issue certificates. This is a deal breaker for many people because exposing port 80 to the web, even if just briefly, is a security vulnerability. And to make matters worse, you have to do this every 90 days, since Let's Encrypt only issues certs for that long.

Therefore I've found that best way to secure your local services is to create your own Certificate Authority by generating self-signed certificates and installing them in your devices. This can be done using a complicated set of openssl commands which I can never remember. Enterprises do this too, but they often use commercial software or in house tools and it gets complicated.

Local CA was created to solve all these issues. It gives you full and granular control over how you manage your own internal cyber security.


Features

  • Secure HTTPS for Your Home Network: Easily enable HTTPS for local services like Proxmox, AdGuard Home, Pi-Hole, Jellyfin, Grafana, Homepage, Home Assistant, Bitwarden, basically any service that supports SSL/TLS.
  • Customizable PKI: Create root certificates (self-signed), intermediate certificates, and leaf/end-user certificates.
  • Web-Based UI: Manage certificates through an intuitive Python Django + Bootstrap-based web interface.
  • Lightweight Deployment: Deploy Local CA quickly using Docker in a Virtual Machine or a Raspberry PI.
  • Personal Branding: Name your root certificates whatever you want!
  • Mutual TLS (mTLS) Support: Use the generated certificates in mTLS applications.


Quick Start: Deploy with Pre-Built Docker Image

Prerequisites

Deployment Steps

  1. Download the Docker Compose file:

    wget https://raw.githubusercontent.com/tgangte/LocalCA/refs/heads/main/docker-compose-from-registry.yml

  2. Start the services

    docker compose -f docker-compose-from-registry.yml up

  3. Access the application in your browser:

    • Navigate to the host's IP address or 127.0.0.1.
    • Default credentials:

      • Username: admin
      • Password: password (Change this immediately after deployment.)

For ARM Architecture (e.g., Raspberry Pi, Apple Silicon)

  1. Download the ARM-specific Docker Compose file:

    wget https://raw.githubusercontent.com/tgangte/LocalCA/refs/heads/main/docker-compose-from-registry-arm.yml

  2. Start the services:

    docker compose -f docker-compose-from-registry-arm.yml up

Managing Services

  • Run in detached mode (background):

    docker compose -f docker-compose-from-registry.yml up -d

  • Stop services:

    docker compose -f docker-compose-from-registry.yml down

Local Development steps

If you want to build and deploy the app from the code repository, follow the following steps.

  1. Clone the repository

    git clone https://github.com/tgangte/LocalCA.git

  2. Set up a virtual environment

    python3 -m venv venv source venv/bin/activate

  3. Install dependencies

    pip install -r requirements.txt

  4. Apply migrations and initialize admin user

    cd localca_projectpython manage.py makemigrations LocalCA python manage.py migratepython manage.py initadmin`

  5. Run the development server:

    bash

    python manage.py runserver

Root Certificate Installation

Once the CA is created, the root public certificate needs to be installed in all client devices for the first time, as a one time only exercise. And since it is a self signed digital certificate, the client devices need to be explicitly told to trust it. The process varies by device.

  1. Download the root public key from the locaca homepage. It is just text file but saved in .pem format.
  2. Install it in the client device, steps vary by operating system.

Windows

To trust a self-signed certificate on Windows, run certmgr.msc and import your certificate into the Trusted Root Certification Authorities.

Linux

To trust a self-signed certificate on Linux, add your certificate to the following directories:

/usr/local/share/ca-certificates/ /usr/share/ca-certificates/

And run the following commands:

sudo dpkg-reconfigure ca-certificates sudo update-ca-certificates

Android

Follow the steps from the android docs https://support.google.com/pixelphone/answer/2844832?hl=en

Mac and iOS

Follow the steps from Apple https://support.apple.com/guide/keychain-access/add-certificates-to-a-keychain-kyca2431/mac https://support.apple.com/en-us/102390

Client/Leaf Certificate Installation

The client/leaf certificates need to be installed on your web services, and the steps vary by operating system and web server. Apache, Nginx, Haproxy etc are some common web servers and the certificate installation steps can be found in their respective websites.

The client devices need three components to work, the intermediate certificate, the actual leaf certificate, and the leaf certificate private key. When you download a public key chain from the Local CA portal, the intermediate and leaf certificates are already combined into one .pem file, and the private key is on the second file.

Here is an example of how to install the TLS certificate on Nginx. https://nginx.org/en/docs/http/configuring_https_servers.html.

server {
    listen              443 **ssl**;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

In his example nginx.conf, the leaf certificate should be created with a CN and SAN of www.example.com. The ssl_certificate should have the public key chain file downloaded from Local CA (which includes intermediate+leaf) and the ssl_certificate_key should be the private key file downloaded from Local CA portal.

Certificate distribution and renewal

The default certificate expiry of the leaf certificate is 1 year. That means you need to create a new certificate and reinstall it when expiry date is near. The old cert can simply be deleted from the admin panel. LocalCA does not currently support the ACME protocol, so this process is not automated yet.

Recommendation is to use configuration management tools like Ansible to install the certificates if there are a large number of hosts to install to.

User Administration

LocalCA use django's admin and auth system, so you can create and manage users, passwords and permissions from the admin panel. You can also delete certificates from the admin panel. The Admin panel can be accessed at /admin, for example: 127.0.0.1/admin and login using the superadmin credentials.

Users can only create and download private key of certificates they created. All public keys can however be downloaded by anyone without logging in and are listed on the homepage.

Backups

All data, including certificates and login info is stored in a SQLite database file using django's built in ORM, called db.sqlite3. This database file is unencrypted, so access to the folder and server must be tightly restricted.

The database is stored in the 'db' directory in the project root, and if deployed via docker, the db is accessible via a docker volume.
In most linux distros, you can find the volume in /var/lib/docker/volumes

You can manually or with a script copy the database file to an offline backup periodically.

Code Repository

Github Repo: https://github.com/tgangte/LocalCA

Docker Hub: https://hub.docker.com/r/practicalsre/local-ca/tags