docs: fix double-encoding, write proper deployment README
This commit is contained in:
1 parent
ffdcfb11cc
commit
1542c3e5a7
1 file changed
+138
-1
@@ -1 +1,138 @@
|
||||
IyBCdXMgTWFuYWdlcgoKQSBEamFuZ28tYmFzZWQgYnVzIGNvb3JkaW5hdGlvbiBhbmQgbWFuYWdlbWVudCBzeXN0ZW0uIEhhbmRsZXMgdHJhbnNwb3J0IHNjaGVkdWxpbmcsIHRyYXZlbGxlciBtYW5hZ2VtZW50LCBsb2NhdGlvbiB0cmFja2luZywgY29vcmRpbmF0b3Igd29ya2Zsb3dzLCBhbmQgb3B0aW9uYWwgU01TIChUZWxzdHJhKSBhbmQgU1NPIChBenVyZSBBRCkgaW50ZWdyYXRpb25zLgoKLS0tCgojIyBTdGFjawoKfCBDb21wb25lbnQgfCBUZWNobm9sb2d5IHwKfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfAp8IFdlYiBmcmFtZXdvcmsgfCBEamFuZ28gNiArIEd1bmljb3JuIHwKfCBEYXRhYmFzZSB8IFBvc3RncmVTUUwgMTYgfAp8IEF1dGggKG9wdGlvbmFsKSB8IEF6dXJlIEFEIFNTTyB2aWEgTVNBTCB8CnwgU01TIChvcHRpb25hbCkgfCBUZWxzdHJhIE1lc3NhZ2luZyBBUEkgfAp8IFNjaGVkdWxpbmcgfCBkamFuZ28tY3JvbnRhYiAobmlnaHRseSBjb29yZGluYXRvciBjaGVjaykgfAp8IENvbnRhaW5lciBydW50aW1lIHwgRG9ja2VyICsgRG9ja2VyIENvbXBvc2UgfAoKLS0tCgojIyBEZXBsb3ltZW50CgojIyMgUHJlcmVxdWlzaXRlcwoKLSBEb2NrZXIgYW5kIERvY2tlciBDb21wb3NlIGluc3RhbGxlZCBvbiB0aGUgaG9zdAotIEEgcmV2ZXJzZSBwcm94eSAoZS5nLiBOZ2lueCBQcm94eSBNYW5hZ2VyKSB0byBmcm9udCB0aGUgYXBwCgojIyMgMS4gQ2xvbmUgdGhlIHJlcG9zaXRvcnkKCmBgYGJhc2gKZ2l0IGNsb25lIGh0dHBzOi8vZ2l0ZWEuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2plc3Npa2l0dHkvYnVzLW1hbmFnZXIuZ2l0CmNkIGJ1cy1tYW5hZ2VyCmBgYAoKIyMjIDIuIENvbmZpZ3VyZSBlbnZpcm9ubWVudAoKYGBgYmFzaApjcCAuZW52LmV4YW1wbGUgLmVudgpgYGAKCkVkaXQgYC5lbnZgIGFuZCBzZXQgYXQgbWluaW11bToKCnwgVmFyaWFibGUgfCBEZXNjcmlwdGlvbiB8CnwtLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgYFNFQ1JFVF9LRVlgIHwgTG9uZyByYW5kb20gc3RyaW5nIOKAlCBnZW5lcmF0ZSB3aXRoIGBweXRob24gLWMgImltcG9ydCBzZWNyZXRzOyBwcmludChzZWNyZXRzLnRva2VuX3VybHNhZmUoNTApKSJgIHwKfCBgU1FMX1BBU1NXT1JEYCB8IFBvc3RncmVzIHBhc3N3b3JkIChwaWNrZWQgdXAgYnkgYm90aCB0aGUgYGRiYCBhbmQgYHdlYmAgY29udGFpbmVycykgfAp8IGBBTExPV0VEX0hPU1RTYCB8IFNwYWNlLXNlcGFyYXRlZCBsaXN0IG9mIGhvc3RuYW1lcyB0aGUgYXBwIHdpbGwgYmUgc2VydmVkIGZyb20gKGUuZy4gYGJ1c21hbmFnZXIueW91cmRvbWFpbi5jb21gKSB8CnwgYEFQUF9QT1JUYCB8IEhvc3QgcG9ydCBHdW5pY29ybSB3aWxsIGJlIGV4cG9zZWQgb24gKGRlZmF1bHQ6IGA4MDAwYCkgfAoKT3B0aW9uYWwgdmFyaWFibGVzIGZvciBlbWFpbCwgQXp1cmUgU1NPLCBhbmQgVGVsc3RyYSBTTVMgYXJlIGRvY3VtZW50ZWQgaW4gYC5lbnYuZXhhbXBsZWAuCgojIyMgMy4gQnVpbGQgYW5kIHN0YXJ0CgpgYGBiYXNoCmRvY2tlciBjb21wb3NlIHVwIC1kIC0tYnVpbGQKYGBgCgpPbiBmaXJzdCBzdGFydCB0aGUgYHdlYmAgY29udGFpbmVyIHdpbGw6CjEuIFdhaXQgZm9yIFBvc3RncmVzIHRvIHBhc3MgaXRzIGhlYWx0aGNoZWNrCjIuIFJ1biBgbWFuYWdlLnB5IG1pZ3JhdGVgIHRvIGluaXRpYWxpc2UgdGhlIGRhdGFiYXNlIHNjaGVtYQozLiBSdW4gYG1hbmFnZS5weSBjb2xsZWN0c3RhdGljYCB0byBnYXRoZXIgc3RhdGljIGFzc2V0cwo0LiBSZWdpc3RlciB0aGUgbmlnaHRseSBjcm9uIGpvYiB2aWEgYG1hbmFnZS5weSBjcm9udGFiIGFkZGAKNS4gU3RhcnQgR3VuaWNvcm4gb24gcG9ydCBgODAwMGAKCiMjIyA0LiBDcmVhdGUgYSBzdXBlcnVzZXIKCmBgYGJhc2gKZG9ja2VyIGNvbXBvc2UgZXhlYyB3ZWIgcHl0aG9uIG1hbmFnZS5weSBjcmVhdGVzdXBlcnVzZXIKYGBgCgojIyMgNS4gUmV2ZXJzZSBwcm94eSAoTmdpbnggUHJveHkgTWFuYWdlcikKCkNyZWF0ZSBhIG5ldyBwcm94eSBob3N0IGluIE5QTSBwb2ludGluZyB0bzoKCmBgYApodHRwOi8vPGRvY2tlci1ob3N0LWlwPjo8QVBQX1BPUlQ+CmBgYAoKRW5hYmxlIFNTTCB2aWEgTGV0J3MgRW5jcnlwdCBhcyB1c3VhbC4gTm8gc3BlY2lhbCBoZWFkZXJzIHJlcXVpcmVkIOKAlCBHdW5pY29ybSBoYW5kbGVzIFdTR0kgZGlyZWN0bHkuCgotLS0KCiMjIFVwZGF0aW5nCgpgYGBiYXNoCmdpdCBwdWxsCmRvY2tlciBjb21wb3NlIHVwIC1kIC0tYnVpbGQKYGBgCgpNaWdyYXRpb25zIHJ1biBhdXRvbWF0aWNhbGx5IG9uIHN0YXJ0dXAsIHNvIHNjaGVtYSBjaGFuZ2VzIGFyZSBhcHBsaWVkIHdpdGhvdXQgbWFudWFsIGludGVydmVudGlvbi4KCi0tLQoKIyMgVXNlZnVsIGNvbW1hbmRzCgp8IFRhc2sgfCBDb21tYW5kIHwKfC0tLS0tLXwtLS0tLS0tLS18CnwgVmlldyBsb2dzIHwgYGRvY2tlciBjb21wb3NlIGxvZ3MgLWYgd2ViYCB8CnwgT3BlbiBEamFuZ28gc2hlbGwgfCBgZG9ja2VyIGNvbXBvc2UgZXhlYyB3ZWIgcHl0aG9uIG1hbmFnZS5weSBzaGVsbGAgfAp8IFJ1biBtaWdyYXRpb25zIG1hbnVhbGx5IHwgYGRvY2tlciBjb21wb3NlIGV4ZWMgd2ViIHB5dGhvbiBtYW5hZ2UucHkgbWlncmF0ZWAgfAp8IENoZWNrIGNyb250YWIgfCBgZG9ja2VyIGNvbXBvc2UgZXhlYyB3ZWIgcHl0aG9uIG1hbmFnZS5weSBjcm9udGFiIHNob3dgIHwKfCBSZXN0YXJ0IGFwcCBvbmx5IHwgYGRvY2tlciBjb21wb3NlIHJlc3RhcnQgd2ViYCB8CnwgU3RvcCBldmVyeXRoaW5nIHwgYGRvY2tlciBjb21wb3NlIGRvd25gIHwKfCBTdG9wIGFuZCB3aXBlIGRhdGFiYXNlIHwgYGRvY2tlciBjb21wb3NlIGRvd24gLXZgIOKaoO+4jyBkZXN0cnVjdGl2ZSB8CgotLS0KCiMjIEVudmlyb25tZW50IHZhcmlhYmxlcyByZWZlcmVuY2UKCnwgVmFyaWFibGUgfCBSZXF1aXJlZCB8IERlZmF1bHQgfCBEZXNjcmlwdGlvbiB8CnwtLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tfC0tLS0tLS0tLS0tLS18CnwgYFNFQ1JFVF9LRVlgIHwg4pyFIHwg4oCUIHwgRGphbmdvIHNlY3JldCBrZXkgfAp8IGBERUJVR2AgfCB8IGBGYWxzZWAgfCBFbmFibGUgRGphbmdvIGRlYnVnIG1vZGUgfAp8IGBBTExPV0VEX0hPU1RTYCB8IOKchSB8IGBsb2NhbGhvc3RgIHwgU3BhY2Utc2VwYXJhdGVkIGFsbG93ZWQgaG9zdG5hbWVzIHwKfCBgU1FMX0RBVEFCQVNFYCB8IHwgYGJ1c21hbmFnZXJgIHwgUG9zdGdyZXMgZGF0YWJhc2UgbmFtZSB8CnwgYFNRTF9VU0VSYCB8IHwgYGJ1c21hbmFnZXJgIHwgUG9zdGdyZXMgdXNlcm5hbWUgfAp8IGBTUUxfUEFTU1dPUkRgIHwg4pyFIHwg4oCUIHwgUG9zdGdyZXMgcGFzc3dvcmQgfAp8IGBBUFBfUE9SVGAgfCB8IGA4MDAwYCB8IEhvc3QgcG9ydCBmb3IgR3VuaWNvcm4gfAp8IGBHVU5JQ09STl9XT1JLRVJTYCB8IHwgYDNgIHwgTnVtYmVyIG9mIEd1bmljb3JuIHdvcmtlciBwcm9jZXNzZXMgfAp8IGBHVU5JQ09STl9USU1FT1VUYCB8IHwgYDEyMGAgfCBHdW5pY29ybiB3b3JrZXIgdGltZW91dCAoc2Vjb25kcykgfAp8IGBFTUFJTF9IT1NUYCB8IHwg4oCUIHwgU01UUCByZWxheSBob3N0bmFtZSB8CnwgYEVNQUlMX1BPUlRgIHwgfCBgMjVgIHwgU01UUCByZWxheSBwb3J0IHwKfCBgQVpVUkVfQ0xJRU5UX0lEYCB8IHwg4oCUIHwgQXp1cmUgYXBwIGNsaWVudCBJRCAoZW5hYmxlcyBTU08pIHwKfCBgQVpVUkVfQ0xJRU5UX1NFQ1JFVGAgfCB8IOKAlCB8IEF6dXJlIGFwcCBjbGllbnQgc2VjcmV0IHwKfCBgQVpLine truncated
|
||||
# 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`.
|
||||
Reference in new issue
Block a user