improve container startup for rootless Podman, plus related refactors and tests. Key changes: - Add/modify Audiobookshelf-related code and wiring (src/lib/services/audiobookshelf/api.ts, library service refs) and update documentation TABLEOFCONTENTS to reference ABS implementation. - Detect user namespace in docker/unified app-start.sh and redis-start.sh and skip gosu when running in rootless Podman to preserve UID mapping; improve startup logging and verification. - Add utility/service files (auth-token-cache.service.ts, credential-migration.service.ts, cleanup-helpers.ts) and corresponding tests; update chapter-merger and metadata-tagger utilities/tests. - Update many admin/auth API routes and tests to reflect changes in settings and integrations. - Remove large AI agent and Audiobookshelf implementation guide docs (AGENTS.md and the implementation guide) and add README note about AI-assisted workflow. These changes enable Audiobookshelf backend mode, improve compatibility with rootless container runtimes, and include cleanup/refactor work and unit tests.
6.6 KiB
Environment Variables
Status: ✅ Implemented | Centralized URL handling via getBaseUrl() utility
Defines all environment variables used by ReadMeABook, configuration priority, and troubleshooting guide.
Public URL Configuration (OAuth Callbacks)
Critical for OAuth: Plex OAuth and OIDC authentication require correct redirect URIs.
Priority Order:
PUBLIC_URL- Primary (documented standard)NEXTAUTH_URL- Legacy fallback (backward compatibility)BASE_URL- Alternative fallbackhttp://localhost:3030- Development default
Format Requirements:
- Must start with
http://orhttps:// - No trailing slash (automatically normalized)
- Must be publicly accessible for OAuth callbacks
- Example:
https://readmeabook.example.com
Docker Compose:
environment:
PUBLIC_URL: "https://readmeabook.example.com"
Implementation: src/lib/utils/url.ts → getBaseUrl()
Used By:
- OIDC OAuth redirect_uri:
{PUBLIC_URL}/api/auth/oidc/callback - Plex OAuth redirect_uri:
{PUBLIC_URL}/api/auth/plex/callback - Login error redirects:
{PUBLIC_URL}/login?error=...
Database Configuration
Required:
DATABASE_URL- PostgreSQL connection string- Auto-generated by entrypoint in unified container
- Format:
postgresql://{user}:{password}@{host}:{port}/{database} - Example:
postgresql://readmeabook:password@localhost:5432/readmeabook
PostgreSQL Settings (Unified Container):
POSTGRES_USER- Default:readmeabookPOSTGRES_PASSWORD- Auto-generated on first run if not setPOSTGRES_DB- Default:readmeabook
Security & Secrets
Auto-generated on first run (Unified Container):
JWT_SECRET- JWT access token signing keyJWT_REFRESH_SECRET- JWT refresh token signing keyCONFIG_ENCRYPTION_KEY- Config field encryption key (Plex tokens, etc.)POSTGRES_PASSWORD- PostgreSQL password
Manual Override: Set in docker-compose.yml before first run to use custom secrets.
File Ownership (Unified Container)
User/Group ID Mapping:
PUID- Default: 1000 (your host user ID)PGID- Default: 1000 (your host group ID)
How It Works:
- PostgreSQL: UID 103, GID={PGID}
- Node/Redis: Fully remapped to PUID:PGID
- See: documentation/deployment/unified.md
Plex Configuration
Optional Overrides:
PLEX_CLIENT_IDENTIFIER- Default: auto-generated UUIDPLEX_PRODUCT_NAME- Default:ReadMeABookPLEX_OAUTH_CALLBACK_URL- Custom OAuth callback (overrides PUBLIC_URL)
Logging
Optional:
LOG_LEVEL- Default:info- Values:
debug,info,warn,error debuglogs base URL resolution source
- Values:
Debug Example:
[URL Utility] Using base URL from PUBLIC_URL: https://example.com
Setup Middleware
Internal Override:
SETUP_CHECK_BASE_URL- Override base URL for setup status check- Use case: Reverse proxies with TLS termination
- Default: Tries request origin, then loopback
- See: documentation/backend/middleware.md
Troubleshooting
Issue: OAuth Redirects to Localhost
Symptoms:
- OIDC/Plex OAuth redirects to
http://localhost:3030/api/auth/... - Authentik/Identity Provider shows
localhostredirect URI - "Redirect URI Error" or "Mismatching redirection URI"
Cause: PUBLIC_URL not set (defaulting to localhost)
Fix:
# docker-compose.yml
environment:
PUBLIC_URL: "https://your-actual-domain.com" # No trailing slash
Restart container after change.
Issue: Invalid Redirect URI Format
Symptoms:
- Warning:
Invalid base URL format - OAuth fails with malformed URL
Cause: PUBLIC_URL missing protocol or has invalid format
Fix:
- ✅ Correct:
https://example.com - ❌ Wrong:
example.com(missing protocol) - ❌ Wrong:
https://example.com/(trailing slash, auto-normalized but avoid)
Issue: Production Using Localhost
Symptoms:
- Warning:
Using localhost URL in production - OAuth fails from external clients
Cause: NODE_ENV=production but PUBLIC_URL not set
Fix: Always set PUBLIC_URL in production deployments.
Issue: checks.state argument is missing (OIDC)
Symptoms:
- Error in URL after OIDC login:
error=TypeError: checks.state argument is missing - Login redirects back to login page after Authentik authentication
Cause: Missing state parameter in openid-client callback checks (fixed in latest version)
Fix: Update to latest version with state parameter fix
Issue: OIDC login succeeds but redirects back to login page
Symptoms:
- OIDC authentication completes in Authentik
- Redirect back to ReadMeABook succeeds
- URL shows
/login?redirect=%2F - Not actually logged in, no auth cookies visible
Cause: httpOnly cookies prevent JavaScript from reading tokens (fixed in latest version)
Fix:
- Update to latest version
- Callback now uses URL hash + accessible cookies (matches Plex OAuth pattern)
- Tokens properly stored in localStorage
Authentik Configuration Requirements:
- Go to Application/Provider → Scopes
- Add:
openid,profile,email,groups - Redirect URI:
https://your-domain.com/api/auth/oidc/callback - Save and retry login
Environment Variable Reference
| Variable | Required | Default | Description |
|---|---|---|---|
PUBLIC_URL |
Prod | localhost:3030 | Public URL for OAuth callbacks |
NEXTAUTH_URL |
No | - | Legacy fallback for PUBLIC_URL |
BASE_URL |
No | - | Alternative fallback for PUBLIC_URL |
DATABASE_URL |
Yes | Auto-generated | PostgreSQL connection string |
POSTGRES_USER |
No | readmeabook | PostgreSQL username |
POSTGRES_PASSWORD |
No | Auto-generated | PostgreSQL password |
POSTGRES_DB |
No | readmeabook | PostgreSQL database name |
JWT_SECRET |
No | Auto-generated | JWT signing secret |
JWT_REFRESH_SECRET |
No | Auto-generated | Refresh token secret |
CONFIG_ENCRYPTION_KEY |
No | Auto-generated | Config encryption key |
PUID |
No | 1000 | Host user ID for file ownership |
PGID |
No | 1000 | Host group ID for file ownership |
PLEX_CLIENT_IDENTIFIER |
No | Auto-generated | Plex API client ID |
PLEX_PRODUCT_NAME |
No | ReadMeABook | Plex product name |
PLEX_OAUTH_CALLBACK_URL |
No | - | Custom Plex OAuth callback |
LOG_LEVEL |
No | info | Logging verbosity |
SETUP_CHECK_BASE_URL |
No | - | Setup middleware override |
NODE_ENV |
No | production | Environment mode |
Related
- OAuth Implementation: documentation/backend/services/auth.md
- OIDC Configuration: documentation/backend/services/auth.md
- Deployment: documentation/deployment/unified.md
- Setup Middleware: documentation/backend/middleware.md