Skip to content

Docker installation

The Docker stack contains three services: web (Django + Daphne), db (PostgreSQL 17) and redis (Redis 7). It should sit behind a reverse proxy with HTTPS. This guide uses Caddy, which obtains a Let's Encrypt certificate automatically.

Requirements

  • A Linux server with Docker and Docker Compose v2 (docker compose).
  • A domain (e.g. odbavto.example.com) with an A/AAAA DNS record pointing to the server.
  • Open ports 80 and 443.
  • Roughly 1 GB RAM and 2 GB disk space.

1. Get the application

git clone https://github.com/michaelkalus/OdbavTo.git odbavto
cd odbavto

2. Configuration

cp .env.docker.example .env

Edit at least these values in .env:

COMPOSE_PROJECT_NAME=odbavto

SECRET_KEY=<long-random-string>
ALLOWED_HOSTS=odbavto.example.com
CSRF_TRUSTED_ORIGINS=https://odbavto.example.com

DB_NAME=odbavto
DB_USER=odbavto
DB_PASSWORD=<strong-password>

Generate a SECRET_KEY for example like this:

python3 -c "import secrets; print(secrets.token_urlsafe(50))"

All variables are described in Configuration (.env).

3. Network for the reverse proxy

The web service does not publish any port on the host. It is attached to the external Docker network web, through which the reverse proxy reaches it. Create the network once:

docker network create web

4. Start

docker compose up -d --build

Every time the web container starts, database migrations and collectstatic run automatically. Check the status with:

docker compose ps
docker compose logs -f web

5. Reverse proxy (Caddy)

If Caddy is not running on the server yet, run it as a separate container on the same web network. For example in ~/caddy:

services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - web

volumes:
  caddy_data:
  caddy_config:

networks:
  web:
    external: true
odbavto.example.com {
    encode gzip
    reverse_proxy odbavto-web:8000
}
cd ~/caddy && docker compose up -d

The container name is ${COMPOSE_PROJECT_NAME}-web, so with COMPOSE_PROJECT_NAME=odbavto it is odbavto-web. Caddy proxies WebSockets automatically, nothing else needs to be configured.

Other reverse proxies

Nginx, Traefik and others work too. The proxy must pass the X-Forwarded-Proto header and support WebSocket upgrade (path /ws/). docker-compose.yml sets BEHIND_PROXY=True, so Django trusts the X-Forwarded-Proto header.

6. First administrator

On a server, the default odbavto account is not created. Create the administrator manually:

docker compose exec web python manage.py createsuperuser

Then open https://odbavto.example.com/, log in and create accounts for other users in the administration at /admin/ (see Users).

Data and volumes

Volume Contents Back up
postgres_data Database Yes
private_media Uploaded label images and logos Yes
app_logs Application logs Optional

Volume names are prefixed with the project name, e.g. odbavto_postgres_data. See Updates and backups for the backup procedure.

Post-install checklist

  • https://odbavto.example.com/ loads with a valid certificate.
  • The administrator can log in.
  • The camera can be turned on in the scanner (this verifies HTTPS).
  • A test special label prints.
  • Regular backups of the database and private_media are set up.