Flask-based exam management and browser-assisted proctoring.
- Install Docker Engine and the Compose plugin.
- Copy
.env.exampleto.envand replace every placeholder secret. - Put the assets listed in MODEL_INVENTORY.md in
models/. - Build, verify, and start:
docker compose build
docker compose run --rm app python scripts/verify_models.py
docker compose up -dFor an empty database volume, import the schema with the credentials from .env:
docker compose exec -T db mariadb -u root -p"$MARIADB_ROOT_PASSWORD" proctoring < proctoring.sqlThe app listens on 127.0.0.1:8000 by default. Use an HTTPS reverse proxy in front of it and never publish MariaDB. Readiness is available at /health; logs are available with docker compose logs -f app.
The default image uses CPU-safe PyTorch and falls back to CPU when CUDA is unavailable. For an explicit NVIDIA run, install the NVIDIA Container Toolkit and check:
nvidia-smi
docker run --rm --gpus all nvidia/cuda:12.1.1-base-ubuntu22.04 nvidia-smi
docker compose run --rm app-gpu python scripts/verify_models.py
docker compose up -d db app-gpuUse CPU if the older GPU cannot run the pinned CUDA/PyTorch stack.
For local development, use Python 3.11 and a virtual environment, install requirements.txt, configure PROCTOR_DATABASE_URI and PROCTOR_SECRET_KEY, then run python run.py. The optional legacy face-encoding dependencies are in requirements-vision.txt. Production uses Gunicorn through Compose and never enables Flask debug mode.
The app_data volume stores runtime uploads and logs. Back up it and the database volume. Rotate PROCTOR_SECRET_KEY, restrict storage permissions, and define a retention period for biometric data.
The exam page requests camera and microphone access from the student's browser, captures periodic JPEG frames, and sends them to an authenticated session endpoint. The server never opens a webcam or microphone. Browser audio aggregation is currently unavailable. Website blocking is unsupported remotely because a server cannot edit a student's hosts file; it would require a separately installed, consented client agent or extension.
Install and authenticate Tailscale on both servers and restrict the tailnet with ACLs. Configure the Ionos reverse proxy to forward the public HTTPS hostname to the home server's Tailscale address and port 8000. Keep the Compose bind address private, point DNS to Ionos, terminate TLS at Ionos or Caddy/Nginx, and use an HTTPS public URL so browsers allow camera and microphone access. This first implementation uses HTTP frame uploads, not WebSockets.
The Deploy Proctor workflow deploys pushes to main through the IONOS gateway
to /opt/apps/proctor on vps01. It preserves the remote .env, model files,
and Docker volumes, then rebuilds the app, verifies the model assets, and checks
/health before reporting success. Configure the repository secrets
DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY, DEPLOY_KNOWN_HOSTS, and
VPS01_KNOWN_HOSTS, plus the optional repository variable PROCTOR_APP_DIR.
- If
/healthis degraded, wait for MariaDB and ensure the URI uses hostdb, notlocalhost. - If model verification reports missing assets, copy the exact files into the configured model directory.
- If camera permission fails, use HTTPS or localhost and grant browser permission.
- Set
PROCTOR_INFERENCE_DEVICE=cpuwhen CUDA is unavailable.