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.
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_VERSION | latest | Image version, e.g. 1.2.0 (Images) |
SEMESTRA_IMAGE_VARIANT | -local | Empty for the image without local OCR and embedding |
SEMESTRA_PUBLIC_URL | http://localhost:8000 | The address users open. Used in email and calendar links; https:// makes cookies Secure |
SEMESTRA_PORT | 8000 | Host port |
SEMESTRA_BIND | 0.0.0.0 | Host 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
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_SESSION_TTL_DAYS | 30 | Web session lifetime |
SEMESTRA_ACCESS_TOKEN_TTL_SECONDS | 900 | Access token lifetime for native clients |
SEMESTRA_REFRESH_TOKEN_TTL_DAYS | 60 | Refresh token lifetime for native clients |
SEMESTRA_NOTIFY_NEW_SIGN_IN | false | Email the user when a new session signs in |
SEMESTRA_GOOGLE_CLIENT_ID | (empty) | Google sign-in. Empty hides the Google button |
SEMESTRA_TRUSTED_PROXY_HOPS | 0 | Reverse 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
| Variable | Default (self-hosted) | Meaning |
|---|---|---|
SEMESTRA_USER_STORAGE_QUOTA_BYTES | 0 compose | Storage per user; 0 means unlimited |
SEMESTRA_FILES_MAX_UPLOAD_BYTES | 26214400 (25 MB) | Largest single upload |
SEMESTRA_FILES_PARSE_TIMEOUT_SECONDS | 300 | Longest a file may take to parse |
SEMESTRA_FILES_PARSE_MEMORY_BYTES | 2147483648 (2 GB) | Memory limit of the parsing process |
Network
| Variable | Default (self-hosted) | Meaning |
|---|---|---|
SEMESTRA_ALLOW_PRIVATE_EGRESS | true compose | Lets 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
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_LMS_CANVAS_SIGN_IN | false | Canvas school account sign-in |
AI
| Variable | Default | Meaning |
|---|---|---|
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_CONCURRENCY | 0 | Most requests sent to it at once (0: no limit); e.g. 1 for a small Ollama server |
SEMESTRA_AI_WARM_UP | true | Load the AI libraries in the background after start |
Local OCR
Only in the default image; see Images.
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_LOCAL_OCR | true in -local | Read scanned pages on the server |
SEMESTRA_LOCAL_OCR_MODEL | PP-OCRv6_medium | Default model: PP-OCRv6_tiny, _small, _medium, PP-OCRv5_mobile, PP-OCRv5_server |
SEMESTRA_LOCAL_OCR_PAGE_TIMEOUT_SECONDS | 60 | Time 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.
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_LOCAL_EMBEDDING | true in -local | Embed text on the server |
SEMESTRA_LOCAL_EMBEDDING_MODEL | multilingual-e5-small | Default model (a preset or a Hugging Face name) |
SEMESTRA_LOCAL_EMBEDDING_CUSTOM | true | Let users add Hugging Face models; turn off on a shared server to save disk |
SEMESTRA_LOCAL_EMBEDDING_MAX_GB | 3 | Largest Hugging Face model users may add |
SEMESTRA_LOCAL_EMBEDDING_THREADS | 0 | CPU threads (0: half the cores) |
SEMESTRA_LOCAL_EMBEDDING_IDLE_SECONDS | 600 | Unload the model after this long without use |
SEMESTRA_LOCAL_EMBEDDING_MAX_LOADED | 2 | Models kept loaded at once (each uses its own memory) |
Background work and backups
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_JOB_CONCURRENCY | 2 | Background job workers in the process |
SEMESTRA_JOB_BULK_CONCURRENCY | 1 | Of 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_KEEP | 7 | Database snapshots kept |
Secrets and logging
| Variable | Default | Meaning |
|---|---|---|
SEMESTRA_SECRET_KEY | generated | Signs sessions and tokens |
SEMESTRA_ENCRYPTION_KEY | generated | Fernet key that encrypts saved provider keys and Canvas tokens |
SEMESTRA_LOG_LEVEL | INFO | Log 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.