It can take anywhere from a few seconds to a few minutes to establish
I2P connections to the desired peers, so Reticulum handles the process
in the background, and will output relevant events to the log.
#### NOTE
While the I2P interface is the simplest way to use
Reticulum over I2P, it is also possible to tunnel the TCP server and
client interfaces over I2P manually. This can be useful in situations
where more control is needed, but requires manual tunnel setup through
the I2P daemon configuration.
It is important to note that the two methods are *interchangably compatible*.
You can use the I2PInterface to connect to a TCPServerInterface that
was manually tunneled over I2P, for example. This offers a high degree
of flexibility in network setup, while retaining ease of use in simpler
use-cases.
## RNode LoRa Interface
To use Reticulum over LoRa, the [RNode](https://unsigned.io/rnode/) interface
can be used, and offers full control over LoRa parameters.
#### WARNING
Radio frequency spectrum is a legally controlled resource, and legislation
varies widely around the world. It is your responsibility to be aware of any
relevant regulation for your location, and to make decisions accordingly.
```ini
# Here's an example of how to add a LoRa interface
# using the RNode LoRa transceiver.
[[RNode LoRa Interface]]
type = RNodeInterface
# Enable interface if you want use it!
enabled = yes
# Serial port for the device
port = /dev/ttyUSB0
# You can connect wirelessly to the
# RNode device if it supports WiFi.
# Connect by IP address
# port = tcp://10.0.0.1
# Or, connect by hostname
# port = tcp://rnodef3b9.local
# It is also possible to use BLE devices
# instead of wired serial ports. The
# target RNode must be paired with the
# host device before connecting. BLE
# devices can be connected by name,
# BLE MAC address or by any available.
# Connect to specific device by name
# port = ble://RNode 3B87
# Or by BLE MAC address
# port = ble://F4:12:73:29:4E:89
# Or connect to the first available,
# paired device
# port = ble://
# Set frequency to 867.2 MHz
frequency = 867200000
# Set LoRa bandwidth to 125 KHz
bandwidth = 125000
# Set TX power to 7 dBm (5 mW)
txpower = 7
# Select spreading factor 8. Valid
# range is 7 through 12, with 7
# being the fastest and 12 having
# the longest range.
spreadingfactor = 8
# Select coding rate 5. Valid range
# is 5 throough 8, with 5 being the
# fastest, and 8 the longest range.
codingrate = 5
# You can configure the RNode to send
# out identification on the channel with
# a set interval by configuring the
# following two parameters.
# id_callsign = MYCALL-0
# id_interval = 600
# For certain homebrew RNode interfaces
# with low amounts of RAM, using packet
# flow control can be useful. By default
# it is disabled.
# flow_control = False
# It is possible to limit the airtime
# utilisation of an RNode by using the
# following two configuration options.
# The short-term limit is applied in a
# window of approximately 15 seconds,
# and the long-term limit is enforced
# over a rolling 60 minute window. Both
# options are specified in percent.
# airtime_limit_long = 1.5
# airtime_limit_short = 33
```
## RNode Multi Interface
For RNodes that support multiple LoRa transceivers, the RNode
Multi interface can be used to configure sub-interfaces individually.
#### WARNING
Radio frequency spectrum is a legally controlled resource, and legislation
varies widely around the world. It is your responsibility to be aware of any
relevant regulation for your location, and to make decisions accordingly.
```ini
# Here's an example of how to add an RNode Multi interface
# using the RNode LoRa transceiver.
[[RNode Multi Interface]]
type = RNodeMultiInterface
# Enable interface if you want to use it!
enabled = yes
# Serial port for the device
port = /dev/ttyACM0
# You can configure the RNode to send
# out identification on the channel with
# a set interval by configuring the
# following two parameters.
# id_callsign = MYCALL-0
# id_interval = 600
# A subinterface
[[[High Datarate]]]
# Subinterfaces can be enabled and disabled in of themselves
enabled = yes
# Set frequency to 2.4GHz
frequency = 2400000000
# Set LoRa bandwidth to 1625 KHz
bandwidth = 1625000
# Set TX power to 0 dBm (0.12 mW)
txpower = 0
# The virtual port, only the manufacturer
# or the person who wrote the board config
# can tell you what it will be for which
# physical hardware interface
vport = 1
# Select spreading factor 5. Valid
# range is 5 through 12, with 5
# being the fastest and 12 having
# the longest range.
spreadingfactor = 5
# Select coding rate 5. Valid range
# is 5 throough 8, with 5 being the
# fastest, and 8 the longest range.
codingrate = 5
# It is possible to limit the airtime
# utilisation of an RNode by using the
# following two configuration options.
# The short-term limit is applied in a
# window of approximately 15 seconds,
# and the long-term limit is enforced
# over a rolling 60 minute window. Both
# options are specified in percent.
# airtime_limit_long = 100
# airtime_limit_short = 100
[[[Low Datarate]]]
# Subinterfaces can be enabled and disabled in of themselves
enabled = yes
# Set frequency to 865.6 MHz
frequency = 865600000
# The virtual port, only the manufacturer
# or the person who wrote the board config
# can tell you what it will be for which
# physical hardware interface
vport = 0
# Set LoRa bandwidth to 125 KHz
bandwidth = 125000
# Set TX power to 0 dBm (0.12 mW)
txpower = 0
# Select spreading factor 7. Valid
# range is 5 through 12, with 5
# being the fastest and 12 having
# the longest range.
spreadingfactor = 7
# Select coding rate 5. Valid range
# is 5 throough 8, with 5 being the
# fastest, and 8 the longest range.
codingrate = 5
# It is possible to limit the airtime
# utilisation of an RNode by using the
# following two configuration options.
# The short-term limit is applied in a
# window of approximately 15 seconds,
# and the long-term limit is enforced
# over a rolling 60 minute window. Both
# options are specified in percent.
# airtime_limit_long = 100
# airtime_limit_short = 100
```
## Serial Interface
Reticulum can be used over serial ports directly, or over any device with a
serial port, that will transparently pass data. Useful for communicating
directly over a wire-pair, or for using devices such as data radios and lasers.
```ini
[[Serial Interface]]
type = SerialInterface
enabled = yes
# Serial port for the device
port = /dev/ttyUSB0
# Set the serial baud-rate and other
# configuration parameters.
speed = 115200
databits = 8
parity = none
stopbits = 1
```
## Pipe Interface
Using this interface, Reticulum can use any program as an interface via stdin and
stdout. This can be used to easily create virtual interfaces, or to interface with
custom hardware or other systems.
```ini
[[Pipe Interface]]
type = PipeInterface
enabled = yes
# External command to execute
command = netcat -l 5757
# Optional respawn delay, in seconds
respawn_delay = 5
```
Reticulum will write all packets to stdin of the `command` option, and will
continuously read and scan its stdout for Reticulum packets. If `EOF` is reached,
Reticulum will try to respawn the program after waiting for `respawn_interval` seconds.
## KISS Interface
With the KISS interface, you can use Reticulum over a variety of packet
radio modems and TNCs, including [OpenModem](https://unsigned.io/openmodem/).
KISS interfaces can also be configured to periodically send out beacons
for station identification purposes.
#### WARNING
Radio frequency spectrum is a legally controlled resource, and legislation
varies widely around the world. It is your responsibility to be aware of any
relevant regulation for your location, and to make decisions accordingly.
```ini
[[Packet Radio KISS Interface]]
type = KISSInterface
enabled = yes
# Serial port for the device
port = /dev/ttyUSB1
# Set the serial baud-rate and other
# configuration parameters.
speed = 115200
databits = 8
parity = none
stopbits = 1
# Set the modem preamble.
preamble = 150
# Set the modem TX tail.
txtail = 10
# Configure CDMA parameters. These
# settings are reasonable defaults.
persistence = 200
slottime = 20
# You can configure the interface to send
# out identification on the channel with
# a set interval by configuring the
# following two parameters. The KISS
# interface will only ID if the set
# interval has elapsed since it's last
# actual transmission. The interval is
# configured in seconds.
# This option is commented out and not
# used by default.
# id_callsign = MYCALL-0
# id_interval = 600
# Whether to use KISS flow-control.
# This is useful for modems that have
# a small internal packet buffer, but
# support packet flow control instead.
flow_control = false
```
## AX.25 KISS Interface
If you’re using Reticulum on amateur radio spectrum, you might want to
use the AX.25 KISS interface. This way, Reticulum will automatically
encapsulate it’s traffic in AX.25 and also identify your stations
transmissions with your callsign and SSID.
Only do this if you really need to! Reticulum doesn’t need the AX.25
layer for anything, and it incurs extra overhead on every packet to
encapsulate in AX.25.
A more efficient way is to use the plain KISS interface with the
beaconing functionality described above.
#### WARNING
Radio frequency spectrum is a legally controlled resource, and legislation
varies widely around the world. It is your responsibility to be aware of any
relevant regulation for your location, and to make decisions accordingly.
```ini
[[Packet Radio AX.25 KISS Interface]]
type = AX25KISSInterface
# Set the station callsign and SSID
callsign = NO1CLL
ssid = 0
# Enable interface if you want use it!
enabled = yes
# Serial port for the device
port = /dev/ttyUSB2
# Set the serial baud-rate and other
# configuration parameters.
speed = 115200
databits = 8
parity = none
stopbits = 1
# Set the modem preamble. A 150ms
# preamble should be a reasonable
# default, but may need to be
# increased for radios with slow-
# opening squelch and long TX/RX
# turnaround
preamble = 150
# Set the modem TX tail. In most
# cases this should be kept as low
# as possible to not waste airtime.
txtail = 10
# Configure CDMA parameters. These
# settings are reasonable defaults.
persistence = 200
slottime = 20
# Whether to use KISS flow-control.
# This is useful for modems with a
# small internal packet buffer.
flow_control = false
```
## Discoverable Interfaces
Reticulum includes a powerful system for publishing your local interfaces to the wider network, allowing other peers to [discover, validate, and automatically connect to them](using.md#using-interface-discovery). This feature is particularly useful for creating decentralized networks where peers can dynamically find entrypoints, such as public Internet gateways or local radio access points, without relying on static configuration files or centralized directories.
When an interface is made **discoverable**, your Reticulum instance will periodically broadcast an announce packet containing the connection details and parameters required for other peers to establish a connection. These announces are propagated over the network using the standard Reticulum announce mechanism using the `rnstransport.discovery.interface` destination type.
#### NOTE
To use the interface discovery functionality, the `LXMF` module must be installed in your Python environment. You can install it using pip:
```sh
pip install lxmf
```
### Enabling Discovery
Interface discovery is enabled on a per-interface basis. To make a specific interface discoverable, you must add the `discoverable` option to that interface’s configuration block and set it to `yes`.
```ini
[[My Public Gateway]]
type = BackboneInterface
...
discoverable = yes
```
Once enabled, Reticulum will automatically handle the generation, signing, stamping, and broadcasting of the discovery announces. It is not *required* to enable Transport to publish interface discovery information, but for most use cases where you want others to connect to you, you will likely want `enable_transport` set to `yes` in the `[reticulum]` section of your configuration.
### Discovery Parameters
When `discoverable` is enabled, a variety of additional options become available to control how the interface is presented to the network. These parameters allow you to fine-tune the metadata, security requirements, and visibility of your interface.
**Basic Metadata**
`discovery_name`
: A human-readable name for the interface. This name will be displayed to users on remote systems when they list discovered interfaces. If not specified, the interface name (the section header) will be used.
`announce_interval`
: The interval in minutes between successive discovery announces for this interface. Default is 360 minutes (6 hours). For stable, long-running infrastructure, higher intervals (12 to 22 hours) are usually sufficient and reduce network load. Minimum allowed value is 5 minutes (but expect to have your announces throttled if using intervals below one hour).
**Connectivity Specification**
`reachable_on`
: Specifies the address that remote peers should use to connect to this interface.
* For TCP and Backbone interfaces, this is typically the public IP address or hostname. Do not include the port, this is fetched automatically from the interface.
* For I2P interfaces, this is usually the I2P `b32` address. This value is fetched automatically from the `I2PInterface` once it is up and connected to the I2P network, so you should not set this manually, unless you absolutely know what you’re doing.
**Dynamic Resolution:** This option also accepts a path to an external executable script or binary. If a path is provided, Reticulum will execute the script and use its `stdout` as the reachability address. This is useful for devices behind dynamic DNS, NATs, or complex cloud environments where the external IP is not known locally. The script must simply print the address to stdout and exit.
#### NOTE
When using an executable script for `reachable_on`, Reticulum expects the script to output only the IP address or hostname to `stdout`, followed by a newline character. Any additional output or errors may cause the resolution to fail. Ensure the script has executable permissions and is robust against temporary network failures.
A minimal example of a script that resolves the externally available, public IP of an internet-connected system could look like this:
```bash
#!/bin/bash
curl -s ip.me
exit $?
```
On a real system, you should make the script robust enough to deal with intermittent Internet or service failures, such that the script *always* returns a sensible value, or if not possible at least exits with a non-zero exit return code, so Reticulum knows the output is invalid.
**Security & Cost**
`discovery_stamp_value`
: Defines the proof-of-work difficulty for the cryptographic stamp included in the announce. This value acts as a cost barrier to prevent network flooding. The default value is `14`. Increasing this value makes it computationally more expensive to generate an announce, which can be useful to prevent spam on very large networks, but it also increases CPU load on your system when generating announces. Stamps are cached, and only generated if interface information changes, or at instance restart. If you have the computational resources, it is generally advisable to use as high a stamp value as possible.
**Privacy & Encryption**
`discovery_encrypt`
: If set to `yes`, the discovery announce payload will be encrypted. To decrypt the announce, remote peers must possess the *network identity* configured for your instance (see `network_identity` in the `[reticulum]` section). This allows you to publish private interfaces that are only discoverable to specific trusted networks.
#### IMPORTANT
If you enable `discovery_encrypt` but do not configure a valid `network_identity` in the `[reticulum]` section of your configuration, Reticulum will abort the interface discovery announce. Encryption requires a valid network identity key to function.
`publish_ifac`
: If set to `yes`, the Interface Access Code (IFAC) name and passphrase for this interface will be included in the discovery announce. This allows peers to automatically configure the correct authentication parameters when connecting to the interface.
: Optional physical coordinates for the interface. These are useful for mapping discovered interfaces geographically or for clients to automatically select the nearest access point. Coordinates should be in decimal degrees, height in meters above mean sea level.
`location_cmd`
: Optional path to executable or script that returns the physical coordinates for the interface. This can be used instead of manually setting `latitude`, `longitude` and `height`. Reticulum expects the script to output the location data to `stdout` on a single line, separated by commas, with values as floating point numbers in the format `LAT, LON, HEIGHT`. Coordinates should be in decimal degrees, height in meters above mean sea level.
#### NOTE
The height value for interface discovery is specified in *height above mean sea level*! This is the geoid-corrected height value, and is distinct from GPS altitude. If you manually specify height, it will typically be set to what you find on a topographical map. If you are using a script to output the location data, make sure that you are using the geoid-corrected altitude, not height above the GPS ellipsoid. Most GPS systems will make both figures available.
For physical radio interfaces like `RNodeInterface` or `KISSInterface`, the following optional parameters allow you to broadcast the operating frequency and characteristics, allowing clients to verify compatibility before connecting:
`discovery_frequency`
: The operating frequency in Hz. Auto-configured on RNode interfaces. Necessary on KISS-based radio interfaces and `TCPClientInterfaces` connecting to radio modems.
`discovery_bandwidth`
: The signal bandwidth in Hz. Auto-configured on RNode interfaces. Useful on KISS-based radio interfaces and `TCPClientInterfaces` connecting to radio modems.
`discovery_modulation`
: The modulation type or scheme. Auto-configured on RNode interfaces, but highly advisable to include on other radio-based interfaces.
### Interface Modes
When you enable discovery on an interface, Reticulum enforces certain interface modes to ensure the interface is actually useful for remote peers.
If an interface is configured as `discoverable`, but its mode is not explicitly set to `gateway` (for server-style interfaces like `BackboneInterface` or `TCPServerInterface`) or `access_point` (for radio interfaces like `RNodeInterface`), Reticulum will automatically configure the appropriate mode and log a notice.
For example, if you enable discovery on a `RNodeInterface` without specifying the mode, Reticulum will automatically set it to `access_point` mode.
### Security Considerations
When making interfaces discoverable, you are effectively broadcasting an invitation to connect to your system. It is important to understand the security implications of the configuration options you choose.
**Publishing Credentials**
If you enable `publish_ifac = yes`, your interface’s authentication passphrase will be included in the announce. If you are operating a public network and want anyone to connect, this is acceptable. However, if you wish to restrict access to a specific group of users, you **must** enable `discovery_encrypt = yes`. This ensures that only peers possessing the correct `network_identity` can decode the passphrase.
**Topology Exposure**
A discoverable interface announces its presence, location (if configured), and capabilities to the network. Even if the connection details are encrypted, the *fact* that a connectable node exists within a certain network becomes public information. In high-security or scenarios requiring operational secrecy, consider the implications of advertising your infrastructure’s existence.
### Example Configuration
Below is an example configuration for a public backbone gateway. This configuration publishes a high-value, publicly discoverable interface, that anyone can connect to.
```ini
[[My Public Gateway]]
type = BackboneInterface
mode = gateway
listen_on = 0.0.0.0
port = 4242
# Enable Discovery
discoverable = yes
# Interface Details
discovery_name = Region A Public Entrypoint
announce_interval = 720
# Use external script to resolve dynamic IP
reachable_on = /usr/local/bin/get_external_ip.sh
# Generate high stamp value
discovery_stamp_value = 24
# Optional location data
latitude = 51.99714
longitude = -0.74195
height = 15
```
The next example create an encrypted discovery-enabled interface, requiring a specific network identity to decode, and includes IFAC credentials for seamless authentication.
```ini
[[My Private Gateway]]
type = BackboneInterface
mode = gateway
listen_on = 0.0.0.0
port = 5858
network_name = internal_1
passphrase = Mevpekyafshak5Wr
# Enable Discovery
discoverable = yes
# Interface Details
discovery_name = Region A Private Backbone
announce_interval = 720
# Use external script to resolve dynamic IP
reachable_on = /usr/local/bin/get_external_ip.sh
# Target stamp value
discovery_stamp_value = 22
# Encrypt announces for our network only
discovery_encrypt = yes
# Include credentials so trusted
# peers can connect automatically
publish_ifac = yes
# Optional location data
latitude = 34.06915
longitude = -118.44318
height = 15
```
In the `[reticulum]` section of your configuration, you would define the network identity used for encryption as follows:
```ini
[reticulum]
...
# The identity used to sign/encrypt discovery announces
With these configuration options applied, your Reticulum instance will actively participate in the network’s discovery ecosystem. Other peers running Reticulum with discovery enabled will be able to see your interface, validate its cryptographic stamp, and (depending on their configuration) automatically connect to it.
For information on how to use these discovered interfaces and configure your system to auto-connect to them, refer to the [Discovering Interfaces](using.md#using-interface-discovery) chapter.
## Common Interface Options
A number of general configuration options are available on most interfaces.
These can be used to control various aspects of interface behaviour.
> * The `enabled` option tells Reticulum whether or not
> to bring up the interface. Defaults to `False`. For any
> interface to be brought up, the `enabled` option