Skip to main content

Configuration Reference

qui reads configuration from two sources:

  • config.toml, which qui creates on first run or with qui generate-config
  • environment variables (QUI__...) that override config.toml

This page documents both in one place.

Precedence​

Highest wins:

  1. QUI__*_FILE (for supported secrets)
  2. QUI__* environment variables
  3. config.toml
  4. built-in defaults

Config file location​

Default config.toml locations:

  • Linux/macOS: ~/.config/qui/config.toml
  • Windows: %APPDATA%\qui\config.toml

Override the location with --config-dir:

  • directory path: --config-dir /path/to/config/ (uses /path/to/config/config.toml)
  • file path (backward compatibility): --config-dir /path/to/custom.toml

Reloading​

qui watches config.toml for changes. qui applies some settings immediately, for example logging, tracker icon fetching, and the auth-disabled settings. If you change other settings, restart qui.

Settings​

TOML keyEnvironment variableTypeDefaultNotes
hostQUI__HOSTstringlocalhost (or 0.0.0.0 in containers)Bind address for the main HTTP server.
portQUI__PORTint7476Port for the main HTTP server.
baseUrlQUI__BASE_URLstring/Serve qui from a subdirectory (example: /qui/). qui normalizes the value at startup and adds missing leading and trailing slashes.
corsAllowedOriginsQUI__CORS_ALLOWED_ORIGINSstring[]empty listExplicit CORS allowlist. An empty list disables CORS. Origins must match http(s)://host[:port]. qui rejects wildcards and normalizes default ports. Restart required.
allowedHostsQUI__ALLOWED_HOSTSstring[]empty listRestricts the received HTTP Host. Accepts exact hostnames, IP addresses, and leading *. subdomain wildcards. Restart required. See Allowed Hosts.
sessionSecretQUI__SESSION_SECRET / QUI__SESSION_SECRET_FILEstringauto-generatedWARNING: a changed value breaks decryption of stored instance passwords. You must enter them again in the UI. The value cannot be empty. Use at least 32 characters on a new install. Leave the value alone on an install that already stores credentials. On the first start after upgrading, qui re-encrypts stored credentials under a key derived from this secret. A credential that does not decrypt is left as it is. qui warns about it on every start until you enter it again. The re-encryption is one way, so an older qui cannot read the new values. After rolling back, enter the credentials again or restore a database backup taken before the upgrade.
sessionCookieSecureQUI__SESSION_COOKIE_SECUREboolfalseSends the browser session cookie only over HTTPS. Enable it when you serve qui through an HTTPS reverse proxy. An HTTPS oidcRedirectUrl enables it automatically. When enabled, login over plain HTTP does not work. See Sessions. Restart required.
logLevelQUI__LOG_LEVELstringDEBUGERROR, DEBUG, INFO, WARN, TRACE. DEBUG records sufficient detail to diagnose most reports. TRACE adds per-request and per-sync-tick detail and makes the file grow quickly. qui applies changes immediately.
logPathQUI__LOG_PATHstringemptyIf empty, qui logs to stdout. qui resolves relative paths against the config directory. qui applies changes immediately.
logMaxSizeQUI__LOG_MAX_SIZEint50Size in MB that starts log rotation. qui applies changes immediately.
logMaxBackupsQUI__LOG_MAX_BACKUPSint10Number of rotated files that qui keeps. 0 keeps all. qui compresses rotated files with gzip. A 50 MB qui log file compresses to 2 to 3 MB. qui applies changes immediately.
dataDirQUI__DATA_DIRstringemptyIf empty, qui uses the directory that contains config.toml. qui stores the tracker icon cache here, and backups by default (<dataDir>/backups). If databaseEngine=sqlite, qui.db also lives here. Log files follow logPath, which qui resolves against the config directory. Restart qui after a change.
backupDirQUI__BACKUP_DIRstringemptyIf empty, qui uses <dataDir>/backups. Directory for backup manifests, archives, and cached .torrent files. qui resolves relative paths against the config directory. If you change this on an existing install, move the contents of <dataDir>/backups to the new directory. Restart required.
customThemesDirQUI__CUSTOM_THEMES_DIRstringemptyDirectory for sideloaded custom theme .css files. If empty, qui uses <config-dir>/themes (auto-created). qui resolves relative paths against the config directory. Listing themes requires premium access. qui applies config changes on the next request.
databaseEngineQUI__DATABASE_ENGINEstringsqlitesqlite or postgres. If you do not migrate, keep sqlite on an existing install. Restart required.
databaseDsnQUI__DATABASE_DSN / QUI__DATABASE_DSN_FILEstringemptyFull Postgres DSN. If databaseEngine=postgres, prefer this setting.
databaseHostQUI__DATABASE_HOSTstringlocalhostIf you do not use databaseDsn, this sets the Postgres host.
databasePortQUI__DATABASE_PORTint5432If you do not use databaseDsn, this sets the Postgres port.
databaseUserQUI__DATABASE_USERstringemptyIf you do not use databaseDsn, this sets the Postgres user.
databasePasswordQUI__DATABASE_PASSWORD / QUI__DATABASE_PASSWORD_FILEstringemptyIf you do not use databaseDsn, this sets the Postgres password.
databaseNameQUI__DATABASE_NAMEstringquiIf you do not use databaseDsn, this sets the Postgres database name.
databaseSSLModeQUI__DATABASE_SSL_MODEstringdisableCommon values: disable, require, verify-ca, verify-full.
databaseConnectTimeoutQUI__DATABASE_CONNECT_TIMEOUTint10Postgres connect timeout in seconds.
databaseMaxOpenConnsQUI__DATABASE_MAX_OPEN_CONNSint25Postgres pool max open connections.
databaseMaxIdleConnsQUI__DATABASE_MAX_IDLE_CONNSint5Postgres pool max idle connections.
databaseConnMaxLifetimeQUI__DATABASE_CONN_MAX_LIFETIMEint300Postgres connection max lifetime in seconds.
qbittorrentTimeoutQUI__QBITTORRENT_TIMEOUTint60HTTP timeout in seconds for requests qui makes to qBittorrent instances (sync, health checks). If you run large or slow instances, raise this value. Restart required.
checkForUpdatesQUI__CHECK_FOR_UPDATESbooltrueControls update checks and UI indicators. qui applies changes on config reload. If you set it with the environment variable, restart qui.
disableSelfUpdateQUI__DISABLE_SELF_UPDATEboolfalseIf true, the web UI cannot install an update. The update dialog explains this and gives manual update steps. qui update from the shell still works. This setting does not affect Restart. If you maintain a package that controls the qui version, set this value in the package. Restart required.
trackerIconsFetchEnabledQUI__TRACKER_ICONS_FETCH_ENABLEDbooltrueDisable this setting to prevent remote tracker favicon fetches. qui applies changes immediately.
crossSeedRecoverErroredTorrentsQUI__CROSS_SEED_RECOVER_ERRORED_TORRENTSboolfalseIf enabled, cross-seed automation attempts recovery (pause, recheck, resume) for errored/missingFiles torrents. This process can add 25+ minutes per torrent. Restart qui after a change.
pprofEnabledQUI__PPROF_ENABLEDboolfalseEnables the pprof server (/debug/pprof/). Restart required.
pprofAddrQUI__PPROF_ADDRstring127.0.0.1:6060pprof server bind address. The default loopback address prevents collisions with other listeners in a shared network namespace (for example a Tailscale sidecar). Restart required.
metricsEnabledQUI__METRICS_ENABLEDboolfalseEnables a Prometheus metrics server on a separate port. Restart required.
metricsHostQUI__METRICS_HOSTstring127.0.0.1Metrics server bind address. Restart required.
metricsPortQUI__METRICS_PORTint9074Metrics server port. Restart required.
metricsBasicAuthUsersQUI__METRICS_BASIC_AUTH_USERSstringemptyOptional basic auth: user:password or user1:password1,user2:password2. Passwords are plaintext and can contain colons. Usernames cannot contain colons. Commas cannot appear in credentials. Restart required.
externalProgramAllowList(none)string[]empty listRestricts which executables qui can launch from the UI. Configure this only in config.toml (no env override).
externalProgramMaxRunningQUI__EXTERNAL_PROGRAM_MAX_RUNNINGint8Maximum number of external programs that run at the same time. Other programs wait for a free slot. A value of 0 or less uses the default. See Execution limit. Restart required.
authDisabledQUI__AUTH_DISABLEDboolfalseDisables all built-in authentication. You must set both this and I_ACKNOWLEDGE_THIS_IS_A_BAD_IDEA to true to disable auth. See Authentication below. qui applies changes on config reload.
I_ACKNOWLEDGE_THIS_IS_A_BAD_IDEAQUI__I_ACKNOWLEDGE_THIS_IS_A_BAD_IDEAboolfalseRequired confirmation for authDisabled. Acknowledges that qui without authentication can permit unauthorized access to your torrent clients and can cause private tracker bans. qui applies changes on config reload.
authDisabledAllowedCIDRsQUI__AUTH_DISABLED_ALLOWED_CIDRSstring[]empty listIf auth is disabled, this setting is required. Restricts access to specific client IPs and CIDRs. Entries can be canonical CIDRs or single IPs. qui applies changes on config reload.
oidcEnabledQUI__OIDC_ENABLEDboolfalseEnables OpenID Connect authentication. Restart required.
oidcIssuerQUI__OIDC_ISSUERstringemptyOIDC issuer URL. Restart required.
oidcClientIdQUI__OIDC_CLIENT_IDstringemptyOIDC client ID. Restart required.
oidcClientSecretQUI__OIDC_CLIENT_SECRET / QUI__OIDC_CLIENT_SECRET_FILEstringemptyOIDC client secret. Restart required.
oidcRedirectUrlQUI__OIDC_REDIRECT_URLstringemptyMust match the provider redirect URI. If you use a reverse proxy, include baseUrl. Restart required.
oidcDisableBuiltInLoginQUI__OIDC_DISABLE_BUILT_IN_LOGINboolfalseIf OIDC is enabled, this hides the local username and password form. Restart required.

Authentication​

To disable the built-in authentication of qui, set all of the following:

QUI__AUTH_DISABLED=true
QUI__I_ACKNOWLEDGE_THIS_IS_A_BAD_IDEA=true
QUI__AUTH_DISABLED_ALLOWED_CIDRS=127.0.0.1/32,192.168.1.0/24

The second variable is an explicit acknowledgement of the risks.

QUI__AUTH_DISABLED_ALLOWED_CIDRS is mandatory and is a hard IP allowlist. If auth is disabled and the value is missing or invalid, qui refuses to start and rejects invalid live reloads.

Entries can be:

  • canonical CIDR ranges (192.168.1.0/24)
  • single IPs (10.0.0.5), which qui treats as /32 (IPv4) or /128 (IPv6)

qui rejects non-canonical CIDRs with host bits set (for example 10.0.0.5/8).

You cannot enable oidcEnabled and auth-disabled mode at the same time.

When authentication is disabled:

  • qui permits requests only from client IPs that match authDisabledAllowedCIDRs.
  • The built-in health endpoints (/health, /healthz/readiness, /healthz/liveness) still allow loopback probes. The official Docker image healthcheck works without 127.0.0.1/32 or ::1/128 in your reverse proxy allowlist.
  • /api/auth/me returns a synthetic admin user, so the frontend works without login.
  • /api/auth/validate returns a synthetic admin user, so callback and session checks work without login.
  • qui skips the setup screen.

Only use this mode when qui is behind a reverse proxy that already handles authentication (for example Authelia, Authentik, or Caddy with forward_auth).

Private tracker risks

If you use private trackers, running qui without authentication creates severe risk. Anyone with network access can add, remove, or modify torrents in your clients. Unwanted uploads, ratio manipulation, or hit-and-runs can cause permanent account bans on private trackers.

If you set QUI__AUTH_DISABLED without QUI__I_ACKNOWLEDGE_THIS_IS_A_BAD_IDEA, qui logs a warning and keeps authentication enabled.

Sessions​

The web UI signs in with a browser session cookie. These rules apply to that cookie:

  • sessionCookieSecure = true adds the Secure attribute to the cookie. An HTTPS oidcRedirectUrl also adds it. With the attribute set, the browser never sends the cookie over plain HTTP, so HTTP access to the same instance stops working. Without it, the cookie travels over both HTTP and HTTPS.
  • Finish the initial setup before you expose qui to the Internet. The first client that reaches an unconfigured instance can create the account.
  • Cookie-authenticated POST, PUT, PATCH, and DELETE requests must send an X-Requested-With header. The web UI and the Swagger UI do this. Scripts and other clients must use an API key instead of the cookie.
  • /api/auth/setup and /api/auth/login accept only Content-Type: application/json. Other media types get HTTP 415.
  • After five failed password logins in one minute, qui rejects password logins with HTTP 429 until the minute passes. This limit is process-wide and does not apply to OIDC or API keys.
  • A password change ends every session, including the browser that changed it. Sign in again with the new password.

Allowed Hosts​

allowedHosts restricts the hostnames and IP addresses that requests can use to reach qui. An unset or empty list permits all hosts, including when authentication is disabled. To enable the restriction, set a TOML string array or a comma-separated environment value:

allowedHosts = ["qui.example.com", "localhost", "::1", "*.home.example.com"]
QUI__ALLOWED_HOSTS=qui.example.com,localhost,::1,*.home.example.com

qui checks the Host that it receives and ignores X-Forwarded-Host. Caddy and Traefik pass the original Host, so list the public name of qui. By default, nginx sends the address of the upstream instead. Set proxy_set_header Host $host; to pass the original name. If a reverse proxy rewrites Host, list the rewritten name. The proxy must then reject unwanted public hostnames itself, because qui only sees the rewritten name.

Matching rules:

  • DNS names ignore case and one final dot. International names and their punycode forms match.
  • qui compares IP addresses by value, so ::1 and [::1] match the same address.
  • Request ports do not affect matching. Do not include ports in the configured list.
  • *.example.com matches qui.example.com and a.qui.example.com. It does not match example.com or badexample.com.
  • Schemes, paths, CIDR ranges, other wildcard forms, and empty entries are invalid. Invalid configuration prevents startup.

The restriction covers all requests on the main HTTP listener, including authenticated requests, static files, and the qBittorrent proxy. With a configured list, a missing, invalid, or unlisted Host returns HTTP 400. Your own browser and API requests must also use a listed hostname or address. qui always adds localhost, 127.0.0.1, ::1, and the hostname of the machine to a configured list, so local access keeps working. qui logs the full list at startup. When authentication is disabled and the list is empty, qui logs a warning at startup.

Health GET and HEAD requests to /health, /healthz/readiness, and /healthz/liveness bypass the list when the immediate connection peer is a loopback address. This includes external health requests forwarded by a local reverse proxy. To restrict health endpoints to local probes, block external health requests at the proxy. Forwarded IP headers do not affect this exemption. The Docker health probe continues to work.

qui reads the list once at startup. Restart qui after each change to allowedHosts. The list works together with authentication and the IP allowlist. It blocks DNS rebinding, an attack where a hostname of the attacker points at the address of qui. That hostname is not on the list, so qui rejects the request. It does not block requests that use a listed hostname.

CORS​

By default, qui does not send CORS allow headers. To allow browser requests from another trusted origin, set corsAllowedOrigins (or QUI__CORS_ALLOWED_ORIGINS) to an explicit allowlist:

QUI__CORS_ALLOWED_ORIGINS=https://sso.example.com,https://panel.example.com

Rules:

  • qui allows only explicit origins (http:// or https:// + host + optional non-default port)
  • qui rejects wildcards (*, https://*.example.com, and similar patterns)
  • qui rejects values with a path, query, fragment, or userinfo
  • If a startup value is invalid, qui stops. On live reload, qui logs an invalid value and keeps the running allowlist until a restart.

For SSO proxy setups, configure CORS on the proxy auth endpoints first. See SSO Proxies and CORS.

Example config.toml​

host = "0.0.0.0"
port = 7476
baseUrl = "/qui/"

logLevel = "DEBUG"
logPath = "log/qui.log"
logMaxSize = 50
logMaxBackups = 10

trackerIconsFetchEnabled = false

externalProgramAllowList = [
"/usr/local/bin",
"/home/user/bin/my-script",
]