This guide provides a comprehensive, step-by-step walkthrough for deploying and managing a Haveno network instance tailored to haveno.com’s modified core. We will cover setting up all key components with best practices for reliability (using systemd on VPS or Docker containers), integrating a Monero node, and configuring network-specific parameters. Each section below focuses on a particular stage or component of the deployment.
Table of Contents:
For maximum reliability, run the Haveno network’s critical services (seed nodes, price nodes, Monero nodes, etc.) on a stable VPS and manage them as background system services. Using systemd is recommended for automatically starting and monitoring these components on boot:
screen or tmux) rather than as strict system services. This allows arbitrators to easily check the GUI while keeping the process running on the server.Make sure your VPS is secure and hardened before deployment. Following Monero’s official server hardening guidelines for Linux servers is advisable. This includes steps like creating a dedicated haveno user for running services, enabling firewalls, and keeping system packages up to date.
Docker Alternative: If you prefer containerization, Haveno supports running services via Docker. Using Docker Compose can greatly simplify multi-service setup (Tor, DNS, seed node, etc.) and provides isolation. In fact, the Haveno team provides a dedicated guide and resources to build and manage a Haveno network using Docker. Docker can automate dependency setup and improve portability. In this guide, we will highlight Docker usage for various components (Monero node, Haveno daemon, etc.) alongside the manual setup instructions.
Before compiling or running Haveno services, ensure the required dependencies are installed on your system. Haveno is written in Java and uses Gradle for builds, so a compatible JDK and build toolchain are necessary.
Install the Java Development Kit (JDK) 21. It’s recommended to use SDKMAN! for managing Java versions on Unix-like systems:
curl -s "https://get.sdkman.io" | bash # install SDKMAN
sdk install java 21.0.2.fx-librca # install JDK 21 via SDKMAN
On Ubuntu 22.04 or similar, you can alternatively install OpenJDK 21 via apt:
sudo apt-get update && sudo apt-get install openjdk-21-jdk
These steps ensure you have Java 21 available, which is required for Haveno’s build .
Other build tools on Linux/macOS (like GCC, Make, etc.) are not explicitly needed beyond what the Haveno build scripts handle, but ensure basic development tools are present. Git is needed to clone the repository.
On Windows, the preferred approach is to use MSYS2 to provide a Unix-like environment and toolchain:
pacman -Syy, then install build tools and Git. For 64-bit Windows, run:bash
pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake git make mingw-w64-i686-... equivalents .bash
curl -s "https://get.sdkman.io" | bash
sdk install java 21.0.2.fx-librca JAVA_HOME is set appropriately if needed.After these steps, whether on Linux, macOS, or Windows, you should have Java 21 and a C++ toolchain available, which are necessary for building Haveno (the Haveno build process will compile some native components and bundled Monero code).
Haveno.com’s network uses a modified core codebase (a fork of the official Haveno DEX). It’s recommended to fork the repository and build from source to incorporate haveno.com’s customizations (such as custom network parameters, removed binaries, etc.). A known fork used in haveno.com’s deployment is maintained by Kewbit, which incrementally removes bundled binaries for cleaner builds .
Steps to build Haveno:
bash
git clone https://foss.haveno.com/haveno-network/haveno-core
cd haveno-core bash
make clean && skip-tests haveno-daemon, haveno-seednode, etc., or .jar files under desktop/build). Note: The haveno.com fork may update over time, ensure you keep your fork in sync with any upstream improvements. The build outputs will be used for setting up seed nodes, arbitrator app, and packaging the desktop application for users.
Since Haveno is a Monero-centric exchange, a Monero daemon (monerod) is a critical part of the infrastructure. Every seed node and arbitrator node must have access to a local, unrestricted Monero node for performance and full functionality . This allows Haveno to verify transactions, create multi-signature wallets, and monitor the Monero blockchain privately. There are multiple ways to set up a Monero node:
monerod as a system service. Haveno’s docs provide example .service and .conf files which you can customize with your preferred settings (data directory, RPC ports, etc.). For instance, you might create a /etc/systemd/system/monerod.service that runs monerod --rpc-bind-port 18081 --rpc-restricted-bind-ip 0.0.0.0 --no-igd --prune-blockchain (and any other desired flags) on startup. Ensure the Monero service runs as a non-root user (for security) and is set to restart on failure.make monerod in the Haveno project directory will start a mainnet Monero daemon, and make monerod-stagenet will start one on stagenet. This is useful for quick testing. In production, though, you’d likely prefer the daemon always running via systemd or Docker rather than a manual terminal.monerod on Windows. This can simplify running a node on a Windows server or even a desktop environment. The key is to run it in unrestricted mode (so that the Haveno processes can use the RPC).havenodex/monerod:latest which can be deployed in a Docker Compose setup . For example, a simple docker-compose.yml to run monerod might look like: ```yaml
version: '3'
services:
monerod:
image: havenodex/monerod:latest
restart: unless-stopped
volumes:
- monero-data:/home/monero/.bitmonero
ports:
- "18080:18080" # P2P port
- "18081:18081" # RPC (full access)
- "18089:18089" # RPC (restricted)
command:
- --rpc-bind-port=18081
- --rpc-restricted-bind-ip=0.0.0.0
- --rpc-restricted-bind-port=18089
- --no-igd
- --enable-dns-blocklist
- --prune-blockchain
volumes:
monero-data:
```
In this setup, port 18081 is the unrestricted RPC accessible (bound to all interfaces for convenience) and 18089 is a restricted RPC port for less trusted access . Haveno seed nodes and arbitrators should use the full RPC (http://localhost:18081 inside the container, or the container’s host IP) for complete access to wallet creation and transaction signing. The restricted RPC (which limits sensitive commands) can be exposed if you need external light wallets to connect. Always secure these ports behind a firewall or run on localhost if possible.
Regardless of how you deploy the Monero node, sync it fully to the Monero blockchain before enabling trading on Haveno. Use --prune-blockchain if disk space is a concern (pruned nodes are supported). Additionally, configure monerod for reliability: enable it to start on boot (via systemd or Docker), and consider using --db-sync-mode safe or fast as needed for your environment. For security, never use a remote third-party Monero node for seed/arbitrator roles, doing so could degrade performance and leak privacy. A local node is strongly recommended for all critical Haveno roles .
Optional: Haveno’s documentation references a Monero Suite tool that generates a Docker deployment based on a simple form. This could be useful if you want a quick way to get a preconfigured monerod container (with settings for remote access, etc.) without writing the compose file manually.
Price nodes are auxiliary services that fetch and serve market price data (exchange rates) to Haveno clients. They provide reference prices for XMR vs other currencies, which traders use when creating offers. In Haveno’s architecture, price nodes run independently (outside of the main Haveno daemon) and can operate on clearnet or as Tor hidden services. While not strictly required for the network to function, having at least one price node is important so that users can see price feeds and the app can compute suggested fiat/XMR conversion rates .
To set up a price node:
haveno-pricenode) and build or run a Docker image if provided. This service will typically fetch prices from external APIs (like Binance, CoinGecko, etc.) and serve them via a simple HTTP API.haveno-pricenode.service that executes the price node jar or binary and keep it running. If Docker is preferred, run the price node inside a container (check if an official image is available, or build one from the repo).DEFAULT_NODES list in ProvidersRepository.java to include the address of your new price node. This could be an onion address (http://<price_node_onion>.onion:port) or a clearnet URL. After adding it, recompile or distribute this updated client so that all users will use your price node by default. Alternatively, users can manually add a price node in their app settings, but having it in the defaults is easier.haveno-pricenode.env configuration file. Use this to set any needed environment variables, like API keys for data sources or listening port. Ensure the price node uses a stable port and, if running on Tor, has a persistent hidden service address.Once running, test that the price node is reachable. You can use a web browser or curl to GET the price endpoint (the specific path will be in the price node docs, e.g. something like /prices returning JSON). Haveno clients periodically poll these nodes to update the market price display.
Tip: Price nodes do not require access to the P2P network or Monero node, they are HTTP services. But to preserve privacy, it’s good practice to run price fetches through Tor or use privacy-respecting APIs. If running a clearnet price node, consider using a separate server from your seed nodes for better isolation.
Seed nodes form the backbone of the Haveno P2P network. They introduce peers to each other, track the network’s offer board, and distribute critical info like trade fees and arbitrator lists. In Haveno (like Bisq, on which it’s based), seed nodes are often run as Tor hidden services whose addresses are hardcoded into client binaries for bootstrapping. You should plan to run multiple seed nodes (for redundancy) and keep them online 24/7.
Haveno supports two modes for seed nodes:
This is the simpler configuration where clients can connect to the seed node without performing any extra handshake proof-of-work (PoW). The setup steps are:
monerod via RPC, so the Monero node must be running on the same machine and listening (e.g., on http://localhost:18081 for mainnet) .haveno-seednode). You can run this directly, but it’s best to set it up as a service. Customize the provided haveno-seednode.service template to your environment. Important settings include:--baseCurrencyNetwork=XMR_MAINNET) unless you are doing a stagenet/testnet.--nodePort=2002 for a seed node, 2002 is a common default for one seed, you can use different ports for others) .tor daemon on port 9050), the seed node will create an onion address automatically. You’ll see this in logs after startup (look for a line like “Hidden Service .onion has been announced to the Tor network” in the output). Copy that onion address, as it is the identifier for your seed node.--xmrNode=http://... option pointing to your Monero node’s RPC (e.g., --xmrNode=http://127.0.0.1:18081 for mainnet). This must be an unrestricted RPC.--useLocalhostForP2P=false (so it binds to all interfaces or to Tor, not just localhost) , and --appName=<name> to set a unique application data directory for the seed (to avoid conflicts with client app data) .bash
sudo systemctl enable haveno-seednode.service
sudo systemctl start haveno-seednode.service journalctl -u haveno-seednode.service -f to ensure it’s running. When it fully starts, note the Tor onion address it prints (as mentioned above) .xmr_mainnet.seedNodes or a constant array in the code). Haveno’s documentation suggests adding the onion to xmr_<network>.seednodes list. If you have multiple seed nodes, add all of them. Then recompile the Haveno client so that the default seed list includes your nodes. If you prefer not to hardcode, you can also manually give users the seed node addresses (via a config file or command-line), but hardcoding in the custom build is easiest for a controlled network.With basic seed nodes configured, new Haveno clients will connect through Tor to one of the seed onions and sync the network data (offers, etc.). Always keep your seed nodes online and monitor their logs for any issues.
Proof-of-Work enabled seed nodes require connecting peers to perform a lightweight computational puzzle to get service. This is a mechanism to mitigate DoS attacks on the seed node by malicious spam. Setting this up is a bit more involved, because Tor does not natively require PoW for hidden service client connections, it’s achieved via a Tor patch or addon.
To deploy a PoW-protected seed node, follow these additional steps (on top of the basic setup):
bash
sudo apt install tor deb.torproject.org-keyring torrc configuration with the one provided by Haveno (in the seednode/torrc file of the Haveno repo). The provided torrc is tuned for Haveno seed nodes. For instance, it likely sets HiddenServiceEnableIntroDoSDefense or similar options if available, and configures the SocksPort and onion service. Haveno’s example torrc also locks down Tor to only allow onion traffic on the Socks port and includes other hardening (like SocksPort 9050 OnionTrafficOnly, access policies, etc.) . Copy these settings to your Tor config (often in /etc/tor/torrc on Linux) and restart the tor service.haveno-seednode process is not launching an internal Tor (you might see an option like --useDevPrivilegeKeys=false which in older versions prevented some built-in Tor control, but primarily, running the tor daemon separately is the goal). If Haveno allows specifying the hidden service address manually (via --hiddenServiceAddress=<onion>), you could use that, but typically letting it register via Tor control is fine.PoW seed nodes are more resilient under potential denial-of-service floods but introduce a slight delay for first-time connections. Haveno’s documentation provides the necessary Tor configuration to enable this defense. It’s recommended to run at least one seed with PoW and perhaps one without (so new clients that don’t support the PoW protocol can still connect, if applicable).
Note: Setting up PoW on Tor can be complex. Haveno recommends using their Docker deployment for ease if you are not comfortable managing Tor configs. The Docker approach in the Haveno guide includes a custom Tor (or hardened torproxy) container with PoW defense enabled, simplifying this process.
Instead of manually installing Tor and configuring systemd, you can run seed nodes via Docker as well. Haveno’s repository includes a Dockerfile and instructions for seed nodes. In summary: build the haveno-seednode image from the repo’s docker/ folder, then run a container mapping the necessary ports. For example:
docker build -t haveno-seednode ./docker
docker run -d --name seed1 --restart unless-stopped -p 9050:9050 -p 2002:2002 haveno-seednode
Here port 2002 is the Haveno P2P port and 9050 is Tor’s SOCKS port. This assumes Tor is running in the container or the host. If using host Tor, you might not need to expose 9050. The container logs will show the onion address on startup , which you can then use as described earlier. Using Docker ensures the environment (Java version, Tor version, etc.) is consistent and easily replicable.
Haveno networks have special privilege keys for developers and admins that allow certain actions like setting network-wide parameters and sending alerts. Since you are launching your own Haveno network (not using the default haveno.exchange keys), you must generate and register new keys for the developer and alert roles in your custom build.
Haveno provides a Gradle task to generate new cryptographic keypairs:
bash
./gradlew generateKeypairs FilterManager.java. Insert the developer public key you generated into the list of recognized developer keys. (The code likely has a static list or array for developer pubkeys that are allowed to, say, set filters or perform certain moderation tasks.) If there were existing keys (from the original project), remove or disable them for your network, you want only your keys to have dev privileges on haveno.com’s network.AlertManager.java, and add the private notification key’s public key to PrivateNotificationManager.java. The “alert” key is used to broadcast system-wide alerts (messages that appear in all users’ apps in case of critical updates or warnings). The “private notification” key might be used for certain special messages or features (specific to Haveno’s design for sending encrypted notifications).Going forward, use the corresponding private keys when you need to perform the privileged actions (discussed in later sections like setting filters or sending alerts). It’s wise to back up these keys securely (offline). Only the network operator or trusted admin should hold the developer and alert private keys, as their misuse could compromise the network (e.g., a malicious “developer” could set harmful trade filters or an attacker with the alert key could send false alarm messages).
Arbitrators are the dispute resolvers and referees of the Haveno network. They operate special Haveno nodes with the authority to mediate trades and, if necessary, co-sign transactions in the 2-of-3 multisig escrow (the arbitrator holds the third key to adjudicate disputes). On a new Haveno network, you (as the operator) will designate one or more arbitrators. This involves generating arbitrator keys, running the arbitrator application, and informing the network of the arbitrators’ presence. Proper management of arbitrators includes their registration, operations, and possible removal.
generateKeypairs) to produce a new pair (or generate multiple at once). If you have already run it, you may have a set of keys ready. Each arbitrator needs a unique keypair. Record the arbitrator public key and private key securely.ArbitratorManager.java (or equivalent) and add the new arbitrator public key to the list of recognized arbitrators. Haveno’s code likely maintains an allowed list of arbitrator pubkeys to prevent unauthorized nodes from claiming to be arbitrators. By inserting the pubkey here, you indicate this key belongs to a valid arbitrator on your network. (Remove any default arbitrator keys that might have been there from testing networks.)arbitrator-desktop binary or you might run make arbitrator-desktop-mainnet to launch it. You can also start the normal Haveno GUI and choose to operate as arbitrator (depending on UI options). When the app opens, go to the Account tab (or a dedicated arbitrator console) and register the arbitrator:Operational notes: An arbitrator node, like seed nodes, must have a local Monero node with unrestricted RPC access. The arbitrator will actually construct and sign transactions during dispute resolution, which requires direct Monero wallet operations. In the arbitrator app settings, ensure it’s pointed to http://localhost:18081 (or wherever your monerod is) and fully synced. Also, run the arbitrator on a server or machine that is online as much as possible. Traders rely on arbitrators being available especially when a dispute arises. It’s acceptable to run an arbitrator on a VPS with a desktop environment (or use X forwarding) since it needs the GUI. Some operators run the arbitrator app in a VNC/XRDP session on a server so it stays running continuously.
If you plan to have multiple arbitrators, repeat the above for each (generate keys, add to code, run app). The network can support several arbitrators, possibly each handling different trades or serving as backup.
Arbitrators typically earn the trading fees or a portion of them as compensation for their service (similar to Bisq’s old model). In Haveno’s configuration, you can choose whether trade fees are “arbitrator-assigned” (i.e., go to the arbitrator) or go to a global address/fund. We will discuss how to configure this in the Trade Fees section, but keep in mind how you want to incentivize arbitrators.
Arbitrators on haveno.com’s network have special UI access as well: they can see open disputes, chat with traders, and ultimately unlock the multisig if needed. Ensure anyone acting as an arbitrator is trustworthy.
If an arbitrator needs to step down (or you need to remove one):
ArbitratorManager.java list in the next release of your client, so it’s no longer advertised as available. This prevents new clients from seeing a defunct arbitrator.After unregistering, traders will not be able to pick that arbitrator for new trades. If you had only one arbitrator and you remove it, your network will effectively pause trading that requires arbitration (since Haveno’s trade protocol typically requires an arbitrator). So ensure you have a replacement ready or plan a network shutdown.
Now that the core components are running, you should configure network-wide parameters to tailor the Haveno network to your needs. Haveno allows developers (with the dev key) to set certain network filters, define a custom network version (so that your forked network doesn’t accidentally mix with others), and adjust trade fee settings.
Network filters control what types of offers and data are allowed on your Haveno network. For example, you might want to restrict certain fiat currencies or payment methods, or set limits like minimum reputation, etc. Using your developer privileges, you can set these via the GUI:
For example, you might set a filter to ban certain payment methods that you consider high-risk, or to temporarily pause trading of an asset by filter. Use this capability cautiously, as it affects all users’ ability to create or take offers.
To ensure your custom Haveno network is isolated, update the network identifiers in the code before distributing your client:
DEFAULT_APP_NAME in HavenoExecutable.java (or similar) and set it to something unique (e.g., "haveno-reto" or "haveno-com" instead of the default). This prevents collisions with any other Haveno installations and clearly separates user data for your network.P2P_NETWORK_VERSION in Version.java and assign a new number or identifier. This version is used in handshake between nodes; by using a unique one, you avoid any chance of cross-talk between, say, haveno.com’s network and haveno.exchange’s test network (they will reject each other’s messages due to version mismatch). It’s good to increment from the base or use an unused high number for a private network.NETWORK_NAME environment variable as seen in the Docker config ). Ensure any configs or environment defaults reflect your network’s name (for example, if using Docker, set NETWORK_NAME=HavenoReto or similar).After changing these, rebuild all components. Distribute this updated version to everyone. This way, your network is distinctly identified — clients will show a custom app name and only connect to peers with matching version.
Haveno supports configuring trade fees (the fee a user pays per trade). Fees can either go to the arbitrator or to a specified address, depending on the model:
HavenoUtils.java (or a similar config class) in the code. There will be parameters for fees, possibly a percentage or a flat amount, and an option for fee recipient .Note: As of late 2024, the RetoSwap network had trade fees technically enabled in code but set effectively to zero or not applied in practice , meaning traders only paid Monero network fees. You can choose to start with zero fees to encourage adoption, then later enable fees via an update. If you change fees or fee distribution later, it likely requires a client update or at least a network alert to inform users.
Finally, keep all these config changes documented. If you ever update the network (new versions), increment the version constants again to force upgrades or maintain compatibility. Also, if you introduce a new filter or fee change on the fly, use the developer key to announce it or require an update (more on that below).
Before launching publicly, perform thorough user acceptance testing on your Haveno network:
bash
make user1-desktop-mainnet
make user2-desktop-mainnet make user1-desktop-stagenet) and run a Monero stagenet node (make monerod-stagenet). This way, XMR transactions are just test coins. (Note: ensure your seed nodes/arbitrator are also on stagenet mode if you do this.)By running these tests, you not only gain confidence in the system, but you’ll also generate signed payment accounts and other data that you can use to test the account signing feature (next sections). It’s also an opportunity to tweak any parameters (like timeouts or trade limits) before real users join.
Finally, recruit a few beta testers if possible. Share your custom Haveno installer with trusted community members to install on their machines and attempt trades with each other. External testers might discover issues you didn’t see (such as UI glitches or connectivity from different countries). Address any problems before public launch.
When you are satisfied with the network’s performance, you’ll need to distribute the Haveno desktop application to end users so they can start trading on your network. Haveno is cross-platform (Linux, macOS, Windows), and the build system can produce packaged installers for each.
Prepare the Build for Mainnet Release:
package.gradle or similar build config file to adjust any branding or network URLs. For example, update any download links or version strings that will be shown to users .Build the installers:
Haveno’s documentation refers to a packaging guide for building distribution files. Typically, you would run Gradle tasks to create installers. Possible tasks (to guess) might be: ./gradlew packager:assemble or similar, which would produce:
.deb or AppImage for LinuxCheck Haveno’s repository (perhaps the desktop/package/README.md) for exact instructions on packaging for each OS. According to community discussions, pre-built binaries are often provided, but since you have a custom network, you’ll build your own. Common tools used might include jpackage or Install4j.
If the build process is complex, consider providing a ZIP or portable version as well (especially for advanced Windows users who may just want a portable .jar or folder).
Distribute the application:
https://haveno.com/downloads/Haveno-1.0.0-Windows.exe etc.Before broad release, do one more smoke test using these actual packaged installers on each OS to ensure they run and connect to your network (for example, install the Windows .exe on a fresh Windows machine and verify it launches and connects to your seed node).
Maintaining the network means you’ll eventually release updates (bug fixes, new features) and you may need to communicate with all users for important announcements. Haveno includes mechanisms for both automatic updates and network-wide alerts, which leverage the keys we set up earlier.
If you have set up an auto-update URL in the app (Haveno may allow the client to check a URL for new versions), make sure to host the update files and update manifest. For example, you might have an endpoint that the client queries to see the latest version and download URL.
When a new version is ready:
To broadcast a message to all online users (and those who come online soon), use the alert system:
Alert messages are useful for urgent communications because they appear directly in the app. Use them sparingly and only for important matters, to avoid users tuning them out.
After sending, check on a client that the alert indeed appears. Alerts may also get logged on the console of clients as confirmation.
Tip: If you need to test alerts, you could do so on stagenet or with a dummy message. But avoid sending test alerts on mainnet as they reach real users.
With updates and alerts combined, you have control to ensure the network stays on the latest safe version and that users are informed of anything affecting their trading experience.
Haveno (like Bisq) implements a reputation system for payment accounts to enhance security in fiat trades. When a new user adds a payment account (e.g., a bank account, PayPal, Revolut, etc.), that account is initially “unsigned”, meaning it has no history of successful trades. Arbitrators can sign payment accounts after a successful trade or a resolved dispute, indicating that the account has been used legitimately in the network. A signed account is more trusted, which can allow higher trading limits or simply give other traders confidence.
As a network operator or arbitrator, you should understand how to sign accounts:
<witness_hash>,<pubkey_hash> for the payment account). Then use the shortcut Ctrl + I (to open the “Insert Key” dialog) followed by Ctrl + P (to sign the payment account). You will paste the hashes and apply your arbitrator signature. This attaches your arbitrator’s approval to that account.When you sign an account, what’s happening under the hood is that your arbitrator node’s private key is used to sign the account’s unique identifier. That signature is distributed and any user’s client can verify it against your arbitrator’s public key (which is known to the network). Thus, any user can see “Account XYZ is signed by arbitrator Alice (on date D)”, meaning it has been used in a real trade mediated by Alice.
Manage arbitrator signing responsibly: Only sign accounts for which you have reasonable assurance that the owner followed through with payment. Do not sign if an account was involved in fraud or if a user failed to pay, those accounts should remain untrusted. If an account is tied to a scam, obviously do not sign it (and perhaps you’d even blacklist it outside of this system).
Over time, accounts with more signatures (or from long-time arbitrators) gain reputation, which can be used to increase trading limits or auto-complete trades faster. Haveno’s implementation is evolving, but as an arbitrator you play a key role in bootstrapping trust.
By following this guide, you will have a fully functional Haveno exchange network, customized for haveno.com’s deployment. You set up robust backend services (seed nodes, price nodes, Monero nodes) on servers, established security through custom keys, and provided the client software for end users. Here are a few final best practices and tips to keep your Haveno network running smoothly:
journalctl for systemd services and docker-compose logs for Docker services to spot any errors (e.g., if a seed node crashes or Tor connection issues). Set up alerts if services go down.With creating a new work as long as you fork any of the main repositories you will be added to the haveno networks page on the website, when you're up and running, you are contributing to the Monero ecosystem by offering a private, peer-to-peer trading platform. Happy trading, and stay safe!