Skip to content

Authentication

Scryer is multi-user from the start. Every account has app permissions, per-library permissions, and one or more ways to sign in: password, MFA, passkeys, or a Plex, Jellyfin, or Emby account.

Create and manage accounts in Settings → Users. Requires manageUsers or managePermissions.

Grant only what a role needs. It is easier to add access later than to audit and remove it. When someone cannot see a page, check their permissions before anything else: the sidebar and command palette only show routes the account can reach.

Users can also arrive through a media server connection, either auto-added on first sign-in with the connection’s default grants or invited by an admin.

App permissions control instance-wide settings:

PermissionUnlocks
manageUsersUsers, Security settings
managePermissionsUsers (permission assignment)
manageSystemSettingsGeneral, Indexers, Download Clients, Plugins, Notifications, Media Servers, Recycle Bin, System pages
manageCatalogSettingsQuality Profiles, Delay Profiles, Rules, Post-processing, Subtitles, facet settings

Library permissions are granted per library:

PermissionUnlocks
viewBrowse the library’s titles
manageTitlesAdd, edit, and remove titles; Wanted History
resolveImportsManual import queue; Activity
manageLibraryLibrary roots and settings
requestRequest titles into the library
autoApproveRequestsRequests skip the approval queue

Everyone can reach their own Profile. Activity appears once you hold manageTitles or resolveImports on any library; System requires manageSystemSettings.

Settings → Security requires manageUsers. It controls:

  • Form login on or off. Media server login and passkeys depend on it being on.
  • Password minimum length.
  • MFA requirements separately for password login, Jellyfin login, Emby login, and configuration step-up (re-verifying before sensitive settings changes).
  • Skip login for local IPs for trusted LAN-only setups.
  • Restrict API keys to users who hold manageSystemSettings.

A setting shown as locked is being overridden by an environment variable. Change the variable, not the UI.

Each user manages their own second factors from Profile: TOTP enrollment with recovery codes, and passkeys. Passkeys use WebAuthn, so in production Scryer, the browser-facing URL, and the reverse proxy must agree about the public HTTPS origin.

SCRYER_WEBAUTHN_RP_ID=scryer.example.com
SCRYER_WEBAUTHN_RP_ORIGIN=https://scryer.example.com
SCRYER_WEBAUTHN_RP_NAME=Scryer

The relying-party ID is a domain, not a URL. The origin is the exact browser origin: scheme, host, and port if non-default. If either is missing, Scryer disables passkeys and logs a warning. WebAuthn requires HTTPS except on localhost.

The proxy must preserve the browser-facing Host, set a single X-Forwarded-Proto value, and pass WebSocket upgrades on /graphql/ws. Caddy’s default reverse_proxy does all of this:

scryer.example.com {
reverse_proxy scryer:8080
}

Scryer itself can stay plain HTTP behind the proxy. Under a path prefix, set SCRYER_BASE_PATH=/scryer, keep the RP origin without the path, and do not strip the prefix in the proxy. Full proxy guidance is in Networking.

Set SCRYER_PUBLIC_URL=https://scryer.example.com on any reverse-proxied install. It fixes the origin advertised by OAuth discovery so clients never see the container’s internal scheme or hostname. It is an origin only: no path, and it does not configure WebAuthn or routing.

To verify:

Terminal window
curl https://scryer.example.com/.well-known/oauth-authorization-server

Every endpoint in the response should use the public HTTPS origin and include the base path when one is configured.

Scryer ignores forwarding headers for rate limiting unless the socket peer is trusted, otherwise everyone behind an unconfigured proxy shares one bucket. Trust only your proxy’s exact address or a narrow CIDR:

SCRYER_RATE_LIMIT_TRUSTED_PROXY_IPS=172.20.0.2

Only X-Forwarded-For is used. Trusted proxies must append the connecting peer. This setting affects rate-limit identity only, not WebAuthn, OAuth, or access policy.

A media server connection with Login enabled adds a Plex, Jellyfin, or Emby button to the sign-in page. Form login must be on. Security settings can require MFA for Jellyfin and Emby logins. Details, including auto-add and account linking, are in Media Servers.

When form login is disabled, Scryer still refuses to treat public clients as admin. SCRYER_ALLOW_UNAUTHENTICATED_PUBLIC_ACCESS=true overrides that, and SCRYER_UNAUTHENTICATED_PUBLIC_ACCESS_ALLOWLIST narrows it to specific IPs, CIDRs, or hostnames. Use this only on a deliberately isolated network. If the instance is reachable from the internet, keep auth on.

If form login is on but no local full-admin account has a usable password, start Scryer once with SCRYER_RECOVERY_ADMIN_PASSWORD set (Scryer 0.16.1 or newer). On that boot Scryer:

  • Creates or repairs the reserved local account recovery-admin with that password and full permissions
  • Clears its TOTP, recovery codes, passkeys, and failed login attempts
  • Disables MFA step-up requirements and forces form login off for that boot

Because auth is off during recovery, block external access first: stop the reverse proxy exposure, close forwards, and reach the instance only from a trusted local machine.

  1. Block external access and stop Scryer.
  2. Start once with SCRYER_RECOVERY_ADMIN_PASSWORD set to a strong temporary password.
  3. Sign in locally and repair your real admin account, passwords, MFA, and passkeys.
  4. Remove the variable and restart normally.
  5. Re-enable external access once normal sign-in works.

Where to set the variable: Homebrew reads $(brew --prefix)/etc/scryer/config.env and restarts with brew services restart scryer. Docker Compose takes it under environment: followed by docker compose up -d. For a binary, prefix the command:

SCRYER_RECOVERY_ADMIN_PASSWORD='choose-a-strong-temporary-password' ./scryer

An empty value is invalid, and the variable must not stay configured. Afterwards confirm at least one local full-admin account has a usable password and review Settings → Users for leftover recovery access.

  • Media Servers covers connections, auto-add, and library refresh notifications.
  • Media Requests uses the request and autoApproveRequests permissions.
  • Configuration lists every environment variable named here.
  • Networking covers bind addresses, TLS, and proxies in depth.