Getting started

Configuration

Every environment variable Papyra reads, what it is for, and when you actually need it. Most people need none of them.

Papyra is configured by environment variables. Every one is optional — the defaults are what most installations want.

The full list

VariableDefaultWhat it does
PAPYRA_DATA_DIR/dataWhere notes, cache and keys live.
PAPYRA_ALLOW_INSECURE_COOKIESfalseAllow the session cookie over plain HTTP.
PAPYRA_OLLAMA_URLWhere the model server is.
PAPYRA_ALLOWED_ORIGINSExtra CORS origins, comma-separated.
PAPYRA_TRUSTED_PROXIESProxy IPs whose forwarded headers to believe.
PAPYRA_WEBAUTHN_DOMAINlocalhostBare hostname passkeys are bound to.
PAPYRA_WEBAUTHN_ORIGINSFull origins passkeys may be used from.
PAPYRA_WHISPER_MODEL_PATHEnables audio transcription.
PAPYRA_OCR_TESSDATA_PATHEnables OCR of images.
PUID / PGID1000Who owns the files on disk.

Lists are comma-separated, as in every other container image.

Papyra also accepts .NET’s own spelling — Papyra__AllowInsecureCookies, Cors__AllowedOrigins__0 — and anything set that way wins. The plain-English names exist because the .NET convention fails silently: get the casing or the doubled underscore subtly wrong and the setting is ignored with no error at all, which is the worst possible failure for something you touch once.

The ones you are most likely to need

PAPYRA_ALLOW_INSECURE_COOKIES

Set true only when Papyra is reached over plain HTTP on a network that is already private. It makes the session cookie non-Secure, which is exactly the thing HTTPS is protecting. See HTTPS and reverse proxies.

PAPYRA_OLLAMA_URL

Points at the model server. Inside compose, that is the service name and Ollama’s own port:

PAPYRA_OLLAMA_URL: "http://ollama:11434"

localhost here means the Papyra container itself, so it is never the answer.

Already running Ollama elsewhere? Delete the ollama service and the depends_on, then either join the other stack’s network and address it by container name, or go through the host:

PAPYRA_OLLAMA_URL: "http://host.docker.internal:11434"
extra_hosts: ["host.docker.internal:host-gateway"]

PAPYRA_TRUSTED_PROXIES

Behind a reverse proxy, every request arrives from the proxy’s address. Without this, your rate limits and logs see one client — the proxy — and a single visitor can exhaust everybody’s budget.

List the proxy’s IP and Papyra will believe its forwarded headers:

PAPYRA_TRUSTED_PROXIES: "172.18.0.1"

Only list proxies you control. An unlisted proxy cannot spoof a client address past the rate limiter, which is the point.

PAPYRA_ALLOWED_ORIGINS

Only needed if you serve the web app from a different address than the API. The standard deployment serves both from one process at one origin, so normally you leave this out entirely.

PAPYRA_WEBAUTHN_DOMAIN and PAPYRA_WEBAUTHN_ORIGINS

Passkeys are bound to a domain by the browser, and it must be the bare hostname — no scheme, no port, no path:

PAPYRA_WEBAUTHN_DOMAIN: "notes.example.com"
PAPYRA_WEBAUTHN_ORIGINS: "https://notes.example.com"

Passkeys require real HTTPS. They will not work over plain HTTP outside localhost, and no configuration flag changes that — it is the browser’s rule.

Configured in the app, not the environment

Deliberately not environment variables, because changing them should not mean editing a compose file and restarting a container:

  • AI provider, models and API keys — Settings → AI
  • SSO / OIDC — Settings → SSO, applied without a restart
  • SMTP — Settings → Email
  • Trash retention — Settings → Data & Storage
  • Git backup — Settings → Backup, per account

Optional extras, off unless configured

PAPYRA_WHISPER_MODEL_PATH enables local audio transcription, and PAPYRA_OCR_TESSDATA_PATH enables OCR of images into searchable text. Both are no-ops until you point them at model data, and neither sends anything anywhere.

Something wrong or missing?Improve this page on GitHub.