Skip to content

How to setup a headless node for Bisq Connect apps

rodvar edited this page Jul 27, 2026 · 6 revisions

Bisq2 Trusted Node (build from source)

Most people don't need this page. Building from source is the advanced / last-resort option — for development or platforms without a packaged build. For an always-on node, the easy paths are a one-click Umbrel app, a Docker image downloadable from Bisq packages, or Bisq2 Desktop — see all ways to run your own node in the main guide.

This guide walks you through building and running a headless Bisq2 Trusted Node from source — a background process (no Desktop UI) that your Bisq Connect mobile app connects to. Useful for development, or servers/platforms not covered by the packaged options above.


What You Need

  • A computer or server (Linux, macOS, or Windows)
  • Java 21 installed (Download here)
  • Git installed
  • Familiarity with the terminal / command line

Note: This page builds the node from source. Prebuilt/packaged options now exist too — see the callout at the top (Umbrel App Store, Docker, or Bisq2 Desktop).


Step 1: Clone and Build Bisq2 API module

Clone and setup

git clone https://github.com/bisq-network/bisq2.git
cd bisq2

Build

Each Bisq Connect release is prepared to work against a specific version of Bisq2. Before building, you need to switch to the branch prepared for Bisq Connect.

git checkout for-mobile-based-on-2.1.10
./gradlew apps:api-app:clean apps:api-app:installDist

The build output will be at:

apps/api-app/build/install/api-app/

Step 2: Choose Your Connection Mode

Before configuring, decide how your mobile device will connect. There are several configurations across two transport types (Clearnet and Tor), varying by TLS encryption, session handling, authorization, and Tor client auth.

Clearnet Scenarios (LAN / same WiFi)

ID TLS Sessions Auth Real Devices Description
C1 Off Off Off Emulator only Plain HTTP, no security. For local dev/testing only.
C2 Off On On Emulator only HTTP with session tokens and auth headers. Dev/testing only.
C3 On Off Off Yes HTTPS with certificate pinning. Encrypted but no session management.
C4 On On On Yes Full clearnet security: HTTPS + sessions + auth. Recommended for LAN.
C5 On On (no expiry) On Yes Same as C4 but sessions never expire (TTL=-1). Convenient for always-on setups.

Why is TLS mandatory for LAN? Real mobile devices on your WiFi cannot reach localhost — the node must bind to a LAN IP. When bound this way, pairing tokens and session credentials travel over your local network, so TLS is required to prevent cleartext interception. C1 and C2 (no TLS) only work on emulators running on the same machine as the node, where localhost is reachable.

Tor Scenarios (remote access / maximum privacy)

ID TLS Sessions Auth Description
T1 Off Off Off Plain Tor onion service, no extra security. Tor encryption only.
T2 Off On On Tor + session tokens + auth headers. Recommended for Tor.

Note: Tor v3 client authentication and TLS over Tor are not yet implemented. These features may be added in a future release.

Quick Comparison

Speed Privacy Works Remotely Real Device Support Recommended For
C1–C2 Fast None No Emulator only Development / testing
C3 Fast Good No Yes (Android + iOS) Quick LAN setup
C4–C5 Fast Good No Yes (Android + iOS) Daily home use
T1 Slower High Yes Yes (Android + iOS) Basic remote access
T2 Slower High Yes Yes (Android + iOS) Recommended for Tor

Our recommendation: Use C4 (LAN + TLS + sessions) for home use and T2 (Tor + sessions + auth) for remote access. Both provide strong security with good usability.


Step 3: Configure Your Node

The configuration file is located at:

bisq2/apps/api-app/src/main/resources/api_app.conf

Edit the application.api section based on your chosen mode. Below are the three main profiles:

Profile A: Quick Start (Emulator only, no TLS)

The fastest way to test locally with an emulator. Not suitable for real devices on LAN — use Profile B instead.

application {
    api {
        accessTransportType = "CLEAR"

        pairing {
            ttlInSeconds = 3600
            writePairingQrCodeToDisk = true
        }

        server {
            websocketEnabled = true

            bind {
                host = "127.0.0.1"
                port = 8090
            }

            tls {
                required = false
            }

            security {
                supportSessionHandling = false
                authorizationRequired = false
            }
        }
    }
}

Warning: Without TLS, pairing tokens and session credentials are sent in cleartext. This only works with emulators on the same machine (localhost). For real devices, TLS is mandatory — see Profile B.

Profile B: LAN + TLS (Recommended for home use)

Encrypted connections with certificate pinning. Your mobile app will verify the server's identity via a SHA-256 fingerprint embedded in the QR code.

application {
    api {
        accessTransportType = "CLEAR"

        pairing {
            ttlInSeconds = 3600
            writePairingQrCodeToDisk = true
        }

        server {
            websocketEnabled = true

            bind {
                host = "192.168.1.100"     # Your LAN IP — see instructions below
                port = 8090
            }

            tls {
                required = true

                keystore {
                    password = "changeme_min8chars"    # Min 8 chars
                }

                certificate {
                    san = ["127.0.0.1", "192.168.1.100"]    # Add your LAN IP here!
                }
            }

            security {
                supportSessionHandling = true
                authorizationRequired = true

                session {
                    ttlInMinutes = 60    # Set to -1 to disable session expiry
                }
            }
        }
    }
}

Important: Set bind.host to your computer's LAN IP address and add it to the tls.certificate.san list. The self-signed certificate will include these addresses as Subject Alternative Names, and the mobile app verifies the connection against them.

To find your LAN IP:

Linux:

hostname -I | awk '{print $1}'

macOS:

ipconfig getifaddr en0

Windows:

ipconfig

(Look for "IPv4 Address" under your active network adapter, e.g. 192.168.1.100)

Profile C: Tor (Recommended for remote access)

Maximum privacy. Your node publishes a Tor onion service and the mobile app connects through Tor automatically.

application {
    api {
        accessTransportType = "TOR"

        pairing {
            ttlInSeconds = 3600
            writePairingQrCodeToDisk = true
        }

        server {
            websocketEnabled = true

            bind {
                host = "127.0.0.1"     # Keep localhost — Tor onion service forwards to loopback
                port = 8090
            }

            tor {
                onionServicePort = 80
            }

            tls {
                required = false       # Not needed over Tor (already encrypted)
            }

            security {
                supportSessionHandling = true
                authorizationRequired = true

                session {
                    ttlInMinutes = 60
                }
            }
        }
    }
}

The node will automatically:

  1. Bootstrap Tor (2–5 minutes on first run)
  2. Generate a .onion address
  3. Embed the onion address in the pairing QR code / pairing token

Step 4: Start Your Trusted Node

Manual start

JAVA_OPTS="-Dapplication.appName=bisq2_http_prod \
    -Dapplication.devMode=false \
    -Dapplication.network.supportedTransportTypes.0=TOR" \
    apps/api-app/build/install/api-app/bin/api-app

For LAN-only (no Tor):

JAVA_OPTS="-Dapplication.appName=bisq2_http_prod \
    -Dapplication.devMode=false \
    -Dapplication.network.supportedTransportTypes.0=CLEAR" \
    apps/api-app/build/install/api-app/bin/api-app

What happens next:

  1. The node starts up and joins the Bisq Easy p2p network
  2. If using Tor: Tor bootstraps (2–5 minutes the first time) and your onion address is generated
  3. The WebSocket server starts on the configured port (default: 8090)
  4. A pairing QR code is generated (and saved to disk as a pairing token)

Keep this terminal window open — your node needs to stay running for your mobile app to connect.


Step 5: Find Your Pairing QR Code / Pairing Token

The QR code is your single trust anchor — it contains everything your mobile app needs to connect securely:

  • The WebSocket URL (LAN IP or .onion address)
  • A TLS certificate fingerprint (if TLS is enabled)
  • A Tor client auth secret (if client auth is enabled)
  • A one-time pairing code (expires after 5 minutes)

If writePairingQrCodeToDisk = true in your config, the QR code data is written to:

Linux:

cat ~/.local/share/<appName>/pairing_qr_code.txt

macOS:

cat ~/Library/Application\ Support/<appName>/pairing_qr_code.txt

Windows:

type %USERPROFILE%\.local\share\<appName>\pairing_qr_code.txt

Replace <appName> with your configured app name (e.g. bisq2_http_prod).

This file contains a Base64-encoded string. You can:

  • Convert it to a scannable QR code image using any QR code generator tool, or
  • Transfer the string to the mobile device and paste it directly in the app

Security note: The pairing QR code expires after 5 minutes. The node generates a new one periodically or when the previous token has been used. If the code expires or is no longer valid, you will find the new one in the same file.

Next step: Go to Pair Your Mobile Device in the main Bisq Connect Guide.


Troubleshooting

"Port 8090 already in use"

  • Another program is using port 8090
  • Edit api_app.conf and change port = 8090 to another port (e.g. 8091)
  • Rebuild and restart your trusted node
  • Generate a new QR code (the port is embedded in it)

"Tor bootstrap timeout" (on trusted node)

  • Tor takes 2–5 minutes to bootstrap the first time
  • Check your internet connection
  • Make sure ports are not blocked by your firewall
  • Check the node's terminal output for error messages

General troubleshooting

See the Troubleshooting section in the main Bisq Connect Guide.


Advanced: Running Multiple Nodes

If you want to serve multiple users (e.g., family members), run separate node instances with different app names and ports. This is recommended because a paired device has control over all profiles on its node instance (except the first profile).

Step 1: Decide your instances

For example, one for Alice and one for Bob:

  • Alice: appName=bisq2_alice, port 8090
  • Bob: appName=bisq2_bob, port 8091

Step 2: Run each instance

Each instance gets its own data directory automatically based on appName:

# Terminal 1 — Alice's node
JAVA_OPTS="-Dapplication.appName=bisq2_alice \
    -Dapplication.devMode=false \
    -Dapplication.network.supportedTransportTypes.0=TOR" \
    apps/api-app/build/install/api-app/bin/api-app

# Terminal 2 — Bob's node
JAVA_OPTS="-Dapplication.appName=bisq2_bob \
    -Dapplication.devMode=false \
    -Dapplication.websocket.server.port=8091 \
    -Dapplication.network.supportedTransportTypes.0=TOR" \
    apps/api-app/build/install/api-app/bin/api-app

Each node will:

  • Have its own data directory (~/.local/share/bisq2_alice/, ~/.local/share/bisq2_bob/, etc.)
  • Generate its own Tor onion address
  • Produce its own pairing QR code
  • Operate completely independently

Step 3: Pair each user

Share the corresponding QR code / pairing token with each user. Alice scans Alice's, Bob scans Bob's.


Configure as a Boot Service (Optional but Recommended)

To ensure your Bisq Trusted Node starts automatically when your computer boots:

  • Linux: Use systemd (systemctl)
  • macOS: Use a launchd plist
  • Windows: Use Task Scheduler

Clone this wiki locally