generated from bisco/codex-bootstrap
96 lines
4.1 KiB
Markdown
96 lines
4.1 KiB
Markdown
# Deployment
|
|
|
|
## Local environment
|
|
|
|
Copy `.env.example` to `.env`, replace the development placeholders, then run:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
docker compose up --build -d
|
|
docker compose ps
|
|
docker compose exec backend python manage.py seed_demo
|
|
```
|
|
|
|
The backend applies migrations and collects static files before starting Gunicorn.
|
|
All services have health checks; wait for healthy status before opening the site.
|
|
|
|
Add `127.0.0.1 azionelab.org` to the local hosts file, then use
|
|
`http://azionelab.org:8080`. NGINX binds to loopback port `8080` by default and routes
|
|
the domain to Astro or Wagtail. Their direct loopback ports `4321` and `8000` remain
|
|
available for diagnostics. PostgreSQL is available only on the Compose network.
|
|
`postgres_data` and `media_data` are persistent named volumes. Local HTTPS is disabled
|
|
by default; `letsencrypt_data` and `certbot_challenges` remain empty unless used.
|
|
|
|
The stack uses explicit PostgreSQL 16.9, Python 3.12.12, Node.js 22.20, and NGINX 1.30.0
|
|
image versions. Containers are not privileged and use `no-new-privileges`.
|
|
|
|
Required runtime variables are `DATABASE_URL`, `DJANGO_SECRET_KEY`, `DJANGO_DEBUG`,
|
|
`DJANGO_ALLOWED_HOSTS`, `WAGTAILADMIN_BASE_URL`, `PUBLIC_CMS_API_URL`,
|
|
`NGINX_BIND_ADDRESS`, `NGINX_HTTP_PORT`, and `NGINX_HTTPS_PORT`. The optional certificate
|
|
variables and PostgreSQL bootstrap variables are documented in `.env.example`. Do not
|
|
use the example credentials outside local development.
|
|
|
|
`WAGTAILADMIN_BASE_URL` must be browser-reachable because it is used for media URLs.
|
|
`PUBLIC_CMS_API_URL` must be reachable by Astro; within Compose it is
|
|
`http://backend:8000`.
|
|
|
|
The PostgreSQL Compose service is `db`, so new `DATABASE_URL` values use `db:5432`.
|
|
The internal `postgres` alias is retained only for compatibility with existing local
|
|
`.env` files and should not be used in new configuration.
|
|
|
|
## TLS deployment modes
|
|
|
|
When an external load balancer terminates TLS, leave `LETSENCRYPT_ENABLED=0`. The
|
|
`certbot` service then has zero replicas and NGINX serves HTTP to the trusted internal
|
|
network. Configure the load balancer to set `X-Forwarded-Proto: https`, keep application
|
|
ports private, and restrict proxy access to the load balancer network.
|
|
|
|
For direct exposure, the HTTP-01 challenge requires public DNS for
|
|
`LETSENCRYPT_DOMAIN` to resolve to this host and inbound TCP ports 80 and 443 to reach
|
|
NGINX. Use a real operator address and production-safe Django settings:
|
|
|
|
```dotenv
|
|
LETSENCRYPT_ENABLED=1
|
|
LETSENCRYPT_DOMAIN=azionelab.org
|
|
LETSENCRYPT_EMAIL=operator@example.org
|
|
LETSENCRYPT_STAGING=1
|
|
NGINX_BIND_ADDRESS=0.0.0.0
|
|
NGINX_HTTP_PORT=80
|
|
NGINX_HTTPS_PORT=443
|
|
WAGTAILADMIN_BASE_URL=https://azionelab.org
|
|
DJANGO_DEBUG=false
|
|
DJANGO_ALLOWED_HOSTS=azionelab.org
|
|
```
|
|
|
|
Then run `docker compose up --build -d` and inspect `docker compose logs certbot proxy`.
|
|
NGINX serves HTTP until a certificate exists, then reloads and redirects normal HTTP
|
|
requests to HTTPS. The ACME path remains available over HTTP for renewal.
|
|
|
|
Use the Let's Encrypt staging CA first. Before switching to the production CA, stop the
|
|
stack and remove only the staging certificate volume after checking its exact Compose
|
|
project name:
|
|
|
|
```bash
|
|
docker compose down
|
|
docker volume ls --filter label=com.docker.compose.volume=letsencrypt_data
|
|
docker volume rm PROJECT_letsencrypt_data
|
|
```
|
|
|
|
Set `LETSENCRYPT_STAGING=0`, restart, and verify the certificate issuer in a browser or
|
|
TLS inspection tool. Never use `docker compose down --volumes` on an environment whose
|
|
database, media, or certificates must be retained.
|
|
|
|
## Production boundary
|
|
|
|
The Compose stack remains a minimal deployment base. A public environment still needs
|
|
production static/media serving, restricted admin access, managed secrets, off-host
|
|
backups, monitoring, firewall rules, and an explicit domain/allowed-host policy.
|
|
|
|
## Rollback
|
|
|
|
Set `LETSENCRYPT_ENABLED=0` to disable the certificate service without deleting
|
|
certificates, or terminate TLS at the load balancer. Revert the application commit and
|
|
rebuild images for a full rollback. Keep database, media, and certificate volumes unless
|
|
deletion is intentional. Schema rollback must be evaluated per Django migration; take
|
|
coordinated database and media backups first.
|