###################### 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 :doc:`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). .. jinja:: requirements-from-source :file: /include/guide-requirements.rst.jinja :header_update_levels: Required software ================= .. jinja:: full-requirements-from-source :file: /include/guide-full-requirements.rst.jinja :header_update_levels: On Debian/Ubuntu, simply do: .. code-block:: console 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: .. code-block:: console 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: .. code-block:: console 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: .. jinja:: :file: /include/guide-get-source.rst.jinja 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! .. code-block:: console 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: .. code-block:: console 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: .. code-block:: console 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 .. _from-source-add-systemd-services: 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``): .. code-block:: console 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 :ref:`missing configuration `. If you use an installation directory other then ``/opt/django-ca``, set ``INSTALL_BASE`` in :file:`/etc/systemd/systemd-local.conf` (see :ref:`systemd-configuration`) *and* add a SystemD override for ``WorkingDirectory=``. .. _from-source-configuration: ************* 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 :doc:`django-ca setting `. If you (mostly) followed the above examples, you can symlink :file:`conf/source/00-settings.yaml` to ``/etc/django-ca`` and just override a few settings in :file:`/etc/django-ca/10-localsettings.yaml`. To create the symlink: .. code-block:: console root@host:~# ln -s /opt/django-ca/src/django-ca/conf/source/00-settings.yaml /etc/django-ca/ And then simply create a minimal :file:`/etc/django-ca/10-localsettings.yaml` - but you can override any other setting here as well: .. template-include:: yaml /include/quickstart_from_source/localsettings.yaml.jinja :caption: /etc/django-ca/10-localsettings.yaml :context: quickstart-from-source Please see :doc:`/settings` for a list of available settings and especially :ref:`settings-yaml-configuration` for more YAML configuration examples. .. _systemd-configuration: SystemD configuration ===================== When you :ref:`added SystemD services ` you also created a symlink for :file:`/etc/django-ca/systemd.conf`. If settings there do not suit you, you can override them in :file:`/etc/django-ca/systemd-local.conf`. .. _from-source-add-manage-py-shortcut: 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 :file:`/usr/local/bin/django-ca`, but of course you can name the symlink anything you like: .. code-block:: console 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: .. code-block:: console 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): .. code-block:: console root@host:~# systemctl start django-ca django-ca-celery django-ca-celerybeat Create admin user and set up CAs ================================ Because we :ref:`created a shortcut above ` above, we can use ``django-ca`` to use **django-ca** from the command line. .. jinja:: manage-from-source :file: /include/create-user.rst.jinja 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 :doc:`/quickstart/docker_compose` for an example. Create a private/public key pair for NGINX to use: .. code-block:: console 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 CN=$HOSTNAME \ > > /etc/ssl/$HOSTNAME.pem Create DH parameters: .. code-block:: console 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 :manpage:`envsubst(1)` that you can use. The template assumes that you have set ``$HOSTNAME``: .. code-block:: console 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 .. jinja:: guide-source-where-to-go :file: /include/guide-where-to-go.rst.jinja :header_update_levels: ****** Update ****** .. include:: /include/update_intro.rst Downloading the new release works the same as before, but you have to remove the old symlink before creating the new one: .. jinja:: :file: /include/guide-update-source.rst.jinja Update the database schema and static files: .. code-block:: console root@host:~# django-ca migrate root@host:~# FORCE_USER=root django-ca collectstatic Restart services: .. code-block:: console root@host:~# systemctl restart django-ca django-ca-celery django-ca-celerybeat Update the NGINX configuration: .. code-block:: console 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: .. code-block:: console 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: .. code-block:: console root@host:~# systemctl restart nginx Remove the system user: .. code-block:: console root@host:~# deluser django-ca Drop the PostgreSQL database: .. code-block:: console root@host:~# sudo -u postgres psql postgres=# DROP DATABASE django_ca; DROP DATABASE postgres=# DROP USER django_ca; DROP ROLE