Top level and common
Generated by website/scripts/build-config.mjs; do not edit. It reads sail’s configuration types (its Rust source), sing-box’s field registry (sail/src/config/singbox/fields.json, sing-box v1.14.2) and the tiers the registry test measured (fields.tiers.json). Change the source comments or those files, then run npm run docs:config in website/.
- Status: each sing-box field as the registry test measured it: Supported (read and acted on; a value sail cannot take is still an error), Warned (dropped with a warning) or Error (the configuration is refused), with the reason; sail extension marks fields and types sing-box does not have.
- Type: sing-box’s JSON type for its fields; from sail’s Rust definitions for extensions.
- Default: from sail’s serde declarations; unset means the field may be left out, and the description says what applies then. Only fields sail reads have one.
- Description: sail’s source comments, in their source language; for an extension without one, the registry test’s note.
- Build: the
cfgconditions in the Rust source (Cargo features and platforms).
Validate a configuration with sail -c config.json -T. Editors check and complete it by the JSON schema: put "$schema": "https://peakpassvpn.github.io/sail/schema.json" at its top (made by the same generator; a field sail refuses is marked not allowed, one it warns of deprecated). The Clash and Surge support tables are under Compatibility.
Top level
Section titled “Top level”Rust: Config
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
$schema |
string | — | Supported | — |
log |
object → object | each field’s default | Supported | — |
dns |
object → object | each field’s default | Supported | — |
ntp |
object → object | unset | Supported | The time the protocols that check it go by, and certificates are verified at, measured against an NTP server; the system’s clock is never set. |
certificate |
object → object | unset | Supported | The root certificates servers are checked against; the system’s when unset. |
certificate_providers |
array → [], [acme], [cloudflare-origin-ca], [tailscale] | — | Error: Certificates from ACME and other providers: the inbounds would serve none | — |
http_clients |
array → [] | [] |
Supported | How sail fetches over HTTP, rule-sets for one, by tag. |
network_namespaces |
array → [], [unshare] | — | Error: Linux network namespaces to listen and dial in | — |
endpoints |
array → [], [openconnect], [openvpn-client], [openvpn-server], [tailscale], [wireguard] | [] |
Supported | Both an inbound and an outbound under one tag, as sing-box’s endpoints: connections routed to the tag go out through it, and what comes in through it is routed with the tag as its inbound. |
inbounds |
array → [], [anytls], [cloudflared], [direct], [hc], [http], [hysteria], [hysteria2], [mixed], [mptp], [naive], [nf], [redirect], [shadowsocks], [shadowtls], [snell], [socks], [tproxy], [trojan], [tuic], [tun], [vless], [vmess] | [] |
Supported | — |
outbounds |
array → [], [anytls], [block], [bridge], [direct], [fallback], [http], [hysteria], [hysteria2], [load-balance], [mptp], [naive], [network], [pass], [plugin], [redirect], [selector], [shadowsocks], [shadowtls], [smart], [snell], [socks], [ssh], [tor], [trojan], [tryall], [tuic], [urltest], [vless], [vmess] | [] |
Supported | — |
route |
object → object | each field’s default | Supported | — |
services |
array → [], [api], [ccm], [derp], [hysteria-realm], [ocm], [oom-killer], [resolved], [ssm-api], [usbip-client], [usbip-server] | — | Supported | — |
experimental |
object → object | each field’s default | Supported | — |
api |
object → object | unset | sail extension | The control API |
clash_api |
object → object | unset | sail extension | The Clash API, which dashboards (yacd, metacubexd) and clients control the instance through. sing-box has it under experimental, which is read too, as the same. |
outbound_providers |
array of object → [] | [] |
sail extension | A sail extension: outbounds given together, downloaded, read from a file or written in place, that groups take as members, as Mihomo’s proxy groups take a proxy-provider’s proxies. |
user_limits |
object of object → object | {} |
sail extension | A sail extension: what each user, by name, may do across every inbound it is in. |
user_limits
Section titled “user_limits”Rust: UserLimits · sail extension
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
max_connections |
number | unset | sail extension | How many connections it may have live at once. |
quota_bytes |
number | unset | sail extension | How many bytes, up and down together, it may send and receive; kept across restarts in the cache file, which it needs. |
expire_at |
string | unset | sail extension | When it may no longer connect, in RFC 3339. |
up_mbps |
number | unset | sail extension | Its rate up, what its clients send, in Mbps: the unit of sing-box’s Hysteria2 up_mbps, not its direction. |
down_mbps |
number | unset | sail extension | Its rate down, what its clients receive, in Mbps. |
Rust: Log
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
disabled |
bool | false |
Supported | Logs nothing. |
level |
string, one of trace, debug, info, warn, warning, error, fatal, panic |
info |
Supported | — |
output |
string | unset | Supported | A file to append to. Logs go to the console when it is not set. |
timestamp |
bool | false |
Supported | Starts each line with the time. |
format |
string, one of full, compact |
full |
sail extension | A sail extension: compact writes the message alone. |
redact |
array of string, one of destination, source, process |
[] |
sail extension | A sail extension: what lines at INFO, WARN and ERROR leave out. DEBUG and TRACE lines are not redacted. |
certificate
Section titled “certificate”Rust: CertificateOptions
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
store |
string, one of system, mozilla, chrome, none |
system |
Supported | — |
certificate |
listable-string | [] |
Supported | Inline PEM, its lines one to an entry or all in one. |
certificate_path |
listable-string | [] |
Supported | — |
certificate_directory_path |
listable-string | [] |
Supported | Directories, every file of which holds certificates. |
http_clients[]
Section titled “http_clients[]”Rust: HttpClient
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
tag |
string | "" |
Supported | Of one in http_clients; none inline. |
engine |
string, one of go, apple |
unset | Supported | Whose client sing-box downloads with: go, its own, when unset, or apple, NSURLSession. sail downloads with its own either way, and warns of apple. |
version |
number, one of 0, 1, 2, 3 |
unset | Supported | The HTTP version sing-box asks for, 1, 2 or 3; 2 when unset (or 0). sail downloads over HTTP/1.1 whichever, as sing-box does from a server that speaks no other: a download is the same download. |
disable_version_fallback |
bool | false |
Supported | version alone, never HTTP/1.1 in its place: warned of with 2 or 3, as sail downloads over HTTP/1.1. |
headers |
map | {} |
Supported | Sent with each request, over sail’s own of the same name. |
tls |
object → object | — | Error: TLS options of an HTTP client’s own: its downloads would be checked otherwise | — |
detour |
string | unset | Supported | The outbound to dial through, in place of a socket of its own. |
bind_interface |
string | unset | Supported | The interface to send through, by name. Loopback destinations still go over loopback, where sing-box applies the bind to them as well. |
inet4_bind_address |
string | unset | Supported | The local address for IPv4 destinations, loopback ones aside: as bind_interface. |
inet6_bind_address |
string | unset | Supported | The local address for IPv6 destinations, loopback ones aside: as bind_interface. |
bind_address_no_port |
bool | false |
Supported | IP_BIND_ADDRESS_NO_PORT on TCP sockets bound to an address, so that the port is picked at connect: Linux only. |
protect_path |
string | unset | Supported | A Unix socket each socket’s descriptor is handed to, with SCM_RIGHTS, before it binds or connects, for the process there to protect it (from its VPN, say); it answers one byte. Besides what the host protects. Unix only. |
routing_mark |
number|string | unset | Supported | SO_MARK, Linux only. |
reuse_addr |
bool | false |
Supported | SO_REUSEADDR, and SO_REUSEPORT on Unix, on UDP sockets. |
netns |
string | — | Error: Linux network namespaces: sockets would leave another way | Not implemented yet. |
connect_timeout |
duration | unset | Supported | How long a TCP connect to one address may take; 5s when unset. |
tcp_fast_open |
bool | false |
Supported | TCP Fast Open: the first data written goes with the SYN. Its addresses are then tried one by one, not raced. |
tcp_multi_path |
bool | — | Warned: Socket tuning: connections go the same way without it | Not implemented yet. |
disable_tcp_keep_alive |
bool | false |
Supported | No TCP keepalive at all. |
tcp_keep_alive |
duration | unset | Supported | How long a TCP connection is idle before keepalive probes it; 5m when unset. |
tcp_keep_alive_interval |
duration | unset | Supported | Between keepalive probes; 75s when unset. |
udp_fragment |
bool | unset | Supported | Whether UDP datagrams may be fragmented on the way; unset, as the place says, see udp_fragment_default. |
domain_resolver |
string|object → object | unset | Supported | The DNS server that resolves the names dialled. |
network_strategy |
string, one of default, fallback, hybrid |
unset | Supported | Which of the host’s interfaces a connection goes out of, and how they race; default where only types are given. Only where the host lists its interfaces (NetworkState::interfaces). |
network_type |
listable-string, one of cellular, ethernet, other, wifi |
[] |
Supported | The types of interface the strategy goes out of first. |
fallback_network_type |
listable-string, one of cellular, ethernet, other, wifi |
[] |
Supported | The types it falls back to, with fallback. |
fallback_delay |
duration | unset | Supported | How long the addresses of one family are tried before those of the other are raced against them (Happy Eyeballs), and the first interfaces before the fallback ones; 300ms when unset. |
idle_timeout |
duration | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
keep_alive_period |
duration | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
stream_receive_window |
number|string | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
connection_receive_window |
number|string | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
max_concurrent_streams |
number | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
initial_packet_size |
number | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
disable_path_mtu_discovery |
bool | — | Warned: HTTP/2 and HTTP/3 tuning: a download over HTTP/1.1 is the same download | — |
domain_strategy |
string | unset | Supported (deprecated in sing-box) | sing-box’s deprecated field for the families names resolve to, which a resolver’s own strategy goes before. |
Rust: Ntp
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
enabled |
bool | false |
Supported | — |
interval |
duration | unset | Supported | How often the offset is measured again; 30m when unset. |
write_to_system |
bool | false |
Supported | Setting the system’s clock, which sail never does: an error. |
server |
string | unset | Supported | The server’s name or address. |
server_port |
number | unset | Supported | 123 when unset. |
detour |
string | unset | Supported | The outbound to dial through, in place of a socket of its own. |
bind_interface |
string | unset | Supported | The interface to send through, by name. Loopback destinations still go over loopback, where sing-box applies the bind to them as well. |
inet4_bind_address |
string | unset | Supported | The local address for IPv4 destinations, loopback ones aside: as bind_interface. |
inet6_bind_address |
string | unset | Supported | The local address for IPv6 destinations, loopback ones aside: as bind_interface. |
bind_address_no_port |
bool | false |
Supported | IP_BIND_ADDRESS_NO_PORT on TCP sockets bound to an address, so that the port is picked at connect: Linux only. |
protect_path |
string | unset | Supported | A Unix socket each socket’s descriptor is handed to, with SCM_RIGHTS, before it binds or connects, for the process there to protect it (from its VPN, say); it answers one byte. Besides what the host protects. Unix only. |
routing_mark |
number|string | unset | Supported | SO_MARK, Linux only. |
reuse_addr |
bool | false |
Supported | SO_REUSEADDR, and SO_REUSEPORT on Unix, on UDP sockets. |
netns |
string | unset | Supported | Not implemented yet. |
connect_timeout |
duration | unset | Supported | How long a TCP connect to one address may take; 5s when unset. |
tcp_fast_open |
bool | false |
Supported | TCP Fast Open: the first data written goes with the SYN. Its addresses are then tried one by one, not raced. |
tcp_multi_path |
bool | unset | Supported | Not implemented yet. |
disable_tcp_keep_alive |
bool | false |
Supported | No TCP keepalive at all. |
tcp_keep_alive |
duration | unset | Supported | How long a TCP connection is idle before keepalive probes it; 5m when unset. |
tcp_keep_alive_interval |
duration | unset | Supported | Between keepalive probes; 75s when unset. |
udp_fragment |
bool | unset | Supported | Whether UDP datagrams may be fragmented on the way; unset, as the place says, see udp_fragment_default. |
domain_resolver |
string|object → object | unset | Supported | The DNS server that resolves the names dialled. |
network_strategy |
string, one of default, fallback, hybrid |
unset | Supported | Which of the host’s interfaces a connection goes out of, and how they race; default where only types are given. Only where the host lists its interfaces (NetworkState::interfaces). |
network_type |
listable-string, one of cellular, ethernet, other, wifi |
[] |
Supported | The types of interface the strategy goes out of first. |
fallback_network_type |
listable-string, one of cellular, ethernet, other, wifi |
[] |
Supported | The types it falls back to, with fallback. |
fallback_delay |
duration | unset | Supported | How long the addresses of one family are tried before those of the other are raced against them (Happy Eyeballs), and the first interfaces before the fallback ones; 300ms when unset. |
domain_strategy |
string | unset | Supported (deprecated in sing-box) | sing-box’s deprecated field for the families names resolve to, which a resolver’s own strategy goes before. |
experimental
Section titled “experimental”Rust: Experimental
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
cache_file |
object → object | unset | Supported | — |
clash_api |
object → object | unset | Supported | sing-box’s place for the Clash API: taken to clash_api when the configuration is validated. |
v2ray_api |
object → object | — | Warned: V2Ray’s statistics API, for watching the instance | — |
debug |
object → object | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
experimental.cache_file
Section titled “experimental.cache_file”Rust: CacheFileOptions
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
enabled |
bool | false |
Supported | — |
path |
string | unset | Supported | cache.db when unset. A relative path is in the host’s cache directory, or the data directory. |
cache_id |
string | unset | Supported | What this configuration keeps is kept apart, under this name, from what others sharing the file keep. |
store_fakeip |
bool | false |
Supported | — |
rdrc_timeout |
duration | — | Warned: The cache of the legacy address filter’s rejected responses, which sail does not have; deprecated in sing-box 1.14 | — |
store_dns |
bool | false |
Supported | The DNS answers kept are kept in the file too, and outlive a restart. |
store_rdrc |
bool | — | Warned: The cache of the legacy address filter’s rejected responses, which sail does not have; deprecated in sing-box 1.14 (deprecated in sing-box) | — |
experimental.clash_api
Section titled “experimental.clash_api”Rust: ClashApi
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
external_controller |
string | unset | Supported | Where it listens, host:port; an empty host is every address, as in Mihomo. Unset, it is not served, though default_mode still sets the mode rules match. |
external_ui |
string | unset | Supported | A directory of a dashboard’s files, served at /ui/; relative to the data directory. |
external_ui_download_url |
string | unset | Supported | Where the dashboard is downloaded from, a ZIP, when external_ui is empty. The core has none of its own: unset, nothing is downloaded, and a warning says so; a host, such as sail-cli, may give one. |
external_ui_download_detour |
string | unset | Supported | The outbound the download goes through; the default one when unset. |
secret |
string | unset | Supported | What callers authenticate with, Authorization: Bearer, or a WebSocket’s ?token=. The API is served only with a strong one (at least 32 characters, 10 distinct): sail generate secret makes one. |
default_mode |
string | unset | Supported | The mode rules match at the start, Rule when unset. |
access_control_allow_origin |
listable-string | [] |
Supported | The origins browsers may call it from (CORS); any when empty. |
access_control_allow_private_network |
bool | false |
Supported | Pages on public addresses may call it on a private one (Private Network Access). |
experimental.v2ray_api
Section titled “experimental.v2ray_api”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
listen |
string | — | Warned: V2Ray’s statistics API, for watching the instance | — |
stats |
object → object | — | Warned: V2Ray’s statistics API, for watching the instance | — |
experimental.v2ray_api.stats
Section titled “experimental.v2ray_api.stats”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
enabled |
bool | — | Warned: V2Ray’s statistics API, for watching the instance | — |
inbounds |
array | — | Warned: V2Ray’s statistics API, for watching the instance | — |
outbounds |
array | — | Warned: V2Ray’s statistics API, for watching the instance | — |
users |
array | — | Warned: V2Ray’s statistics API, for watching the instance | — |
experimental.debug
Section titled “experimental.debug”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
listen |
string | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
gc_percent |
number | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
max_stack |
number | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
max_threads |
number | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
panic_on_fault |
bool | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
trace_back |
string | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
memory_limit |
number|string | — | Warned: Go runtime tuning and debugging: sail is not Go | — |
oom_killer |
bool | — | Error: Removed in sing-box 1.13, which refuses it: the oom-killer service took its place | — |
Rust: Api · sail extension
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
path |
string | unset | sail extension | The unix socket the API is served on, in the data directory unless absolute; api.sock there when neither it nor listen is set. |
listen |
string | unset | sail extension | A loopback address the API is served on too, as 127.0.0.1:9091; it takes secret. |
secret |
string | unset | sail extension | What every call carries, as Authorization: Bearer <secret>: one sail generate secret makes. Needed with listen; on the unix socket, checked when set. |
clash_api
Section titled “clash_api”Rust: ClashApi · sail extension
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
external_controller |
string | unset | sail extension | Where it listens, host:port; an empty host is every address, as in Mihomo. Unset, it is not served, though default_mode still sets the mode rules match. |
secret |
string | unset | sail extension | What callers authenticate with, Authorization: Bearer, or a WebSocket’s ?token=. The API is served only with a strong one (at least 32 characters, 10 distinct): sail generate secret makes one. |
external_ui |
string | unset | sail extension | A directory of a dashboard’s files, served at /ui/; relative to the data directory. |
external_ui_download_url |
string | unset | sail extension | Where the dashboard is downloaded from, a ZIP, when external_ui is empty. The core has none of its own: unset, nothing is downloaded, and a warning says so; a host, such as sail-cli, may give one. |
external_ui_download_detour |
string | unset | sail extension | The outbound the download goes through; the default one when unset. |
access_control_allow_origin |
string or array of string | [] |
sail extension | The origins browsers may call it from (CORS); any when empty. |
access_control_allow_private_network |
bool | false |
sail extension | Pages on public addresses may call it on a private one (Private Network Access). |
default_mode |
string | unset | sail extension | The mode rules match at the start, Rule when unset. |
outbound_providers[]
Section titled “outbound_providers[]”Rust: OutboundProvider · sail extension
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
type |
string, one of remote, local, inline |
required | sail extension | — |
tag |
string | required | sail extension | Its members’ keys name it, and groups’ providers. |
url |
string | unset | sail extension | remote: where it is downloaded from. |
path |
string | unset | sail extension | local: the file, in the data directory unless absolute. |
update_interval |
duration | unset | sail extension | remote: how often it is downloaded again, 1d when unset. local: how often the file is read again, never when unset. |
download_detour |
string | unset | sail extension | remote: the outbound it is downloaded through, as a remote rule-set’s. |
http_client |
string or object | unset | sail extension | remote: the HTTP client it is downloaded with, as a remote rule-set’s. |
size_limit |
number | unset | sail extension | remote, a sail extension (Mihomo’s size-limit): the most a download of it may be, in bytes; past it the download fails and the outbounds in use are kept. Unset, the download client’s own cap. |
filter |
string or array of string | [] |
sail extension | remote, local: regular expressions, as Mihomo’s filter; only the outbounds whose names match one are taken, those of the first first. |
exclude_filter |
string or array of string | [] |
sail extension | remote, local: regular expressions no name taken may match. |
exclude_type |
string or array of string | [] |
sail extension | remote, local: the Clash types (ss, vmess, …) not taken, without case. |
override |
object of any JSON | unset | sail extension | remote, local: what is changed in every outbound taken, in the keys of Mihomo’s override (skip-cert-verify, additional-prefix, proxy-name, …). |
detour |
string | unset | sail extension | remote, local: the outbound every outbound taken dials through, as Mihomo’s dialer-proxy. |
outbounds |
array of object → [] | [] |
sail extension | inline: the outbounds, their tags their names as members. |
outbound_providers[].outbounds[]
Section titled “outbound_providers[].outbounds[]”Rust: Outbound · sail extension
| Field | Type | Default | Status | Description |
|---|---|---|---|---|
type |
string | required | sail extension | — |
tag |
string | "" |
sail extension | Defaults to the type. |
certificate_providers[]
Section titled “certificate_providers[]”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
type |
string, one of acme, cloudflare-origin-ca, tailscale |
— | Error: Certificates from ACME and other providers: the inbounds would serve none | — |
network_namespaces[]
Section titled “network_namespaces[]”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
type |
string, one of default, unshare |
— | Error: Linux network namespaces to listen and dial in | — |
tag |
string | required | Error: Linux network namespaces to listen and dial in | — |
path |
string | — | Error: Linux network namespaces to listen and dial in | — |
services[]
Section titled “services[]”| Field | Type | Default | Status | Description |
|---|---|---|---|---|
type |
string, one of api, ccm, derp, hysteria-realm, ocm, oom-killer, resolved, ssm-api, usbip-client, usbip-server |
— | Warned: A service: sail runs none besides its inbounds | — |
Types sail does not implement: certificate_providers
Section titled “Types sail does not implement: certificate_providers”| Type | Status | Fields |
|---|---|---|
certificate_providers[acme] |
Error: Certificates from ACME and other providers: the inbounds would serve none | 122 |
certificate_providers[cloudflare-origin-ca] |
Error: Certificates from ACME and other providers: the inbounds would serve none | 86 |
certificate_providers[tailscale] |
Error: Certificates from ACME and other providers: the inbounds would serve none | 2 |
Types sail does not implement: network_namespaces
Section titled “Types sail does not implement: network_namespaces”| Type | Status | Fields |
|---|---|---|
network_namespaces[unshare] |
Error: Linux network namespaces to listen and dial in | 2 |
Types sail does not implement: services
Section titled “Types sail does not implement: services”| Type | Status | Fields |
|---|---|---|
services[api] |
Warned: sing-box’s gRPC API, for its clients and dashboard to watch and control the instance | 165 |
services[ccm] |
Error: A service: sail runs none besides its inbounds | 84 |
services[derp] |
Error: A service: sail runs none besides its inbounds | 171 |
services[hysteria-realm] |
Error: A service: sail runs none besides its inbounds | 87 |
services[ocm] |
Error: A service: sail runs none besides its inbounds | 84 |
services[oom-killer] |
Error: A service: sail runs none besides its inbounds | 5 |
services[resolved] |
Error: A service: sail runs none besides its inbounds | 15 |
services[ssm-api] |
Error: A service: sail runs none besides its inbounds | 80 |
services[usbip-client] |
Error: A service: sail runs none besides its inbounds | 37 |
services[usbip-server] |
Error: A service: sail runs none besides its inbounds | 21 |