############################## Quickstart with Docker Compose ############################## .. _docker-compose: .. structured-tutorial:: compose/tutorial.yaml 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. * ACMEv2 support (= get certificates using certbot). * A browsable admin interface and a REST API. * Certificate revocation using CRLs and OCSP. * ACMEv2, admin interface and REST API are served with HTTPS using Let's Encrypt certificates. .. NOTE:: This tutorial uses `structured-tutorials `_. This means that the documentation you see here is rendered from a configuration file and can also be run locally to verify correctness and completeness. ************ Requirements ************ .. include:: /include/guide-requirements.rst Required software ================= To run **django-ca**, you need Docker (at least version 19.03.0) and Docker Compose (at least version 1.28.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: .. structured-tutorial-part:: install-dependencies For a different OS, please read `Install Docker `_, `Install docker compose `_ and `Get certbot `_. .. structured-tutorial-part:: add-docker-group ***************** Get configuration ***************** .. 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: .. structured-tutorial-part:: create-ca-directory To run **django-ca**, you'll need a couple of files: * :ref:`dhparam.pem `, the DH parameters (required for TLS connections). * :ref:`conf/ `, a directory with YAML configuration files. * :ref:`compose.yaml `, the configuration for Docker Compose. * :ref:`compose.override.yaml `, system-local configuration overrides for Docker Compose. * :ref:`.env `, the environment file for Docker Compose. * :ref:`nginx-reload.sh `, a certbot *deploy hook* to reload NGINX after certificate renewal. Read the sections below how to retrieve or generate all these files. .. _quickstart-compose-dhparam.pem: Generate DH parameters ====================== The TLS configuration requires that you generate a DH parameter file, which used by some TLS ciphers. You can generate it with: .. structured-tutorial-part:: generate-dh-params .. _quickstart-compose-config-files: Add configuration files ======================= .. versionchanged:: 2.5.0 Previous versions documented a single file in ``~/ca/``, the new style allows you to split the configuration into multiple files. **django-ca** is configured via a YAML configuration files. It is not strictly required, as the defaults are fine in most cases. Creating at least an empty file is recommended, as it will make any future changes easier. .. NOTE:: Do not set ``CA_DEFAULT_HOSTNAME`` and ``CA_URL_PATH`` here! They are set in `.env `_, as the NGINX container also uses them. First, simply create a configuration directory: .. structured-tutorial-part:: mkdir-conf You can create any number of files in that directory, and they will be read in alphabetical order. Here we add an example that just enables the :doc:`/rest_api`: .. structured-tutorial-part:: create-config-rest You can configure any `Django setting `_ or any of the :doc:`custom settings ` here. Almost all settings can be changed later, if that is not the case, the settings documentation mentions it. .. _quickstart-compose-compose.yaml: Add ``compose.yaml`` ==================== Docker Compose needs a configuration file, :download:`compose.yaml `. You can also download the file for other versions `from github `_. 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 :ref:`postgresql_update` for upgrade instructions. .. Keep no more then 10 releases in this table. ==================================================================================== ===== ========== ======== Version Redis PostgreSQL NGINX ==================================================================================== ===== ========== ======== `3.0.0 `_ 8 16 1.28 `2.5.0 `_ **8** 16 **1.28** `2.4.0 `_ 7 16 1.26 `2.3.0 `_ 7 16 1.26 `2.2.0 `_ 7 16 1.26 `2.1.1 `_ 7 16 1.26 `2.1.0 `_ 7 16 1.26 `2.0.0 `_ 7 16 1.26 `1.29.0 `_ 7 16 1.24 `1.28.0 `_ 7 **16** 1.24 `1.27.0 `_ 7 12 1.24 ==================================================================================== ===== ========== ======== Note that until ``django-ca==2.1.1``, this file was called ``docker-compose.yml``. .. _quickstart-compose-compose.override.yaml: Add ``compose.override.yaml`` ============================= The default :file:`compose.yaml` does not offer HTTPS, because too many details (cert location, etc.) are different from system to system. We need to add a `compose override file `_ to open the port and map the directories with the certificates into the container. Simply add a file called :file:`compose.override.yaml` next to your main configuration file: .. structured-tutorial-part:: copy-compose-override-yaml 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 :file:`.env` file below. .. _quickstart-compose-.env: Add ``.env`` file ================= Some settings in **django-ca** can be configured with environment variables (except where a more complex structure is required). Simply create a file called :file:`.env` next to :file:`compose.yaml`. For a quick start, there are only a few variables you need to specify: .. structured-tutorial-part:: copy-env .. _quickstart-compose-nginx-reload.sh: Add ``nginx-reload.sh`` file ============================ :file:`nginx-reload.sh` is a certbot deployment hook that will reload the web server when the certbot certificate is renewed: .. structured-tutorial-part:: copy-nginx-reload Certbot requires the script to be executable: .. structured-tutorial-part:: chmod-nginx-reload Recap ===== By now, you should have *five* files and *one* directory in ``~/ca/``: .. structured-tutorial-part:: ls-recap .. _quickstart-compose-get-initial-certificates: ************************ Get initial certificates ************************ Some endpoints of the CA (ACMEv2, REST API and the admin interface) are available via HTTPS. In our tutorial, we will use Let's Encrypt certificates for maximum compatibility for clients. You could also use certificates from a CA managed by **django-ca** itself, but such a setup could lead to a situation where endpoints are no longer working due to faulty (e.g. expired) certificates, but you need working endpoints to renew them. Retrieving initial certificates must be done `before` you run **docker compose**, as both bind to port 80 (HTTP): .. structured-tutorial-part:: get-certificates-with-certbot The above example uses the ``standalone`` plugin to fulfill a `HTTP-01 challenge type `_. This challenge requires your server to export port 80 to the internet. If that does not work for you but you still want to use Let's Encrypt, you can use any of the `many plugins `_. ************* Start your CA ************* 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): .. structured-tutorial-part:: start-compose 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/. Verify setup ============ You can run the deployment checks for your setup, which should not return any issues: .. structured-tutorial-part:: run-manage-check Create admin user and set up CAs ================================ Inside the backend container, ``manage`` is an alias for ``manage.py``. .. jinja:: manage-in-docker-compose :file: /include/create-user.rst.jinja .. _docker-compose-use-ca: .. jinja:: guide-docker-compose-where-to-go :file: /include/guide-where-to-go.rst.jinja :header_update_levels: ***************************** Automatic certificate renewal ***************************** If you used the ``certbot certonly --standalone`` to retrieve Let's Encrypt certificates (:ref:`see above `), you still need to configure automatic certificate renewal. The current setup will not work, as port 80 is now occupied by nginx. Tell certbot to renew certificates using the :spelling:ignore:`"webroot"` plugin instead: .. structured-tutorial-part:: setup-certbot-automatic-renewal If you used any other ACMEv2 authentication method (e.g. a DNS-based setup), you probably don't need to do anything here. .. _docker-compose-backup: ****** Backup ****** 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: .. code-block:: console user@host:~/ca/$ docker compose stop frontend user@host:~/ca/$ docker compose stop backend Create a database backup: .. code-block:: console 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.: .. code-block:: console 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 ... ****** Update ****** .. include:: /include/update_intro.rst .. WARNING:: * **Updating from django-ca 1.28.0 or earlier?** Please see :ref:`postgresql_update`. * **Updating from django-ca 1.18.0 or earlier?** Please see :ref:`update_119`. Remember to :ref:`backup your data ` before you perform any update. In general, updating django-ca is done by getting the :ref:`latest version of compose.yaml ` and then simply recreating the containers: .. code-block:: console user@host:~/ca/$ curl -O https://.../compose.yaml user@host:~/ca/$ docker compose up -d .. _postgresql_update: PostgreSQL update ================= When a new version :file:`compose.yaml` 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: .. code-block:: console 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 :file:`compose.yaml` but then **only start the database**: .. code-block:: console user@host:~/ca/$ curl -O https://.../compose.yaml 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: .. code-block:: console user@host:~/ca/$ cat backup.sql | docker compose exec -T db psql -U postgres -d postgres user@host:~/ca/$ docker compose up -d Forgot to backup? ----------------- 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 :file:`compose.yaml` and then proceed to do the backup normally.