Configuration
Risuko configuration reference — all available options.
Risuko stores configuration in two JSON files in the config directory:
system.json— Engine options such asdir,split,doh-*, andrpc-secretuser.json— App preferences plus a fixed set of user-scope engine keys
The desktop app creates both files on first run. The CLI and Node.js API never create them; missing files or keys fall back to built-in defaults in memory.
The engine does not merge the two files wholesale. It starts from system.json, copies only the user-scope keys from user.json, then applies engine-overrides. Any other key in user.json is ignored by the engine, even if it has the same name as an engine option.
User Config
These user.json keys override system.json when the engine starts:
rpc-host, m3u8-output-format, keep-seeding, bt-create-subfolder, bt-enable-upnp, bt-upnp-lease, bt-encryption-policy, bt-listen-v6, bt-enable-lsd, purge-record-on-start, task-routing-rules, file-category-dirs, max-worker-retries, usenet-profiles, usenet-archive-limits, usenet-cleanup-mode, pbh-enable, pbh-listen-port, pbh-rpc-secret, and proxy (flattened into all-proxy / p2p-*).
| Key | Default | Description |
|---|---|---|
engine-overrides | — | Object of arbitrary engine keys applied on top of the global options at startup, so backend options work without a dedicated form field. Keys starting with rpc- or ending in -port or -secret are skipped; a non-object value is ignored with a warning |
Config Directory Locations
| Environment | Path |
|---|---|
| macOS | ~/Library/Application Support/<name> |
| Linux | $XDG_CONFIG_HOME/<name> (~/.config/<name> when unset) |
| Windows | %APPDATA%\<name> |
<name> depends on the host:
| Host | Directory name |
|---|---|
| Desktop app | app.risuko.Risuko |
Headless mode of the app binary (risuko serve, risuko download and similar) | app.risuko.Risuko, same as the desktop app; falls back to the legacy dev.risuko.app only when app.risuko.Risuko does not exist and dev.risuko.app does |
Standalone risuko CLI and Node.js API | app.risuko.Risuko on a fresh install; an existing legacy dev.risuko.app directory wins, so older installs keep their config and session. EngineConfig.configDir overrides it in Node.js |
The standalone CLI and Node.js API therefore share the desktop app's directory on fresh installs, but keep using dev.risuko.app if it already exists.
Reading Configuration
CLI
# List all settings
risuko config list
# Get a specific value
risuko config get dir
# JSON output
risuko config list --jsonNode.js
import risuko from "@risuko/risuko-js";
const options = await risuko.getGlobalOption();
console.log(options.dir);
console.log(options["max-concurrent-downloads"]);Writing Configuration
CLI
# User-scope keys can be set directly
risuko config set rpc-host 0.0.0.0
risuko config set keep-seeding true
# Engine keys go through engine-overrides (replaces the whole object)
risuko config set engine-overrides '{"dir":"/home/user/downloads","max-concurrent-downloads":5}'Values are parsed as JSON; anything that isn't valid JSON is stored as a plain string.
risuko config set always writes user.json. Setting an engine key such as dir or max-concurrent-downloads directly has no effect on the engine, although config get and config list (which layer user.json over system.json) will show the new value. Use engine-overrides, or edit system.json for the keys it skips (such as rpc-secret and rpc-listen-port).
Node.js
import risuko from "@risuko/risuko-js";
await risuko.changeGlobalOption({
dir: "/home/user/downloads",
"max-concurrent-downloads": "5",
});changeGlobalOption changes the running engine only; nothing is written to the config files, so the values are lost at stopEngine.
Option Reference
General
| Key | Default | Description |
|---|---|---|
dir | OS default | Default download directory |
max-concurrent-downloads | 5 | Maximum active non-torrent download workers. The desktop app can raise this up to 10; the engine uses the value directly and preempts lower-priority non-torrent tasks back to waiting when the queue order requires it |
continue | — | Removed. Still accepted but has no effect; interrupted downloads always resume |
pause | false | Per-task: add a non-torrent task in the paused state |
purge-record-on-start | false | When the engine starts, drop completed/stopped task records from the session and clear desktop download-history stats. On-disk files for stopped torrent tasks are preserved (the orphan-purge step is told to keep files for those info-hashes); HTTP/FTP/etc. payloads on disk are never touched |
Desktop App
These keys are read by the Tauri desktop app. They are stored in user.json
and are not part of the engine's JSON-RPC surface.
| Key | Default | Description |
|---|---|---|
auto-check-update | false | Automatically check the Tauri updater endpoint for signed release updates. Desktop-only and opt-in on every platform |
last-check-update-time | 0 | Last update-check timestamp recorded by the app |
legal-accepted | false | First-launch Terms/Privacy acceptance flag; device-local and excluded from cloud sync |
clipboard-watch | true on desktop | Watch the clipboard for download links and show a prompt. Not created on Android |
clipboard-watch-extensions | archive, installer, media, document, .torrent, meta4, metalink extensions | HTTP(S) file extensions that trigger the clipboard prompt. Protocol links such as magnet, ED2K, FTP/SFTP, M3U8, and thunder:// do not need an extension match |
clipboard-watch-notice-seen | false on desktop | Device-local flag for the one-time clipboard-watch notice |
Connection
| Key | Default | Description |
|---|---|---|
split | 16 | Connections per download (HTTP/HTTPS); ignored when the file is smaller than min-split-size or the server doesn't support Range |
max-connection-per-server | split | Cap on connections to one server per download (aria2-compatible) |
max-worker-retries | 5 | Retries per HTTP segment worker before the task fails (user.json) |
min-split-size | 1M | Minimum segment size before the file is split (bytes; accepts K/M/G suffixes) |
Speed Limiting
| Key | Default | Description |
|---|---|---|
max-overall-download-limit | 0 | One overall download budget (bytes/s, 0 = unlimited) shared by HTTP/FTP/SFTP/HLS, BitTorrent, ED2K, and Usenet. Applied live to running downloads, no restart needed |
max-overall-upload-limit | 0 | Overall upload cap (bytes/s, 0 = unlimited), enforced for BitTorrent uploads. Combined with bt-upload-rate-limit: the smaller non-zero value wins. Applied live |
max-download-limit | 0 | Per-task download speed limit (bytes/s). Applies to HTTP, m3u8, FTP, torrent, ED2K, and Usenet downloads; retuned live by changeOption |
max-upload-limit | 0 | Per-task upload speed limit (bytes/s) for torrents; retuned live by changeOption |
HTTP
| Key | Default | Description |
|---|---|---|
user-agent | Chrome UA string | Default user agent string |
referer | — | Default HTTP referer |
header | — | Default HTTP headers (array) |
load-cookies | — | Path to a Netscape/Mozilla format cookies.txt (also accepts curl/wget output) loaded into the per-task cookie jar |
cookie | — | Per-task cookie string sent as a Cookie header |
checksum | — | Per-task whole-file checksum <algo>:<hex> (sha-256, sha-1, or md5; aria2's checksum= prefix is accepted), verified on completion |
netrc-path | ~/.netrc (%USERPROFILE%\_netrc on Windows) | Override the .netrc file used to inject HTTP Basic auth when a URL has no embedded credentials |
no-netrc | false | Skip .netrc lookup entirely |
Proxy
See the Proxy Support guide for URL schemes, scopes, and bypass syntax.
| Key | Default | Description |
|---|---|---|
all-proxy | — | HTTP-profile proxy server URL derived from proxy.http. Accepts http://, socks5://, or socks5h://. Used for HTTP/HTTPS, Metalink, HLS, yt-dlp, FTP/FTPS/SFTP, and Usenet when the Download scope is selected |
no-proxy | — | Bypass list for all-proxy, one entry per line (comma-separated also accepted). Accepts hosts (example.com, matching subdomains too), host:port, IP literals, CIDR ranges (10.0.0.0/8), and * to bypass everything. Matching is case-insensitive; localhost, *.localhost, and loopback addresses are always bypassed. Unparseable entries are dropped |
p2p-proxy | — | P2P TCP proxy URL derived from proxy.p2p. Same schemes as all-proxy. Used for BitTorrent TCP peers and HTTP tracker announces, eD2K TCP, Gnutella, G2, and giFT |
p2p-no-proxy | — | Bypass list for p2p-proxy (same syntax as no-proxy) |
p2p-udp-proxy | — | Optional P2P UDP proxy URL. When empty, UDP traffic reuses p2p-proxy. SOCKS5/SOCKS5H is required for DHT, UDP trackers, µTP, and Kad; an HTTP proxy cannot carry UDP |
p2p-udp-no-proxy | — | Bypass list for p2p-udp-proxy |
proxy | nested object | Desktop/UI preference. Canonical shape is { http: { enable, server, bypass, scope }, p2p: { enable, server, bypass, udp: { server, bypass } } }. The engine reads the flattened keys above |
DNS over HTTPS
When enabled, hostnames are resolved by POSTing RFC 8484 wire-format queries
(application/dns-message) to a DoH endpoint instead of using the system
resolver. A and AAAA records are queried together and the answers cached in
memory (smallest record TTL, clamped to 30–3600 s, plus a 5 s negative cache).
This applies to every HTTP client in the engine — downloads, m3u8 segments, RSS, WebDAV/S3 uploads, BitTorrent HTTP trackers, and UPnP. It does not cover BitTorrent UDP trackers/DHT or FTP/SFTP/ED2K/ADC connections, which still resolve through the system. SOCKS5h proxies keep resolving names proxy-side.
| Key | Default | Description |
|---|---|---|
doh-enable | false | Route DNS lookups over HTTPS. Only takes effect when doh-url is also set |
doh-url | — | DoH endpoint URL. Must be https:// (e.g. https://cloudflare-dns.com/dns-query) |
doh-bootstrap | — | Comma/space/newline-separated IPs used to reach the endpoint host without a system-DNS lookup. Entries that don't parse as an IP are dropped. When empty, the endpoint host is resolved via the system resolver |
doh-fallback | true | When a DoH query fails (timeout, network error, SERVFAIL), fall back to the system resolver instead of failing the connection. An NXDOMAIN or NODATA answer is final and does not fall back |
doh-provider | cloudflare | UI-only preference (user.json). The desktop app's provider dropdown (cloudflare, google, quad9, custom); selecting a preset fills doh-url and doh-bootstrap automatically. Not read by the engine |
DoH settings are hot-reloaded — changing any doh-* key takes effect on the
next connection without an engine restart.
Reliability
| Key | Default | Description |
|---|---|---|
connect-timeout | 60 | Connect timeout in seconds for HTTP/HTTPS downloads and NZB URL fetches. FTP/SFTP do not read it |
nzb-body-timeout | 30 | Maximum idle time in seconds between chunks while fetching an NZB URL body; applies only to URL-based NZB ingestion |
lowest-speed-limit | 0 | Stalled-transfer threshold in bytes/s. If the EMA stays below this for lowest-speed-limit-timeout, the worker is aborted (and restarted when auto-retry is enabled). 0 disables the watchdog |
lowest-speed-limit-timeout | 30 | How many seconds the transfer must stay below lowest-speed-limit before it is considered stalled |
auto-retry | false | Desktop app (user.json): automatically retry errored tasks |
auto-retry-interval | 5 | Desktop app: base retry delay in seconds (1–300) |
auto-retry-strategy | static | Desktop app: static (fixed delay) or exponential |
uri-selector | feedback | Mirror selection strategy when a task has multiple URIs: feedback (drop slow/failing mirrors), inorder (try left-to-right), or adaptive (prefer fastest) |
Low-Speed Auto-Recovery
A separate watchdog from lowest-speed-limit. The renderer's EngineClient
samples active task speeds, and any task whose downloadSpeed stays under
low-speed-threshold for 5 consecutive polling ticks is force-paused and
resumed (with a 30-second per-task cooldown between recovery cycles).
| Key | Default | Description |
|---|---|---|
auto-detect-low-speed-tasks | false | Master switch. When false, the recovery loop never runs |
low-speed-threshold | 20 | Speed threshold in KB/s below which a task counts toward the strike count |
Pause/resume only revives a single stalled TCP connection — useful for
HTTP/HTTPS, FTP/SFTP, and HTTP-segment streams (m3u8, media/yt-dlp).
Peer-swarm protocols (BitTorrent, ED2K, ADC, Gnutella, G2, giFT) are
explicitly excluded from this recovery: pause tears down peer
connections, aborts in-flight tracker announces and choke negotiations, and
the swarm spends minutes warming up again. Tasks whose kind is not in
{http, ftp, media, m3u8}, or whose kind is missing, are skipped.
Storage
| Key | Default | Description |
|---|---|---|
file-allocation | falloc (none on Android) | Disk reservation strategy. falloc reserves real blocks via fallocate(2) (Linux) or fcntl(F_PREALLOCATE) (macOS), falling back to set_len. trunc only sets the file length. none lets writes grow the file as needed. The aria2 alias prealloc is accepted as a synonym for falloc |
auto-file-renaming | true | When the target output file already exists, rename to name.1.ext, name.2.ext, … instead of overwriting |
remote-time | false | Stamp the local file mtime from the server's Last-Modified header on completion (per-task) |
use-remote-file-time | — | UI/global preference mirrored into per-task remote-time when set |
m3u8-output-format | ts | Container produced after concatenating HLS segments (ts keeps the original transport stream; other values trigger a remux) |
file-category-dirs | — | Per-category default directory overrides (object keyed by category id, e.g. { "video": "/downloads/video" }); applied as a fallback when no routing rule matches |
BitTorrent
| Key | Default | Description |
|---|---|---|
keep-seeding | false | Seed until manually stopped (overrides seed-time / seed-ratio) |
seed-ratio | 0 | Stop seeding at this ratio. 0 disables this goal; if both goals are 0 and keep-seeding is off, torrents stop at completion |
seed-time | 0 | Seed for this many minutes after completing. 0 disables this goal |
bt-tracker | — | Additional tracker URLs (comma- or newline-separated) |
select-file | — | Per-task: 1-based indices of the files to download, with aria2-style ranges such as 1-3,7. Padding files are not counted. Applied live via changeOption. See file selection |
bt-max-peers-per-torrent | 100 | Max concurrent peer connections per torrent (engine restart) |
bt-max-outstanding-per-peer | 0 | Per-peer pipelined chunk-request cap (engine restart); 0 uses adaptive control starting at 6 and growing up to 500, while an explicit value is capped at 500 |
bt-max-connections | 400 | Total peer connections plus pending dials across all torrents (integer 20-5000; Preferences -> Advanced -> BitTorrent -> Max Peer Connections). Applied live, no engine restart. The effective value is capped at half the process file-descriptor soft limit, which the app raises at startup (to 8192 where the OS allows), so 400 is normally effective. Lowering it never drops open connections; it only holds back new ones. A small reserve (8 slots or 2%, at most a quarter of the cap) is kept for magnet metadata fetches, which count against the budget and wait for a slot instead of failing. Synced in the bittorrent category |
bt-upload-rate-limit | 0 | BitTorrent upload rate cap in bytes/s (0 = unlimited); accepts size suffixes such as 512K. The effective cap is the smaller non-zero of this and max-overall-upload-limit. Applied live |
bt-ban-corrupt-peers | true | Ban peers that send data failing piece hash checks (engine restart). false disables bans |
bt-ban-corrupt-strikes | 3 | Failed pieces attributed to one peer before its IP is banned for the rest of the session in every torrent (engine restart; the app UI accepts 1-100). Only used while bt-ban-corrupt-peers is on |
bt-enable-upnp | true | Map the listen port on the router via UPnP IGD (engine restart) |
bt-upnp-lease | 300 | UPnP mapping lease in seconds (engine restart) |
bt-enable-lsd | true | BEP-14 Local Service Discovery via multicast (engine restart) |
bt-encryption-policy | prefer | MSE/PE policy: plaintext, prefer, or require (engine restart) |
bt-listen-v6 | false | Also bind an IPv6 TCP listener on the same port (engine restart) |
ed2k-port | 4662 | eD2K TCP listen port (engine restart) |
ed2k-server | built-in list | Comma-separated eD2K servers (host:port) |
ed2k-enable-kad | true | Enable client-only eMule Kad source discovery over UDP (engine restart) |
ed2k-kad-port | 4672 | Local Kad UDP port; must be in 1..=65535 (engine restart) |
bt-create-subfolder | true | When true, multi-file torrents and magnets are placed under <dir>/<name>/. When false, files are written directly into dir. Single-file torrents are unaffected. Read on each task add (no restart needed); accepted as a per-task option override |
bt-save-metadata | true | When true and a magnet link is added, the engine resolves the torrent metadata first and writes a synthesized .torrent file to the task's dir before starting the download. Has no effect when adding a .torrent file directly |
The DHT (BEP-5) is always enabled and runs as a dual-stack client when an
IPv6 socket can be bound. The BitTorrent TCP listener binds listen-port
(21301 by default; for a range or list such as 6881-6889 the first port is
used), falling back to a random port if it cannot be bound. dht-listen-port
is not bound by anything yet (the DHT shares the listener's UDP port); it is
only validated by the health check. bt-force-encryption maps to
bt-encryption-policy require when the policy is unset or prefer; an
explicit plaintext or require policy wins. The legacy aria2 keys
enable-dht, enable-dht6, enable-peer-exchange, bt-enable-lpd (use
bt-enable-lsd), bt-exclude-tracker, follow-torrent, allow-overwrite, and
continue have been removed from the engine defaults because nothing read
them. They are still accepted if a client or saved config sends them, but have
no effect, and continue and follow-torrent are no longer synced.
bt-load-saved-metadata (default
true) makes a magnet reuse the .torrent saved by bt-save-metadata
instead of resolving its metadata over the network again.
RPC
| Key | Default | Description |
|---|---|---|
rpc-listen-port | 16800 | RPC server port |
rpc-host | 127.0.0.1 | RPC bind address (set to 0.0.0.0 for LAN access); a user.json key. Also used by the PeerBanHelper listener when that API is enabled |
rpc-secret | generated on first run | RPC authentication token. On first run the engine generates a random 256-bit hex secret and saves it in system.json with an rpc-secret-initialized marker; a secret you later clear on purpose stays cleared. See RPC authentication |
pbh-enable | false | Start a second JSON-RPC listener in Aria2Next compatibility mode so PeerBanHelper can monitor and ban BitTorrent peers (engine restart) |
pbh-listen-port | 16801 | PeerBanHelper RPC port (engine restart). In PeerBanHelper, add an Aria2Next downloader pointed at http://127.0.0.1:<port>/jsonrpc |
pbh-rpc-secret | — | Token required as token:<secret> on the PeerBanHelper listener (engine restart) |
Media (yt-dlp)
| Key | Default | Description |
|---|---|---|
media-format | yt-dlp default | yt-dlp --format selector (e.g. bestvideo+bestaudio/best, mp4). Aliases: youtube-format, yt-format |
media-merge-format | mp4 | Container passed to --merge-output-format when ffmpeg is available. Alias: youtube-merge-format |
RSS
See the RSS Feeds guide for the full workflow. RSS subscriptions, items, and rules are persisted via the desktop app's storage. Each feed is polled on its own interval (default 1800 s, minimum 60 s).
The old rss-auto-update and rss-update-interval keys are no longer used or listed by the app.
Task Routing
See the Task Routing guide.
| Key | Default | Description |
|---|---|---|
task-routing-rules | [] | Array of { id, label, pattern, dir, enabled } rules. The first enabled rule whose case-insensitive glob pattern matches the inferred filename wins; dir overrides the download directory and label is exposed as the task tag. Falls through to file-category-dirs then global dir |
Completion Scripts
Run a script after every download finishes (success or failure). Per-task overrides are accepted via the desktop app's task options. See the Completion Scripts guide.
| Key | Default | Description |
|---|---|---|
completion-script-enabled | false | Master switch. When false, no script runs even if command is set |
completion-script-command | — | Absolute path to the executable to invoke (no shell parsing) |
completion-script-args | — | Whitespace-tokenised arguments template. Supported placeholders inside any token: {path} (final file path), {hash} (BitTorrent info hash; empty for non-torrent tasks), {status} (complete / error). The same values are also exported as RISUKO_PATH, RISUKO_HASH, RISUKO_STATUS env vars |
completion-script-timeout-ms | 30000 | Per-invocation timeout in milliseconds. Clamped to 1000–300000 (5 minutes). stdout/stderr captured into the log are truncated to 8 KiB |
Usenet / NZB
See the Usenet and NZB Downloads guide for the provider setup and recovery workflow. These settings are used for new NZB tasks; task options snapshot the selected profile reference, cleanup policy, and any confirmed archive-limit override.
| Key | Default | Description |
|---|---|---|
usenet-profiles | [] | Non-secret provider profile metadata. Each profile has an ID, name, host, port, security mode, enabled state, priority, connection cap, plain-NNTP opt-in, and update timestamp. Usernames and passwords are kept in the OS keychain. |
usenet-archive-limits | Platform defaults | Task-wide archive and PAR2 safety limits. Desktop defaults: 500,000 entries, 2 TiB total expansion, 512 GiB per entry, depth 16, 1000:1 ratio, 10 GiB reserve, 6 active hours. Android defaults: 100,000, 256 GiB, 64 GiB, depth 16, 1000:1, 2 GiB, 2 active hours. |
usenet-cleanup-mode | keep-all | Successful cleanup policy: keep-all, delete-par2, or delete-par2-and-volumes. delete-par2-and-archives remains accepted as a legacy alias. |
usenet-limits-adjusted | false | Set when a synchronized archive-limit value was invalid or had to be reduced for this device. |
Provider profiles use camel-case fields inside the usenet-profiles array:
[
{
"id": "primary",
"name": "Primary provider",
"host": "news.example.net",
"port": 563,
"securityMode": "implicit-tls",
"enabled": true,
"priority": 0,
"maxConnections": 4,
"allowPlain": false,
"updatedAt": 1765000000000
}
]Valid securityMode values are implicit-tls, starttls, and plain.
Plain NNTP also needs allowPlain: true; the app requires a separate user
acknowledgement before it saves that state. Lower priority values run first.
The following option keys may be set through risuko.addNzb. The current Add
Task form uses the global Usenet archive policy and does not expose per-task
archive controls yet:
| Key | Description |
|---|---|
usenet-profile-id | Restrict the task to one configured provider profile. Omit it to use the enabled provider pool. |
usenet-cleanup-mode | Override the global cleanup policy for this task. |
usenet-archive-limits | Object with any of maxEntries, maxExpandedBytes, maxEntryBytes, maxNestingDepth, maxCompressionRatio, freeSpaceReserveBytes, and maxActiveSeconds. |
usenet-archive-limit-override-confirmed | Required when a per-task override raises an enforced safety limit above its platform default. |
Task options must not include a username, password, archive password, or credential-bearing provider object. Risuko removes those values before it saves the task or returns it through RPC.
Saved Credentials
| Key | Default | Description |
|---|---|---|
saved-credentials | [] | Non-secret credential profile metadata (id, label, scope, username). Passwords and SSH private keys are stored separately in the OS keychain (risuko-credentials service) and never written to user.json |
Legacy P2P / IPC stacks
| Key | Default | Description |
|---|---|---|
gift-enabled | false | Allow gift:// URIs to be forwarded to a local giftd daemon. Shown in Preferences -> Advanced next to the legacy protocol toggles; once enabled and a giftd is reachable, gift:// links work |
gift-host | 127.0.0.1 | giFT daemon host (also in Preferences -> Advanced) |
gift-port | 1213 | giFT IPC port (also in Preferences -> Advanced) |
The old adc-hub, adc-nick, gnutella-cache, and g2-cache keys are no longer listed by the app and nothing reads them. Gnutella and G2 downloads connect directly to the peer in the URI, and ADC / DC transfers are not implemented.
External Engine
By default the desktop app boots an embedded engine in-process. Switch to
External Engine mode to point the UI at a separately running
risuko serve (or any aria2-compatible RPC server). When enabled, the
embedded engine is not started; all add_uri, polling, and config writes
are routed over JSON-RPC.
| Key | Default | Description |
|---|---|---|
external-engine-enabled | false | Skip the embedded engine and connect to a remote RPC server instead |
external-engine-host | — | Hostname or IP of the remote RPC server |
external-engine-port | 16800 | Port of the remote RPC server |
external-engine-secret | — | Token to send as token:<secret> on each call |
Logging
| Key | Default | Description |
|---|---|---|
log-dir-override | "" | Override the directory where rolling log files are written. Must be an absolute path to a writable directory. When empty (the default), logs go to the OS-specific app log directory. Useful on Android to redirect logs to a publicly accessible path |
log-level | warn | Verbosity of the tracing subscriber. One of error, warn, info, debug, trace (these are tracing_subscriber::EnvFilter directives). Takes effect only after an app restart, because the subscriber is initialised once at startup |
Startup-only Keys
The following keys are read once when the engine starts. Changing them at
runtime is accepted (the value is persisted) but does not take effect
until the engine is restarted (Quit & relaunch the desktop app, or restart
risuko serve):
dht-listen-port, ed2k-enable-kad, ed2k-kad-port, ed2k-port, listen-port, rpc-host, rpc-listen-port,
rpc-secret, pbh-enable, pbh-listen-port, pbh-rpc-secret,
bt-max-peers-per-torrent, bt-max-outstanding-per-peer,
bt-ban-corrupt-peers, bt-ban-corrupt-strikes, bt-enable-upnp, bt-upnp-lease, bt-enable-lsd,
bt-encryption-policy, bt-listen-v6.
All other keys are hot-reloaded on the next task or polling cycle.