Environment variables
These are the variables in the install guides’ compose.yaml and .env
files. Basic Compose installs keep .env beside compose.yaml; HTTPS installs
keep .env beside the release configuration folder.
Select the platform version in .env; PostgreSQL has an independent version.
The generated .env and its manual example contain the same settings and comments;
only the shortened secret examples are replaced with independent random values.
For how to generate, protect and change secrets, see
Configuration and secrets.
Settings you fill in
Section titled “Settings you fill in”| Variable | Purpose |
|---|---|
COMPOSE_PROJECT_NAME |
Optional Compose instance name. Basic Compose defaults to lunarpaper; Publisher defaults to lunarpaper-publisher. Select a previously unused name for fresh named volumes. An explicit --project-name flag takes precedence, as in the HTTPS guide. It has no effect on docker run. |
LUNAR_PAPER_VERSION |
Published platform version, such as 0.8.1. Selects ghcr.io/lunarpaper/platform:<version>. |
LUNAR_PAPER_IMAGE |
Optional image repository override, without a tag (for example ghcr.io/lunarpaper/platform). Defaults to the public repository. Compose appends LUNAR_PAPER_VERSION and forwards the combined reference to the app. |
PGUSER |
PostgreSQL owner username for setup, upgrades and backups. Defaults to postgres. See Database usernames. |
APP_PLATFORM_USER |
Platform runtime login name. Defaults to app_platform. |
APP_INTAKE_USER |
Intake runtime login name. Defaults to app_intake. |
POSTGRES_IMAGE |
Optional PostgreSQL image selection; defaults to official postgres:17-alpine. Keep major version 17. It is independent of the platform version. |
HOST_PORT |
HTTP host port; defaults to 3000. Used by the basic Compose and Docker Run examples. Include any changed port in APP_URL. Does not change Caddy’s HTTPS ports or the publisher’s port. |
HTTP_BIND_ADDRESS |
Optional HTTP interface; defaults to 127.0.0.1. Set a server interface IP for LAN access. |
APP_URL |
The exact address people open in their browser, such as http://192.168.1.20:3000. |
SYSTEM_ADMIN_USERNAME |
The email address of the first administrator, created during guided setup. |
SYSTEM_ADMIN_PASSWORD |
The password of the first administrator. It needs 12 or more characters, with upper case, lower case, a number and a symbol. |
CADDY_TLS_DIRECTIVE |
Used only in the HTTPS guide. Set it to tls internal on a private network, or tls you@example.com to get a public certificate. |
COOKIE_NAMESPACE |
Optional cookie prefix: 1–32 letters, numbers, _ or -. Use a different value for each additional instance on the same hostname; browser cookies are shared across ports. |
PUBLISHER_PRIVATE_TARGETS |
Optional. Publishing instances on your own network that Lunar Paper may send content to, as host:port, separated by commas. See Set up a publishing instance. |
Running multiple instances
For a fresh basic Compose installation beside an existing one, generate a new
.env in a separate folder, then set:
COMPOSE_PROJECT_NAME=lunarpaper-testHOST_PORT=3100HTTP_BIND_ADDRESS=127.0.0.1APP_URL=http://localhost:3100COOKIE_NAMESPACE=lunarpaper_testChoose an unused project name and port. Keep the default volume settings for
separate project-prefixed storage, such as lunarpaper-test_postgres-data.
Custom host folder paths must also be unique. A new folder alone does not override
the fixed Compose project name; new secrets do not reset an existing database.
See Running multiple instances.
HTTPS commands explicitly select a project name, Arcane manages its project identity, and Docker Run uses fixed names. Follow each guide’s multiple-instance section rather than applying this block unchanged to those methods.
Database usernames
Section titled “Database usernames”The generated .env includes these defaults, exactly as in the manual example:
PGUSER=postgresAPP_PLATFORM_USER=app_platformAPP_INTAKE_USER=app_intakeYou can manually override any of these before the first start and keyed web setup.
Use three distinct names. For custom names, start with a lowercase letter, followed
by lowercase letters, digits or underscores, up to 63 characters. Keep app_*,
pg_*, postgres, public, svc_datalayer and reporting reserved, except for
the defaults shown above. For example, paper_owner, paper_platform and
paper_intake are suitable overrides.
Each account has its own generated password: PGPASSWORD, APP_PLATFORM_PASSWORD
and APP_INTAKE_PASSWORD. Compose uses the same settings for the PostgreSQL owner,
application connections and keyed setup. Custom application logins inherit the
existing restricted permission roles; the owner remains separate.
These are fresh-install settings. Changing .env does not rename users or rotate
passwords in an existing database. Keep your current values across upgrades;
changing an established installation needs coordinated database-role and deployment
configuration changes by the operator. Do not recreate data volumes to change a username.
Storage settings
Section titled “Storage settings”For Compose installations, these optional settings select each service’s storage source. They default to the existing Docker-managed named volumes. Use an absolute host folder path to select a bind mount instead. See Choose storage locations.
| Variable | Default | Stores |
|---|---|---|
POSTGRES_DATA |
postgres-data |
PostgreSQL data at /var/lib/postgresql/data. |
REDIS_DATA |
redis-data |
Redis data at /data. |
UPLOADS_DATA |
uploads-data |
Application uploads at /app/uploads. |
SEAWEEDFS_DATA |
seaweedfs-data |
SeaweedFS file contents and index at /data. |
Named volumes receive the effective Compose project prefix. The default
POSTGRES_DATA=postgres-data becomes lunarpaper_postgres-data; changing the
project name selects different named storage. Arbitrary new volume names need
matching declarations in compose.yaml.
Changing a value does not move existing data. Back up and migrate the data before changing storage for an existing installation. Reusing existing storage requires its original credentials and encryption keys, even if the containers were removed.
Generated secrets
Section titled “Generated secrets”The install guides generate each value independently using 32 random bytes. There are no shared default database passwords. Preserve these values after the first start; changing a password in .env does not change the password stored in PostgreSQL.
| Variable | Purpose |
|---|---|
SETUP_KEY |
Unlocks initial guided setup and database upgrades. |
SESSION_SECRET |
Signs sign-in sessions. |
ENCRYPTION_KEY |
Encrypts form submissions and publishing data. |
INTERNAL_API_TOKEN |
Authenticates requests between Lunar Paper’s own services. |
AI_ENCRYPTION_KEY |
Encrypts saved AI provider credentials. |
MFA_ENCRYPTION_KEY |
Encrypts two-factor sign-in secrets. |
SSO_ENCRYPTION_KEY |
Encrypts single sign-on client secrets. |
DATA_SOURCE_ENCRYPTION_KEY |
Encrypts data source credentials, proxy profiles and the licence activation. |
WORKFLOW_CREDENTIAL_ENCRYPTION_KEY |
Encrypts credentials saved for workflows. |
PUBLISHER_CREDENTIAL_ENCRYPTION_KEY |
Encrypts form publisher credentials. |
EMAIL_ENCRYPTION_KEY |
Encrypts outbound email connector credentials. |
ADDRESS_PROVIDER_ENCRYPTION_KEY |
Encrypts map and address provider credentials. |
EMAIL_TRACKING_SECRET |
Signs email open and click tracking links. |
PDF_EXPORT_SECRET |
Signs PDF export requests. |
FORM_FILE_ENCRYPTION_KEYS |
Keys that encrypt files uploaded through forms, in the form {"v1":"<key>"}. |
PGPASSWORD |
Password of the PostgreSQL owner account, used for setup, upgrades and backups. |
APP_PLATFORM_PASSWORD |
Password of the restricted account selected by APP_PLATFORM_USER. The platform initializer configures it on fresh installation; preserve it on upgrades. |
APP_INTAKE_PASSWORD |
Password of the restricted account selected by APP_INTAKE_USER. The platform initializer configures it on fresh installation; preserve it on upgrades. |
REDIS_PASSWORD |
Password for Redis. |
The internal permission roles app_platform and app_intake remain stable for migrations. Custom login names inherit their respective permissions; do not use the owner for runtime connections.
Set in compose.yaml
Section titled “Set in compose.yaml”These have fixed values in compose.yaml, and you do not need to change them.
| Variable | Purpose |
|---|---|
NODE_ENV |
Runs Lunar Paper in production mode. |
PORT |
The port Lunar Paper listens on inside its container: 3000. |
PROCESS_ROLE |
Which parts run in the container. all runs the web app and background jobs together. |
CLUSTER_WORKERS |
Web worker count. The standard single-container installation uses 1. |
TRUST_PROXY_HOPS |
How many proxies sit in front of Lunar Paper: 0 for direct access, 1 behind Caddy. |
API_URL |
The API address, set to APP_URL. |
ALLOWED_ORIGINS |
Browser origins allowed to call the API, set to APP_URL. |
PUBLISHER_CALLBACK_ORIGINS |
Origins allowed to receive form publisher callbacks, set to APP_URL. |
LUNAR_PAPER_IMAGE |
Resolved platform image reference, identical to the container image selected above. Used for release checks. |
FORM_FILE_ENCRYPTION_ACTIVE_KEY_ID |
Which key in FORM_FILE_ENCRYPTION_KEYS encrypts new files: v1. |
PGHOST, PGPORT, PGDATABASE |
Where the PostgreSQL owner account connects: postgres, 5432, platform. |
DATABASE_URL |
Connection to the platform database for day-to-day use. |
INTAKE_DATABASE_URL |
Connection to the intake database for day-to-day use. |
MIGRATION_PLATFORM_DATABASE_URL |
Owner connection to the platform database, used for explicit initialization and upgrades. |
MIGRATION_INTAKE_DATABASE_URL |
Owner connection to the intake database, used for explicit initialization and upgrades. |
APP_DB_ROLE |
Makes Lunar Paper use the restricted database accounts. |
DB_POOL_MAX |
Maximum database connections per pool: 40. |
SESSION_STORE |
Where sessions are kept: redis. |
REDIS_REQUIRED |
Stops Lunar Paper from starting without Redis: true. |
REDIS_HOST, REDIS_PORT |
Where Redis is: redis, 6379. |
SEAWEEDFS_MASTER_URL, SEAWEEDFS_FILER_URL, SEAWEEDFS_VOLUME_URL |
Addresses of the file storage service. |
The official PostgreSQL container receives POSTGRES_DB, POSTGRES_USER and
POSTGRES_PASSWORD. These create its cluster and empty platform database only
when its data directory is empty. POSTGRES_USER comes from PGUSER and POSTGRES_PASSWORD comes from PGPASSWORD.
Changing these settings does not rename an existing owner or rotate its password
in an existing volume. Runtime passwords go to the platform
initializer; official PostgreSQL does not interpret APP_PLATFORM_PASSWORD
or APP_INTAKE_PASSWORD. No Lunar Paper database image or paired digest is needed.
Publisher settings
Section titled “Publisher settings”The publisher has a separate .env and no PostgreSQL database. Copy its credentials
from Publisher Inventory; do not run the main application’s secret generator
for it. See Set up a publishing instance.
| Variable | Purpose |
|---|---|
LUNAR_PAPER_VERSION |
Publisher tag matching the main platform release. |
PUBLISHER_IMAGE |
Optional repository override without a tag; defaults to ghcr.io/lunarpaper/publisher. |
PUBLISHER_HOST_PORT |
Publisher host port; defaults to 8081. Container port remains 8080. Register the chosen host port in Publisher Inventory. |
PUBLISHER_BIND_ADDRESS |
Interface to publish on; defaults to 0.0.0.0 for reachability from the main app. Use an assigned server IP to restrict interfaces, or loopback behind a proxy on the same host. |
PUBLISHER_DATA |
Storage source at /app/data; defaults to the project-prefixed publisher-data named volume. An absolute host path selects a bind mount. |
MAIN_APP_URL |
Reachable main platform address, matching its APP_URL. This is not the publisher’s address or port. |
PUBLISHER_INSTANCE_ID, API_KEY, PUBLISHER_BROKER_TOKEN |
Connection settings copied from Publisher Inventory. Preserve them with existing content. |
ASSET_ENCRYPTION_KEY |
Publisher’s asset key; retain it with its stored content. |
EMAIL_TRACKING_SECRET |
Email tracking key. When using tracking, match the main installation’s value. |
PUBLISHER_TRUST_PROXY_HOPS |
0 for direct access; set 1 behind one reverse proxy. |
Optional
Section titled “Optional”Add these to the lunarpaper service in compose.yaml only if you need them.
| Variable | Purpose |
|---|---|
ADDRESS_SELF_HOSTED_NOMINATIM_URL |
Address of your own Nominatim or Photon server for address lookup. See Address lookup. |
NODE_EXTRA_CA_CERTS |
Path to a root certificate, inside the container, for an outbound proxy that inspects TLS. |
RENDER_BASE_URL |
The address the built-in headless browser opens to take homepage screenshots and render dashboard exports. Leave it unset: each container uses its own internal address. Set it only if Administration > System Configuration > Thumbnails says screenshots are paused because that address is unreachable or redirected. |
CONTENT_CAPTURE_CONCURRENCY |
How many homepage screenshots a container takes at once. The default is 1. See Screenshots and exports. |
