Our PKI certificate authority configuration & documentation
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
client-signer client CSR: update Common Name Sep 25, 2018
.travis.yml Build it with Turbo Bob Sep 25, 2018
LICENSE Initial commit Jan 9, 2017


Build Status Download


You obviously cannot use this directly, but this repository serves to others as an example for setting up a modern certificate authority. I wanted to publish this because this is a complex subject and there is not a lot of simple information written for achieving this. This is based on Cloudflare's cfssl which seems to be the current best-of-breed and simple and easy tool for this. However - cfssl is not that well documented.


function61.com's certificate authority is implemented as a Docker image.

The setup is somewhat unconventional because the scripts that you see in this repository are decoupled from the Docker image - the image only contains the cfssl binaries.

This is because you are going to need to mount at least the CA's private key into the container anyway, and this project is currently intended to be used as a manual tool anyway, so in this case it's an added bonus that the scripts and config are mounted directly from the repository as well (=> edit-run doesn't require image rebuild).

Enter it by running (while your current directory is this repository):

$ docker run -it --rm -v "$(pwd):/app" fn61/certificate-authority

Initialize CA

You have to do this only once during your root certificate's lifetime (currently configured at 20 years).

$ ca/init_ca.sh

You'll end up with these new files:

  • ca/ca.crt - this is your CA certificate ("root certificate")
  • ca/ca.key - this is the private key to the CA certificate. Protect this at all costs.

You have to import this root certificate to all of your devices that you want to trust accessing services backed by the server certs that you'll be signing with this project.

Import this root certificate in Windows:

  • Click on the .crt file
  • Install Certificate
  • Storate Location: Local Machine
  • Place all certificates in the following store: Trusted Root Certification Authorities

Sign a server certificate

$ server-signer/sign.sh

You'll end up with these new files:

  • server-signer/signed/server.crt - the new server certificate
  • server-signer/signed/server.key - the private key to the certificate. Protect this.

Sign a client certificate

$ client-signer/sign.sh

You'll end up with these new files:

  • client-signer/signed/client.crt - the new client certificate
  • client-signer/signed/client.key - the private key to the certificate. Protect this.
  • client-signer/signed/client.p12 - p12 = encrypt(.crt + .key): for delivering client cert to browsers / mobile devices

Import the .p12 file in Windows:

  • Click the .p12 file
  • Store Location: Current User
  • Password: (the password you used for the .p12 export)
  • Automatically select the certificate store based on the type of certificate

File layout

  • server-signer/sign.sh => for signing server certificates.
  • client-signer/sign.sh => for signing client certificates.


  • Make the server-signer take hostnames from the command line.
  • Implement intermediate CA:s, so the root CA cert can be kept totally offline.

Notes & links

Why cfssl?

Alternatives, in order of attractiveness: