Connect with fellow learners in the PlacePrep Discord communityㆍ Join now →
R's PlacePrep

Command reference for PlacePrep exam mode: Docker, ports and firewall, sync APIs and fixes for the most common setup problems.

Technical Reference

Quick reference for every command you'll need when running PlacePrep in self-hosted / exam mode.

For the full step-by-step guide, see Self-Hosting.


Application Commands

Start / Stop

powershell
# Start Docker (local Appwrite) + Next.js dev server (students can connect over LAN)
bun run exam:start

# Stop everything — kills Next.js process and stops Docker containers
bun run exam:stop

# Build the Next.js app (required after changing .env or after updating code)
bun run build

# Start the Next.js dev server manually (without Docker)
bun run dev

# Start the Next.js production server manually (after build)
bun run start

Database Setup

powershell
# Create all Appwrite collections in the CLOUD database
bun run setup:appwrite

# Create all Appwrite collections in the LOCAL (Docker) database
bun run setup:appwrite:local

# Preview what the setup script would create, without writing anything
bun run setup:appwrite:dry

# Bootstrap the local admin user (only needed once, before first pre-exam sync)
bun run exam:bootstrap-admin
The setup script creates 16 collections and the tnp_documents storage bucket. It skips anything that already exists, so it is safe to re-run.

Docker Commands

Start / Stop Containers

powershell
# Start local Appwrite stack in background (detached)
docker compose -f docker/exam-mode/docker-compose.yml up -d

# Stop containers (data is preserved in volumes)
docker compose -f docker/exam-mode/docker-compose.yml down

# Stop containers AND wipe ALL local data (volumes deleted — run ONLY after post-exam sync)
docker compose -f docker/exam-mode/docker-compose.yml down -v

# Restart containers
docker compose -f docker/exam-mode/docker-compose.yml restart

Status & Verification

powershell
# List all running containers
docker ps

# List all containers (including stopped ones)
docker ps -a

# Show status of exam-mode compose services
docker compose -f docker/exam-mode/docker-compose.yml ps

# Check resource usage (CPU, memory) of running containers
docker stats

# List Docker images on your machine
docker images

# Show disk usage by images, containers, and volumes
docker system df

Logs

powershell
# Stream Appwrite server logs (live — press Ctrl+C to stop)
docker logs appwrite -f

# Stream MariaDB logs
docker logs appwrite-mariadb -f

# Stream Redis logs
docker logs appwrite-redis -f

# Stream the PlacePrep app container logs
docker logs placeprep-app -f

# View last 100 lines of Appwrite logs (no streaming)
docker logs appwrite --tail 100

# View logs for all compose services at once
docker compose -f docker/exam-mode/docker-compose.yml logs -f
Container names: placeprep-app, appwrite, appwrite-console, appwrite-realtime, appwrite-traefik, appwrite-mariadb, appwrite-redis, plus the worker containers appwrite-worker-databases, appwrite-worker-audits, appwrite-worker-deletes, and appwrite-task-maintenance.

Volumes & Data

powershell
# List Docker volumes
docker volume ls

# Inspect a volume (find its mount path)
docker volume inspect appwrite-uploads

# Remove a specific volume manually
docker volume rm <volume-name>

# Remove ALL unused volumes (careful — affects all Docker projects)
docker volume prune
Volumes: appwrite-mariadb, appwrite-redis, appwrite-cache, appwrite-uploads, appwrite-imports, appwrite-certificates, appwrite-functions, appwrite-sites, appwrite-builds, appwrite-config.

Cleanup

powershell
# Remove stopped containers, unused networks, dangling images, and build cache
docker system prune

# Also remove unused volumes (frees the most space — use carefully)
docker system prune --volumes

# Remove all unused images (not just dangling ones)
docker image prune -a

Network & Port Commands (Windows)

Find Your Machine's IP

powershell
# Show all network adapters and their IPs
ipconfig

# Show only the IPv4 address of your active adapter
ipconfig | findstr "IPv4"
Look for the IPv4 Address under your active Wi-Fi or Ethernet adapter (e.g. 192.168.1.42). Students connect to http://192.168.1.42:3000.

Port Troubleshooting

powershell
# Find which process is using port 3000
netstat -ano | findstr :3000

# Find which process is using port 80 (used by local Appwrite)
netstat -ano | findstr :80

# Kill a process by PID (replace <PID> with the number from netstat output)
taskkill /F /PID <PID>

# Kill the entire process tree by PID (use if the above doesn't work)
taskkill /T /F /PID <PID>

Firewall

powershell
# Allow port 3000 through Windows Firewall (so students can connect)
netsh advfirewall firewall add rule name="PlacePrep Exam" dir=in action=allow protocol=TCP localport=3000

# Remove the rule when done
netsh advfirewall firewall delete rule name="PlacePrep Exam"

# Allow port 80 (if students need direct Appwrite console access — usually not needed)
netsh advfirewall firewall add rule name="PlacePrep Appwrite" dir=in action=allow protocol=TCP localport=80

Sync API Reference

These endpoints are called by the exam dashboard UI. You can also call them directly for scripting or debugging.

Pre-Exam Sync: Cloud → Local

POST http://localhost:3000/api/exam-mode/sync-to-local
Headers:
  x-user-id: <admin-user-id>          (normal auth)
  x-admin-key: <APPWRITE_LOCAL_API_KEY>  (bootstrap auth — use when DB is empty)

Body (optional — restrict to specific exams):
{
  "examIds": ["exam_id_1", "exam_id_2"]
}

Post-Exam Sync: Local → Cloud

POST http://localhost:3000/api/exam-mode/sync-to-cloud
Headers:
  x-user-id: <admin-user-id>

Body (optional — restrict to specific exams):
{
  "examIds": ["exam_id_1"]
}

Auto-Submit Expired Exams

POST http://localhost:3000/api/exam-mode/auto-submit-expired

Force-submits all in-progress attempts whose exam end time has passed. The exam dashboard calls this every 15 seconds while Auto-refresh (15s) is enabled and the tab is open. There is no server-side cron, so keep the dashboard open during the exam.

Register Walk-in Student

API-only — there is no button for this on the dashboard.

POST http://localhost:3000/api/exam-mode/register-local
Body:
{
  "name": "Student Name",
  "email": "student@college.edu",
  "registration_number": "22105109024",
  "branch": "CSE",
  "college_name": "Example College"
}
Response:
{
  "userId": "...",
  "examPassword": "exam2026"
}
The returned examPassword is always the EXAM_PASSWORD_PREFIX value — the same shared password every student uses.

Other Exam Mode Endpoints

EndpointPurpose
GET /api/exam-mode/statusExam mode configuration and connectivity
GET /api/exam-mode/list-examsLive exams available to monitor
GET /api/exam-mode/active-studentsStudents currently attempting
GET /api/exam-mode/completed-studentsStudents who have submitted
GET /api/exam-mode/student-progressPer-student progress within an exam
GET /api/exam-mode/list-credentialsStudent name + shared password list
POST /api/exam-mode/force-submitForce-submit one student's attempt
POST /api/exam-mode/restart-examClear a student's answers and restart their timer
POST /api/exam-mode/delete-attemptDelete a completed attempt

Common Bug Fixes

Port 3000 still in use after Ctrl+C

powershell
# Find the PID using port 3000
netstat -ano | findstr :3000

# Kill it
taskkill /T /F /PID <PID>

Or use the dedicated stop command:

powershell
bun run exam:stop

Port 80 already in use (Appwrite won't start)

Port 80 is typically occupied by IIS (Windows), Nginx, or XAMPP.

powershell
# Stop IIS
iisreset /stop

# Or find and kill the process using port 80
netstat -ano | findstr :80
taskkill /F /PID <PID>

Then retry:

powershell
docker compose -f docker/exam-mode/docker-compose.yml up -d

"exam-db" database missing after container restart

The database persists in a Docker volume and should survive restarts. If it's gone, it means you ran down -v previously. Recreate the schema:
powershell
bun run setup:appwrite:local

Then run the pre-exam sync again to pull data from cloud.

Docker containers keep restarting / crashing

powershell
# Check logs for the specific container that's failing
docker logs appwrite -f

# Common cause: not enough disk space
docker system df

# Free up space if needed
docker system prune

Pre-exam sync authentication error (first run)

The local DB is empty, so there is no admin account to authenticate with yet. Use bootstrap auth:

  1. On the exam dashboard, the Bootstrap Sync dialog asks for a local API key
  2. Enter the value of APPWRITE_LOCAL_API_KEY from your .env
  3. Run the sync

Post-exam sync: users not appearing in cloud

Make sure you're running Post-Exam Sync (Local → Cloud), not pre-exam. Check the sync report — the users (local → cloud) row should show +N for newly created users. Existing cloud users show as skipped (normal).

Build fails after changing .env

Environment variables with NEXT_PUBLIC_ prefix are baked into the build at compile time. After changing them:
powershell
# Clear Next.js build cache
Remove-Item -Recurse -Force .next

# Rebuild
bun run build

Appwrite console unreachable at localhost/console

powershell
# Check if the container is running
docker ps

# If not running, start it
docker compose -f docker/exam-mode/docker-compose.yml up -d

# If running but console is unreachable, check logs
docker logs appwrite --tail 50

Wait 30–60 seconds after starting for Appwrite to fully initialize.


Important File Locations

FilePurpose
.envAll environment variables — never commit this file
.env.exampleTemplate to copy to .env
docker/exam-mode/docker-compose.ymlDocker Compose config for local Appwrite stack
docker/exam-mode/appwrite.envAppwrite internal secrets — change before production use
.next-server.pidPID file written by exam:start — used by exam:stop to kill the process
scripts/exam-start.tsStarts Docker, then next dev --hostname 0.0.0.0 --port 3000
scripts/exam-stop.tsKills the Next.js process tree and stops Docker
scripts/setup-appwrite.tsCreates all Appwrite collections and the storage bucket (cloud or local)
scripts/bootstrap-local-admin.tsCreates the first admin in the local Appwrite instance
src/lib/exam-mode/config.tsExam mode configuration and the shared exam password
src/lib/exam-mode/syncService.tsCore sync logic (cloud↔local)
src/app/api/exam-mode/All exam-mode API routes
src/app/exam-dashboard/The live exam monitoring dashboard

Environment Variable Quick Reference

env
# Cloud Appwrite
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT_ID=your_cloud_project_id
NEXT_PUBLIC_APPWRITE_DATABASE_ID=your_cloud_database_id
APPWRITE_API_KEY=your_cloud_api_key

# Exam mode
EXAM_MODE=true
APPWRITE_LOCAL_ENDPOINT=http://localhost/v1
APPWRITE_LOCAL_PROJECT_ID=your_local_project_id
APPWRITE_LOCAL_DATABASE_ID=exam-db
APPWRITE_LOCAL_API_KEY=your_local_api_key

# Exam password (shared by all students; the value IS the password)
EXAM_PASSWORD_PREFIX=exam2026

# Optional: IP restriction for exam APIs (blank = allow all)
EXAM_ALLOWED_IPS=192.168.1.0/24
See .env.example in the repository root for the full list, including the AI provider, feedback, analytics, and email variables.

Found a problem with this page? Help us fix it.

Still stuck? Read the FAQ or the troubleshooting guide.