# Configuration guide
This guide covers the settings that affect a self-hosted Orchestrarr deployment. Start with the Docker or local installation steps in the [README](../README.md), then use this guide when you connect services or expose the dashboard beyond localhost.
## Configuration sources
Orchestrarr can read settings from a JSON file and environment variables.
| Source | Default | Use |
| --- | --- | --- |
| CONFIG_PATH | config.json in the project root | Choose the JSON configuration file |
| STATE_DIR | .data in the project root | Choose the directory for local event history |
| DEMO_MODE | true when no saved setting exists | Set the deployment default for demo mode |
| DEMO_PROFILE | medium | Set the demo usage profile when no saved profile exists |
| PUBLIC_DEMO | false | Run a shared public demo: demo data only, with settings and outgoing requests locked |
| TRUST_PROXY | false | Behind Cloudflare or a reverse proxy: take the visitor's address from CF-Connecting-IP or X-Forwarded-For for rate limits |
| Environment variables | — | Supply deployment secrets and override matching saved values |
| config.json | — | Store settings entered through the dashboard |
Native Node processes do not load .env automatically. Export variables in the shell or configure them through your service manager. Docker Compose loads .env and passes the values into the container.
For most service fields, environment variables take precedence over values in config.json. Environment-managed access settings appear as locked in **Settings → Access**.
The saved demoMode value takes precedence over DEMO_MODE. If neither is set, the app starts in demo mode.
## Authentication
Authentication is configured with **Settings → Access** or with environment variables.
| Mode | Required values | Client behavior |
| --- | --- | --- |
| none | None | Local API access without login |
| apikey | ORCHESTRARR_API_KEY, or a key generated on first start | Browser login with the key; API clients send X-Orchestrarr-Key |
| basic | AUTH_USERNAME, AUTH_PASSWORD | API clients send an Authorization: Basic ... header |
Only none, apikey and basic are valid modes. Docker Compose uses apikey by default.
In apikey mode without a key from the environment or the JSON file, Orchestrarr generates a random key on first start. It prints the key once, stores it with owner-only permissions in api_key.json in the state folder (/app/.data in Docker) and reuses it on later starts. A key from ORCHESTRARR_API_KEY or Settings takes precedence.
Browser clients use POST /api/auth/login with a JSON body containing the API key ({"key": …}) or, in basic mode, the username and password ({"username": …, "password": …}). A successful login creates an HttpOnly session cookie, which images and other plain browser requests carry automatically. POST /api/auth/logout invalidates that session. Login attempts are rate-limited in memory. Scripts can keep sending the X-Orchestrarr-Key header or Basic credentials instead. Browser writes also require a same-origin request.
The dashboard does not store a Basic Auth password in plain text when it is saved through Settings; it stores a salted scrypt hash. Environment variables remain the deployment authority when they are present.
If a native installation locks you out, stop the server and update the auth.mode value in the configured JSON file to none, then restart it. For Docker, read the generated key with docker exec orchestrarr cat /app/.data/api_key.json, or set ORCHESTRARR_API_KEY in .env and recreate the container.
## Demo mode
Demo mode is useful for previews, screenshots and first-time setup.
- Enable it from **Settings → Demo mode**.
- Set DEMO_MODE=true for a deployment default.
- Set demoMode to true in config.json.
- Disable it from Settings or with DEMO_MODE=false, then configure the services you want to use.
An explicit saved setting wins over the environment default. When demo mode is active, the dashboard shows a persistent banner. Demo data never requires real service credentials. The catalog, users, history and service events are synthetic, and the local posters in public/demo/posters/ are original fictional placeholder artwork. Demo mode does not call external metadata services.
Actions work on the demo data: approving and declining requests, requesting a title, importing, blocklisting, pausing, resuming, searching and dismissing alerts. Each browser gets its own changes through an orchestrarr_demo cookie. They are kept in memory only, never written to disk or sent to a service, and reset when the server restarts.
A **Try the demo** checklist in the corner walks through eight tasks: request Daybreak Motel from Discover, approve that request, decline another, import a download that failed to import, pause a download, blocklist a stalled one, create an invitation, and remove someone's access. A removed user stays gone from your Access list until the server restarts. Each task opens its page and ticks off once done. It starts folded on narrow screens and remembers whether you folded it.
### Public demo
Set PUBLIC_DEMO=true (with AUTH_MODE=none) to host a demo that anyone can open. Every visitor shares the same server, so a public demo:
- always shows demo data, whatever DEMO_MODE or config.json say, and uses DEMO_PROFILE as its fixed profile;
- answers every write with 403, except signing in and out, refreshing, and the actions demo mode answers itself (each visitor only sees their own changes);
- blocks all Docker routes, connection tests, notification tests and incoming webhooks, and serves only the local demo posters, so visitors cannot make the server reach another host;
- allows at most 5 live-update connections per visitor and 500 in total; refused tabs fall back to the 30-second refresh;
- disables the demo switch and the profile picker, and its banner says changes only show for that visitor and links to orchestrarr.com.
Choose the demo usage profile from **Settings → Demo usage profile**:
- **Light usage** (small) keeps the fixture light for quick previews and smaller screens.
- **Rich home server** (medium) provides the default scenario.
- **High activity** (large) adds more requests, playback history, queue activity, streams and calendar entries for a heavily used household.
The selected profile is saved as demoProfile in config.json. The setting affects the dashboard and the demo discovery, calendar, request, user and title-history endpoints together.
## Service connections
You can configure services from **Services**. For deployments, use environment variables or a private configuration file instead of committing credentials.
The supported environment variable names are listed in the [README](../README.md#supported-integrations-and-environment-variables). Service URLs should be reachable from the Orchestrarr process or container, not necessarily from the browser.
Some integrations have additional behavior:
- Tdarr uses its server/API port by default. Its web UI may use a different port.
- Cleanuparr only needs CLEANUPARR_API_KEY when API authentication is enabled.
- Tdarr authentication is disabled by default; set TDARR_API_KEY when it is enabled.
- WIZARR_PUBLIC_URL is the address invitation recipients open. It may differ from the internal WIZARR_URL.
- TMDb and OMDb use cloud API keys and do not need a service URL.
- Docker controls are opt-in. Set DOCKER_ENABLED=true only for trusted administrators.
Credentials are kept on the server and are not returned to the React application.
## Notifications
Set NOTIFICATION_WEBHOOK_URL to receive JSON notifications for test events and newly observed alerts. Use the **Test notification** action in Settings after saving the URL.
Keep the URL private. A notification destination can receive information about service events, so treat it like a credential.
## Incoming webhooks
Orchestrarr accepts forward-only events from:
- POST /api/webhooks/plex
- POST /api/webhooks/radarr
- POST /api/webhooks/sonarr
Configure those URLs in the corresponding services using the host and port where Orchestrarr is reachable.
Protect the endpoints with ORCHESTRARR_WEBHOOK_SECRET or webhooks.secret in config.json. Send the secret either as:
- ?secret=<your-secret> in the webhook URL
- X-Orchestrarr-Webhook-Secret: <your-secret> as a request header
A configured webhook secret is required even when dashboard authentication uses a different mode. Without a secret, webhook endpoints remain available only when you intentionally run the dashboard without authentication on a trusted local deployment.
Accepted payloads can be JSON bodies or form bodies containing a JSON payload field. Events are written to .data/request-events.json or the directory selected by STATE_DIR. The file is written atomically and is shown in Activity from the point tracking begins.
## Storage and backups
The default locations are:
- config.json: integration and application settings
- .data/request-events.json: locally recorded webhook events
- Docker /app/.data: the persistent configuration and state directory
Back up these files or the Docker volume privately. They may contain service credentials, webhook settings and operational history. Do not commit them to Git or include them in public support requests.
To move the files, set CONFIG_PATH and STATE_DIR before starting the server. Ensure the process can read and write both locations.
## Remote access
Native and development servers bind to 127.0.0.1 by default. To serve the dashboard on a network, deliberately configure HOST=0.0.0.0, enable authentication and put the service behind a trusted HTTPS reverse proxy or VPN.
The Docker image listens on 0.0.0.0 inside the container, while the Compose example publishes only to host loopback. Preserve the browser's Host header through a reverse proxy. Do not expose the Vite development server or an unauthenticated deployment to the public internet.
All signed-in users currently have administrative access to configured integrations. There are no separate viewer and administrator roles.