Skip to content

Latest commit

 

History

History
350 lines (235 loc) · 11.6 KB

quickstart_from_source.rst

File metadata and controls

350 lines (235 loc) · 11.6 KB

Quickstart from source

This guide provides instructions for running your own certificate authority by installing django-ca from source. This method requires a lot of manual configuration and a lot of expert knowledge, but is a good choice if you use an exotic system or other options do not work for you for some reason. If you're looking for a faster and easier option, you might consider using docker-compose <quickstart_docker_compose>.

Note

All commands below assume that you have a shell with superuser privileges.

This tutorial will give you a CA with

  • A root and intermediate CA.
  • A browsable admin interface, protected by TLS (using certificates signed by your CA).
  • Certificate revocation using CRLs and OCSP.
  • (Optional) ACMEv2 support (= get certificates using certbot).

requirements-from-source

Required software

full-requirements-from-source

On Debian/Ubuntu, simply do:

root@host:~# apt update
root@host:~# apt install python3 python3-venv python3-dev \
>     gcc libpq-dev postgresql postgresql-client \
>     redis-server nginx uwsgi uwsgi-plugin-python3

Environment

To make the guide less error-prone, we export the domain name for your certificate authority to $HOSTNAME. In all commands below assume that you have set the environment variable like this:

root@host:~# export HOSTNAME=ca.example.com

Installation

With this guide, you will install django-ca to /opt/django-ca/, with your local configuration residing in /etc/django-ca/. You also need to create a system user to run the uWSGI application server and Celery task worker:

root@host:~# mkdir -p /opt/django-ca/src/ /etc/django-ca/
root@host:~# adduser --system --group --disabled-login --home=/opt/django-ca/home/ django-ca
root@host:~# adduser django-ca www-data

Get the source

You can clone django-ca from git or download an archive from GitHub. In the example below, we extract the source to /opt/django-ca/src/ and create a symlink without a version so that you can roll back to old versions during an update:

Create a virtualenv

In our setup, we create a virtualenv to install the Python environment. Several tools building on virtualenv exist (e.g. pyenv or virtualenvwrapper) that you might want to try out.

Warning

Always run pip in a virtualenv or it will update system dependencies and break your system!

root@host:~# python3 -m venv /opt/django-ca/venv/
root@host:~# /opt/django-ca/venv/bin/pip install -U \
>    pip setuptools wheel
root@host:~# /opt/django-ca/venv/bin/pip install -U \
>    -e /opt/django-ca/src/django-ca[postgres,celery,redis,yaml]

Alternatively, you can also use a pinned set of requirements created at the time of release by replacing the last command with:

root@host:~# /opt/django-ca/venv/bin/pip install -U \
>     -r /opt/django-ca/src/django-ca/requirements-pinned.txt \
>     -e /opt/django-ca/src/django-ca

Both commands will install PostgreSQL support, but not install MySQL support. If you want to use MySQL, install the mysql extra.

PostgreSQL database

Create a PostgreSQL database and make sure to use a randomly generated password and keep it for later configuration:

root@host:~# openssl rand -base64 32
...
root@host:~# sudo -u postgres psql
postgres=# CREATE DATABASE django_ca;
CREATE DATABASE
postgres=# CREATE USER django_ca WITH ENCRYPTED PASSWORD 'random-password';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE django_ca TO django_ca;
GRANT

Add SystemD services

SystemD services are included with django-ca. You need to add three services, one for the uWSGI application server (django-ca), one for the Celery task worker (django-ca-celery) and one for the Celery task scheduler (django-ca-celerybeat):

root@host:~# ln -s /opt/django-ca/src/django-ca/systemd/systemd.conf /etc/django-ca/
root@host:~# ln -s /opt/django-ca/src/django-ca/systemd/*.service /etc/systemd/system/
root@host:~# systemctl daemon-reload
root@host:~# systemctl enable django-ca django-ca-celery django-ca-celerybeat

Note that the services will not yet start due to missing configuration <from-source-configuration>.

If you use an installation directory other then /opt/django-ca, set INSTALL_BASE in /etc/systemd/systemd-local.conf (see systemd-configuration) and add a SystemD override for WorkingDirectory=.

Configuration

django-ca will load configuration from all *.yaml files in /etc/django-ca/ in alphabetical order. These files can contain any Django setting, Celery setting or django-ca setting <settings>.

If you (mostly) followed the above examples, you can symlink conf/source/00-settings.yaml to /etc/django-ca and just override a few settings in /etc/django-ca/10-localsettings.yaml. To create the symlink:

root@host:~# ln -s /opt/django-ca/src/django-ca/conf/source/00-settings.yaml /etc/django-ca/

And then simply create a minimal /etc/django-ca/10-localsettings.yaml - but you can override any other setting here as well:

yaml include/quickstart_from_source/localsettings.yaml.jinja

Please see settings for a list of available settings and especially settings-yaml-configuration for more YAML configuration examples.

SystemD configuration

When you added SystemD services <from-source-add-systemd-services> you also created a symlink for /etc/django-ca/systemd.conf. If settings there do not suit you, you can override them in /etc/django-ca/systemd-local.conf.

Add manage.py shortcut

As optional convenience, you can create a symlink to a small wrapper script that allows you to easily run manage.py commands. In the examples below the guide assumes you created this symlink at /usr/local/bin/django-ca, but of course you can name the symlink anything you like:

root@host:~# ln -s /opt/django-ca/src/django-ca/conf/source/manage /usr/local/bin/django-ca
root@host:~# django-ca check
System check identified no issues (0 silenced).

Setup Database and static files

Populate the database and setup the static files directory:

root@host:~# django-ca migrate
root@host:~# FORCE_USER=root django-ca collectstatic

The collectstatic command needs to run as root.

Start

You can now finally start the uWSGI application server and the Celery worker (omit django-ca service if you do not intend to run a web server):

root@host:~# systemctl start django-ca django-ca-celery django-ca-celerybeat

Create admin user and set up CAs

Because we created a shortcut above <from-source-add-manage-py-shortcut> above, we can use django-ca to use django-ca from the command line.

manage-from-source

Setup NGINX

A web server is required for the admin interface, certificate revocation status via OCSP or CRLs and ACMEv2 (the protocol used by Let's Encrypt/certbot integration).

Warning

While theoretically possible, do not use a local CAs ACMEv2 interface to get certificates. Any misconfiguration might make it impossible to retrieve a certificate!

In this setup, we'll create certificates using the CA we created above. If you want to use Let's Encrypt certificates instead, you can have a look at our quickstart_docker_compose for an example.

Create a private/public key pair for NGINX to use:

root@host:~# openssl genrsa -out /etc/ssl/$HOSTNAME.key 4096
root@host:~# openssl req -new -key /etc/ssl/$HOSTNAME.key -out /tmp/ca.csr -utf8 -batch
root@host:~# django-ca sign_cert --ca=Intermediate --csr=/tmp/ca.csr --bundle --webserver --subject-format=rfc4514 --subject CN=$HOSTNAME \
>     > /etc/ssl/$HOSTNAME.pem

Create DH parameters:

root@host:~# mkdir -p /etc/nginx/dhparams/
root@host:~# openssl dhparam -dsaparam -out /etc/nginx/dhparams/dhparam.pem 4096

django-ca includes a template for envsubst(1) that you can use. The template assumes that you have set $HOSTNAME:

root@host:~# envsubst < /opt/django-ca/src/django-ca/nginx/source.template \
>     > /etc/nginx/sites-available/django-ca.conf
root@host:~# ln -fs /etc/nginx/sites-available/django-ca.conf /etc/nginx/sites-enabled/
root@host:~# nginx -t
root@host:~# systemctl restart nginx

guide-source-where-to-go

Update

Downloading the new release works the same as before, but you have to remove the old symlink before creating the new one:

Update the database schema and static files:

root@host:~# django-ca migrate
root@host:~# FORCE_USER=root django-ca collectstatic

Restart services:

root@host:~# systemctl restart django-ca django-ca-celery django-ca-celerybeat

Update the NGINX configuration:

root@host:~# envsubst < /opt/django-ca/src/django-ca/nginx/source.template \
>     < /opt/django-ca/src/django-ca/nginx/source.template \
>     > /etc/nginx/sites-available/django-ca.conf
root@host:~# nginx -t
root@host:~# systemctl restart nginx

Uninstall

To completely uninstall django-ca, stop related services and remove files that where created:

root@host:~# systemctl stop django-ca django-ca-celery django-ca-celerybeat
root@host:~# systemctl disable django-ca django-ca-celery django-ca-celerybeat
root@host:~# rm -f /etc/nginx/sites-*/django-ca.conf
root@host:~# rm -f /var/log/nginx/$HOSTNAME*.log
root@host:~# rm -f /usr/local/bin/django-ca
root@host:~# rm -rf /etc/django-ca/ /opt/django-ca/ /var/log/django-ca
root@host:~# rm -f /etc/ssl/$HOSTNAME.{key,pem}

Restart NGINX so that it no longer knows about the configurations:

root@host:~# systemctl restart nginx

Remove the system user:

root@host:~# deluser django-ca

Drop the PostgreSQL database:

root@host:~# sudo -u postgres psql
postgres=# DROP DATABASE django_ca;
DROP DATABASE
postgres=# DROP USER django_ca;
DROP ROLE