Menu
Penombre docs

Environment Variables

Configure your Penombre instance with environment variables.

See .example.env for a complete reference.

Core

General application settings that control the runtime identity, environment mode, and logging behavior.

ORIGIN must be set to the public URL where your instance is accessible. It is used to generate absolute URLs in OAuth callbacks and email links. In development this is typically http://localhost:3000.

Behind a reverse proxy, also set ADDRESS_HEADER (and XFF_DEPTH for X-Forwarded-For) so Penombre reads the real client address instead of the proxy's own; see Reverse proxy.

VariableDescriptionDefault
APP_NAMEApplication name (used in UI and emails)Penombre
APP_ENVEnvironment (dev/production)production
ORIGINPublic origin URL (used for OAuth callbacks)http://localhost:3000
ADDRESS_HEADERHeader carrying the real client IP, e.g. x-forwarded-forUnset
XFF_DEPTHTrusted proxy hops to count back in X-Forwarded-For1
LOG_LEVELdebug, info, warn, error, traceinfo
LOG_FORMATconsole or jsonconsole

Database

Penombre runs on SQLite by default — no database server to install, back up or keep patched. The Docker image ships pointing at a file inside its data volume, so a fresh install needs no database configuration at all.

The dialect is picked from the DATABASE_URL scheme: a postgres:/ postgresql: URL runs PostgreSQL, anything else runs SQLite — including an empty value, which falls back to the default below. With a file:/sqlite: URL the rest of the value is the path to the database file, created on first boot.

# SQLite (default) — no database server needed
DATABASE_URL=file:/data/db/penombre.sqlite

# PostgreSQL (optional)
DATABASE_URL=postgresql://penombre:penombre@localhost:5432/penombre

PostgreSQL is optional. It is still fully supported and worth the extra container if you run multiple app instances against one database. For a single container — which is what most self-hosted installs are — SQLite is the simpler and faster choice.

VariableDescriptionDefault
DATABASE_URLSQLite file: path, or a Postgres connection stringfile:$DATA_DIR/db/penombre.sqlite

Initial Setup

These variables are only used during the first-time database seed to create the initial admin account. They have no effect after the database has been initialized and can be removed from your environment afterwards.

There are no admin credential variables. The first administrator is created through the setup screen on first boot — see Authentication.

Authentication

Controls how users authenticate. AUTH_SECRET must be a long, random string — you can generate one with openssl rand -hex 32. Keep it secret and do not rotate it without invalidating all existing sessions.

VariableDescriptionDefault
AUTH_SECRETSecret key for signing auth tokensRequired
ENABLE_EMAIL_SIGNINEnable email/password sign-intrue
ENABLE_OAUTH_SIGNINEnable OAuth sign-inAuto
ENABLE_PASSKEY_SIGNINEnable passkey sign-intrue
MIN_PASSWORD_LENGTHMinimum password length8

AUTH_AUTO_REDIRECT_PROVIDER skips the sign-in screen and sends users straight to one OIDC provider. See Skipping the sign-in screen.

VariableDescriptionDefault
AUTH_AUTO_REDIRECT_PROVIDERProvider name to redirect to on load/

OAuth Providers (Optional)

Penombre supports any OIDC-compliant provider. Configure one with the naming pattern OAUTH_<PROVIDER>_<SETTING>, where <PROVIDER> is an uppercase identifier of your choice (e.g. GOOGLE, GITHUB, POCKET_ID) — declaring a provider is enough to turn OAuth sign-in on. ENABLE_OAUTH_SIGNIN forces it either way, and taking it out of the environment hands the decision to the admin UI, which can manage providers of its own.

VariableDescriptionDefault
OAUTH_<PROVIDER>_ENABLEDEnable this providertrue
OAUTH_<PROVIDER>_CLIENT_IDOAuth client IDRequired
OAUTH_<PROVIDER>_CLIENT_SECRETOAuth client secretRequired
OAUTH_<PROVIDER>_DISCOVERY_URLOIDC discovery URLRequired
OAUTH_<PROVIDER>_PRETTY_NAMEDisplay name in the UIProvider name
OAUTH_<PROVIDER>_PKCEUse PKCEtrue
OAUTH_<PROVIDER>_SCOPESComma-separated scopesopenid,profile,email

Redis (Optional)

Penombre includes an in-memory cache for file listings and metadata. By default, each app instance maintains its own cache in-process. To share the cache across multiple instances or preserve it across restarts, you can connect an external Redis server.

When REDIS_URL is set, all caching is offloaded to Redis. When it is not set, caching falls back to an in-process memory cache (production) or is disabled entirely (development).

VariableDescriptionDefault
REDIS_URLRedis connection string/

Worker

Thumbnails, waveforms, scans, zip downloads and trash/copy byte work run in a separate Go worker process. By default it runs embedded inside this container; set WORKER_MODE=external to run it as its own container instead. See Worker for the full guide.

VariableDescriptionDefault
WORKER_MODEembedded (this container) or externalembedded
WORKER_CONCURRENCYNumber of jobs the worker runs concurrently4

SMTP (Optional)

Required for email features such as password reset and email verification. Set SMTP_ENABLED=true and provide the connection details for your mail server. If SMTP is disabled, email-dependent features will be unavailable.

VariableDescriptionDefault
SMTP_ENABLEDEnable SMTPfalse
SMTP_HOSTSMTP server hostnameRequired if enabled
SMTP_PORTSMTP server port587
SMTP_USERSMTP usernameRequired if enabled
SMTP_PASSWORDSMTP passwordRequired if enabled
SMTP_FROMSender email addressRequired if enabled
SMTP_SECUREUse TLS (true/false)false

Storage

Everything Penombre writes — uploaded files and the SQLite database — hangs off one data directory, so a single mounted volume covers a whole install. Set DATA_DIR to move all of it at once, or override a single path on its own. See Storage for the full guide.

VariableDescriptionDefault
DATA_DIRBase directory for all app data/data (./data in dev)
STORAGE_PATHAbsolute path to the storage root$DATA_DIR/storage

Mounted Volumes (Optional)

Extra directories mounted alongside the main drive, one block per volume. See Mounted volumes for the full guide.

<NAME> is uppercase with underscores; it is lowercased and hyphenated to form the volume's id, so VOLUME_MEDIA_PATH gives /volumes/media. A block without a _PATH is ignored.

VariableDescriptionDefault
VOLUME_<NAME>_PATHAbsolute path to the directory (required)/
VOLUME_<NAME>_LABELWhat the sidebar showsNAME
VOLUME_<NAME>_READONLYRefuse every write to the volumefalse
VOLUME_<NAME>_ENCRYPTSeal what Penombre writes (needs a key)false

A volume is one tree shared by every account, in both modes: mount a library and everybody browses the files already on it. Pair it with _READONLY when nobody should be able to change them.

Encryption (Optional)

Seals file bytes at rest on personal and shared drives. Losing the key loses every sealed file: keep a copy apart from DATA_DIR and its backups. Refused with SIMPLE_MODE=true. See Encryption for the full guide.

VariableDescriptionDefault
ENCRYPTION_KEY32 random bytes, base64Unset
ENCRYPTION_KEY_FILEFile holding the key, e.g. a Docker secretUnset
ENCRYPTION_KEY_PREVIOUSRetired keys, comma-separated, read-onlyUnset

Simple Mode (Optional)

Turns Penombre into a bare shared file browser: one storage volume shared by every account instead of a drive per user. See Simple mode for the full guide.

BYPASS_AUTH removes authentication entirely — see No sign-in at all before enabling it. It is ignored unless SIMPLE_MODE=true.

VariableDescriptionDefault
SIMPLE_MODEEnable simple mode (true/false)false
BYPASS_AUTHDisable sign-in, everyone is the ownerfalse

Version Check (Optional)

An hourly check against GitHub releases, shown as an "update available" banner. Also settable in Admin → Settings; the environment wins whenever it is set. See Deployment for the tags each channel watches.

VariableDescriptionDefault
ENABLE_VERSION_CHECKRun the check at all (true/false)true
RELEASE_CHANNELCompare against stable or canary releasescanary on a -canary.N build, stable otherwise

Data Retention (Optional)

How long activity, notifications and finished background job rows are kept before a nightly sweep deletes them. Also settable in Admin → Settings; the environment wins whenever it is set. See Admin panel.

VariableDescriptionDefault
DATA_RETENTION_DAYSDays to keep the rows aboveunset (keeps forever)

This guide lives in the project repo: edit it there, and this page follows within a day.