Skip to main content

Node Configuration

Node Configuration​

Set the Variables​

Before creating the configuration files, set up a few variables by running the following commands:

# Define application directory
APP_DIR="${HOME}/.sentinel-dvpnx"

# Get your public IP addresses
MY_IPv4_ADDR=$(curl --silent ipv4.icanhazip.com 2>/dev/null)
MY_IPv6_ADDR=$(curl --silent ipv6.icanhazip.com 2>/dev/null)

REMOTE_ADDRS_FLAGS=""
if [ -n "${MY_IPv4_ADDR}" ]; then
REMOTE_ADDRS_FLAGS="${REMOTE_ADDRS_FLAGS} --node.remote-addrs ${MY_IPv4_ADDR}"
fi
if [ -n "${MY_IPv6_ADDR}" ]; then
REMOTE_ADDRS_FLAGS="${REMOTE_ADDRS_FLAGS} --node.remote-addrs ${MY_IPv6_ADDR}"
fi

# Set Docker volume mapping
VOLUME="${APP_DIR}:/root/.sentinel-dvpnx"

# Set key name for transactions
TX_FROM_NAME="key-1"

# Display configuration for verification
echo "App Directory: $APP_DIR"
echo "Public IPv4: $MY_IPv4_ADDR"
echo "Public IPv6: $MY_IPv6_ADDR"
echo "Key Name: $TX_FROM_NAME"

You should see something like this:

App Directory: /home/<your_user>/.sentinel-dvpnx
Public IPv4: <your_ipv4>
Public IPv6: <your_ipv6>
Key Name: key-1

Initialize the Configuration​

The following command creates the configuration files, which you can later customise.

Be sure to choose your preferred node type using the --node.service-type flag β€” options are amneziawg, hysteria2, openvpn, v2ray, wireguard, or xray.

sudo docker run \
--rm \
--volume "${VOLUME}" \
sentinel-dvpnx init \
--keyring.backend "test" \
--node.service-type "wireguard" \
--tx.from-name "${TX_FROM_NAME}" \
${REMOTE_ADDRS_FLAGS}

Expected output:

Validating configuration
Writing app config file=/root/.sentinel-dvpnx/config.toml
Initializing PKI with CA certificate and key dir=/root/.sentinel-dvpnx
Issuing certificate and key name=tls
Initializing service force=false type=wireguard
Configuration initialized successfully
note

Re-running init won't overwrite an existing configuration unless you pass --force. You can also skip parts of initialization with --skip-tls (don't generate the API TLS certificate) or --skip-service (don't write the service-specific config). Besides the files listed below, init also writes the API TLS material (tls.crt, tls.key) and a local session database (data.db) under ${APP_DIR}.

The created files are:​

Main configuration file: ${APP_DIR}/config.toml

config.toml

# Keyring Configuration
[keyring]

# Storage backend for managing cryptographic keys and sensitive data.
# Different backends offer varying levels of security and OS integration.
# Allowed: file, kwallet, memory, os, pass, test
# Example: "file"
backend = "test"

# Unique identifier name for the keyring instance to distinguish it from other keyrings.
# Used internally to organize and retrieve stored cryptographic keys and credentials.
# Allowed: Any string
# Example: "my-node-keyring"
name = "sentinel"

# Query Configuration
[query]

# Whether to get cryptographic proofs for query results and verify the proof for data authenticity.
# Proofs increase security but add network overhead and processing time.
# Allowed: true, false
# Example: true
prove = false

# Maximum number of retry attempts for failed query operations before giving up.
# More retries improve reliability but may increase response times.
# Allowed: Any positive integer
# Example: 3
retry_attempts = 5

# Waiting period between consecutive retry attempts for failed queries.
# Longer delays reduce network load but increase total response time.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "2s"
retry_delay = "1s"

# RPC Configuration
[rpc]

# List of RPC server endpoints for blockchain communication.
# Multiple endpoints provide redundancy and load distribution for improved reliability.
# Allowed: Array of valid URLs
# Example: ["https://rpc.example.com:443", "https://backup-rpc.example.com:443"]
addrs = ["https://rpc.sentinel.co:443"]

# Unique identifier of the blockchain network to connect to.
# Ensures communication with the correct network and prevents accidental connections.
# Allowed: Valid chain identifier string
# Example: "testnet-1"
chain_id = "sentinelhub-2"

# Maximum time to wait for RPC requests before considering them failed.
# Balance between responsiveness and reliability based on network conditions.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "10s"
timeout = "5s"

# Transactions Configuration
[tx]

# Blockchain address that has granted authorization to submit transactions on behalf of this node.
# Enables delegated transaction signing for automated operations.
# Allowed: Valid address string
# Example: "sent1yftwk6a4h5fk4xzp3znk6puqj92uxw7jhxwd76"
authz_granter_addr = ""

# Number of retry attempts for broadcasting transactions if initial submission fails.
# Helps overcome temporary network issues but should be limited.
# Allowed: Any positive integer
# Example: 3
broadcast_retry_attempts = 1

# Waiting period between transaction broadcast retry attempts.
# Allows temporary network issues to resolve and prevents overwhelming the blockchain.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "10s"
broadcast_retry_delay = "5s"

# Address of an account that automatically pays transaction fees on behalf of this node.
# Enables gasless transactions while the fee granter covers costs.
# Allowed: Valid address string
# Example: "sent1yftwk6a4h5fk4xzp3znk6puqj92uxw7jhxwd76"
fee_granter_addr = ""

# Local account name used to sign and send transactions.
# Must exist in keyring with sufficient balance to cover transaction fees and deposits.
# Allowed: Any string
# Example: "node-operator"
from_name = "key-1"

# Maximum computational resources (gas) that can be consumed by a single transaction.
# Higher limits allow complex operations but cost more in fees.
# Allowed: Any positive integer
# Example: 300000
gas = 200000

# Multiplier applied to estimated gas usage to ensure sufficient allocation.
# Values above 1.0 add safety margin but increase transaction costs.
# Allowed: Any positive decimal number
# Example: 1.25
gas_adjustment = 1.15

# Price per unit of gas for transaction processing.
# Higher prices increase likelihood of fast inclusion but cost more in fees.
# Allowed: Valid price string with denomination
# Example: "0.2udvpn"
gas_prices = "0.1udvpn"

# Maximum attempts to query blockchain for transaction status after submission.
# More attempts improve detection chances but may delay error reporting.
# Allowed: Any positive integer
# Example: 50
query_retry_attempts = 30

# Time interval between consecutive transaction status queries.
# Balance between fast confirmation and blockchain load.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "2s"
query_retry_delay = "1s"

# Whether transactions are simulated before execution to estimate gas usage and detect failures.
# Improves success rates and cost accuracy but adds overhead.
# Allowed: true, false
# Example: false
simulate_and_execute = true

# Handshake DNS Configuration
[handshake_dns]

# Enables Handshake DNS daemon for decentralized domain name resolution.
# When enabled, both the node and its clients can resolve Handshake domain names through the decentralized network.
# Allowed: true, false
# Example: true
enable = false

# Number of peer connections to maintain within the Handshake DNS network.
# More peers provide better reliability but consume more network resources.
# Allowed: Integer between 1 and 8
# Example: 8
peers = 8

# Maximum number of times the Handshake DNS (hnsd) daemon may be restarted before the node stops.
# Use 0 to disable automatic restarts, or -1 to allow unlimited restarts.
# Allowed: Integer (-1, 0, or any positive integer)
# Example: 5
max_restarts = 5

# Node Configuration
[node]

# TCP port for client communication as a single port number or <in_port:out_port> mapping format.
# The mapping format allows the node API to run internally on in_port while being available to clients on out_port.
# Enables clients to connect to the node's API for management and service access.
# Allowed: Single port or port mapping format
# Example: "8080" or "8080:8081"
api_port = "19781"

# Pricing per gigabyte in format <denomination:base_value,quote_value> where base_value is USD price and quote_value is
# equivalent token amount. Blockchain prioritizes base_value and converts to quote_value.
# Multiple denominations separated by semicolons.
# Allowed: Valid prices format string
# Example: "udvpn:0.05,2500000;atom:0.05,10000"
gigabyte_prices = "udvpn:0.0025,12_500_000"

# Pricing per hour in format <denomination:base_value,quote_value> where base_value is USD price and quote_value is
# equivalent token amount. Blockchain prioritizes base_value and converts to quote_value.
# Multiple denominations separated by semicolons.
# Allowed: Valid prices format string
# Example: "udvpn:0.10,5000000;atom:0.10,20000"
hourly_prices = "udvpn:0.005,25_000_000"

# Frequency for evaluating and switching to the best performing RPC endpoint.
# Regular switching ensures optimal blockchain connectivity and service quality.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "10m0s"
interval_best_rpc_addr = "5m0s"

# How often the node queries external services to determine its geographic location for service discovery and helping
# clients find nearby nodes.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "12h0m0s"
interval_geoip_location = "6h0m0s"

# Frequency for fetching updated pricing data from the specified oracle and publishing it to the blockchain.
# Ensures that on-chain pricing information remains accurate and reflects current market conditions.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "1h0m0s"
interval_prices_update = "6h0m0s"

# Frequency for synchronizing session usage data to the blockchain ledger.
# Records payment obligations and service consumption on-chain for transparency.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "2h0m0s"
interval_session_usage_sync_with_blockchain = "1h55m0s"

# How often session usage statistics are updated in the local database for real-time billing and monitoring purposes.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "5s"
interval_session_usage_sync_with_database = "2s"

# Frequency of validation checks to ensure recorded session usage data is accurate and consistent.
# Helps detect and prevent billing discrepancies.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "10s"
interval_session_usage_validate = "5s"

# How often the node verifies that active client sessions are still valid.
# Cleanup process helps free resources from abandoned sessions.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "2m0s"
interval_session_validate = "5m0s"

# Frequency for running automated network performance tests to measure bandwidth, latency, and connectivity quality for
# service optimization.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "24h0m0s"
interval_speedtest = "168h0m0s"

# How often the node broadcasts its status and service information to the network.
# Regular updates ensure discoverability and accurate client information.
# Allowed: Duration string (e.g., 1s, 5m, 1h)
# Example: "30m0s"
interval_status_update = "55m0s"

# Human-readable display name for this node in network listings and client applications.
# Choose a unique, descriptive name to distinguish your node.
# Allowed: Any string
# Example: "my-node-moniker"
moniker = "<your_node_moniker>"

# Addresses that clients use to reach this node for service connections.
# Can include IP addresses with ports or domain names with ports for flexible client connectivity.
# Allowed: Comma-separated address list
# Example: ["192.168.1.100:8080", "node.example.com:9090"]
remote_addrs = ["1.2.3.4"]

# Type of VPN or proxy service protocol this node provides.
# Each type has different capabilities, security features, and client compatibility.
# Allowed: amneziawg, hysteria2, openvpn, v2ray, wireguard, xray
# Example: "wireguard"
service_type = "wireguard"

# Oracle Configuration
[oracle]

# Oracle provider used to fetch quote prices for base prices and update them on-chain.
# Leave empty to disable oracle functionality entirely.
# Allowed: "coingecko", "osmosis", or empty
# Example: "osmosis"
name = "coingecko"

# CoinGecko Oracle Configuration
[oracle.coingecko]

# API key for authenticating requests to the CoinGecko API.
# Some endpoints may require an API key for higher rate limits or premium features.
# Allowed: Any valid API key string
# Example: "your-coingecko-api-key"
api_key = ""

# Osmosis Oracle Configuration
[oracle.osmosis]

# REST API endpoint for accessing Osmosis market data.
# The oracle queries this endpoint to fetch token prices and liquidity pool information.
# Allowed: Valid URL string
# Example: "https://api.example.com:443"
api_addr = "https://lcd.osmosis.zone:443"

# QoS Configuration
[qos]

# Maximum number of simultaneous peer connections the node will accept.
# Helps prevent resource exhaustion and ensures stable performance under high load.
# Allowed: Any positive integer
# Example: 50
max_peers = 250

warning

Handshake DNS ([handshake_dns] enable = true) only takes effect when service_type is wireguard or amneziawg β€” these are the protocols that push a DNS resolver to connected clients. It has no effect for openvpn, v2ray, xray, or hysteria2.

Service-Specific Configurations:

  • WireGuard: ${APP_DIR}/wireguard/config.toml
  • AmneziaWG: ${APP_DIR}/amneziawg/config.toml
  • V2Ray: ${APP_DIR}/v2ray/config.toml
  • Xray: ${APP_DIR}/xray/config.toml
  • OpenVPN: ${APP_DIR}/openvpn/config.toml
  • Hysteria2: ${APP_DIR}/hysteria2/config.toml
Wireguard

# Specifies the IPv4 address block for routing and networking.
# Used to define the network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv4 CIDR notation
# Example: "10.0.0.1/24"
ipv4_addr = "10.0.0.1/24"

# Specifies the IPv6 address block for routing and networking.
# Used to define the IPv6 network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv6 CIDR notation
# Example: "fd00::/64"
ipv6_addr = ""

# Specifies the outbound network interface for NAT and routing.
# Defines which network interface the VPN traffic should be routed through for internet access.
# Allowed: Valid network interface name
# Example: "eth0"
out_interface = "eth0"

# Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# The mapping format allows the VPN service to run internally on in_port while being available to clients on out_port.
# Typically, UDP for WireGuard protocol.
# Allowed: Single port or port mapping format
# Example: "51820" or "51820:51820"
port = "25068"

# Specifies the private key for WireGuard encryption.
# The cryptographic private key used for establishing secure connections with clients.
# Allowed: Valid WireGuard private key
# Example: "AMuDADXXc5S1b8J6wxKhX29AiNKgNej6k6/Ol+Fof0g="
private_key = ""

AmneziaWG

# Specifies the IPv4 address block for routing and networking.
# Used to define the network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv4 CIDR notation
# Example: "10.0.0.1/24"
ipv4_addr = "10.0.0.1/24"

# Specifies the IPv6 address block for routing and networking.
# Used to define the IPv6 network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv6 CIDR notation
# Example: "fd00::/64"
ipv6_addr = ""

# Specifies the outbound network interface for NAT and routing.
# Defines which network interface the VPN traffic should be routed through for internet access.
# Allowed: Valid network interface name
# Example: "eth0"
out_interface = "eth0"

# Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# The mapping format allows the VPN service to run internally on in_port while being available to clients on out_port.
# Typically, UDP for AmneziaWG protocol.
# Allowed: Single port or port mapping format
# Example: "51820" or "51820:51820"
port = "42891"

# Specifies the private key for AmneziaWG encryption.
# The cryptographic private key used for establishing secure connections with clients.
# Allowed: Valid AmneziaWG private key
# Example: "AMuDADXXc5S1b8J6wxKhX29AiNKgNej6k6/Ol+Fof0g="
private_key = ""

# AmneziaWG obfuscation parameters (auto-generated on init).
# Handshake-affecting parameters (S1-S4, H1-H4, I1-I5) must match on both server and client.
# Local-only junk parameters (Jc, Jmin, Jmax) need not match the remote peer.
[obfs]
jc = 4
jmin = 40
jmax = 70
s1 = 15
s2 = 62
s3 = 0
s4 = 0
h1 = 1148195868
h2 = 1783849485
h3 = 1400453623
h4 = 693281700
i1 = ""
i2 = ""
i3 = ""
i4 = ""
i5 = ""
advanced_security = false

V2Ray

# Each [[inbounds]] block defines one V2Ray inbound listener with the four fields below.

# port: Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# Allowed: Single port or port mapping format β€” Example: "10086" or "10086:10086"

# proxy_protocol: Proxy protocol used for the inbound connection.
# Allowed: vmess, vless β€” Example: "vmess"

# transport_protocol: Underlying transport used for handling requests and data transmission.
# Allowed: domainsocket, gun, grpc, http, mkcp, quic, tcp, websocket β€” Example: "tcp"

# transport_security: Transport encryption applied to the inbound connection.
# Allowed: none, tls β€” Example: "tls"

[[inbounds]]
port = "54556"
proxy_protocol = "vmess"
transport_protocol = "quic"
transport_security = "tls"

[[inbounds]]
port = "13860"
proxy_protocol = "vless"
transport_protocol = "grpc"
transport_security = "none"

Xray

# Each [[inbounds]] block defines one Xray inbound listener with the fields below.

# port: Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# Allowed: Single port or port mapping format β€” Example: "10086" or "10086:10086"

# proxy_protocol: Proxy protocol used for the inbound connection.
# Allowed: vless, vmess, trojan, shadowsocks-2022 β€” Example: "vless"

# transport_protocol: Underlying transport used for the connection.
# Allowed: tcp, websocket, grpc, httpupgrade, xhttp β€” Example: "tcp"

# transport_security: Transport encryption applied to the connection.
# Allowed: none, tls, reality β€” Example: "reality"

# flow: Flow control for the inbound connection (VLESS only).
# Allowed: none, xtls-rprx-vision β€” Example: "xtls-rprx-vision"

# method: Encryption method for the inbound connection (Shadowsocks-2022 only).
# Example: "2022-blake3-aes-128-gcm"

# When transport_security = "reality", Xray dials out to an internally-configured target
# host (e.g. "www.microsoft.com:443") using a uTLS fingerprint (e.g. "chrome").

[[inbounds]]
port = "24816"
proxy_protocol = "vless"
transport_protocol = "tcp"
transport_security = "reality"
flow = "xtls-rprx-vision"
method = ""

[[inbounds]]
port = "38200"
proxy_protocol = "vmess"
transport_protocol = "websocket"
transport_security = "tls"
flow = "none"
method = ""

[[inbounds]]
port = "51900"
proxy_protocol = "shadowsocks-2022"
transport_protocol = "tcp"
transport_security = "none"
flow = "none"
method = "2022-blake3-aes-128-gcm"

OpenVPN

# Specifies the IPv4 address block for routing and networking.
# Used to define the network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv4 CIDR notation
# Example: "10.8.0.1/24"
ipv4_addr = "10.247.176.1/24"

# Specifies the IPv6 address block for routing and networking.
# Used to define the IPv6 network range that clients will be assigned addresses from for VPN connectivity.
# Allowed: Valid IPv6 CIDR notation
# Example: "fd00::/64"
ipv6_addr = ""

# Specifies the outbound network interface for NAT and routing.
# Defines which network interface the VPN traffic should be routed through for internet access.
# Allowed: Valid network interface name
# Example: "eth0"
out_interface = "eth0"

# Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# The mapping format allows the server to run internally on in_port while being available to clients on out_port.
# Typically, UDP or TCP for OpenVPN protocol.
# Allowed: Single port or port mapping format
# Example: "1194" or "1194:1194"
port = "11608"

# Specifies the transport protocol for communication.
# Determines whether the service uses UDP for better performance or TCP for better reliability through firewalls.
# Allowed: udp, tcp
# Example: "udp"
protocol = "udp"

Hysteria2

# Port for incoming client connections.
# The UDP port the Hysteria2 server listens on for incoming QUIC connections from clients.
# Allowed: Non-zero uint16
# Example: 36712
port = 36712

# Salamander obfuscation password for masking QUIC traffic.
# Both the server and client must share this password; an empty value disables obfuscation.
# Allowed: Any string, or empty to disable
# Example: "a-strong-obfs-password"
obfs_password = "a-strong-obfs-password"

# Loopback port for the SDK-hosted HTTP authentication backend.
# Hysteria2 calls this local endpoint to validate each connecting client's credential.
# Bound to loopback only β€” it does not need to be exposed through your firewall.
# Allowed: Non-zero uint16
# Example: 8080
auth_port = 8080

# Loopback port for Hysteria2's Traffic Stats API.
# Used by the service to collect per-user traffic usage and to kick disconnected peers.
# Bound to loopback only β€” it does not need to be exposed through your firewall.
# Allowed: Non-zero uint16
# Example: 8081
stats_port = 8081

# Authorization secret protecting the Traffic Stats API.
# Sent as the Authorization header on every request to the Traffic Stats API.
# Allowed: Any non-empty string
# Example: "a-strong-stats-secret"
stats_secret = "a-strong-stats-secret"

Add a Mnemonic​

Now, add the account key specified in your config.toml file:

sudo docker run \
--rm \
--volume "${VOLUME}" \
--interactive \
--tty \
sentinel-dvpnx keys add "${TX_FROM_NAME}"

You can either enter your existing BIP-39 mnemonic or generate a new one by pressing Enter. You’ll then be prompted for an optional passphrase (press Enter again to skip).

This will generate an operator address (starting with sent1) and a mnemonic phrase. Write the mnemonic down and store it securely, you’ll need it to recover your key.

Output

Enter your BIP-39 mnemonic, or hit enter to generate one:

Enter your BIP-39 passphrase, or hit enter to use the default:

####################################################################
WARNING: YOU MUST SAVE THE FOLLOWING MNEMONIC SECURELY!
THIS MNEMONIC IS REQUIRED TO RECOVER YOUR KEY.
IF YOU LOSE THIS MNEMONIC, YOU WILL NOT BE ABLE TO RECOVER YOUR KEY.
####################################################################

address: sent1x4faeeu8lqjnnjywa89j9xv34h0wm2yre96uc
mnemonic: kind smart guide build join dutch stairs chat frown camp capital glory allow van purity monster gauge impact title hand erupt surface scale december
name: key-1
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AvOE9Fxzmtb5RMKQDvpBE3K1xih5qVPWshRWHth8Awfu"}'
type: local

Key created successfully

Enable Firewall Ports​

Detect Required Ports Automatically​

You can automatically find all the ports your node needs with:

# Automatically detect and configure required ports
PUBLISH_PORT_ARGS=$(find "${APP_DIR}" -name "config.toml" -exec tomljson {} \; |
jq -sr '[.[] | .. | objects | to_entries[] | select(.key == "port" or (.key | endswith("_port"))) | .value] |
flatten | unique | map("-p \(.):\(.)/tcp -p \(.):\(.)/udp") | join(" ")')

# Verify port configuration
echo "Port arguments: $PUBLISH_PORT_ARGS"

Example output:

Port arguments: -p 11608:11608/tcp -p 11608:11608/udp -p 13860:13860/tcp -p 13860:13860/udp -p 19781:19781/tcp -p 19781:19781/udp -p 25068:25068/tcp -p 25068:25068/udp -p 54556:54556/tcp -p 54556:54556/udp

If you’re using zsh, also run:

PUBLISH_PORT_ARGS=("${(@s/ /)PUBLISH_PORT_ARGS}")

Open the Ports with UFW​

Once you have the required ports, open them in your firewall:

sudo ufw allow 11608,13860,19781,25068,54556/tcp
sudo ufw allow 11608,13860,19781,25068,54556/udp

Enable Port Forwarding (for Residential Nodes)​

If you’re running your node from home, you’ll need to enable port forwarding on your router so others can connect to it.

Forward every port your node uses β€” the same ports you detected above and opened with UFW. Add one rule per port, and if your router lets you pick a protocol, create both a TCP and a UDP rule for each (exactly like the UFW step), so the rules work for any service type.

In your router’s WAN settings, add entries like this:

Name Protocol WAN Port LAN Port Destination IP
API TCP + UDP <api_port> <api_port> <your_local_ip>
SERVICE TCP + UDP <service_port> <service_port> <your_local_ip>

If your router only allows one protocol per rule, use the transport each port actually needs:

PortProtocol
Node API (api_port)TCP
WireGuard / AmneziaWGUDP
Hysteria2UDP (QUIC)
OpenVPNUDP or TCP β€” matches its protocol setting
V2Ray / XrayTCP or UDP β€” depends on each inbound’s transport