Update

Each installation guide includes backup and update instructions matching the installation method used.

This document lists special update instructions when you update to a certain version.

Update from 1.26.0 or earlier

Update notes when upgrading to 1.27.0 or later.

RFC 4514 subjects

Note

The new format is described in detail in Subjects on the command-line.

django-ca==1.27.0 adds support for RFC 4514-style subjects, while support for the old OpenSSL-style format is deprecated. The subject format can be named with the --subject-format={rfc4514,openssl} option, with the default switching from openssl to rfc4514 in django-ca==2.0. The old format will be removed in django-ca==2.2.

The --subject-format is supported by the manage.py init_ca, manage.py sign_cert and manage.py resign_cert commands. The following migration examples are valid for all commands.

In django-ca==1.26.0, you would create a certificate authority like this:

OLD syntax
$ python manage.py init_ca NameOfCA /C=AT/O=MyOrg/OU=MyOrgUnit/CN=ca.example.com

With django-ca>=1.27.0, this command will show a warning about the old format. It will work unchanged until django-ca==1.29.0. The default will switch to the RFC 4514 format in django-ca==2.0.

To future-proof your code, pass --subject-format=rfc4514 and use an RFC 4514 subject instead:

NEW syntax
$ python manage.py init_ca --subject-format=rfc4514 \
>     NameOfCA C=AT,O=MyOrg,OU=MyOrgUnit,CN=ca.example.com

In django-ca==2.0, you will be able to remove the --subject-format=rfc4514 option, as it will become the default:

django-ca>=2.0
$ python manage.py init_ca NameOfCA C=AT,O=MyOrg,OU=MyOrgUnit,CN=ca.example.com

The default will switch from openssl to rfc4514 in django-ca==2.0, meaning in django-ca>=2.0, you can use the old format (until support will be removed in django-ca==2.2):

legacy syntax, available in django-ca>=2.0,<2.3
$ python manage.py init_ca --subject-format=openssl \
>     NameOfCA /C=AT/O=MyOrg/OU=MyOrgUnit/CN=ca.example.com

Update from 1.24.0 or earlier

Update notes when upgrading to 1.25.0.

Renamed command-line arguments

To make the interface more consistent, some command-line arguments have been renamed. Old versions will continue to work until django-ca==1.27.0.

old option

new option

--issuer-url

--sign-ca-issuer

--issuer-alt-name

--sign-issuer-alternative-name

--crl-url

--sign-crl-full-name

--ocsp-url

--sign-ocsp-responder

--ca-ocsp-url

--ocsp-responder

--ca-issuer-url

--ca-issuer

So if your old invocation looked like this:

$ python manage.py init_ca --crl-url ... --ocsp-url ... ...

instead use:

$ python manage.py init_ca --sign-crl-full-name ... --ocsp-responder ... ...

Update from 1.23.0 or earlier

Update notes when upgrading to 1.24.0.

Switch to USE_TZ=True by default

The USE_TZ was set to True in django-ca==1.24.0. This affects you if you if:

If both conditions are true for you, you should convert timestamps stored in the database to UTC. If you skip this step, timestamps stored in the database will shift by the offset from UTC of the default timezone.

The default is Europe/Vienna, so the shift is either one or two hours in this case. This affects stored expiry times, so certificates authorities and certificates will be considered as expired either too early or to late. ACME orders will also be affected by the shift, so any order made during upgrade will throw an error.

Warning

Invoking the below command multiple times will shift timestamps as many times, causing corrupt timestamps.

You can convert timestamps using a single manage.py command:

$ manage.py convert_timestamps

Command-line tools

  • manage.py init_ca: The --pathlen and --no-pathlen parameters are replaced with --path-length and --no-path-length. Old parameter names will work until django-ca==1.25.0.

  • manage.py sign_cert: The --key-usage option is split into the --key-usage and --key-usage-non-critical option. The --key-usage takes multiple arguments (instead of a comma-separated list).

    New, since django==1.24.0:

    $ manage.py sign_cert \
    >     --key-usage keyAgreement keyEncipherment
    

    Before, in earlier versions:

    $ manage.py sign_cert --key-usage critical,keyAgreement,keyEncipherment
    
  • manage.py sign_cert: The --ext-key-usage option is split into the --extended-key-usage and --extended-key-usage-critical option. The --extended-key-usage takes multiple arguments (instead of a comma-separated list) and also allows you to pass dotted strings for OIDs unknown to django-ca.

    New, since django==1.24.0:

    $ manage.py sign_cert \
    >     --extended-key-usage clientAuth serverAuth \
    >     --extended-key-usage-critical
    

    Before, in earlier versions:

    $ manage.py sign_cert --ext-key-usage critical,clientAuth,serverAuth
    
  • manage.py sign_cert: The --tls-feature option is split into the --tls-feature and --tls-feature-critical option. The --tls-feature-usage takes multiple arguments (instead of a comma-separated list) and also allows you to pass dotted strings for OIDs unknown to django-ca.

    New, since django==1.24.0:

    $ manage.py sign_cert \
    >     --tls-feature status_request \
    >     --tls-feature-critical
    

    Before, in earlier versions:

    $ manage.py sign_cert --tls-feature critical,status_request
    

Update from 1.20.0 or earlier

docker compose

In the configuration of 1.20.0 and earlier, the PostgreSQL container does not store data on a named volume. This means that the database would be lost if the container is removed. This does not happen during the reboot of a server or during the normal upgrade procedure. None the less, it is still safer to use named volumes to store data, so the docker compose setup starting with 1.21.0 uses named volumes for PostgreSQL (and also Redis).

If you perform the normal update procedure, no data is lost, but you will receive a warning about the services using data from the previous container:

$ docker compose up -d
Recreating django-ca_db_1 ...
Recreating django-ca_cache_1 ...
WARNING: Service "db" is using volume "/var/lib/postgresql/data" from the previous container. Host mapping
"django-ca_pgdata" has no effect. Remove the existing containers (with `docker compose rm db`) to use the host volume mapping.
...

To switch to named volumes, create a database backup, remove and recreate the db container with the new configuration and import the backup again. While possible, these instructions do not backup Redis data, since it is only a cache.

First, stop containers that might access the database:

$ docker compose stop frontend
$ docker compose stop backend

Second, create a dump of the database (Note: if you use a different database name or username, adapt accordingly):

$ docker compose exec db pg_dump -U postgres postgres > db.sql

Third, you might want to check if db.sql contains a valid database dump.

Fourth, remove the containers:

$ docker compose rm -sf cache db

Fifth, if you haven’t already, update your docker-compose.yml. To verify you have the named volumes, check that both the db and cache services have a volume with them. It does not matter if you have updated the file before performing the above steps.

Sixth, start the db container again (it will be recreated) and import the dump.

$ docker compose up -d db
$ docker compose exec -T db psql -U postgres postgres < db.sql

Seventh, start all other containers:

$ docker compose up -d

And finally, verify success - you should see your CAs:

$ docker compose exec backend manage list_cas
...

Update from 1.18 or earlier

If you use docker compose, you need to backup private keys and update your docker-compose.yml before upgrading. If you don’t private keys will be lost. The change to docker-compose.yml will make sure that keys will survive the next update.

First, you need to copy your private keys to a permanently stored location. If you do not have any keys in either the backend or frontend, mv will throw an error, which is of course fine in this case:

$ docker compose exec backend mkdir -p /var/lib/django-ca/certs/ca/shared/backend/
$ docker compose exec backend /bin/sh -c "cp /var/lib/django-ca/certs/ca/*.key /var/lib/django-ca/certs/ca/shared/backend/"
$ docker compose exec frontend mkdir -p /var/lib/django-ca/certs/ca/shared/frontend/
$ docker compose exec frontend /bin/sh -c "cp /var/lib/django-ca/certs/ca/*.key /var/lib/django-ca/certs/ca/shared/frontend/"

Note that if you have stored private keys in any custom location with the --path argument, you need to backup these locations as well.

Second, update your docker-compose.yml file. Either get the latest version of the file, or apply this diff:

--- docker-compose.yml.orig
+++ docker-compose.yml
@@ -33,6 +33,7 @@ services:
             - database
             - public
         volumes:
+            - backend_ca_dir:/var/lib/django-ca/certs/
             - shared_ca_dir:/var/lib/django-ca/certs/ca/shared/
             - ocsp_key_dir:/var/lib/django-ca/certs/ocsp/
             - shared:/var/lib/django-ca/shared/
@@ -65,6 +66,7 @@ services:
             - frontend
         volumes:
             - static:/usr/share/django-ca/static/
+            - frontend_ca_dir:/var/lib/django-ca/certs/
             - shared_ca_dir:/var/lib/django-ca/certs/ca/shared/
             - ocsp_key_dir:/var/lib/django-ca/certs/ocsp/
             - shared:/var/lib/django-ca/shared/
@@ -116,6 +118,8 @@ services:
 volumes:
     shared:
     static:
+    backend_ca_dir:
+    frontend_ca_dir:
     shared_ca_dir:
     ocsp_key_dir:
     nginx_config:

Third, do a normal upgrade:

$ docker compose pull
$ docker compose up -d

Finally, move the keys from the temporary location to the primary location:

$ docker compose exec backend /bin/sh -c "mv /var/lib/django-ca/certs/ca/shared/backend/*.key /var/lib/django-ca/certs/ca/"
$ docker compose exec backend rmdir /var/lib/django-ca/certs/ca/shared/backend/
$ docker compose exec frontend /bin/sh -c "mv /var/lib/django-ca/certs/ca/shared/frontend/*.key /var/lib/django-ca/certs/ca/"
$ docker compose exec frontend rmdir /var/lib/django-ca/certs/ca/shared/frontend/

Update from 1.17 or earlier

Please see documentation for previous versions on documentation how to upgrade.