Files
bus-manager/README.md
T

139 lines
4.2 KiB
Markdown

# Bus Manager
A Django-based bus coordination and management system. Handles transport scheduling, traveller management, location tracking, coordinator workflows, and optional SMS (Telstra) and SSO (Azure AD) integrations.
---
## Stack
| Component | Technology |
|-----------|-----------|
| Web framework | Django 6 + Gunicorn |
| Database | PostgreSQL 16 |
| Auth (optional) | Azure AD SSO via MSAL |
| SMS (optional) | Telstra Messaging API |
| Scheduling | django-crontab (nightly coordinator check) |
| Container runtime | Docker + Docker Compose |
---
## Deployment
### Prerequisites
- Docker and Docker Compose installed on the host
- A reverse proxy (e.g. Nginx Proxy Manager) to front the app
### 1. Clone the repository
```bash
git clone https://gitea.hideawaygaming.com.au/jessikitty/bus-manager.git
cd bus-manager
```
### 2. Configure environment
```bash
cp .env.example .env
```
Edit `.env` and set at minimum:
| Variable | Description |
|----------|-------------|
| `SECRET_KEY` | Long random string — generate with `python -c "import secrets; print(secrets.token_urlsafe(50))"` |
| `SQL_PASSWORD` | Postgres password (picked up by both the `db` and `web` containers) |
| `ALLOWED_HOSTS` | Space-separated list of hostnames the app will be served from (e.g. `busmanager.yourdomain.com`) |
| `APP_PORT` | Host port Gunicorn will be exposed on (default: `8000`) |
Optional variables for email, Azure SSO, and Telstra SMS are documented in `.env.example`.
### 3. Build and start
```bash
docker compose up -d --build
```
On first start the `web` container will:
1. Wait for Postgres to pass its healthcheck
2. Run `manage.py migrate` to initialise the database schema
3. Run `manage.py collectstatic` to gather static assets
4. Register the nightly cron job via `manage.py crontab add`
5. Start Gunicorn on port `8000`
### 4. Create a superuser
```bash
docker compose exec web python manage.py createsuperuser
```
### 5. Reverse proxy (Nginx Proxy Manager)
Create a new proxy host in NPM pointing to:
```
http://<docker-host-ip>:<APP_PORT>
```
Enable SSL via Let's Encrypt as usual. No special headers required — Gunicorn handles WSGI directly.
---
## Updating
```bash
git pull
docker compose up -d --build
```
Migrations run automatically on startup, so schema changes are applied without manual intervention.
---
## Useful commands
| Task | Command |
|------|---------|
| View logs | `docker compose logs -f web` |
| Open Django shell | `docker compose exec web python manage.py shell` |
| Run migrations manually | `docker compose exec web python manage.py migrate` |
| Check crontab | `docker compose exec web python manage.py crontab show` |
| Restart app only | `docker compose restart web` |
| Stop everything | `docker compose down` |
| Stop and wipe database | `docker compose down -v` ⚠️ destructive |
---
## Environment variables reference
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `SECRET_KEY` | ✅ | — | Django secret key |
| `DEBUG` | | `False` | Enable Django debug mode |
| `ALLOWED_HOSTS` | ✅ | `localhost` | Space-separated allowed hostnames |
| `SQL_DATABASE` | | `busmanager` | Postgres database name |
| `SQL_USER` | | `busmanager` | Postgres username |
| `SQL_PASSWORD` | ✅ | — | Postgres password |
| `APP_PORT` | | `8000` | Host port for Gunicorn |
| `GUNICORN_WORKERS` | | `3` | Number of Gunicorn worker processes |
| `GUNICORN_TIMEOUT` | | `120` | Gunicorn worker timeout (seconds) |
| `EMAIL_HOST` | | — | SMTP relay hostname |
| `EMAIL_PORT` | | `25` | SMTP relay port |
| `AZURE_CLIENT_ID` | | — | Azure app client ID (enables SSO) |
| `AZURE_CLIENT_SECRET` | | — | Azure app client secret |
| `AZURE_REDIRECT_URI` | | — | Azure OAuth redirect URI |
| `AZURE_AUTHORITY` | | — | Azure authority URL |
| `TELSTRA_CLIENT_ID` | | — | Telstra API client ID (enables SMS) |
| `TELSTRA_CLIENT_SECRET` | | — | Telstra API client secret |
---
## Data persistence
Two named Docker volumes are created automatically:
- `postgres_data` — PostgreSQL data directory
- `static_files` — collected Django static assets
These survive `docker compose down` and are only removed with `docker compose down -v`.