Since ClassQuiz is open-source, it can also be self-hosted.
Although some versions are already released, I would recommend to run the latest commit (where checks pass) from the master-branch.
At first, clone the repo:
git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz
Now, you'll configure your frontend. You'll have to change the following in
VITE_MAPBOX_ACCESS_TOKEN: A Mapbox-token which is optional.
VITE_HCAPTCHA: The hCaptcha-Siteky for captchas
VITE_CAPTCHA_ENABLED: Set it to
true, if the captcha should be available
VITE_SENTRY: A Sentry-DSN for Sentry (optional)
VITE_GOOGLE_AUTH_ENABLED: Set it to
true, if Google-Auth is set up. Otherwise, leave it unset.
VITE_GITHUB_AUTH_ENABLED: Set it to
true, if GitHub-Auth is set up. Otherwise, leave it unset.
You'll have to set up a storage provider for some pictures (these getting imported from
Kahoot!). For now, you can use Minio (S3) or
the local filesystem. Please not that I'd recommend Minio for larger instances, since it can
be scaled and the media doesn't have to streamed through the (comparatively) slow ClassQuiz
server. Now, that you've decided on a storage backend, you can set the
STORAGE_BACKEND-environment-variable to either
local. If you ask yourself what happened with deta, I've decided to remove it,
since the went all-in with their spaces and I think that hardly anyone used it anyway.
If you chose Minio (S3)...
...you'll also have to set the
S3_BUCKET_NAME can also be set, but defaults to
If you chose the local filesystem...
...you'll have to set the
STORAGE_PATH environment variable. The path must be
absolute (so start with a
Before you can start your stack, you have to set some environment-variables in your
This step is purely optional, but it will enable users to log in using their Google/GitHub-accounts.
You're done! Not the client-secret and the client-id down, you'll need it later.
First, go to github.com/settings/developers and create a "new OAuth App". The "Authorization callback URL" has the following schema:
That's it. Click on "Register application" and generate a new client secret and save it for later, together with your client-id.
version: "3" services: frontend: restart: always build: context: ./frontend dockerfile: Dockerfile depends_on: - redis - api environment: REDIS_URL: redis://redis:6379/0?decode_responses=True # don't change API_URL: http://api:80 # don't change api: build: &build_cfg context: . dockerfile: Dockerfile restart: &restart always depends_on: &depends - db - redis environment: &env_vars ROOT_ADDRESS: "https://classquiz.de" # Base-URL (change it) DB_URL: "postgresql://postgres:classquiz@db:5432/classquiz" # don't change MAIL_ADDRESS: "firstname.lastname@example.org" # Email-Address (change it) MAIL_PASSWORD: "MAIL_PASSWORD" # Email-Password (change it) MAIL_USERNAME: "email@example.com" # Email-Username (change it) MAIL_SERVER: "smtp.gmail.com" # SMTP-Server (change it) MAIL_PORT: "587" # SMTP-Port SKIP_EMAIL_VERIFICATION: True # Set this to skip sending emails MAX_WORKERS: "1" # Very important and don't change it! REDIS: "redis://redis:6379/0?decode_responses=True" # don't change SECRET_KEY: "TOP_SECRET" # openssl rand -hex 32 MEILISEARCH_URL: "http://meilisearch:7700" # don't change ACCESS_TOKEN_EXPIRE_MINUTES: 30 # don't change HCAPTCHA_KEY: "" # Private hCaptcha key for verification (change it) STORAGE_BACKEND: "local" # MUST BE EITHER "s3" OR "local" FREE_STORAGE_LIMIT: "1074000000" # Free storage limit in bytes (default: 1GB) # If STORAGE_BACKEND is "s3" S3_ACCESS_KEY=YOUR_ACCESS_KEY S3_SECRET_KEY=YOUR_SECRET_KEY S3_BASE_URL=YOUR_S3_BASE_URL # If STORAGE_BACKEND is "local" STORAGE_PATH: "/var/storage" # GOOGLE_AUTH GOOGLE_CLIENT_ID: # Your Google-Client ID, or leave it unset if you don't want it. GOOGLE_CLIENT_SECRET: # Your Google-Client Secret, or leave it unset if you don't want it. # GITHUB_AUTH GITHUB_CLIENT_ID: # Your GitHub-Client ID, or leave it unset if you don't want it. GITHUB_CLIENT_SECRET: # Your GitHub-Client Secret, or leave it unset if you don't want it. volumes: # Only needed if you chose the "local" storage-backend - ./uploads:/var/storage redis: image: redis:alpine restart: always healthcheck: test: [ "CMD", "redis-cli","ping" ] db: image: postgres:14-alpine restart: always healthcheck: test: [ "CMD-SHELL", "pg_isready -U postgres" ] interval: 5s timeout: 5s retries: 5 environment: POSTGRES_PASSWORD: "classquiz" POSTGRES_DB: "classquiz" volumes: - data:/var/lib/postgresql/data proxy: image: caddy:alpine restart: always volumes: - ./Caddyfile-docker:/etc/caddy/Caddyfile ports: - "8000:8080" # Adjust the 8000 to your needs meilisearch: image: getmeili/meilisearch:latest restart: always environment: MEILI_NO_ANALYTICS: true volumes: - meilisearch-data:/data.ms worker: build: *build_cfg environment: *env_vars restart: *restart depends_on: *depends command: arq classquiz.worker.WorkerSettings volumes: data: meilisearch-data:
Run the following command to generate and set the secret up automatically
sed -i "s/TOP_SECRET/$(openssl rand -hex 32)/g" docker-compose.yml
Now build and deploy:
docker compose build && docker compose up -d
ClassQuiz needs HTTPS/SSL to work properly!