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.
| Variable | Description | Default |
|---|---|---|
APP_NAME | Application name (used in UI and emails) | Penombre |
APP_ENV | Environment (dev/production) | production |
ORIGIN | Public origin URL (used for OAuth callbacks) | http://localhost:3000 |
ADDRESS_HEADER | Header carrying the real client IP, e.g. x-forwarded-for | Unset |
XFF_DEPTH | Trusted proxy hops to count back in X-Forwarded-For | 1 |
LOG_LEVEL | debug, info, warn, error, trace | info |
LOG_FORMAT | console or json | console |
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/penombrePostgreSQL 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.
| Variable | Description | Default |
|---|---|---|
DATABASE_URL | SQLite file: path, or a Postgres connection string | file:$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.
| Variable | Description | Default |
|---|---|---|
AUTH_SECRET | Secret key for signing auth tokens | Required |
ENABLE_EMAIL_SIGNIN | Enable email/password sign-in | true |
ENABLE_OAUTH_SIGNIN | Enable OAuth sign-in | Auto |
ENABLE_PASSKEY_SIGNIN | Enable passkey sign-in | true |
MIN_PASSWORD_LENGTH | Minimum password length | 8 |
AUTH_AUTO_REDIRECT_PROVIDER skips the sign-in screen and sends users straight
to one OIDC provider. See
Skipping the sign-in screen.
| Variable | Description | Default |
|---|---|---|
AUTH_AUTO_REDIRECT_PROVIDER | Provider 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.
| Variable | Description | Default |
|---|---|---|
OAUTH_<PROVIDER>_ENABLED | Enable this provider | true |
OAUTH_<PROVIDER>_CLIENT_ID | OAuth client ID | Required |
OAUTH_<PROVIDER>_CLIENT_SECRET | OAuth client secret | Required |
OAUTH_<PROVIDER>_DISCOVERY_URL | OIDC discovery URL | Required |
OAUTH_<PROVIDER>_PRETTY_NAME | Display name in the UI | Provider name |
OAUTH_<PROVIDER>_PKCE | Use PKCE | true |
OAUTH_<PROVIDER>_SCOPES | Comma-separated scopes | openid,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).
| Variable | Description | Default |
|---|---|---|
REDIS_URL | Redis 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.
| Variable | Description | Default |
|---|---|---|
WORKER_MODE | embedded (this container) or external | embedded |
WORKER_CONCURRENCY | Number of jobs the worker runs concurrently | 4 |
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.
| Variable | Description | Default |
|---|---|---|
SMTP_ENABLED | Enable SMTP | false |
SMTP_HOST | SMTP server hostname | Required if enabled |
SMTP_PORT | SMTP server port | 587 |
SMTP_USER | SMTP username | Required if enabled |
SMTP_PASSWORD | SMTP password | Required if enabled |
SMTP_FROM | Sender email address | Required if enabled |
SMTP_SECURE | Use 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.
| Variable | Description | Default |
|---|---|---|
DATA_DIR | Base directory for all app data | /data (./data in dev) |
STORAGE_PATH | Absolute 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.
| Variable | Description | Default |
|---|---|---|
VOLUME_<NAME>_PATH | Absolute path to the directory (required) | / |
VOLUME_<NAME>_LABEL | What the sidebar shows | NAME |
VOLUME_<NAME>_READONLY | Refuse every write to the volume | false |
VOLUME_<NAME>_ENCRYPT | Seal 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.
| Variable | Description | Default |
|---|---|---|
ENCRYPTION_KEY | 32 random bytes, base64 | Unset |
ENCRYPTION_KEY_FILE | File holding the key, e.g. a Docker secret | Unset |
ENCRYPTION_KEY_PREVIOUS | Retired keys, comma-separated, read-only | Unset |
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.
| Variable | Description | Default |
|---|---|---|
SIMPLE_MODE | Enable simple mode (true/false) | false |
BYPASS_AUTH | Disable sign-in, everyone is the owner | false |
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.
| Variable | Description | Default |
|---|---|---|
ENABLE_VERSION_CHECK | Run the check at all (true/false) | true |
RELEASE_CHANNEL | Compare against stable or canary releases | canary 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.
| Variable | Description | Default |
|---|---|---|
DATA_RETENTION_DAYS | Days to keep the rows above | unset (keeps forever) |
This guide lives in the project repo: edit it there, and this page follows within a day.