# Copy this file to .env next to docker-compose.yml and fill in real values. # .env is git-ignored — never commit it. # # cp .env.example .env # docker compose up -d # --- Image --- # Which published image tag to run (a version like "1.2.0", or "latest"). APP_TAG=latest # --- App --- API_PORT=3000 # Public origin the app is served from (used for CORS/CSP). Point this at # the URL your users actually load, e.g. https://books.example.com FRONT_END_URL=http://localhost:3000 # Generate with: openssl rand -hex 32 JWT_SECRET= # Session/cookie lifetime in milliseconds SESSION_TIME=3600000 # Absolute session lifetime in days, counted from when a session was first # created - forces a fresh login even if the session keeps getting silently # renewed by activity (see AuthMiddleware.ts). MAX_SESSION_AGE_DAYS=30 # NEVER set to true when reachable by anyone but you: bypasses login # entirely with a fake dev session. ALLOW_DEV_AUTH=false # Set to true to run this instance as a read-only public demo: every # request other than GET/HEAD/OPTIONS and the login flow is rejected with # 403, and /register is blocked outright. Pair with a seeded demo account # and a scheduled reseed - see "Public read-only demo" in DEPLOYMENT.md. DEMO_MODE=false # Set to true to require admin approval for new accounts: registration # still succeeds, but the account is created disabled and can't log in # until an admin manually enables it (there's no in-app admin role/UI for # this - see "Approving a new registration" in DEPLOYMENT.md). Useful if # registration is reachable by more than just people you trust. REGISTRATION_REQUIRES_APPROVAL=false # Set to false to turn registration off entirely: GET/POST /register both # 403/redirect away and the "No account? Register" link is hidden on the # login page. No account is created either way - unlike # REGISTRATION_REQUIRES_APPROVAL above. Useful once you and anyone else who # needs an account have already registered. REGISTRATION_ENABLED=true # Written inside the container; the app-logs volume in docker-compose.yml # persists it across restarts. Leave as-is unless you changed the volume. LOGGER_PATH=/app/logs # Verbose request tracing (raw SQL text, record names, usernames) written to # LOGGER_PATH via the debug log level. Off by default because this can # include personal data (borrower/customer/author names). Only turn this on # temporarily while troubleshooting, never leave it on in a production # deployment that stores real people's data. DEBUG_LOGGING=false # Optional: extra ISBN metadata from Google Books (quota). Open Library is # always tried first; leave empty if you don't have a key. GOOGLE_BOOKS_API_KEY= # Optional: third cover-lookup fallback (after Google Books and Open # Library), used when neither has a cover for an ISBN. Free with any # LibraryThing account: https://www.librarything.com/services/keys.php LIBRARYTHING_API_KEY= # Max size (in MB) accepted for a book's ebook file upload (.epub/.pdf/.mobi/.azw3). # Increase this if your library has large scanned PDFs or big ebook files. MAX_EBOOK_FILE_SIZE_MB=10 # Max size (in MB) accepted for a library import CSV (Goodreads export, or # Vaultisse's own template - see POST /import/library). MAX_IMPORT_FILE_SIZE_MB=10 # Controls the maximum request body size for JSON body parse. Default is 100kb. # Example of possible values: 500kb, 1mb, 5mb MAX_JSON_BODY_PARSE=100kb # Controls the maximum url encoded size. Default is 100kb. # Example of possible values: 500kb, 1mb, 5mb MAX_URLENCODED_BODY_PARSE=100kb # Set to true ONLY if a reverse proxy or tunnel (Cloudflare Tunnel, your # own Nginx/Caddy, ...) sits in front of this app and sets X-Forwarded-* # headers. It makes the login rate limiter key off the real client IP # instead of the proxy's. Leave false if the app's port is reachable # directly — enabling it without a real proxy in front lets anyone spoof # their IP and bypass rate limiting. TRUST_PROXY=false # Optional OpenID Connect (Authentik, Keycloak, ...). Leave all four # required values blank to keep password-only login. When they are set, # the login page also shows "Sign in with SSO". See AUTHENTICATION.md # and "OIDC / Authentik" in DEPLOYMENT.md. # Required (all four): OIDC_ISSUER= OIDC_CLIENT_ID= OIDC_CLIENT_SECRET= # Must be the exact redirect URI registered on the IdP, e.g. # https://books.example.com/auth/oidc/callback — never derived from Host. OIDC_REDIRECT_URI= # Optional: OIDC_SCOPES=openid profile email OIDC_BUTTON_LABEL=Sign in with SSO # Optional: comma-separated extra origins allowed by the CSP img-src # directive, on top of the built-in cover providers (Google Books, Open # Library, archive.org, LibraryThing). Use this to allow a custom cover # image host without waiting for a new release, e.g.: # CSP_EXTRA_IMG_SRC=https://example.com,https://*.example.org CSP_EXTRA_IMG_SRC= # Set to true ONLY when this instance is reachable exclusively over plain # HTTP (e.g. a LAN IP with no reverse proxy/TLS in front, scenarios A and D # in DEPLOYMENT.md). Without it, the CSP upgrade-insecure-requests directive # makes browsers rewrite every in-app http:// link to https://, which fails # since nothing is listening with TLS. Leave false whenever FRONT_END_URL is # https:// or a TLS-terminating proxy/tunnel sits in front. ALLOW_HTTP=false # --- Database --- # Consumed by the "db" service itself (docker-compose.yml). The "app" # service always connects to DB_HOST=db, DB_PORT=5432 on the compose # network — it ignores DB_HOST/DB_PORT set here. DB_NAME=vaultisse DB_USER=postgres DB_PASSWORD= # --- Cloudflare Tunnel (optional) --- # Only used if you start compose with the "cloudflare" profile — see # "Exposing it to the internet" in the README. Leave blank otherwise. CLOUDFLARE_TUNNEL_TOKEN=