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
# 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+=("--node.remote-addrs" \"${MY_IPv4_ADDR}\"); fi
if [ -n "${MY_IPv6_ADDR}" ]; then 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/<you_user>/.sentinel-dvpnx
Public IPv4: <your_ip>
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 wireguard, v2ray, or openvpn.

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

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: Any positive integer
# Example: 12
peers = 8

# 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_moniket>"

# 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 = ["123.456.7.8"]

# Type of VPN or proxy service protocol this node provides.
# Each type has different capabilities, security features, and client compatibility.
# Allowed: openvpn, v2ray, wireguard
# 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

Service-Specific Configurations:

  • WireGuard: ${APP_DIR}/wireguard/config.toml
  • V2Ray: ${APP_DIR}/v2ray/config.toml
  • OpenVPN: ${APP_DIR}/openvpn/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 = "# Example: "AMuDADXXc5S1b8J6wxKhX29AiNKgNej6k6/Ol+Fof0g="

V2Ray

# Port for incoming connections as a single port number or "in_port:out_port" mapping format.
# The mapping format allows the V2Ray service to run internally on in_port while being available to clients on out_port.
# Must be unique and not conflict with other services on the same machine.
# Allowed: Single port or port mapping format
# Example: "10086" or "10086:10086"

# Proxy protocol type for communication on the inbound connection.
# Determines the protocol used for establishing connections with clients connecting to this V2Ray instance.
# Allowed: vmess, vless
# Example: "vmess"

# Transport protocol type for handling incoming requests and data transmission.
# Determines the underlying transport mechanism used for communication between client and server.
# Allowed: domainsocket, gun, grpc, http, mkcp, quic, tcp, websocket
# Example: "tcp"

# Transport Security setting for the inbound connection encryption.
# Determines whether the connection uses encryption and what type of security protocol is applied.
# 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"

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"

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.

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

Name ProtocolWAN Port LAN port Destination IP
TCP_PORT TCP <tcp_port> <tcp_port> your_local_ip
WIREGUARD_PORT UDP <wireguard_udp_port> <wireguard_udp_port> your_local_ip
V2RAY_PORT TCP <v2ray_tcp_port> <v2ray_tcp_port> your_local_ip