Run a SOV Node
Anyone can run a SOV node, join the peer mesh as a fully-equal peer, and earn the
operator payout for keeping the network alive. The hardware bar is deliberately low
— "a person with a small free VPS" qualifies. This guide takes you from nothing to a
converged, earning node, on any of the common hosts.This is the same operator walkthrough shown in the SOV app's Academy, expanded with
copy-pasteable commands for a technical reader.
Contents
- Where to run it — pick a host
- The firewall — the part that actually blocks people
- Google Cloud — stand up a free node
- Amazon AWS — stand up a node
- Oracle Cloud — free-forever node (recommended)
- Install the node software (the snap)
- Run a node on Windows — no VPS, no Linux
- How your node is found
- Earning — the operator payout
1. Where to run it — pick a host
| Host | Cost | Notes |
|---|---|---|
| Oracle Cloud "Always Free" ✅ recommended | Always Free tier (advertised with no expiry at the time of writing) | Pick shape VM.Standard.E2.1.Micro (AMD x86_64). |
Google Cloud e2-micro |
Always-free tier | Free in us-west1 / us-central1 / us-east1. Keep a billing alert on. |
Amazon AWS t3.micro/t2.micro |
Time-limited free offer, then paid (check current terms) | Fine to learn on; not ideal for a node you want to keep for years. |
| Your own computer at home (Windows, macOS or Linux) | Free · no VPS · easiest | The SOV app is itself a full node — see section 7. |
Any provider works — a paid droplet, a home server. A public IPv4 with ports you can open makes
a node a direct peer; without one it still serves through other nodes.
🔴 The one hard rule: choose x86_64, not ARM
The node ships an x86_64 Node.js runtime and a native AES SQLite module. It will
not start on an ARM machine. Avoid Oracle Ampere A1 (VM.Standard.A1.Flex)
and AWS Graviton — pick an Intel/AMD (x86_64) shape.
Tested on: Ubuntu 22.04 LTS, 1 GB RAM (Google e2-micro, Oracle E2.1.Micro). A public IPv4 makes it a direct peer.
2. The firewall — the part that actually blocks people
The single most common reason a node "installs fine but nobody can reach it" is the
firewall. Cloud providers block inbound ports in two separate places, and a directly reachable node needs both open. A node that cannot open them still works — it falls back to serving through other nodes automatically (see “Circuit relay” below), which is slower but needs no configuration at all. Opening both is how you become a fully direct peer, not how you become a peer.
- Door 1 — the cloud firewall (in the provider console): a Security List on
Oracle, a Security Group on AWS, or a VPC firewall rule on Google. - Door 2 — the machine's own firewall (Ubuntu
iptables/ufwon the box).
Oracle images in particular ship this closed — it's the number-one "the console
says the port is open but the box still drops it" cause.
Open these inbound, TCP, source 0.0.0.0/0:
| Port | Purpose | Open? |
|---|---|---|
| 443 | Citizens connect here (the main one) | ✅ open |
| 7771 | Peer mesh — node to node | ✅ open |
| 80 | Snap download + health | ✅ open |
| 22 | SSH — admin (tighten source to your IP) | ✅ open |
| 8080 | Node dashboard — localhost only | ❌ keep closed |
Never expose 8080 to the internet — it is the private node dashboard and is meant
to stay on localhost.
Get these ports right and the rest of running a node is easy. The three cloud sections
below show exactly where each provider hides Door 1.
3. Google Cloud — stand up a free node
Recorded for real on Google Cloud (account details and addresses hidden). Three short parts:
Create the instance
- Compute Engine → VM instances → Create instance. Name it (we use
sov-node). Regionus-central1,us-west1orus-east1— the regions where the freee2-microis offered. Series E2, machine typee2-micro. - OS and storage → Change: Ubuntu 22.04 LTS (x86/64), boot disk Standard persistent disk, 30 GB (the size the free tier covers) → Select.
- Networking: in Network tags type
sov-node— the firewall rule below uses this tag. Keep External IPv4 address: Ephemeral (the public address). - Security → Manage access → Add manually generated SSH keys → Add item: paste your public key. The key's last word becomes your username on the server.
- Create. Note the External IP.
The price estimate shows the normal price; Google's free tier covers one e2-micro a month in those
three regions.
Open the ports (VPC firewall — Door 1)
- Search firewall → Firewall → Create firewall rule. Name
allow-sov-node, networkdefault, direction Ingress, action Allow. - Targets Specified target tags →
sov-node· Source IPv4 ranges0.0.0.0/0. - Specified protocols and ports → TCP →
80,443,7771→ Create. (SSH, port 22, is already allowed by Google's default rule.)
Door 2: Google's Ubuntu image has no host firewall to open — sudo iptables -L INPUT -n
shows policy ACCEPT. Check from your own computer with nc -zv -w 5 <your-server-ip> 443 7771:
Connection refused means open (nothing listening yet); No route to host means the rule or the tag is missing.
Then install the node as in section 6.
⚠️ GCP free instances have been billing-terminated before. Set a Budget alert
(e.g. at \$1) so an accident can't silently run up a bill.
4. Amazon AWS — stand up a node
Launch the instance
- EC2 → Launch instance. AMI Ubuntu 22.04 LTS (64-bit x86), type
t3.micro
ort2.micro(free-tier eligible). - Create/choose a key pair and download the
.pem— that's your SSH key. Launch,
and note the Public IPv4.
Open the ports (Security Group — Door 1)
- EC2 → Network & Security → Security Groups → select this instance's group →
Inbound rules → Edit. - Add rule → Custom TCP → port
443→ source Anywhere-IPv4 (0.0.0.0/0). Repeat
for 7771 and 80. - Keep the SSH (22) rule but tighten its source to My IP. Save rules.
⏳ The AWS free offer is time-limited — great to learn on, but for a permanent node
prefer Oracle Always Free (check current terms).
5. Oracle Cloud — free-forever node (recommended)
Recorded for real on Oracle Cloud (account details and addresses hidden). Three short parts:
Oracle Cloud Infrastructure "Always Free" is the recommended host: at the time of writing it is
advertised as free with no expiry (check Oracle's current terms).
Create the instance
- Compute → Instances → Create. Image Canonical Ubuntu 22.04.
- Change shape → AMD →
VM.Standard.E2.1.Micro(Always-Free-eligible). Do NOT
pick Ampere A1 — that is ARM and the node won't run on it. - Assign a public IPv4 = Yes. Paste your SSH public key. Create, and copy the
Public IP.
Door 1 — cloud Security List
- Networking → Virtual Cloud Networks → your VCN → Security Lists → Default → Add
Ingress Rules. - Source
0.0.0.0/0· IP Protocol TCP · Destination Port Range80,443,7771(22 is already there). Oracle creates one rule per port.
Door 2 — the box's own firewall (Oracle images block these by default)
sudo iptables -I INPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT
sudo iptables -I INPUT -p tcp -m state --state NEW --dport 7771 -j ACCEPT
sudo netfilter-persistent save # persists across reboot
sudo iptables -L INPUT -n --line-numbers # the new rules must sit ABOVE the REJECT line
No position number: -I INPUT puts each rule at the top. (An older version of this guide said
-I INPUT 6; on a current Oracle Ubuntu 22.04 image the REJECT rule is line 5, so that put the rules
below it and the ports stayed blocked.)
Check it from your own computer (needs nc):
nc -zv -w 5 <your-server-ip> 443 7771
No route to host or a timeout = still blocked (check both doors). Connection refused = the
port is open and reachable — nothing answers only because the node is not running yet. Test 443 and 7771:
many home connections answer port 80 by themselves, so a port-80 test from home proves nothing.
❗ Skipping Door 2 is the classic Oracle mistake — the console shows the ports "open"
while the box still silently drops them.
6. Install the node software (the snap)
You may not need this section at all. The desktop app is a full node on all three systems: Windows, macOS and Linux. Install it, switch the node on, and you are serving — no snap, no VPS, no terminal. That is section 7, and for most operators it is the whole job.
This section is the headless server route: the standalone package for a machine with no desktop. Every command below works as written, and every output shown is real, taken from a fresh install of version 1.4.88 (your version and hashes will be whatever the network runs today); only the SOV ID is replaced with an example. You never need a node’s address: they are not published, and the node finds the network by itself.
The node software is the exact package every node on the network runs. Get it whichever way suits you — the checksum is the same for all of them:
- In a browser: the download page, under Run a node on a server.
- In a terminal (below): straight from the public release.
- By torrent — seeded by a network node, with a GitHub web seed, so it completes even if one source is down: sov-relay.snap.torrent.
- On IPFS — the CID is on the download page.
Download
curl -LO https://github.com/sov-network/relay-releases/releases/latest/download/sov-relay.snap
curl -LO https://github.com/sov-network/relay-releases/releases/latest/download/sov-relay.snap.sha256
sha256sum -c sov-relay.snap.sha256
Real output of the last line:
sov-relay.snap: OK
Check it a second way. The torrent comes over a different route, from a network node (with a GitHub web seed). Two routes agreeing is what makes a tampered copy implausible:
aria2c --seed-time=0 -d via-torrent https://sov-network.github.io/torrents/sov-relay.snap.torrent
sha256sum sov-relay.snap via-torrent/sov-relay.snap # both MUST match
91d58f27a67700b1d285247f469394263f0ba73bf4ab8d60dccfdd2abd86385f sov-relay.snap
91d58f27a67700b1d285247f469394263f0ba73bf4ab8d60dccfdd2abd86385f via-torrent/sov-relay.snap
If they differ, stop. Do not install it.
Install (--dangerous = not from the Snap Store, by design; --devmode =
unconfined sandbox for now)
sudo apt-get update && sudo apt-get install -y snapd
sudo snap install --dangerous --devmode sov-relay.snap
Then verify what actually landed on disk. This is the step people skip, and it is the one that matters: it proves the software now installed is the software you checked.
snap list sov-relay # note the Rev, e.g. x1
sudo sha256sum /var/lib/snapd/snaps/sov-relay_x1.snap
Real output (your version and hash will be whatever the network runs today):
Name Version Rev Tracking Publisher Notes
sov-relay 1.4.88-plain x1 - - devmode
91d58f27a67700b1d285247f469394263f0ba73bf4ab8d60dccfdd2abd86385f /var/lib/snapd/snaps/sov-relay_x1.snap
The hash must equal the one you checked above. There is one more check you cannot skip, and it is automatic: the network admits a node only if it runs exactly the software the network runs, so a node that joins is running a genuine copy.
Tell the node who you are
One command. It asks for your SOV ID, checks it while you are still sitting there, and writes the configuration itself.
sudo snap run sov-relay.setup
This is real output from an operator setting up a node, including the typo, because mistyping the ID is the mistake that actually happens. At the network address, just press Enter:
SOV Node — operator setup
------------------------------------------------------------
Your Sovereign ID is the wallet the network pays for your proof of service.
Enrol on the SOV phone app, then copy it from Profile.
Form: SOV- followed by 16 hex characters.
Sovereign ID: SOV-1A2B3C4D5E6F7A8
That is not a Sovereign ID. Expected SOV- then 16 hex characters,
for example SOV-1A2B3C4D5E6F7A8B. Copy it exactly from Profile.
Your Sovereign ID is the wallet the network pays for your proof of service.
Enrol on the SOV phone app, then copy it from Profile.
Form: SOV- followed by 16 hex characters.
Sovereign ID: SOV-1A2B3C4D5E6F7A8B
Looks right.
No network address is needed: just press Enter and the node finds the network by itself.
If another operator gave you their node's address, you can enter it to connect faster.
Network address (optional, press Enter to skip):
Host hygiene
------------------------------------------------------------
journald has no size cap, so logs grow until the disk is full.
Cap the system journal at 200 MB? [Y/n]
journald capped at 200 MB and vacuumed (backup: journald.conf.bak_sovsetup)
Swap present: 4096 MB
vm.swappiness is 60 (swaps eagerly). 10 is better for a node.
Set vm.swappiness=10? [Y/n]
vm.swappiness=10 (persisted in /etc/sysctl.conf)
Everything else looks after itself: the node prunes its own history hourly,
compacts its database (auto_vacuum=INCREMENTAL), reaps dead peers, and
back-fills any table that drifts from its peers. Nothing here recurs.
Saved to /var/snap/sov-relay/x1/.env
operator : SOV-1A2B3C4D5E6F7A8B
network address: none - the node finds the network by itself
Start the node and watch it join:
sudo snap restart sov-relay
sudo snap logs -f sov-relay.sov-relay
The mistake is caught while you are typing rather than three restarts later. That is the entire reason this command exists.
Run setup first. A freshly installed node waits for it: until it has your SOV ID
it does not start, and its log says Not set up yet and names this command.
About the network address. Leave it blank. Node addresses are not published anywhere, on purpose, and a node needs none: it finds the network through the public peer-to-peer directory (the BitTorrent DHT), usually within a minute.
A brand-new node refuses to start without a SOV ID, on purpose. Left empty, the network has no wallet to credit — you would serve citizens for weeks and earn nothing, with nothing on screen to tell you. A mistyped ID is refused too, because an ID nobody owns sends your payouts nowhere. Upgrading a node that already has an identity only warns, so an update can never take your node down over a config field.
What a refusal actually looks like. Two mistakes account for nearly every failed first boot, and the node names both of them rather than exiting quietly. This is real output, not an illustration.
You left the field blank:
[1/9] Verifying software integrity...
✓ Source files verified
✓ Source root: e1e934b3889658c6... (63 files)
[2/9] Loading node identity...
==============================================================
CANNOT START — operator Sovereign ID problem
==============================================================
OPERATOR_SOVEREIGN_ID is not set.
This node would serve citizens but earn nothing, because the network has
no wallet to credit for your proof of service.
Enrol on the SOV phone app, copy your SOV ID from Profile, set it in
your .env, then start the node again.
You mistyped it — here, one character short:
[2/9] Loading node identity...
==============================================================
CANNOT START — operator Sovereign ID problem
==============================================================
OPERATOR_SOVEREIGN_ID is "SOV-CA234DCCA7BDEDE", which is not a SOV ID.
Expected SOV- followed by 16 hex characters, e.g. SOV-1A2B3C4D5E6F7A8B.
Copy it exactly from your wallet: Profile -> your SOV ID.
Refusing is deliberate. A node that started anyway would serve citizens perfectly well for weeks while quietly earning nothing, and you would have no way to notice. A wrong ID is worse than a blank one, because the payouts go somewhere real that simply is not you.
And when it is right, step 2 says so plainly:
[2/9] Loading node identity...
First run — generating node identity...
Private key stored in encrypted file (AES-256-GCM)
✓ Operator: SOV-CA234DCCA7BDEDEB
✓ Node ID: 31dbbe855da81c624c37825a50ac0797...
✓ Key: encrypted-file
What the rest of the network does with that ID. Your node does not admit itself. When it first meets the mesh it sends a signup, and the peers that receive it check, on their own copies of the ledger, that the SOV ID belongs to a real enrolled citizen and that the node runs exactly the software the rest of the network runs. Extra nodes are admitted, but a citizen's fourth and later relays earn nothing. A node offering no ID at all is refused outright — anonymous nodes are exactly what a Sybil attack is made of.
It is not put to every node on the network, which would get slower the more the network grew. A small sample of peers is asked (currently 5), and a set number of them (currently 3, never more than the peers available) must sign approval; other nodes accept the newcomer only with a certificate of those signatures from nodes they already know. The cost stays flat as the network grows. The check itself is free — every node already holds the enrollment ledger, so "is this a real citizen" is answered locally, never by asking anyone.
Start it and watch it join
sudo snap restart sov-relay
sudo snap logs -f sov-relay.sov-relay
A healthy first boot walks through nine steps, finds the network with no address given, receives the network’s biometric seed and the citizen records, and asks a sample of peers to approve it. These are real lines from a fresh install (a selection; node IDs shortened):
[1/9] Verifying software integrity...
✓ Source root: e1e934b3889658c6... (63 files)
[2/9] Loading node identity...
✓ Operator: SOV-1A2B3C4D5E6F7A8B
[3/9] Opening node database...
ℹ No citizens yet - their records arrive from peers once this node joins.
[4/9] Configuring network reachability...
✓ Reachability: circuit-relay
[5/9] Loading node discovery pool...
No address given - finding the network through the DHT (this can take a minute)
✓ DHT announce active (infohash 97d02d0ec4c5…, storage refused)
Peer mesh server listening on :7771
[6/9] Starting phone mesh fragment router...
[7/9] Starting SOV transfer engine...
✓ Guard 1 (nonce chain) active
✓ Guard 2 (spend lock) active
✓ Guard 3 (version gate) active
✓ Operator engine initialised
[8/9] Opening citizen gateway...
✓ Listening for SOV app connections
[9/9] Starting system tray and operator dashboard...
✓ Operator dashboard at http://127.0.0.1:8080/dashboard
✓ Operator dashboard at http://127.0.0.1:8080/dashboard
[Mesh] Waiting for the network biometric seed - it arrives with this node's approval; duplicate detection starts then
[Mesh] Peer connected: … v1.0.0
[Mesh] Peer connected: … v1.0.0
[Mesh] Adopted the network seed from … — biometric dedup is now interoperable (fp=…).
[Mesh] Peer connected: … v1.0.0
[Mesh] STATE_DELTA: synced 2 enrollments
[Operator] Signing up: asking 3 peer(s); 3 signed approval(s) needed
[Operator] Approval 1/3 from …
[Operator] Approval 2/3 from …
[Operator] ✓ Registration approved by 3 peer(s)
[Operator] Registered locally (approved by: …, …, …)
How to read it. Step 2 is the one to check first: if it stops with
CANNOT START — operator Sovereign ID problem, run
sudo snap run sov-relay.setup again before walking away. The last lines are the
ones that matter: Registration approved by 3 peer(s) means the network has checked
you and accepted the node. At step 4, Reachability: circuit-relay is
normal and fine — it means your box sits behind NAT and reaches the mesh through peers
instead of directly. Step 5 binding :7771 is what proves the peer mesh came up; if
you see EADDRINUSE retries there instead, a second copy of the node is almost
certainly already running.
Once it converges and stays continuously up for the qualifying period (about three weeks), your node begins earning the operator payout.
The default ports are
SOV_PORT=443(citizen WebSocket) andSYNC_PORT=7771(peer
mesh). If you must move the citizen port (e.g. 443 is already taken by nginx), set
SOV_PORTin the.envand open that port in both firewall layers instead.
7. Run a node on Windows — no VPS, no Linux
You don't need a VPS, Linux, or any firewall edits to be an operator — the SOV Windows
app is itself a full node.
Path A — normal home broadband
- Install the SOV app (
SovNode.exe) and sign in / restore your wallet. - On Home, tap "SOV Network · View Dashboard →" to open Node Status. Leave "How citizens reach this node" on Automatic.
- Switch Full Node ON. It opens your router by UPnP, or relays through the SOV
mesh if it can't. When it is serving, the status line reads "Serving citizens".
That's the whole setup for most people. Keep the PC on — uptime is what earns.
Path B — mobile hotspot / CGNAT / "can't port-forward"
Use this if Path A can't make you reachable (common on mobile hotspots and CGNAT ISPs).
Tailscale Funnel gives your node a stable public HTTPS address (free on its personal plan at the time of writing), over a
purely outbound connection — no port-forward, no domain, no VPS.
- Make a free Tailscale account at
login.tailscale.com/startand install Tailscale for
Windows; log in once. (Tailscale uses SSO — there is no in-app password by design.) - In the SOV app: Home → "SOV Network · View Dashboard →" → set "How citizens reach this node" to Tailscale Funnel → switch Full Node ON.
- The first time only, tap "Enable Tailscale Funnel" and click Approve in the
browser. The app then serves atwss://<your-pc>.<tailnet>.ts.net.
Behind CGNAT the peer-mesh port (7771) is outbound-only — that's normal; citizens still
reach you inbound on 443 via Funnel.
Reachable vs running — what the status means
A node can be on the network and still be reaching nobody. It holds the ledger, it talks to other nodes outbound, and it looks busy — but if nothing from the outside can open a connection to it, no citizen is being served there. The two are different, and the app says which is true instead of flattering you:
- Starting • joining the mesh… — the node has just been switched on.
- Joining the mesh — the node is up and working out how the network will route citizens to it. If no direct route exists it serves through the mesh automatically.
- Serving citizens — citizens can reach the node: directly, through Tailscale Funnel, or through the mesh.
On a home connection the most common reason a node stays on "Joining the mesh" for a while is simply that nothing is letting the outside in yet. There are three ways to fix it, and the node picks the best one it can:
- Forward the ports on your router. Open the mesh and gateway ports and point them at the computer running the node. This is the most direct route: peers connect straight to you. It needs a router you can log into and a connection that isn't behind carrier-grade NAT (most home lines are fine).
- Use a tunnel (no port-forward needed). If you can't open ports — a locked-down router, or a mobile/hotspot connection where the address isn't yours to forward — a tunnel service can carry inbound traffic to your node over an outbound connection it makes itself. This is the path that works behind carrier NAT, where forwarding is impossible.
- Circuit relay (automatic). If neither of the above is set up, the node is still reached indirectly, through other nodes. It works everywhere with no configuration, but a direct route is better when you can get one.
An old, always-on computer at home is well suited to this: left on with the screen off, it can serve the network around the clock. The node has no window and needs none — it is a server, the same as any cloud node. You run the wallet app on whatever device you already use; the home machine just earns to that wallet.
8. How your node is found
Nothing publishes your address for you, and no address is written into the wallet app. If it were, every published build would be a list of the machines worth pressuring — and the app would stop working the day those particular machines went away.
Instead the app ships a path to discovery and walks it in order:
- Nodes it has reached before — nothing to look up.
- Pointer mirrors — small files on independent hosts that say where the network currently is. They can be updated without shipping a new app, and they are asked all together rather than trusting whichever answers first, so one stale mirror can never shrink the list.
- The public BitTorrent DHT — the same global table torrent clients have kept running for twenty years. Nobody owns it, so there is nobody to serve an order to, and nothing for anyone to switch off.
Your node announces itself to that table when it starts, and re-announces every fifteen minutes. That announcement is what lets someone who has never heard of you, holds no list, and was given no address, find you.
Telling a SOV node apart from a stranger. Anyone can announce on a public identifier, and some do — crawlers announce across many of them just to map the network. So a discovered address is a place to knock, never a node. Two checks, one free and one conclusive:
- The port. A SOV node always announces the mesh port. Anything else is dropped without a single packet being sent. In a real run, ten announcements came back and seven were discarded this way — including the right machine on the wrong port, because the port is what identifies the service.
- The signed pool. What survives must serve a pool listing that is signed and carries proper node identities. A parked domain or a crawler's web server will happily return something; none of them return that.
Only what passes both is connected to, and only what answers correctly is remembered. This is why a stranger on the same identifier costs nothing, and why the pool stays a list of real nodes rather than a list of addresses that were once mentioned somewhere.
If your node is behind Tailscale or CGNAT, it will not appear in the DHT — and that is correct, not a fault. A DHT entry can only hold a raw address and a port; there is no room in it for a name. Publishing one anyway would advertise your home connection, where nothing is listening, and hand every new user a dead address. Your node is found through the pool instead, which carries full addresses and is passed between nodes as they meet. Discovery still works in the other direction: your node finds the network through the DHT perfectly well from behind any NAT.
9. Earning — the operator payout
Running a node earns SOV for the real work of keeping the network running: staying online and
serving (a per-transaction reward also exists, currently set to 0 by vote).
- A node must be continuously up for a qualifying period (a governance-set default of
about three weeks) before it earns — sleeping or shutting the machine down breaks the
streak, so payouts reward genuine uptime, not machines that are mostly off. - Payment is a fixed reward per relay per 30-day period (currently 20 SOV, set by vote), with a
steep anti-monopoly curve: your first relay earns the full reward, a second and third
earn a quarter each, and a fourth or beyond earns nothing — so running a farm of
nodes gives you no advantage, and the network stays spread across many independent
operators. - Operators are paid from the fees that flow in first, and only then, capped, from
the genesis reserve — so as the network grows and fee revenue rises, it funds its own
operators and the reserve becomes a long-term runway rather than a pot that drains.
You can watch every fee flow into the pool and every payout leave it on the app's live
SOV Economy screen — the ledger is public.
This guide is part of the SOV Network Academy. For what SOV is and how to use it, see
the Knowledge Bank.
SOV NETWORK