admin
Start the web admin site for managing Ritual from a browser.
This page covers the server: starting it, creating and recovering the admin account, its security options, and its config keys. What you can do once signed in is documented in the Admin Site section.
ritual admin [options]ritual admin setup --username <username> [--password-stdin]ritual admin reset-password [--username <username>] [--password-stdin]ritual admin disable-totpritual admin starts the web admin server. The setup, reset-password, and disable-totp subcommands manage the admin account without starting a server. See Account Recovery.
Options
Section titled “Options”| Option | Description | Default |
|---|---|---|
-p, --port <number> |
Port to serve on | 8080 |
--host <address> |
Host address to bind to | 0.0.0.0 |
--theme <name> |
Initial theme. Append -inverted (e.g. boros-inverted) for the inverted variant. See build-site themes for the palettes. |
default |
--refresh <mode> |
Card cache and buylist refresh policy on startup: ask (prompt; skip when prompts are unavailable), auto, no-bulk, or never |
ask |
--mcp |
Also serve an MCP endpoint in this process (requires --mcp-token) |
|
--mcp-port <number> |
Port for the embedded MCP server (only with --mcp) |
8765 |
--mcp-token <secret> |
Bearer token required on the embedded MCP endpoint (with --mcp) |
|
--sell-mode |
(Beta) Offer sell mode for this run even when site.sellMode is off (enable-only). See Sell mode. |
On startup, admin:
- Runs the card-ID backfill, writing any missing
&Ncard IDs into the list files, since the editors rely on them. - Checks whether the Scryfall card cache is missing or stale and offers to refresh it.
- When sell mode is on or
priceSourcesincludescardkingdom, redownloads the Card Kingdom buylist if it is more than a day old. Startup only updates a buylist: a workspace that has never downloaded one is left alone, with no prompt. A failed download keeps the older feed and warns instead of failing startup. - On a release build, prints the update notice from its cache if a newer Ritual is out, and refreshes that cache in the background.
--refresh auto, no-bulk, or never answers the cache prompt non-interactively; no-bulk/never also skip the buylist refresh. Under the default ask, a run where prompts are unavailable (see When prompts are unavailable) skips the refresh. bun run dev admin requires an explicit mode (see Development → Dev Workflow).
Sell mode
Section titled “Sell mode”Sell mode adds Card Kingdom buy prices in the editors, buylist filters and groupings, and the sell-cart export. It is off unless you ask for it. Turn it on for the workspace with ritual config set site.sellMode true, or for one run:
ritual admin --sell-modeWith sell mode off, and priceSources not naming cardkingdom (which uses the same feed), the admin server:
- skips the startup buylist refresh (no ~70 MB download);
- answers
404on/api/sell/report,/api/sell/cart,/api/sell/refresh,/api/buylist/status, and/api/buylist/quotes. The setting is read per request, so aconfig settakes effect without a restart; - hides the surfaces that call them: the editors’ Sell mode toggle and buyer selector (see Editors), the Refresh buylist card on the Refresh Cache page, and the sell controls on all three panes of Move Cards.
The admin UI learns the effective value from GET /api/status, so --sell-mode shows the surfaces even with nothing in the config file.
The Settings page has an Offer sell mode checkbox for site.sellMode and Price Stores checkboxes for priceSources. Checking the box stores site.sellMode: true. Unchecking removes the key, so config get site.sellMode reports it unset rather than an explicit false.
The change applies immediately, without a reload or restart: the routes re-read the config per request, and the save re-reads GET /api/status, so the sell surfaces appear or disappear on the spot. If that status read fails (the server went away between the save and the re-read), the surfaces keep their previous state; the save still landed, so reload to resynchronize. A server started with --sell-mode keeps offering sell mode whatever the checkbox says, since the flag overrides the stored key for that run.
Checking the box commits every later site build and cache refresh to downloading and indexing Card Kingdom’s ~70 MB buylist.
ritual sell is unaffected by sell mode. Running it is itself the request for Card Kingdom prices.
Embedded MCP Server
Section titled “Embedded MCP Server”--mcp starts an MCP (Model Context Protocol) endpoint in the same process as the web admin, on a separate port (--mcp-port, default 8765). Both --port and --mcp-port must be 1–65535, and --mcp-port must differ from --port; otherwise the command exits with code 2 before starting:
ritual admin --mcp --mcp-token "$MCP_TOKEN"# http://<host>:8080/ web admin# http://<host>:8765/mcp MCP (Streamable HTTP)This is one process, not a second ritual mcp instance, so it shares the same config, card cache, and data directory. Authentication uses the same bearer-token model as the standalone server. A token is required because the admin binds 0.0.0.0 by default: pass --mcp-token <secret> or set RITUAL_MCP_TOKEN. Every MCP request must send Authorization: Bearer <token>; requests without it get 401. The token is independent of the browser admin login.
The endpoint is stateless and serves both the 2026-07-28 and the 2025-era protocol. See ritual mcp → HTTP for what that means for sessions, GET/DELETE, and error responses.
Both listeners stop together on Ctrl-C (SIGINT) or SIGTERM, so neither port is left bound.
The standalone ritual mcp command is still the way to run MCP without the web admin (over stdio, or HTTP with a bearer token).
First-Time Setup
Section titled “First-Time Setup”While no admin account exists, ritual admin prints a setup link when it starts:
No admin account yet. Create it at: http://localhost:8080/?setupToken=Qm9yb3NDaGFybUJvbHQxMjM0(or run `ritual admin setup` in this workspace)Open that link to create the account:
- Username: any username
- Password: 8–128 characters
- Setup token: filled in from the link. If you open the plain URL instead, paste the token from the terminal.
The account can only be created with that token. Because the admin binds every interface (0.0.0.0) by default, anyone on your network can reach a fresh server, and without the token the first person to open it would own it. The token is printed only to the terminal that started the server (in Docker, to docker logs). A new one is drawn on every start, and once an account exists the setup form is gone. To pin the token, for example to create the account from a provisioning script, set RITUAL_ADMIN_SETUP_TOKEN.
Credentials are hashed with bcrypt and stored in .logins/admin-auth.json. Later visits sign in with these credentials and get a session cookie.
You can also create the account ahead of time from the terminal with ritual admin setup, which needs no token. See Account Recovery.
Account Recovery
Section titled “Account Recovery”Three subcommands manage the admin account without a running server. They read and write .logins/admin-auth.json directly, for scripted provisioning and for recovering access when you are locked out. All three support the standard scripting options (--output text|json|ndjson, --quiet) and append an entry to the audit log (.logins/admin-audit.log).
ritual admin setup
Section titled “ritual admin setup”Create the admin account before opening the browser:
# Interactive password promptritual admin setup --username ops
# Scripted: password piped on stdin (exactly one trailing newline is stripped)printf '%s\n' "$ADMIN_PASSWORD" | ritual admin setup --username ops --password-stdin --output json# → { "username": "ops", "created": true }| Option | Description |
|---|---|
--username <username> |
Username for the new admin account (required) |
--password-stdin |
Read the password from stdin (for scripting) |
Exit code 1 if an admin user already exists. Exit code 2 for validation problems (missing username, password too short or too long) or when a password prompt is needed but stdin is not a terminal.
ritual admin reset-password
Section titled “ritual admin reset-password”Replace the stored password (and optionally the username) of the existing account:
printf '%s\n' "$NEW_PASSWORD" | ritual admin reset-password --password-stdin# Also replace the username:printf '%s\n' "$NEW_PASSWORD" | ritual admin reset-password --username root --password-stdin| Option | Description |
|---|---|
--username <username> |
Also replace the admin username (optional) |
--password-stdin |
Read the new password from stdin |
Everything else in the credentials file is kept, including a TOTP secret and any pending TOTP enrollment. Exit code 3 when no admin user exists yet (run ritual admin setup instead).
ritual admin disable-totp
Section titled “ritual admin disable-totp”Remove the TOTP secret so login needs only the password again:
ritual admin disable-totp --output json# → { "totpDisabled": true }This clears both an active TOTP secret and a stuck pending: enrollment, such as one you started in the browser but never verified. Exit code 1 when no TOTP secret is stored, and 3 when no admin user exists.
Recovery runbook
Section titled “Recovery runbook”Lost password (with or without TOTP still working):
- On the machine hosting Ritual, run
ritual admin reset-password(interactive) or pipe the new password with--password-stdin. - Restart the admin server (see the caution below).
- Sign in with the new password.
Lost TOTP device (or a broken half-finished TOTP enrollment):
- Run
ritual admin disable-totp. - Restart the admin server.
- Sign in with username + password, then re-enroll TOTP from Settings → Two-Factor Authentication if desired.
Lost everything: delete .logins/admin-auth.json and run ritual admin setup (or restart ritual admin and open the setup link it prints) to start fresh.
Configuration File
Section titled “Configuration File”Settings are stored in ritual.config.json in the base directory. The file is shared by the whole app; see Configuration for the full reference and how it interacts with --base-dir. It is created the first time something writes a setting (a Settings page save, config set, init-site). Until then the defaults apply.
Admin-server settings live under the admin key. Set them from the Settings page, with config set admin.<field>, or by hand.
Git Integration
Section titled “Git Integration”When git integration is enabled:
- The admin checks whether the target directory (decks, collections, or config) is inside a git repository
- After a file-modifying operation (editing decks or collections, importing decks, updating config), the changed files are staged and committed
- Commit messages describe the action (for example, “Save 3 changes to burn.md”)
Enable it on the Settings page by checking both Enable Git integration and Auto-commit changes.
Auto-commit covers the admin web UI and the MCP server only. CLI commands never auto-commit. See Git integration for the keys and the import-changes exception.
Security
Section titled “Security”Network options
Section titled “Network options”admin.trustProxy makes the server take the client address from the last X-Forwarded-For entry, the one a reverse proxy appends, instead of the connection’s own address. Turn it on only behind a proxy you control. admin.secureCookies marks the session cookie Secure, so browsers send it over HTTPS only.
Failed Login Delay
Section titled “Failed Login Delay”Every failed authentication attempt is delayed (default: 3 seconds) before the server responds. The delay does not slow other requests.
Rate Limiting
Section titled “Rate Limiting”After a number of failed login attempts (default: 5) from one IP address within the rate-limit window (default: 5 minutes), that IP is locked out for the same duration. Rate limiting can be disabled in settings.
| Config Field | Default | Description |
|---|---|---|
admin.rateLimitEnabled |
true |
Enable/disable rate limiting |
admin.rateLimitMaxAttempts |
5 |
Failed attempts before lockout |
admin.rateLimitWindowMinutes |
5 |
Counting window and lockout duration, in minutes |
admin.failedAuthDelayMs |
3000 |
Delay (ms) on failed auth |
Rate limit state is kept in memory and resets when the server restarts.
Two-Factor Authentication (TOTP)
Section titled “Two-Factor Authentication (TOTP)”TOTP (Time-based One-Time Password) adds a second factor. When enabled, login requires your password and a 6-digit code from an authenticator app (Google Authenticator, Authy, 1Password, and the like).
Setup:
- Go to Settings → Two-Factor Authentication
- Click “Set Up TOTP”. The server generates a secret key
- Add the secret to your authenticator app (manual entry, or the
otpauth://URI with a QR code generator) - Enter the current 6-digit code to verify and activate TOTP
Login with TOTP:
The login form shows an additional code field. For API access, include the totpCode field in the POST /api/login request body.
The TOTP secret is stored in .logins/admin-auth.json alongside the password hash.
IP Allow/Deny Lists
Section titled “IP Allow/Deny Lists”Control which IP addresses can access the admin interface:
- Allow list: if non-empty, only IPs matching a pattern can connect. All others get
403 Forbidden, answered in the API’s shared error envelope (messageKey: admin.api.server.forbidden). - Deny list: IPs matching any pattern are blocked. Deny is checked before allow.
Patterns support simple wildcards: 192.168.1.*, 10.0.*, * (match all).
User-Agent Allow/Deny Lists
Section titled “User-Agent Allow/Deny Lists”Control which browsers and clients can access the admin interface:
- Allow list: if non-empty, only matching User-Agent strings can connect.
- Deny list: matching User-Agent strings are blocked.
A blocked client gets the same 403 error envelope as a blocked IP.
Patterns support wildcards: *bot* (blocks common bots), Mozilla* (allows browsers).
HTTP API
Section titled “HTTP API”Every admin page is backed by an HTTP route under /api/. The same routes serve the MCP server and any client you write. See the Admin API page.
Examples
Section titled “Examples”Start the admin on the default port:
ritual adminStart on a custom port:
ritual admin --port 9090Bind to localhost only:
ritual admin --host 127.0.0.1Ritual is unofficial Fan Content permitted under the Fan Content Policy. Not approved or endorsed by Wizards of the Coast. Portions of the materials used are property of Wizards of the Coast. ©Wizards of the Coast LLC.
Card data, images and symbols come from Scryfall, which is not affiliated with this project. Ritual is free software under the AGPL-3.0. License and attribution.