Semestra

All settings

Every setting is an environment variable in deploy/selfhost/.env.

Put settings in deploy/selfhost/.env and run docker compose up -d. The compose file passes the file to the container and sets the defaults marked compose below. The full list with comments is deploy/.env.example; the source of truth is apps/api/src/semestra/core/config.py.

Compose file

These are read by docker-compose.yml itself.

VariableDefaultMeaning
SEMESTRA_VERSIONlatestImage version, e.g. 1.2.0 (Images)
SEMESTRA_IMAGE_VARIANT-localEmpty for the image without local OCR and embedding
SEMESTRA_PUBLIC_URLhttp://localhost:8000The address users open. Used in email and calendar links; https:// makes cookies Secure
SEMESTRA_PORT8000Host port
SEMESTRA_BIND0.0.0.0Host interface. Use 127.0.0.1 behind a reverse proxy
SEMESTRA_DOMAIN(empty)Domain for the bundled Caddy (Server with a domain)
COMPOSE_PROFILES(empty)https adds the bundled Caddy, ai-local a bundled Ollama

Accounts and sign-in

VariableDefaultMeaning
SEMESTRA_SESSION_TTL_DAYS30Web session lifetime
SEMESTRA_ACCESS_TOKEN_TTL_SECONDS900Access token lifetime for native clients
SEMESTRA_REFRESH_TOKEN_TTL_DAYS60Refresh token lifetime for native clients
SEMESTRA_NOTIFY_NEW_SIGN_INfalseEmail the user when a new session signs in
SEMESTRA_GOOGLE_CLIENT_ID(empty)Google sign-in. Empty hides the Google button
SEMESTRA_TRUSTED_PROXY_HOPS0Reverse proxies in front of the API; the client IP is read from X-Forwarded-For that many hops from the right
SEMESTRA_COOKIE_SECURE(unset)Unset means Secure cookies when the public URL is https

Email settings are on Email.

Storage and files

VariableDefault (self-hosted)Meaning
SEMESTRA_USER_STORAGE_QUOTA_BYTES0 composeStorage per user; 0 means unlimited
SEMESTRA_FILES_MAX_UPLOAD_BYTES26214400 (25 MB)Largest single upload
SEMESTRA_FILES_PARSE_TIMEOUT_SECONDS300Longest a file may take to parse
SEMESTRA_FILES_PARSE_MEMORY_BYTES2147483648 (2 GB)Memory limit of the parsing process

Network

VariableDefault (self-hosted)Meaning
SEMESTRA_ALLOW_PRIVATE_EGRESStrue composeLets the server call private and loopback addresses: a LAN Ollama, an on-premises Canvas, plain-http Canvas. Outside the compose file the default is false

With false, requests to user-chosen hosts are refused when the host resolves to a private, loopback or link-local address: AI base URLs with common.egress_blocked, Canvas addresses with lms.blocked_address. Every redirect target Canvas sends goes through the same check.

Canvas

VariableDefaultMeaning
SEMESTRA_LMS_CANVAS_SIGN_INfalseCanvas school account sign-in

AI

VariableDefaultMeaning
SEMESTRA_INSTANCE_AI_KIND(empty)Instance-wide provider kind
SEMESTRA_INSTANCE_AI_BASE_URL(empty)Its base URL
SEMESTRA_INSTANCE_AI_CHAT_MODEL(empty)Model for chat, document reading and titles
SEMESTRA_INSTANCE_AI_EMBEDDING_MODEL(empty)Model for search embeddings
SEMESTRA_INSTANCE_AI_API_KEY(empty)Its key, optional for Ollama
SEMESTRA_INSTANCE_AI_MAX_CONCURRENCY0Most requests sent to it at once (0: no limit); e.g. 1 for a small Ollama server
SEMESTRA_AI_WARM_UPtrueLoad the AI libraries in the background after start

See Instance-wide provider.

Local OCR

Only in the default image; see Images.

VariableDefaultMeaning
SEMESTRA_LOCAL_OCRtrue in -localRead scanned pages on the server
SEMESTRA_LOCAL_OCR_MODELPP-OCRv6_mediumDefault model: PP-OCRv6_tiny, _small, _medium, PP-OCRv5_mobile, PP-OCRv5_server
SEMESTRA_LOCAL_OCR_PAGE_TIMEOUT_SECONDS60Time allowed per page (plus two minutes to load the model); raise it on a very slow CPU

Local embedding

Only in the default image; see Images.

VariableDefaultMeaning
SEMESTRA_LOCAL_EMBEDDINGtrue in -localEmbed text on the server
SEMESTRA_LOCAL_EMBEDDING_MODELmultilingual-e5-smallDefault model (a preset or a Hugging Face name)
SEMESTRA_LOCAL_EMBEDDING_CUSTOMtrueLet users add Hugging Face models; turn off on a shared server to save disk
SEMESTRA_LOCAL_EMBEDDING_MAX_GB3Largest Hugging Face model users may add
SEMESTRA_LOCAL_EMBEDDING_THREADS0CPU threads (0: half the cores)
SEMESTRA_LOCAL_EMBEDDING_IDLE_SECONDS600Unload the model after this long without use
SEMESTRA_LOCAL_EMBEDDING_MAX_LOADED2Models kept loaded at once (each uses its own memory)

Background work and backups

VariableDefaultMeaning
SEMESTRA_JOB_CONCURRENCY2Background job workers in the process
SEMESTRA_JOB_BULK_CONCURRENCY1Of those, how many may rebuild search vectors or download models at once; at least one stays free for imports and new files
SEMESTRA_BACKUP_DIR(empty)Turns on the daily built-in backup into this directory
SEMESTRA_BACKUP_KEEP7Database snapshots kept

Secrets and logging

VariableDefaultMeaning
SEMESTRA_SECRET_KEYgeneratedSigns sessions and tokens
SEMESTRA_ENCRYPTION_KEYgeneratedFernet key that encrypts saved provider keys and Canvas tokens
SEMESTRA_LOG_LEVELINFOLog level
SEMESTRA_SENTRY_DSN(empty)Error reporting to Sentry; empty turns it off

The container only generates keys while SEMESTRA_AUTO_SECRETS=true, which the compose file sets. The key that signs notifications is derived from SEMESTRA_SECRET_KEY; after changing it, each browser subscribes again the next time Semestra opens there. Notifications need HTTPS (or localhost) and outbound HTTPS to the browsers' push services. SEMESTRA_SKIP_MIGRATIONS=true skips the migration on start.