tobira 0.3.3

A VMess relay written in Rust.
# ─────────────────────────────────────────────────────────────────────────────
# Tobira — VMess relay daemon  example configuration
# ─────────────────────────────────────────────────────────────────────────────

# Tracing filter string, e.g. "info", "debug", "tobira=debug,h2=warn".
# Overridden by the RUST_LOG environment variable.
# Default: "info"
# log_level = "info"

# ── Relay inbound ─────────────────────────────────────────────────────────────
# Accepts plain VMess+TCP connections from clients.
# Hot-reload does NOT restart the listener; changing these fields requires a
# full process restart.
[relay]
# listen = "[::]"   # dual-stack wildcard (IPv4 + IPv6); default when omitted
port = 10808
# network = "tcp"        # default; set to "grpc" for VMess+gRPC h2c inbound
# service_name = "GunService"
# idle_timeout = 0       # seconds; 0 disables relay idle reaping
# grpc_pool_idle_timeout = 300  # seconds; 0 disables cached gRPC H2 idle pruning

# ── HTTP subscription server ──────────────────────────────────────────────────
[http]
# listen = "[::]"   # dual-stack wildcard (IPv4 + IPv6); default when omitted
# port   = 8080     # default when omitted

# Basic Auth users.  Omit the entire [[http.users]] section to allow
# unauthenticated access.
[[http.users]]
username = "alice"
password = "s3cr3t"
# outputs = ["main"]   # restrict to specific outputs; omit for all outputs

[[http.users]]
username = "bob"
password = "hunter2"

# Subscription output endpoints.
# Each entry exposes:
#   GET /sub/<name>         → v2rayN base64-JSON links
#   GET /sub/<name>/base64  → same
#   GET /sub/<name>/url     → standard URL-format links
#
# The relay address (host/port) is rewritten into every link so clients
# connect to this relay.  UUID and encryption are kept from the source nodes.
# Transport follows [relay].network. TLS is derived from it: tcp => none,
# grpc => tls. The gRPC service name follows [relay].service_name.
[[http.outputs]]
name = "main"
host = "relay.example.com"
port = 10808
# sni = "relay.example.com"  # optional; emitted only for grpc/tls client links
# skip-cert-verify = false    # optional; for grpc/tls client links with self-signed certs

# Per-output processing pipeline (applied after the source-level pipeline).
# Steps run in order; each step selects nodes by name/source then acts on them.
#
# Selection fields (AND logic; empty list = match all):
#   filter        — regex list matched against node name
#   filter_source — regex list matched against subscription source name
#   invert        — invert the selection
#
# Action fields (applied to selected nodes):
#   remove            — remove selected nodes from the list
#   rename            — [[pattern, replacement], …]  regex rename on node name
#   remove_emoji      — strip emoji characters from node name
#   override_security — replace VMess encryption algorithm on selected nodes

# Example: remove nodes from the "free" source, keep only premium nodes,
# strip emoji, and force a specific encryption.
# [[http.outputs.process]]
# filter_source = ["free_sub"]
# remove        = true
#
# [[http.outputs.process]]
# filter  = ["(?i)premium"]
# invert  = true        # select non-premium
# remove  = true        # remove them
#
# [[http.outputs.process]]
# remove_emoji = true
#
# [[http.outputs.process]]
# override_security = "aes-128-gcm"

# Second output on a different address/port — useful for multiple inbound IPs.
# [[http.outputs]]
# name = "backup"
# host = "relay2.example.com"
# port = 10808

# ── Subscription sources ──────────────────────────────────────────────────────
[subscription]
cache_file      = "cache.json"  # persist parsed nodes; used as fallback on fetch failure
update_interval = 3600          # re-fetch all sources every hour (0 = disabled)
                                # does NOT re-read config.toml — use SIGUSR1 for that

# Deduplication strategy for nodes with the same name across all sources.
# Applied after all source-level pipelines, when merging nodes from all sources.
#
#   "rename" (default)        — keep all; append " (1)", " (2)" suffixes to duplicates
#   "first"                   — keep the first occurrence
#   "last"                    — keep the last occurrence
#   "prefer_ipv4"             — IPv4 > Domain > IPv6
#   "prefer_ipv6"             — IPv6 > Domain > IPv4
#   "prefer_domain_then_ipv4" — Domain > IPv4 > IPv6
#   "prefer_domain_then_ipv6" — Domain > IPv6 > IPv4
#
# deduplication = "rename"

[[subscription.sources]]
name       = "main"
url        = "https://example.com/sub?token=abc123"
user_agent = "clash-verge/1.0"   # optional; omit to use the default reqwest UA

# Per-source processing pipeline — runs immediately after parsing this source.
# Same step syntax as [[http.outputs.process]] above.

# Example: remove expired/trial nodes, then strip emoji from names.
# [[subscription.sources.process]]
# filter = ["(?i)expired|trial"]
# remove = true
#
# [[subscription.sources.process]]
# remove_emoji = true
# rename       = [["^🇺🇸\\s*", "US "], ["^🇭🇰\\s*", "HK "]]

# [[subscription.sources]]
# name = "backup_sub"
# url  = "https://backup.example.com/sub"