Docker
The repository ships with a production-style docker-compose.yml that brings up everything you need: Postgres, Redis, the Django backend, a Celery worker, and the SvelteKit frontend.
Minimum requirements
- CPU: 2 vCPU (4 for production)
- RAM: 2 GB (4 GB recommended)
- Disk: 10 GB
- OS: Anything that runs Docker — Linux, macOS, Windows with WSL2
Topology
┌────────────┐ ┌────────────┐ ┌─────────┐
│ frontend │ → │ backend │ → │ db │
│ (sveltekit│ │ (django) │ │ (psql) │
│ :5173) │ │ :8000 │ └─────────┘
└────────────┘ └────────────┘ │
│ │
↓ │
┌─────────┐ │
│ redis │ ← worker ─┘
└─────────┘ (celery)
The frontend talks to the backend over HTTP. The backend uses Redis as the Celery broker and result store. Both backend and worker connect to Postgres through a non-superuser role so row-level security is enforced.
Running it
git clone https://github.com/MicroPyramid/Django-CRM.git
cd Django-CRM
cp .env.docker.example .env.docker # set secrets here
docker compose up --build -d
docker compose exec backend python manage.py migrate
docker compose exec backend python manage.py seed_data # optional
The frontend is now at http://localhost:5173, the API at http://localhost:8000/api/.
Production deployment
For production, run the stack behind a reverse proxy (Caddy, nginx, Traefik) that terminates TLS, and put the backend in DEBUG=False mode.
Key changes from the dev compose file:
- Pin image tags rather than building from source.
- Mount
/app/mediaand the Postgres data dir on persistent volumes. - Set
ALLOWED_HOSTSandCORS_ALLOWED_ORIGINSto your real domain. - Rotate
DJANGO_SECRET_KEYandJWT_SIGNING_KEYto fresh values. - Run
python manage.py manage_rls --statusto confirm RLS policies are present.
Backups
There are two things to back up:
- The Postgres database —
pg_dump --format=customis enough. Take it nightly and offsite-replicate it. - Uploaded media — anything under the backend's
media/directory (attachments on cases, contact avatars, etc).
Restore is a vanilla pg_restore plus copying the media directory back.