CockroachDB With Django and MIT Kerberos

Today, I’m going to talk about the means of using Django with a kerberized CockroachDB and what that entails. This is not uncommon in a production use case and expecting enterprise-grade access to development frameworks is table stakes for some of our customers.

Articles Covering CockroachDB and Kerberos

I find the topic of Kerberos very interesting and my colleagues commonly refer to me for help with this topic complex. I am by no means an expert at Kerberos, I am however familiar enough with it to be dangerous. That said, I’ve written multiple articles on the topic which you may find below:

  1. CockroachDB With MIT Kerberos
  2. CockroachDB With Active Directory
  3. CockroachDB With MIT Kerberos and Docker Compose
  4. Executing CockroachDB table import via GSSAPI
  5. CockroachDB With SQLAlchemy and MIT Kerberos
  6. CockroachDB With MIT Kerberos Cert User Authentication

Today, I’m going to demonstrate how to leverage CockroachDB with MIT Kerberos and the Django project. We have a lot of customers using us for their Python database needs and you can view some of the options on our docs site. For today’s setup, I have a multi-node CockroachDB cluster, a Django container called weba load balancer container, and a Kerberos KDC container.

You can find the code for this example in my repo. My example is a slight modification of the one you can find from Docker.

  1. Clone the repo.
git clone
cd cockroach-docker/cockroach-gssapi-django

  1. Create a Django project.

As I said, my version is a bit different from the one on the Docker website, as I’m adding a Kerberos Distribution Center, a load balancer, and a three-node CockroachDB cluster. Otherwise pretty much everything else is the same. What does not work is creating a project via the container like in the Docker quickstart. So docker-compose run web django-admin startproject composeexample . won’t work as I have an additional entry point in my Django container to kinit to the KDC. This is a small price to pay so instead, we’re going to run this manually.

a) Install Django locally.

Collecting django==2.2
  Using cached Django-2.2-py3-none-any.whl (7.4 MB)
Requirement already satisfied: pytz in /usr/local/lib/python3.8/site-packages (from django==2.2) (2020.1)
Requirement already satisfied: sqlparse in /usr/local/lib/python3.8/site-packages (from django==2.2) (0.3.1)
Installing collected packages: django
  Attempting uninstall: django
    Found existing installation: Django 3.1
    Uninstalling Django-3.1:
      Successfully uninstalled Django-3.1
Successfully installed django-2.2

Django 2.2 is the current long-term release but this setup works with Django 3.0 and 3.1 as well and I’ll cover that in a bit.

b) Create a project.

In the root of the docker-compose directory, initialize a new Django project.

django-admin startproject example .

Now you should see a directory called example and a file called

  1. Edit the Django properties file.

Edit the example/ with the following properties:

    'default': {
        'ENGINE': 'django_cockroachdb',
        'NAME': 'defaultdb',
        'USER': 'tester',
        'HOST': 'lb',
        'PORT': '26257',
        'OPTIONS': {
            'sslmode': 'verify-full',
            'sslrootcert': '/certs/ca.crt',

This is not much different from the standard Django properties except for the following subtle differences.

ENGINE is our CockroachDB native driver for Django, NAME is the database name, USER is a user in our Kerberos KDC, HOST Points to our load balancer instance, please review the previous articles if you need further context on that. We also include sslmode and sslrootcert to verify the authenticity of our clients and nodes.

  1. Verify the requirements file has the proper version of Django and CockroachDB driver.
cd ./django
vi requirements.txt

Uncomment the desired versions of Django and CockroachDB driver.

  1. Run ./ script to start the environment.
cockroach uses an image, skipping
Building roach-cert
Step 1/15 : FROM cockroachdb/cockroach:v20.1.4 AS generator
 ---> 25bee4f016c4

Time: 8.1053ms

  1. Check to make sure all containers are up.
kdc          /                        Up
lb           / hapr ...   Up>26257/tcp,
roach-0      /cockroach/ st ...   Up      26257/tcp, 8080/tcp
roach-1      /cockroach/ st ...   Up      26257/tcp, 8080/tcp
roach-2      /cockroach/ st ...   Up      26257/tcp, 8080/tcp
roach-cert   /bin/sh -c tail -f /dev/null     Up
web          / python ...   Up>8000/tcp

  1. Inspect the logs for the web container.
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python migrate' to apply them.
August 07, 2020 - 19:41:52
Django version 2.2.15, using settings 'example.settings'
Starting development server at
Quit the server with CONTROL-C.

We can see the server is up, we can navigate to the Django portal from your host.

I had a customer ask how to pass a custom SPN to a Django project. It was not documented and not that intuitive but after some trial and error, the following was achieved by adding krbsrvname to the example/ file.

  1. Django with custom SPN.
    'default': {
        'ENGINE': 'django_cockroachdb',
        'NAME': 'defaultdb',
        'USER': 'tester',
        'HOST': 'lb',
        'PORT': '26257',
        'OPTIONS': {
            'sslmode': 'verify-full',
            'sslrootcert': '/certs/ca.crt',
            'krbsrvname': 'customspn',

Tear down the environment with a helper script called ./ and restart it with ./

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python migrate' to apply them.
August 07, 2020 - 19:55:59
Django version 2.2.15, using settings 'example.settings'
Starting development server at
Quit the server with CONTROL-C.

Let’s apply those migrations!

  1. Apply migration.
docker-compose exec web python migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

  1. Upgrade Django.

There are many reasons to upgrade Django. Let’s do that with our project.

We need to edit our django/requirements.txt file to match the target version of Django, in our case 3.1.

# Django 3.1

Tear down the environment with and start it up again with Navigate to the Django portal and you will see the new version.

And just so there are no doubts, let’s connect to the web container and see whether a connection has been made with Kerberos.

docker exec -ti web sh

Default principal: tester@EXAMPLE.COM

Valid starting     Expires            Service principal
08/07/20 20:11:20  08/08/20 20:11:20  krbtgt/EXAMPLE.COM@EXAMPLE.COM
    renew until 08/07/20 20:11:20
08/07/20 20:11:31  08/08/20 20:11:20  customspn/lb@
    renew until 08/07/20 20:11:20
08/07/20 20:11:31  08/08/20 20:11:20  customspn/lb@EXAMPLE.COM
    renew until 08/07/20 20:11:20

That’s it for today, hope you enjoyed this tour of Django with Kerberos.


Leave a Comment