ClassQuiz/docs - Self-Host

Self-Hosting

Since ClassQuiz is open-source, it can also be self-hosted.

Warning

Since ClassQuiz is in pretty early development, breaking changes come and go! Please check these docs again before updating your instance. I may also add more dependencies like Typesense ore something similar in the future, but I'll always provide a docker-compose.yml file, so the self-hosting process is still easy.

Requirements

Software

3rd-Parties

Required

Optional

Installation

At first, clone the repo:

git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz

Now, set a VALID Redis-URI in frontend/Dockerfile and, if you want Sentry, set a valid Sentry-DSN.

You must set a valid hCaptcha-Sitekey in the frontend/Dockerfile.

You'll also have to provide a valid VITE_MAPBOX_ACCESS_TOKEN in frontend/Dockerfile. The provided token only works on the following urls:

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 Deta or the local filesystem. Please note that I would NOT use the local file system because of these funny path-things. I tried to prevent these attacks, but i really wouldn't trust it. You'll have to set the STORAGE_BACKEND-environment-variable to either deta or local.

If you chose Deta...

...you'll also have to set the DETA_PROJECT_KEY and the DETA_PROJECT_ID.

If you chose the local filesystem...

...you'll have to set the STORAGE_PATH enviromnent 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.

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 # For runtime
      API_URL: http://api:80 # For runtime
  api:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    depends_on:
      - db
      - redis

    environment:
      ROOT_ADDRESS: "https://classquiz.mawoka.eu" # Base-URL
      DB_URL: "postgresql://postgres:classquiz@db:5432/classquiz"
      MAIL_ADDRESS: "classquiz@mawoka.eu" # Email-Address
      MAIL_PASSWORD: "MAIL_PASSWORD" # Email-Password
      MAIL_USERNAME: "classquiz@mawoka.eu" # Email-Username
      MAIL_SERVER: "smtp.gmail.com" # SMTP-Server
      MAX_WORKERS: "1" # Very important and don't change it!
      MAIL_PORT: "587" # SMTP-Port
      REDIS: "redis://redis:6379/0?decode_responses=True" # decode_response is important!
      SECRET_KEY: "ghfvfgjgvjgvbh" # openssl rand -hex 32
	  MEILISEARCH_URL: "http://meilisearch:7700"
      ACCESS_TOKEN_EXPIRE_MINUTES: 30
      HCAPTCHA_KEY: "" # Private hCaptcha key for verification
	  STORAGE_BACKEND: "deta" # MUST BE EITHER "deta" OR "local"

	  # If STORAGE_BACKEND is "deta"
	  DETA_PROJECT_KEY: "YOUR_DETA_PROJECT_KEY"
	  DETA_PROJECT_ID: "YOUR_DETA_PROJECT_ID"

	  # If STORAGE_BACKEND is "local"
	  STORAGE_PATH: "/var/storage"
  redis:
    image: redis:alpine
    restart: always
    healthcheck:
      test: [ "CMD", "redis-cli","ping" ]

  db:
    image: postgres: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
volumes:
  data:
  meilisearch-data:
	

Now build and deploy:

docker compose build && docker compose up -d

You'll have to create an index in Meilisearch with the following command:

docker compose exec api python3 import_to_meili.py

Enjoy! ❤️