139 lines
4.2 KiB
Markdown
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`.
|