Deployment
This guide covers running OLDP in production. For local development use Getting Started; for the containerised quickstart see Docker & Podman. All environment variables referenced here are documented in the Configuration reference.
Overview
A production OLDP deployment consists of:
the OLDP app (Django, served by an application server such as Gunicorn),
a relational database (MariaDB/MySQL recommended),
Elasticsearch 7.17.x for search,
optionally Redis as the cache backend and a CDN / reverse proxy (e.g. Nginx) in front of the app.
The shipped docker-compose.yaml defines the app, db (MariaDB) and search
(Elasticsearch) services and is a good starting point for a single-host
deployment.
Production configuration
Select the production settings class and provide the required secrets:
export DJANGO_CONFIGURATION=ProdConfiguration
export DJANGO_SECRET_KEY="<a long random secret>"
export DJANGO_ALLOWED_HOSTS="de.openlegaldata.io"
export DJANGO_SITE_URL="https://de.openlegaldata.io"
export DATABASE_URL="mysql://oldp:<password>@db/oldp"
export DJANGO_ELASTICSEARCH_URL="http://search:9200/"
When deploying the German site, point Django at the theme settings instead and
keep DJANGO_CONFIGURATION at the theme’s production class (see
The OLDP ecosystem):
export DJANGO_SETTINGS_MODULE=oldp_de.settings
export DJANGO_CONFIGURATION=ProdDEConfiguration
See the Configuration reference for caching (Redis), email, MCP rate limits, logging and CDN cache settings.
First-time setup
Prepare the database, assets and translations:
# Apply database migrations
./manage.py migrate
# Build front-end assets and collect static files
./manage.py compress
./manage.py collectstatic --no-input
# Compile translations (needed for production)
./manage.py compilemessages --l de --l en
# Build the search index
./manage.py rebuild_index
With Docker Compose the equivalent steps are available as Make targets
(make migrate, make rebuild-index, make compile-locale).
Create an administrator account:
./manage.py createsuperuser
Deploying updates
When rolling out new code:
Back up the database (and review test/CI status before deploying).
Pull the new code or container image.
Run
./manage.py migratefor any schema changes.Rebuild assets if they changed:
./manage.py compressand./manage.py collectstatic --no-input.Run
./manage.py update_index(incremental) or./manage.py rebuild_index(full) if search mappings changed.Restart the application server.
Production checklist
[ ]
DJANGO_CONFIGURATION=ProdConfiguration(or the theme’s prod class)[ ]
DJANGO_SECRET_KEYset to a strong, secret value[ ]
DJANGO_DEBUG=False(implied by the prod configuration)[ ]
DJANGO_ALLOWED_HOSTSandDJANGO_CSRF_TRUSTED_ORIGINSrestricted to your domains[ ]
DJANGO_SITE_URLset to the public HTTPS origin (also used for MCP OAuth discovery)[ ] Database backups configured
[ ] Elasticsearch reachable and index built
[ ] TLS terminated at the proxy/CDN; static files served efficiently
[ ] Cache backend chosen (
DJANGO_CACHE_BACKEND=redisfor multi-process deployments)
Operations
Elasticsearch — reindexing, realtime sync, index fields.
Sitemaps — XML sitemaps and search-engine pinging.
Data Dumps & Bulk Downloads — exporting snapshots with
dump_api_data.
Going further
For tuning the application server, reverse proxy, database, Elasticsearch and Redis beyond Django defaults, see the internal Performance notes. These are engineering notes rather than a prescriptive configuration — benchmark against your own traffic.