deploy: add bootstrap.sh + Caddyfile + systemd unit + demo pool
One-shot deploy for fresh Ubuntu 24.04 root SSH: curl -fsSL https://gitea.ahkhan.me/apps/quiz/raw/branch/master/deploy/bootstrap.sh | bash bootstrap.sh: idempotent stage-by-stage installer for Caddy, Python venv, quiz system user, repo clone to /opt/quiz, env-var prompts, systemd unit, Caddyfile, and a healthz check. Reattaches /dev/tty so curl|bash can read the admin password interactively. quiz.service: uvicorn under the quiz system user (no shell, no SSH), ProtectSystem=full, ProtectHome=true, PrivateTmp=true, NoNewPrivileges=true. Caddyfile.tpl: reverse_proxy 127.0.0.1:8001 with auto Let's Encrypt; DOMAIN substituted at install time. examples/pool_example.json: generic demo pool, schema reference only. README rewritten around the deploy flow + class-day lifecycle.
This commit is contained in:
84
README.md
84
README.md
@@ -1,45 +1,77 @@
|
||||
# Live In-Lecture Quiz Portal
|
||||
# Live in-lecture quiz portal
|
||||
|
||||
FastAPI, SQLite, WebSocket, and vanilla frontend implementation for a live classroom quiz.
|
||||
FastAPI + WebSocket + SQLite quiz portal designed for ~40 students per
|
||||
class session. Single-process, in-memory room manager, vanilla HTML/JS
|
||||
front-end, Caddy in front for TLS.
|
||||
|
||||
## Install
|
||||
## Quick local run
|
||||
|
||||
```bash
|
||||
cd /home/ameer/RD/Projects/Apps/quiz
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -e '.[dev]'
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` and set real values for `QUIZ_SECRET_KEY` and `QUIZ_ADMIN_PASSWORD`.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
. .venv/bin/activate
|
||||
cp .env.example .env # edit QUIZ_SECRET_KEY + QUIZ_ADMIN_PASSWORD
|
||||
uvicorn app.main:app --host 127.0.0.1 --port 8001 --reload
|
||||
```
|
||||
|
||||
Open `http://127.0.0.1:8001/admin/`, log in, create a quiz pool, then create a session. Use the displayed join URL in another browser or private window for the student view.
|
||||
Open `http://127.0.0.1:8001/admin/`, log in, create a quiz pool from a
|
||||
JSON pool file (see `examples/pool_example.json` for the schema), create
|
||||
a session, and share the join URL.
|
||||
|
||||
## Test
|
||||
## VPS deploy (one-shot)
|
||||
|
||||
On a fresh Ubuntu 24.04 LTS root SSH:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://gitea.ahkhan.me/apps/quiz/raw/branch/master/deploy/bootstrap.sh | bash
|
||||
```
|
||||
|
||||
The bootstrap:
|
||||
1. apt-installs Caddy + Python venv tooling
|
||||
2. Creates a `quiz` system user (no shell, no SSH)
|
||||
3. Clones this repo to `/opt/quiz`
|
||||
4. Builds the venv and installs the app
|
||||
5. Generates `QUIZ_SECRET_KEY`, prompts for `QUIZ_ADMIN_PASSWORD`
|
||||
6. Drops the systemd unit and Caddyfile
|
||||
7. Starts both services
|
||||
8. Curl-checks `127.0.0.1:8001/healthz`
|
||||
|
||||
After: `quiz.ahkhan.me` is live with auto-Let's-Encrypt cert. To override
|
||||
the domain or repo URL, set `DOMAIN=` or `REPO_URL=` in the environment
|
||||
before running the script.
|
||||
|
||||
## Class-day workflow
|
||||
|
||||
1. Provision Aliyun Intl HK ECS pay-as-you-go (`ecs.t6-c2m1.large`,
|
||||
Ubuntu 24.04 LTS).
|
||||
2. Point DNS A-record `quiz.ahkhan.me` at the new IP.
|
||||
3. SSH in as root, run the curl|bash one-liner above.
|
||||
4. Open `quiz.ahkhan.me/admin/`, log in, upload the week's pool JSON,
|
||||
create a session.
|
||||
5. Share the QR / join URL with the class.
|
||||
6. After class:
|
||||
`scp root@<ip>:/opt/quiz/quiz.db ./backups/quiz-YYYY-MM-DD.db`
|
||||
7. Destroy the instance.
|
||||
|
||||
## Quiz pool files
|
||||
|
||||
Real pool JSON files contain answer keys and **must not be committed**
|
||||
to this repo. `.gitignore` excludes `examples/*_pool.json` (only
|
||||
`examples/pool_example.json` may be tracked). Author pools elsewhere
|
||||
(e.g., your course-material directory) and upload at runtime via the
|
||||
admin UI.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
. .venv/bin/activate
|
||||
pytest -q
|
||||
pytest --cov=app
|
||||
```
|
||||
|
||||
The load simulation test creates 50 student WebSocket clients and runs a 5-question quiz.
|
||||
For the WebSocket adversarial stress harness (Node.js + Playwright,
|
||||
runs in a tmux loop), see `tests/stress/README.md`.
|
||||
|
||||
## Manual Smoke Test
|
||||
## Spec
|
||||
|
||||
```bash
|
||||
export QUIZ_DB_PATH=/tmp/quiz-smoke.db QUIZ_SECRET_KEY=smoke-secret QUIZ_ADMIN_PASSWORD=smoke-pass QUIZ_PUBLIC_URL=http://127.0.0.1:8001
|
||||
. .venv/bin/activate
|
||||
uvicorn app.main:app --host 127.0.0.1 --port 8001
|
||||
curl http://127.0.0.1:8001/healthz
|
||||
```
|
||||
|
||||
Expected health response starts with `{"ok":true`.
|
||||
`SPEC.md` documents the locked v1.0 design (state machine, scoring,
|
||||
identity flow, all WS message types).
|
||||
|
||||
Reference in New Issue
Block a user