doc: run-lokinet-exit
Run a Lokinet exit node on a XmrCloud VPS — lokinet install, exit lokinet.ini, IP forwarding, abuse posture
abstract
abstract
Procedure for running a Lokinet exit node — a service that relays other people's traffic out to the clearnet — on an offshore XmrCloud VPS. Covers the deb.oxen.io install of lokinet, the exact exit lokinet.ini (exit=true, the persistent exit keyfile, ifaddr, hops), the IP-forwarding and NAT MASQUERADE that make the exit actually route, and how clients attach with lokinet-vpn. It is honest about the two things that matter: a Lokinet exit is a clearnet exit and attracts the same DMCA-and-abuse traffic as a Tor exit (unlike a low-abuse obfs4 bridge), and the distinction between a self-hosted exit SNApp — which needs no stake — and a network-advertised Oxen service node, which does.
Scope and assumptions
This is the operational walk-through for running a Lokinet exit node on a XmrCloud VPS. Lokinet is the Oxen project’s onion router; unlike a Tor onion service (which never touches the clearnet) or an I2P eepsite, an exit node’s entire job is to relay Lokinet clients’ traffic OUT to the public internet, so the exit’s IP is the source address a third-party server sees. That single fact drives everything honest about this doc — see the abuse discussion in step 5 before you commit. For how the three overlays compare, see /vs/i2p-vs-tor-vs-lokinet.
Baseline assumptions:
- Debian 12 (bookworm) on a XmrCloud VPS. Steps are identical on Ubuntu 22.04 / 24.04 LTS.
- The brand’s
hardened-by-defaultbaseline is in place. Seeharden-sshdandkernel-hardening-checklist. - The upstream provider has been told the box will run an exit that originates clearnet traffic, and permits it. XmrCloud’s exit-friendly jurisdictions apply here as they do for Tor exits; the productized, Oxen-service-node-backed tier is
/node/lokinet-exit, and a plain VPS for a self-hosted exit is/node/vps/vps-1. - Because the box is privacy infrastructure the operator usually wants it unlinkable — provisioned without KYC and paid in a way that leaves no billing trail. See
/paymentsfor the no-KYC rails.
1. Install lokinet from deb.oxen.io
Install from the Oxen project’s own apt repo, not the distro. Add the signing key and the release-matched repo line, then install: [oxen-io/lokinet — Debian/Ubuntu install]
apt update
apt install -y curl ca-certificates lsb-release
curl -so /etc/apt/trusted.gpg.d/oxen.gpg https://deb.oxen.io/pub.gpg
echo "deb https://deb.oxen.io $(lsb_release -sc) main" \
> /etc/apt/sources.list.d/oxen.list
apt update
apt install -y lokinet
The package installs its config at /etc/loki/lokinet.ini, runs the daemon under systemd as lokinet.service, keys and state live under /var/lib/lokinet/, and it creates a lokitun0 TUN interface at runtime. Confirm the daemon installed:
lokinet 0.9.11
2. Write the exit lokinet.ini
Edit /etc/loki/lokinet.ini. This is the upstream exit configuration: exit=true turns the instance into an exit, and a persistent keyfile gives it a stable .loki address across restarts (omit it and the address is ephemeral). [oxen-io/lokinet — exit-setup.md]
# /etc/loki/lokinet.ini — self-hosted Lokinet exit node.
[router]
# Keep enough router connections open to build reliable paths.
min-connections=8
max-connections=16
[network]
# exit=true is what makes this an EXIT: it relays clients' traffic to clearnet.
exit=true
# Persistent identity for the exit's .loki address. Without a keyfile the
# address changes on every restart, which breaks every client you handed it to.
keyfile=/var/lib/lokinet/exit.private
# reachable=1 publishes the exit so clients can find and use it.
reachable=1
# ifaddr = the internal range handed to clients routed through this exit.
# It must match the MASQUERADE source range you set in step 3.
ifaddr=10.0.0.1/16
# hops/paths — path length and count for the exit's own tunnels.
hops=2
paths=8
Restart the daemon to apply the config and mint the exit keypair:
systemctl restart lokinet
Back up /var/lib/lokinet/exit.private OFFLINE — it is the exit’s permanent identity, and losing it changes the .loki address your clients depend on.
3. Enable IP forwarding and NAT
exit=true tells lokinet to accept exit traffic, but the kernel still has to forward those packets to the real network and rewrite their source address. Enable forwarding and add a NAT MASQUERADE rule for the client range, sending it out the box’s real uplink interface (eth0 on most XmrCloud VPS — confirm with ip route get 1.1.1.1): [oxen-io/lokinet — exit-setup.md (forwarding + NAT)]
# Enable IPv4 forwarding now, and persist it across reboots.
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-lokinet-exit.conf
sysctl --system
# NAT the client range out the uplink. Source range MUST match ifaddr.
iptables -t nat -A POSTROUTING -s 10.0.0.0/16 -o eth0 -j MASQUERADE
The stock iptables command is not persistent — install iptables-persistent (or add the rule to your firewall management of choice) so the MASQUERADE survives a reboot:
apt install -y iptables-persistent
netfilter-persistent save
4. Confirm the exit is up and read its .loki address
Check the service and confirm the TUN interface came up:
● lokinet.service - Lokinet Onion Router Active: active (running) lokitun0 UNKNOWN 172.16.0.1/24
The exit’s .loki address is derived from exit.private and resolvable via lokinet’s own DNS resolver. Lokinet answers .loki lookups on 127.3.2.1 — query the special localhost.loki name to read THIS node’s own address: [Oxen docs — hosting SNApps (finding the .loki address)]
localhost.loki is an alias for <your-exit-address>.loki
That .loki address is what you hand to the clients you want to allow through this exit.
5. Understand the abuse posture before you announce it
This is the step most exit-node write-ups skip and the one that decides whether you should run an exit at all. Because the exit’s IP is the source address for its clients’ clearnet traffic, you will receive abuse mail — copyright notices, “your IP scanned us”, automated IDS reports — addressed to that IP. The Oxen exit documentation ships operator email-response templates precisely because upstream providers forward these to the exit operator. [oxen-io/oxen-docs — Lokinet exit node guide (abuse templates)]
Three things follow from that:
- Publish an operator contact and answer promptly. Silence reads to upstream as “unresponsive customer” and gets boxes suspended. XmrCloud’s operator does not process third-party abuse reports against tenant traffic — but the exit operator (you) still needs a monitored role address for upstream coordination.
- Pick the jurisdiction deliberately. An exit belongs in a jurisdiction with operator-friendly intermediary precedent, the same calculus as a Tor exit — not wherever is cheapest.
- Consider a non-exit role if the abuse surface is unacceptable. A Lokinet SNApp (a
.lokiservice that hosts content, withexitleft off) carries none of the clearnet-origin exposure — it is to a Lokinet exit what a hidden service is to a Tor exit.
6. Attach a client and verify egress
From a machine running lokinet, route it through your exit with lokinet-vpn, passing the exit’s .loki address (and an auth token if you gated the exit): [oxen-io/oxen-docs — using an exit (lokinet-vpn)]
exit enabled: <your-exit-address>.loki
With the client routed through the exit, a clearnet IP check from the client should now report the EXIT’s public IP, not the client’s:
<your-exit-vps-public-ip>
Tear the route down with lokinet-vpn --down. If the IP check still shows the client’s own address, forwarding or the MASQUERADE rule is wrong — recheck step 3, especially that -s 10.0.0.0/16 matches ifaddr.
Next steps
The exit is operational. In order:
- Distribute the
.lokiaddress to your intended clients over a trusted channel, and keep the operator contact monitored for the abuse mail that will arrive. - Watch the first weeks of abuse volume and decide honestly whether the role is sustainable for you. If it is not, retarget the box to a non-exit SNApp or a different overlay.
- If you want the exit to be a network-advertised, staked Oxen service node rather than a hand-distributed self-hosted exit, that is the
/node/lokinet-exittier — it bonds the box to the 15,000-OXEN service-node stake; the hosting fee itself is still payable in the usual rails, see/payments. - For the lower-abuse ways to contribute to an anonymity network on the same class of box, compare
run-obfs4-bridge(near-zero abuse) and the overlay trade-offs at/vs/i2p-vs-tor-vs-lokinet.
An exit is the most useful and the most demanding role in this manual. Run it only if you will answer the mail.