This guide provides instructions for running your own certificate authority using docker compose. This is the quickest and easiest way to run django-ca, especially if you do not care to much about custom configuration or extending django-ca.
This tutorial will give you a CA with
- A root and intermediate CA.
- A browsable admin interface, protected by TLS (using Let's Encrypt certificates).
- Certificate revocation using CRLs and OCSP.
- (Optional) ACMEv2 support (= get certificates using certbot).
requirements-in-docker-compose
To run django-ca, you need Docker (at least version 19.03.0) and Docker Compose (at least version 1.27.0). You also need certbot to acquire Let's Encrypt certificates for the admin interface. OpenSSL is used to generate the DH parameter file. On Debian/Ubuntu, simply do:
user@host:~$ sudo apt update
user@host:~$ sudo apt install docker.io docker-compose certbot openssl
For a different OS, please read Install Docker, Install docker compose and Get certbot.
Use certbot to acquire initial certificates. This must be done before you run docker compose, as both bind to port 80 (HTTP).
user@host:~$ sudo certbot certonly --standalone -d ca.example.com
...
user@host:~$ sudo ls /etc/letsencrypt/live/ca.example.com
README cert.pem chain.pem fullchain.pem privkey.pem
Docker-compose needs a configuration file, docker-compose.yml </_files/docker-compose.yml>
. You can also download the file for other versions from github.
Note
Because of how Docker Compose works, it is better to put the file in a sub-directory and not directly into your home directory. We assume you put all files into ~/ca/
from now on.
You can also get versions for specific versions of django-ca from the table below, which also shows bundled third-party Docker images.
Warning
When updating, check if the PostgreSQL version has been updated. If yes, see postgresql_update
for upgrade instructions.
Version | Redis | PostgreSQL | NGINX |
---|---|---|---|
1.28.0 | 7 | 16 | 1.24 |
1.27.0 | 7 | 12 | 1.24 |
1.26.0 | 7 | 12 | 1.24 |
1.25.0 | 7 | 12 | 1.24 |
1.24.0 | 7 | 12 | 1.23 |
1.23.0 | 7 | 12 | 1.23 |
1.22.0 | 7 | 12 | 1.20 |
1.21.0 | 6 | 12 | 1.20 |
The default docker-compose.yml
does not offer HTTPS, because too many details (cert location, etc.) are different from system to system. We need to add a docker-compose override file to open the port and map the directories with the certificates into the container. Simply add a file called docker-compose.override.yml
next to your main configuration file:
yaml /include/quickstart_with_docker_compose/docker-compose.override.yml.jinja
This will work if you get your certificates using certbot
or a similar client. If your private key in public key chain is named different, you can set NGINX_PRIVATE_KEY
and NGINX_PUBLIC_KEY
in your .env
file below.
Some settings in django-ca can be configured with environment variables (except where a more complex structure is required). Simply create a file called .env
next to docker-compose.yaml
.
For a quick start, there are only a few variables you need to specify:
bash /include/quickstart_with_docker_compose/.env.jinja
The TLS configuration also requires that you generate a DH parameter file, used by some TLS ciphers. You can generate it with:
Although the defaults are fine for most scenarios, django-ca and Django itself support a wide range of settings to customize your installation. Django has its settings documented under Settings, django-ca settings are documented under custom
settings </settings>
.
Just like when using the plain Docker container, you can configure django-ca using either environment variables (set in e.g. docker-compose.override.yml
) or using an extra YAML configuration file. For more details on how to configure the Docker container, refer to docker-configuration
.
Note
In our docker compose setup, django-ca is used in both the backend
and frontend
containers. Make sure you configure both of them.
Using an extra configuration file is the most flexible way to configure django-ca, as it allows you to update even complex settings. It has the added advantage that docker compose will not recreate the containers if you update the configuration.
As with the normal docker container, django-ca will read configuration files in /usr/src/django-ca/ca/conf/
in alphabetical order, but it will also read files in the subfolder /usr/src/django-ca/conf/ca/compose/
, which provides configuration specific to our docker compose setup.
To add a configuration file, first add a volume mapping in your docker-compose.override.yml
:
/include/quickstart_with_docker_compose/docker-compose.override-localsettings-example.yml
... and then simply add a file called localsettings.yaml
in your current directory, for example:
/include/quickstart_with_docker_compose/localsettings.example.yml
Please see /settings
for a list of available settings and especially settings-yaml-configuration
for more YAML configuration examples.
If you want to use environment variables for configuration, we recommend you first add them to your docker-compose.override.yml
, for example to configure a different SMTP server for sending out emails:
/include/quickstart_with_docker_compose/docker-compose.override-env-example.yml
and in your .env
file, set the variable:
DJANGO_CA_EMAIL_HOST=smtp.example.com
By now, you should have at least four files in ~/ca/
:
user@host:~/ca/$ ls -A
docker-compose.yml docker-compose.override.yml .env dhparam.pem
Now, you can start django-ca for the first time. Inside the folder with all your configuration, run docker compose (and verify that everything is running):
By now, you should be able to see the admin interface (but not log in yet - you haven't created a user yet). Simply go to https://ca.example.com/admin/.
You can run the deployment checks for your setup, which should not return any issues:
Inside the backend container, manage
is an alias for manage.py
.
manage-in-docker-compose
guide-docker-compose-where-to-go
To backup your data, you need to store the PostgreSQL database and the private key files for your certificate authorities.
If possible for you, you can first stop the frontend
and backend
containers to make absolutely sure that you have a consistent backup:
user@host:~/ca/$ docker compose stop frontend
user@host:~/ca/$ docker compose stop backend
Create a database backup:
user@host:~/ca/$ docker compose exec db pg_dump -U postgres postgres > db.backup.sql
Backing up Docker volumes is not as straight forward as maybe it should be, please see the official documentation for more information.
You should always backup /var/lib/django-ca/certs/
from both the backend
and the frontend
container.
Here is an example that should work for the backend
container.:
user@host:~/ca/$ docker run -it --rm --volumes-from `basename $PWD`_backend_1 \
> -v `pwd`:/backup ubuntu tar czf /backup/backend.tar.gz /var/lib/django-ca/certs/
user@host:~/ca/$ tar tf backend.tar.gz
var/lib/django-ca/certs/
var/lib/django-ca/certs/ca/
var/lib/django-ca/certs/ca/1BBB69C1D3B64AB5EF39C2946015F57A0FB04107.key
var/lib/django-ca/certs/ca/shared/
var/lib/django-ca/certs/ca/shared/secret_key
...
Warning
- Updating from django-ca 1.28.0 or earlier? Please see
postgresql_update
. - Updating from django-ca 1.18.0 or earlier? Please see
update_119
.
Remember to backup your data <docker-compose-backup>
before you perform any update.
In general, updating django-ca is done by getting the latest version of docker-compose.yml
<docker-compose.yml>
and then simply recreating the containers:
user@host:~/ca/$ curl -O https://.../docker-compose.yml
user@host:~/ca/$ docker compose up -d
When a new version docker-compose.yml
includes a new version of PostgreSQL, you have to take some extra steps to migrate the PostgreSQL database.
Before you upgrade, back up your PostgreSQL database as usual:
user@host:~/ca/$ docker-compose down
user@host:~/ca/$ docker compose up -d db
user@host:~/ca/$ docker compose exec db pg_dump -U postgres -d postgres > backup.sql
Now update docker-compose.yml
but then only start the database:
user@host:~/ca/$ curl -O https://.../docker-compose.yml
user@host:~/ca/$ docker compose up -d db
Once the database is started, update the database with data from your backup and normally start your setup:
user@host:~/ca/$ cat backup.sql | docker compose exec -T db psql -U postgres -d postgres
user@host:~/ca/$ docker compose up -d
If you forgot to backup your database and started the update already, don't panic. Whenever we update the PostgreSQL version, we use a a new Docker volume. You should be able to reset docker-compose.yml
and then proceed to do the backup normally.