generated from bisco/codex-bootstrap
223 lines
8.3 KiB
Markdown
223 lines
8.3 KiB
Markdown
# Deployment
|
|
|
|
## Production Readiness
|
|
|
|
Before a real deployment, treat `.env.example` as local-development only. Create a separate `.env` for production and replace all placeholder values.
|
|
|
|
Required production changes:
|
|
|
|
- set `DJANGO_DEBUG=false`;
|
|
- set a strong random `DJANGO_SECRET_KEY`;
|
|
- set `DJANGO_ALLOWED_HOSTS` to the real public hostnames only;
|
|
- set `DJANGO_CSRF_TRUSTED_ORIGINS` to the real public HTTPS origins;
|
|
- set `SITE_BASE_URL` to one real public HTTPS base URL used for confirmation emails and QR/check-in links;
|
|
- replace the console email backend with real SMTP settings and a valid sender address;
|
|
- publish only nginx and terminate HTTPS at nginx or a trusted upstream reverse proxy;
|
|
- keep `collectstatic --noinput` in the deployment flow before `up -d`;
|
|
- persist the PostgreSQL named volume and configure tested backups before accepting bookings;
|
|
- create the first admin account explicitly with `python manage.py createsuperuser`.
|
|
|
|
Reverse proxy and HTTPS notes:
|
|
|
|
- the current nginx template listens on plain HTTP port `80` only and must be adapted for production TLS;
|
|
- if TLS is terminated by another reverse proxy, forward the public host and scheme correctly so generated links remain accurate;
|
|
- keep `SITE_BASE_URL`, `DJANGO_ALLOWED_HOSTS`, and `DJANGO_CSRF_TRUSTED_ORIGINS` aligned with the final public URL.
|
|
|
|
AzioneLab should deploy with a simple Docker Compose topology:
|
|
|
|
- `nginx`: public reverse proxy and static frontend server;
|
|
- `frontend`: Angular build source or build stage for static assets;
|
|
- `backend`: Django 5.2 LTS application served by gunicorn;
|
|
- `postgres`: PostgreSQL database.
|
|
|
|
Only nginx should expose public ports. The backend and database should stay on the internal Compose network.
|
|
|
|
The initial Compose setup is located at `infra/docker/compose.yml`.
|
|
|
|
## Services
|
|
|
|
### nginx
|
|
|
|
Responsibilities:
|
|
|
|
- listen on public HTTP and HTTPS ports;
|
|
- serve built Angular files;
|
|
- proxy `/api/` and `/admin/` requests to the backend;
|
|
- serve static and media files according to the selected storage layout;
|
|
- apply request size and timeout limits appropriate for booking and admin usage.
|
|
|
|
Public ports:
|
|
|
|
- `80` for HTTP;
|
|
- `443` for HTTPS in production.
|
|
|
|
### frontend
|
|
|
|
The frontend is an Angular application using Angular Material.
|
|
|
|
Deployment options:
|
|
|
|
- build the Angular app in a Docker build stage and copy static files into the nginx image;
|
|
- or run a one-shot build container that writes static files to a shared volume consumed by nginx.
|
|
|
|
The first option is preferred for a simple production deployment because nginx can serve immutable built assets without a long-running Node process.
|
|
|
|
At the infrastructure placeholder stage, the `frontend` service serves a static placeholder page with nginx. The Angular build will replace this placeholder later.
|
|
|
|
### backend
|
|
|
|
The backend is a Django application served by gunicorn.
|
|
|
|
Responsibilities:
|
|
|
|
- REST API;
|
|
- Django admin;
|
|
- booking, confirmation, QR generation, and check-in logic;
|
|
- transactional capacity validation;
|
|
- email sending.
|
|
|
|
The backend should run database migrations before or during deployment through an explicit operational command, not as hidden startup magic unless that choice is documented later.
|
|
|
|
The `backend` service runs gunicorn against the Django WSGI application. The current backend is an initial skeleton with Django admin, Django REST Framework, CORS configuration, the `shows`, `bookings`, and `checkins` apps, and a health endpoint.
|
|
|
|
### postgres
|
|
|
|
PostgreSQL is the only database service.
|
|
|
|
Responsibilities:
|
|
|
|
- persistent application data;
|
|
- reservation and check-in state;
|
|
- transactional capacity enforcement.
|
|
|
|
Use a named Docker volume for database data.
|
|
|
|
## Networks
|
|
|
|
Recommended Compose networks:
|
|
|
|
- `public`: nginx-facing network when needed;
|
|
- `internal`: private network for nginx, backend, and db communication.
|
|
|
|
The database should not be published to the host in production.
|
|
|
|
## Volumes
|
|
|
|
Recommended volumes:
|
|
|
|
- `postgres_data`: PostgreSQL data directory;
|
|
- `media`: uploaded show images and generated QR assets if stored on disk;
|
|
- `static`: collected Django static files if served by nginx from a shared volume.
|
|
|
|
Generated QR codes may also be generated on demand instead of stored as files. If stored, they must not reveal personal data and access must remain controlled.
|
|
|
|
## Configuration
|
|
|
|
Copy `.env.example` to `.env` and replace all placeholder values before running or deploying the stack.
|
|
|
|
`.env.example` is intentionally local-dev oriented. Do not use it unchanged for production.
|
|
|
|
Required backend configuration:
|
|
|
|
- `DJANGO_SECRET_KEY`;
|
|
- `DJANGO_ALLOWED_HOSTS`;
|
|
- `DJANGO_CSRF_TRUSTED_ORIGINS`;
|
|
- `DJANGO_DEBUG=false`;
|
|
- `CORS_ALLOWED_ORIGINS`;
|
|
- `SITE_BASE_URL`;
|
|
- `TIME_ZONE`;
|
|
- `DATABASE_URL` or equivalent database settings;
|
|
- email host, port, username, password, TLS settings, and sender address;
|
|
- public site URL used to build confirmation and QR verification links.
|
|
|
|
Local Docker convention:
|
|
|
|
- use nginx as the public entrypoint at `http://localhost`;
|
|
- set `SITE_BASE_URL=http://localhost`;
|
|
- keep `SITE_BASE_URL` as a single URL value, never a comma-separated list;
|
|
- keep `DJANGO_CSRF_TRUSTED_ORIGINS` and browser-facing `CORS_ALLOWED_ORIGINS` aligned with that public URL;
|
|
- if you publish nginx on a different port, update `SITE_BASE_URL` and trusted origins to the same host and port.
|
|
- local/debug reservation email sends also log the confirmation URL so browser testing can continue even if SMTP is missing or fails.
|
|
|
|
Required database configuration:
|
|
|
|
- database name;
|
|
- database user;
|
|
- database password;
|
|
- data volume path.
|
|
|
|
Required nginx configuration:
|
|
|
|
- upstream backend service name and port;
|
|
- static frontend root;
|
|
- proxy rules for `/api/` and `/admin/`;
|
|
- media root for `/media/` if uploaded assets are served by nginx from a shared volume;
|
|
- TLS certificate paths for production.
|
|
|
|
Secrets must be provided through deployment-managed environment variables, Docker secrets, or another secret manager. Do not commit real secret values.
|
|
|
|
## Example Request Routing
|
|
|
|
```text
|
|
Visitor browser
|
|
-> nginx
|
|
-> Angular static files
|
|
-> /api/ requests proxied to backend:gunicorn
|
|
-> /admin/ requests proxied to backend:gunicorn
|
|
Backend
|
|
-> PostgreSQL
|
|
-> SMTP provider
|
|
```
|
|
|
|
## Deployment Commands
|
|
|
|
The exact commands will be finalized when application code and Compose files are added.
|
|
|
|
Expected production-style flow:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f infra/docker/compose.yml build
|
|
docker compose --env-file .env -f infra/docker/compose.yml run --rm backend python manage.py migrate
|
|
docker compose --env-file .env -f infra/docker/compose.yml run --rm backend python manage.py collectstatic --noinput
|
|
docker compose --env-file .env -f infra/docker/compose.yml run --rm backend python manage.py createsuperuser
|
|
docker compose --env-file .env -f infra/docker/compose.yml up -d
|
|
```
|
|
|
|
Expected validation commands:
|
|
|
|
```bash
|
|
docker compose --env-file .env.example -f infra/docker/compose.yml config
|
|
docker compose --env-file .env.example -f infra/docker/compose.yml run --rm --build backend python manage.py test
|
|
docker compose --env-file .env -f infra/docker/compose.yml run --rm backend python manage.py check --deploy
|
|
docker compose --env-file .env -f infra/docker/compose.yml run --rm backend python manage.py test
|
|
```
|
|
|
|
The canonical repository check for the current stage is:
|
|
|
|
```bash
|
|
docker compose --env-file .env.example -f infra/docker/compose.yml config
|
|
docker compose --env-file .env.example -f infra/docker/compose.yml run --rm --build backend python manage.py test
|
|
```
|
|
|
|
## Rollback
|
|
|
|
Rollback should be designed around immutable images and database backups.
|
|
|
|
Basic rollback steps:
|
|
|
|
1. identify the previous known-good image tags or Git commit;
|
|
2. stop the current Compose stack;
|
|
3. deploy the previous image tags or commit;
|
|
4. restore the database from backup only if a migration or data change requires it;
|
|
5. run smoke checks for public pages, booking creation, confirmation, and check-in.
|
|
|
|
Database rollback needs special care once migrations exist. Down migrations or backup restore procedures should be documented before production use.
|
|
|
|
## Operational Notes
|
|
|
|
- Configure database backups before accepting real bookings.
|
|
- Back up the shared media volume together with the database if staff uploads show images.
|
|
- Monitor backend errors, email delivery failures, and check-in failures.
|
|
- Keep container images explicitly versioned; do not use `latest` tags.
|
|
- Keep the system small until operational needs justify additional services.
|