mow backend¶
Backend for Meals-on-Wheels Charlottesville operations: customers, routes, orders, reports, and portals (admin + volunteer).
Built with Python 3.13 / Django 5.2 LTS / DRF, packaged via Docker Compose, and shipped to AWS with GitHub Actions.
Project links:
• Main GitHub: https://github.com/thecodejim
• Backend repo: https://github.com/thecodejim/mow-backend
• Project website: https://mow.codejim.com
• Developer docs: https://developer.mow.codejim.com
• OpenAPI/Swagger: https://api.developer.mow.codejim.com
TL;DR — Get Started (macOS)¶
Windows guide is coming soon. For the full macOS guide, see macOS Development Environment Setup.
-
Install prerequisites
-
macOS 15+ with admin rights
- Xcode CLT:
xcode-select --install -
Docker Desktop (includes Compose v2): https://docs.docker.com/desktop/setup/install/mac-install/
-
Clone & enter the repo
git clone https://github.com/thecodejim/mow-backend.git
cd mow-backend
- Create your
.envfrom the dev example
make env # copies env.dev.example → .env and opens it
At minimum, confirm Postgres vars and set local secrets if you want (safe defaults exist for dev). See Environment files below for details.
- Build & run the dev stack
make build
make up
- (Optional) Create a superuser
make dj-createsuperuser
-
Open local endpoints
-
http://localhost(Caddy root) http://admin.localhost(Admin portal)http://portal.localhost(Volunteer portal)http://developer.localhost(Docs, if running)http://api.developer.localhost(Swagger UI, if enabled)http://grafana.localhost/http://prometheus.localhosthttp://localhost:5050(pgAdmin)http://localhost:8025(Mailpit)
Tip (macOS only):
make open-allwill open the common endpoints in Safari.
Why this project (and what it fixes)¶
This codebase replaces an older system that had hard limitations:
- Data model now supports multiple pets and multiple diets per customer (no more 1-pet/1-diet constraint).
- Immutable historical reporting preserves past facts even when current customer data changes.
- Configurable domains and environment-driven settings (no hard-coded hostnames).
- Safer defaults: CORS/CSRF locked down, non-root containers, security headers, no “allow all origins” in prod.
Architecture at a glance¶
- App: Python 3.13, Django 5.2 LTS, DRF, JWT (simplejwt), Gunicorn
- Data: PostgreSQL 17, Redis 8
- Web/TLS: Caddy (static, TLS, CSP/HSTS)
- Packaging: Docker + Compose (base/dev/prod overlays)
- Docs: OpenAPI JSON in
/api, MkDocs service for developer site - Observability: OpenTelemetry Collector → Prometheus, Loki, Tempo, Grafana
- CI/CD: GitHub Actions → multi-arch images → ECR; Release-Please for versioning and changelogs; stage/prod deploy workflows
- Project Mgmt: GitHub Issues + Projects, PR quality gates (lint, tests, commit checks)
For the full stack inventory, see the Master Technology Inventory in the project repo.
Developer workflow¶
Common Make targets¶
Run
make helpto see all targets with descriptions.
# Build & run (dev)
make build # build dev containers
make up # start dev stack (foreground)
make up-detach # start in background
make logs # follow logs
make down # stop
make clean # stop + delete volumes (⚠ deletes dev data)
# Django helpers
make dj-test # run tests (spins up postgres/redis if needed)
make dj-coverage # coverage report (console)
make dj-coverage-html# writes ./django/src/htmlcov/index.html
make dj-migrate # run migrations
make dj-createsuperuser
make dj-openapi # (re)generate OpenAPI → ./api/
# Linting & formatting (Ruff)
make dj-lint
make dj-format
make dj-lint-diff # CI-style diff check
# Env file management
make env # dev .env (copies env.dev.example)
make prod-env # prod .env (copies env.prod.example)
# Secrets (generated inside containers)
make dj-secret # Django SECRET_KEY (50 chars)
make token-32 # 32-byte hex token
make token-64 # 64-byte hex token
# Utilities
make pg-conninfo # psql \conninfo inside postgres
make pg-tables # list tables
make open-all # open common local endpoints (macOS)
Environment files¶
- Dev:
make envto copyenv.dev.example→.envand edit. - Stage/Prod:
make prod-envto copyenv.prod.example→.envand edit with real hostnames and secrets.
Use Make targets to generate secrets inside containers:
make dj-secret # SECRET_KEY
make token-32 # e.g. HEALTH_CHECK_TOKEN
make token-64 # e.g. OTEL_WRITE_TOKEN
Key sections to review for stage/prod:
ALLOWED_HOSTS,CORS_ALLOWED_ORIGINS,CSRF_TRUSTED_ORIGINSDOMAIN_NAME,ADMIN_DOMAIN,PORTAL_DOMAIN- Database credentials, TLS email, docs settings, OpenAPI path/URLs
For the complete guide, see Environment Files for Dev, Stage, and Prod.
Documentation¶
- Developer site: https://developer.mow.codejim.com
- API (Swagger/OpenAPI): https://api.developer.mow.codejim.com
-
Docs in repo: see
/docsfor: -
macOS setup, GitHub/AWS CLI, env files
- EC2 deploys (manual + from GitHub Actions)
- SSM Parameter Store, tagging, release-please, verifying dev deployments
- Google Maps API keys
Generate/refresh local OpenAPI files:
make dj-openapi # writes ./api/openapi-admin.json and openapi-volunteer.json
CI/CD & releases¶
- PR Quality Gate (
.github/workflows/pr-quality-gate.yml): Ruff lint, tests, commit message checks (Conventional Commits). - Build Images → ECR (
build-images.yml), multi-arch (amd64/arm64). - Release Please (
release-please.yml): automated GitHub Releases + CHANGELOG from Conventional Commits. - Deploy:
deploy-stage.yml(pre-release) anddeploy-prod.yml(release). OIDC to AWS; no long-lived keys.
Contributing¶
We use GitHub Issues and GitHub Projects for planning. PRs must pass the quality gate.
Conventional Commits are required. Examples:
feat(reports): add immutable history for meal changes
fix(auth): prevent CSRF double submit on login
chore(ci): speed up ruff cache
Local checklist before opening a PR:
make dj-lint
make dj-format
make dj-test
Security¶
- Non-root containers, CSP + HSTS via Caddy, strict CORS/CSRF in prod.
- No hard-coded domains or “allow all origins” in prod.
- Secrets are injected via
.envin dev and SSM Parameter Store in stage/prod.
To report a vulnerability, please open a private security advisory or contact the maintainers.
Local endpoints (dev)¶
- Root:
http://localhost - Admin portal:
http://admin.localhost - Volunteer portal:
http://portal.localhost - Docs:
http://developer.localhost - API docs:
http://api.developer.localhost - Grafana:
http://grafana.localhost - Prometheus:
http://prometheus.localhost - pgAdmin:
http://localhost:5050 - Mailpit (dev email):
http://localhost:8025 - Django admin (via admin portal):
http://admin.localhost/dj-admin
If using Caddy’s local CA on macOS, you can trust it with:
bash make caddy-mac-trust
Troubleshooting¶
- Docker says volumes/ports in use →
make prune-orphansormake clean(⚠ deletes dev data). - Health check 403 → use the external token:
make dj-test-health-external. - Static files missing →
make dj-collectstatic. - Docs not rebuilding → ensure
DOCS_BUILD_TOKENis set andmkdocsservice is running, or trigger:make mk-build.
License¶
TBD — see LICENSE (or open an issue if missing).
Acknowledgements¶
This project is a modern rewrite addressing long-standing data model, reporting, configurability, and security gaps found in earlier systems. Thank you to all community contributors and partners who informed this effort.
Happy hacking! If anything in this README seems off, please open an issue or PR.
Note: This file is the root
README.mdfor themow-backendGitHub repository. The links below are for navigating themkdocsdeveloper site.Next: Backend — Changelog >