Self-Hosting
Since ClassQuiz is open-source, it can also be self-hosted.
Warning
Although some versions are already released, I would recommend to run the latest commit (where checks pass) from the master-branch.
Requirements
Software
3rd-Parties
Required
Optional
Installation
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 frontend/Dockerfile
:
VITE_MAPBOX_ACCESS_TOKEN
: A Mapbox-token which is optional.VITE_HCAPTCHA
: The hCaptcha-Siteky for captchasVITE_CAPTCHA_ENABLED
: Set it totrue
, if the captcha should be availableVITE_SENTRY
: A Sentry-DSN for Sentry (optional)VITE_GOOGLE_AUTH_ENABLED
: Set it totrue
, if Google-Auth is set up. Otherwise, leave it unset.VITE_GITHUB_AUTH_ENABLED
: Set it totrue
, if GitHub-Auth is set up. Otherwise, leave it unset.
Configuration
Storage Provider
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 s3
or
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_ACCESS_KEY
, S3_SECRET_KEY
and
the
S3_BASE_URL
. The S3_BUCKET_NAME
can also be set, but defaults to
classquiz
.
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
docker-compose.yml
.
GitHub/Google-Auth
This step is purely optional, but it will enable users to log in using their Google/GitHub-accounts.
First, go to console.cloud.google.com/apis/dashboard and create a new project and select it. Then, go to the "OAuth consent screen" and set it up. Next, go to the "Credentials"-tab and click on "Create Credentials" and create a new "OAuth Client ID". This ID should be from the application-type "Web application". Afterwards, add a new "Authorised JavaScript origin", which is just the base-domain (with https) of your ClassQuiz-installation. Then, add a new "Authorised redirect URI". This URI will have the following scheme:
https://[BASE_URL]/api/v1/users/oauth/google/auth
You're done! Not the client-secret and the client-id down, you'll need it later.
GitHub
First, go to github.com/settings/developers and create a "new OAuth App". The "Authorization callback URL" has the following schema:
https://[BASE_URL]/api/v1/users/oauth/github/auth
That's it. Click on "Register application" and generate a new client secret and save it for later, together with your client-id.
Docker-Compose File
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: "classquiz@mawoka.eu" # Email-Address (change it)
MAIL_PASSWORD: "MAIL_PASSWORD" # Email-Password (change it)
MAIL_USERNAME: "classquiz@mawoka.eu" # 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!
Enjoy! ❤️