How to Set Up a TRON Node (the Pragmatic Way)
Run a TRON node without 3 TB of disk: Lite FullNode from a snapshot, systemd and Docker setups, hardware table, costs, and the API break-even.
Most people who search for “tron node” want one thing: direct access to the chain that moves a huge share of the world’s USDT. The official documentation answers with a Java toolchain — install JDK 1.8, clone java-tron, build with Gradle, tune the JVM. This guide takes the pragmatic route instead: the prebuilt FullNode.jar from the release page plus a Lite FullNode snapshot, which shrinks the disk requirement from more than 3 TB to a few hundred GB. Docker follows as the zero-Java alternative, then sync times, a cost calculation and the honest break-even against an API.
What is a TRON node?
A TRON node runs java-tron, the reference client, and connects you to the network that validates transactions every 3 seconds. It exposes two APIs for applications: HTTP on port 8090 and gRPC on port 50051. Through them you can deploy and call contracts, transfer TRX and tokens, and query chain state — the node is the entry point for everything you build on TRON.
The client moves faster than its JDK-8 toolchain suggests: GreatVoyage-v4.8.0 (Kant) shipped in February 2026, and the current release is v4.8.1.1 (Hypatia, June 2026). Nearly every release carries the “mandatory upgrade” label, which shapes the maintenance routine later in this guide.
Node roles, sorted by relevance. A FullNode validates and relays blocks and answers API queries; in almost every case, this is the one you want. A witness node produces blocks, which is reserved for the 27 super representatives elected by TRX votes — everyone else’s --witness flag does nothing useful. On the storage axis there are two variants: a standard FullNode carries the full transaction history — around 3 TB in mid-2026 and growing; the official March 2026 snapshots weigh 2.9–3.1 TB depending on variant — while a Lite FullNode starts from a state-only snapshot in the 100 GB class.
The Lite FullNode covers everything a payments backend needs: current state, new blocks, broadcasting transactions, watching deposits. What it cannot do is answer questions about history from before its snapshot — querying an old transaction by ID will fail. Explorers and analytics platforms need full history. Most integrations do not.
The three roles side by side, with mid-2026 numbers:
| Lite FullNode | FullNode (full history) | Witness (SR) node | |
|---|---|---|---|
| Disk | snapshot in the 100 GB class; plan 300–500 GB | official snapshots 2.9–3.1 TB; plan 4 TB | full-history spec plus production headroom |
| History | from its snapshot forward | complete since genesis | complete |
| HTTP/gRPC APIs | yes | yes | yes, though SRs separate RPC from block production |
| Produces blocks | no | no | yes — only the 27 elected SRs |
| Typical operator | payment backends, integrations | explorers, analytics, compliance archives | elected super representatives |
Hardware: FullNode vs. Lite FullNode
| Component | FullNode (full history) | Lite FullNode |
|---|---|---|
| CPU | 16 cores | 8–16 cores |
| RAM | 32 GB (64 GB for block production) | 16–32 GB |
| Disk | 3 TB+ NVMe, growing | 300–500 GB NVMe (snapshot ~100–200 GB plus growth) |
| Network | 100 Mbit/s | 100 Mbit/s |
The CPU and RAM rows extend the official recommendation (16 cores, 32 GB, “2.5 TB+” — written when the chain was smaller). The RAM matters twice on TRON: once for the JVM heap and once for the operating system’s file cache, which is why a 32 GB machine runs noticeably smoother than a 16 GB one even for a Lite node.
Step by step: Lite FullNode with the release jar
Commands assume Ubuntu 24.04.
1. Install Java 8
java-tron still targets JDK 1.8 in 2026 — an oddity, but non-negotiable. Newer JVMs fail at startup.
sudo apt updatesudo apt install -y openjdk-8-jdkjava -version # must report 1.8.x2. Create a user and directories
sudo useradd --no-create-home --shell /usr/sbin/nologin tronsudo mkdir -p /opt/tron /var/lib/tronsudo chown -R tron:tron /opt/tron /var/lib/tron3. Download the release jar and the mainnet config
No Gradle build needed; every java-tron release ships a ready FullNode.jar:
cd /opt/tronsudo -u tron wget $(curl -s https://api.github.com/repos/tronprotocol/java-tron/releases/latest \ | grep browser_download_url | grep FullNode.jar | cut -d '"' -f 4)sudo -u tron wget https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.confRelease pages publish checksums — run sha256sum FullNode.jar and compare before you run code that will hold network connections open for months.
4. Restore the Lite FullNode snapshot
The official database-snapshots page on the TRON developer hub lists mirrors in Singapore and the US that publish fresh archives daily, in LevelDB and RocksDB flavors — take LevelDB unless your config says otherwise, because the database engine must match the snapshot. Lite archives follow TIP-128’s design goal of about 3 percent of a full database; with the March 2026 full snapshots at 2.9–3.1 TB (3.6 TB for the variant that adds address balance history), that puts the Lite download in the low hundreds of GB. Pick the mirror closest to your server, copy the current link and:
cd /var/lib/tronsudo -u tron wget '<PASTE_LITE_SNAPSHOT_URL>'sudo -u tron tar xzf LiteFullNode_output-directory.tgzAfter extraction you should have /var/lib/tron/output-directory containing the database. That folder is the entire “sync from snapshot” trick — the node starts on top of this state instead of replaying years of blocks. If you ever restore the full-history variant instead, use the streamed form the mirrors recommend — wget -qO- '<URL>' | tar xz — so the 3 TB archive never sits on disk next to its extracted copy. For the Lite archive, download-then-extract is fine.
5. systemd unit
Create /etc/systemd/system/tron.service:
[Unit]Description=TRON Lite FullNode (java-tron)After=network-online.targetWants=network-online.target
[Service]User=tronGroup=tronType=simpleRestart=alwaysRestartSec=10WorkingDirectory=/var/lib/tronExecStart=/usr/bin/java -Xmx24g -XX:+UseConcMarkSweepGC \ -jar /opt/tron/FullNode.jar \ -c /opt/tron/main_net_config.conf \ -d /var/lib/tron/output-directory
[Install]WantedBy=multi-user.targetTwo JVM details straight from the official docs: the garbage-collector flag belongs before -jar, not after it, and -Xmx should be about 80% of physical RAM — 24g fits a 32 GB machine; scale it down on smaller boxes. systemd stops the service with SIGTERM, which matches the docs’ kill -15 instruction. Never kill -9 a TRON node; LevelDB corrupts, and you will be restoring a snapshot instead of having dinner.
Open the P2P port, keep the API ports private:
sudo ufw allow 18888 comment 'tron p2p'Ports 8090 and 50051 carry no authentication. They stay closed to the internet.
6. Start and verify
sudo systemctl daemon-reloadsudo systemctl enable --now tronjournalctl -fu tronOnce block messages appear, check the height:
curl -s http://127.0.0.1:8090/wallet/getnowblock | jq '.block_header.raw_data.number'Compare the number with the latest block on tronscan.org; curl http://127.0.0.1:8090/wallet/getnodeinfo additionally shows peer count and sync status. When your height tracks the explorer’s, the node is live.
A word on block production, since the official docs spend pages on it: a witness node only makes sense for the 27 elected super representatives. The mechanics — --witness flag plus the SR private key in the localwitness list of main_net_config.conf, or the keystore-plus-password variant if you refuse plaintext keys — are documented upstream. For everyone else, a plain FullNode is the right target.
Docker instead of Java
The top-ranking TRON guides all skip Docker, yet the official image makes the JDK-8 requirement someone else’s problem:
docker pull tronprotocol/java-trondocker run -d --name tron --restart unless-stopped \ -p 127.0.0.1:8090:8090 -p 127.0.0.1:50051:50051 \ -p 18888:18888 -p 18888:18888/udp \ -v /var/lib/tron/output-directory:/java-tron/output-directory \ tronprotocol/java-tronThe volume mount reuses the Lite snapshot from step 4, so starting the container is not a re-sync. Binding 8090 and 50051 to 127.0.0.1 keeps the APIs private while the P2P port stays reachable. For custom settings, mount your main_net_config.conf into the container and pass -c as a command argument; without it, the image runs mainnet defaults. If your host runs anything else in containers already, this is the cleaner setup — one image upgrade replaces the whole Java stack.
Sync time and snapshot handling
Arithmetic, not promises. A 150 GB Lite archive at a sustained 50 MB/s downloads in about 50 minutes; extraction adds minutes on NVMe. The snapshot is at most a day old, and TRON produces about 28,800 blocks per day at its 3-second interval — a healthy node imports far faster than real time, so catch-up costs minutes to a few hours. Total: a working Lite FullNode in one afternoon.
For a full-history node the same math hurts: 3 TB+ at 100 MB/s means 8+ hours of download before extraction even starts, and syncing from genesis without any snapshot runs for weeks. One asymmetry to know: java-tron ships a toolkit that shrinks a FullNode database down to Lite format, but there is no path from Lite back to full — if you will ever need complete history, start from the full snapshot.
Event streams and gRPC
Polling blocks over HTTP works, but java-tron can also push. The event subscription mechanism, enabled in the event.subscribe block of main_net_config.conf, publishes triggers for new blocks, transactions, contract logs and contract events — into a built-in ZeroMQ queue for light setups, or through plugins into Kafka or MongoDB for real pipelines.
For deposit detection this replaces block scanning: subscribe to contract events, filter for the USDT contract, match the recipient against your customer addresses. One detail decides correctness. The plain triggers fire when a block arrives, but a TRON block only becomes irreversible once enough super representatives have confirmed it; the solidified-trigger variants fire at that point, and they are the ones to credit customer balances from. A deposit credited from an unsolidified block can, rarely, disappear in a reorg.
The second machine interface is gRPC on port 50051: the same wallet operations as HTTP, but protobuf-typed and faster per call under load, which is why most indexers and exchange backends on TRON use it. A practical split: gRPC for your indexer’s bulk reads, HTTP for ad-hoc probes like the curl checks in this guide, and the solidity API (port 8091, when enabled) for queries that must only ever see irreversible state.
What a TRON node costs
A calculation path, not a price list. A Lite FullNode needs 8–16 cores, 32 GB RAM and roughly 500 GB of NVMe — upper-midrange VPS or entry-level dedicated territory, which at European hosts means a mid double-digit to low three-digit euro amount per month, as an order of magnitude. A full-history node needs the 3 TB+ NVMe class, i.e. a proper dedicated server in the low-to-mid three digits.
Add your hours: half a day for setup with this guide, java-tron updates every few months, and an occasional snapshot refresh after a crash. The Lite FullNode is the rare case where self-hosting blockchain infrastructure is genuinely cheap — as long as nobody’s revenue depends on it staying up at 3 a.m.
Monitoring and health checks
Everything worth checking sits behind one endpoint. /wallet/getnodeinfo reports the client version, peer counts, the latest block and the latest solidified block in a single call:
curl -s http://127.0.0.1:8090/wallet/getnodeinfo | jq \ '{version: .configNodeInfo.codeVersion, peers: .currentConnectCount, head: .block, solidified: .solidityBlock}'A healthy node shows the head advancing every 3 seconds and the solidified block trailing roughly 19–20 blocks behind — that is the two-thirds-of-27-SRs confirmation depth, about a minute of chain time. For alerting, compare your head against tronscan or a second node every few minutes and page when the gap passes 40 blocks, two minutes of chain time. systemctl is-active tron plus the peer count from the same call covers liveness.
Because this node is a JVM, watch memory separately: jstat -gcutil $(pgrep -f FullNode.jar) 10s shows garbage-collection pressure, and rising full-GC times appear in that output before the node starts lagging. Round it off with df -h /var/lib/tron at an 85 percent threshold — a Lite node grows slowly, but it grows, and the same cron job that mails you sync status can carry the disk line for free.
Maintenance and upgrades
java-tron releases arrive every couple of months, and most carry the “mandatory upgrade” label — Kant (v4.8.0, February 2026), Democritus (v4.8.1) and Hypatia (v4.8.1.1, June 2026) all did. Mandatory means the network activates rule changes on a schedule and old versions end up on the wrong side of consensus, so treat TRON releases the way BSC operators treat hard forks: subscribe to the tronprotocol/java-tron release feed and upgrade within the announced window.
The upgrade keeps the database. Download the new FullNode.jar, compare sha256sum against the release page, stop the service (systemd sends SIGTERM, which is the documented clean shutdown), swap the jar in /opt/tron, start again. The node replays the few minutes it missed and is back at the head shortly after.
Two slower-moving chores belong on the list. The Lite database grows with state plus its accumulating block tail; when it outgrows comfort, restore a fresh Lite snapshot — the same move as crash recovery, and the reason this setup keeps recovery cheap. And keep an eye on the Java requirement: the standard x86 build still targets JDK 1.8 as of mid-2026, while v4.8.1 added ARM builds on JDK 17. The pin is loosening, but until the release notes say otherwise, a standard server stays on Java 8.
Security: two API ports, zero authentication
Ports 8090 (HTTP) and 50051 (gRPC) accept anyone who can reach them — no tokens, no accounts, nothing. A node set up as in this guide holds no private keys, so an exposed port does not directly lose funds, but it hands strangers a free RPC service, and heavy query loops against block endpoints will eat the machine’s disk I/O until your own software starves. Assume any internet-reachable port is being scanned today.
The firewall from step 5 is the policy: ufw default deny incoming, then SSH and 18888 (TCP and UDP) — nothing else. When other machines need the API, tunnel with WireGuard or SSH, or put nginx in front with TLS and an IP allowlist, and even then forward only the endpoints you actually call. After every config change, check what really listens with ss -tlnp: java-tron can open additional ports from the config file, the solidity API on 8091 among them, and a port you forgot is a port you did not firewall.
One special case. If you ever put a witness key on a machine, that machine stops being infrastructure and becomes a hot wallet. Separate it from RPC serving, and treat its config file — which can hold the key in plaintext — with the care you would give the key itself.
Troubleshooting
Startup dies immediately with a Java version error
UnsupportedClassVersionError or similar means the JVM is version 11 or newer. Select Java 8 with sudo update-alternatives --config java, or sidestep the problem entirely with the Docker image.
OutOfMemoryError or minute-long GC pauses
-Xmx is sized wrong. Follow the 80%-of-RAM rule but leave several GB for the OS file cache, and don’t co-host other memory-hungry services. On a 16 GB machine, -Xmx12g is the ceiling.
The node starts but stays at the snapshot height
No peers. Check that port 18888 is open for TCP and UDP, look at the peer count in /wallet/getnodeinfo, and verify the clock with timedatectl — NTP must be active. Right after the first start, give peer discovery a few minutes before digging deeper.
Database errors after a crash or reboot
kill -9, an OOM kill or power loss corrupts the database. The fastest fix is also the intended one: wipe output-directory, restore a fresh Lite snapshot, restart — that is the payoff of the small snapshot size. Prevention: always stop via systemd, and keep enough free RAM that the kernel never OOM-kills Java.
The node keeps falling behind the head
Peers are connected, blocks arrive, but the gap to tronscan widens. Check in this order: disk latency (fio random-read benchmark — LevelDB on network storage or SATA is the classic cause), GC pressure (jstat -gcutil, see the monitoring section), then CPU contention from co-hosted workloads. TRON’s 3-second cadence forgives short stalls; a lag that grows for hours means the machine cannot keep up, and no configuration flag fixes undersized hardware.
The disk runs full
df -h, then du -h --max-depth=2 /var/lib/tron. The usual finding is a forgotten snapshot archive — the .tgz can rival the extracted database in size. If output-directory itself has outgrown the volume, restore the newest Lite snapshot onto a bigger disk; the restore resets the accumulated block tail at the same time. The 85-percent alert from the monitoring section turns this from an outage into a calendar entry.
Why people run TRON nodes at all: USDT
The dominant answer is USDT-TRC20. Low fees and 3-second blocks made TRON a default rail for exchanges and payment providers, and tens of billions of dollars in USDT circulate on the chain. Your own node means you can watch customer deposits and broadcast payouts without a middleman, which is exactly why payment companies ask about TRON nodes far more often than about most other chains.
The mechanics deserve one level more detail, because they shape the architecture. A USDT deposit is not a TRX transfer — it is a call to the USDT smart contract, so it never appears in plain TRX balance queries. Detecting it means decoding TRC-20 Transfer events out of every block, or subscribing to them through the event mechanism above, and crediting only after solidification: roughly 19 blocks, about a minute. Payouts have their own economics. A USDT transfer consumes energy, and a wallet without staked TRX pays that energy by burning TRX — roughly 6.4 TRX to an address that already holds USDT and roughly 13.4 TRX to an empty one, at the 100-Sun energy price in force since proposal #104. Operations at volume stake TRX for energy instead, which is what the freeze and delegate mechanics exist for.
But be clear about what a raw node hands you: HTTP and gRPC endpoints, nothing more. Detecting a customer’s USDT deposit means scanning every block for TRC-20 transfer events against your address list, handling confirmations and retries yourself. And TRON’s fee system — bandwidth, energy, freezing TRX, sponsoring fees for users — is its own field of study; the TRON fee calculator shows what a USDT transfer really costs before you build around it.
FAQ
How much disk space does a TRON node need?
A Lite FullNode starts from a snapshot in the 100 GB class; plan 300–500 GB of NVMe for growth. A full-history FullNode is around 3 TB in mid-2026 — the official March 2026 snapshots weigh 2.9–3.1 TB — and the number keeps climbing.
Can I run a TRON node on Windows?
Officially java-tron targets Linux and macOS. On Windows, the practical route is the Docker image, which pins the whole environment including Java 8.
Does running a TRON node earn TRX?
No. Block rewards go to the 27 elected super representatives and their voters through staking. A FullNode gives you independent chain access, not income.
Which Java version does java-tron need?
JDK 1.8 for the standard x86 build, still, in mid-2026; v4.8.1 added ARM builds on JDK 17, but on a normal server, newer JVMs abort at startup. This is the single most common setup failure, and the reason the Docker image exists in this guide.
What is the difference between a FullNode and a Lite FullNode?
Same software, different database. The Lite variant starts from a state-only snapshot and serves everything about the current chain, but cannot answer queries about transactions from before its snapshot. Payments work; block-explorer history does not.
Run your own node — or use an API?
An honest comparison, since Chaingateway sells the alternative.
Run the node when you read the chain at scale — indexing, monitoring the network beyond your own addresses, feeding gRPC into your own pipeline — or when policy says no third parties. The Lite FullNode’s low cost means heavy read workloads amortize quickly; this is one of the cheapest self-hosted nodes among the major chains.
Use an API when the node would only be plumbing for payments. On top of a synced node you would still build address generation per customer, TRC-20 deposit detection, webhook delivery, key storage and fee management. Chaingateway’s TRON API is that layer as REST endpoints: import addresses (POST /api/v2/tron/addresses/import), send USDT and other TRC-20 tokens (POST /api/v2/tron/transactions/trc20) or TRC-10 assets, freeze and delegate resources for energy (POST /api/v2/tron/freeze, POST /api/v2/tron/delegate), and receive HMAC-signed deposit webhooks; failed deliveries appear at GET /api/v2/tron/webhooks/notifications/failed and can be resent via the retry endpoint.
The break-even as arithmetic: (server + snapshot refreshes + your hours × your rate) versus a plan on /pricing/. For deposit-and-payout use cases, the API side stays smaller until serious scale; for raw chain reading, the node side wins almost immediately. The quickstart and the webhook guide cover a first end-to-end test, and the 7-day trial requires no KYC (register).
Running EVM chains too? See the setup guides for Ethereum and BNB Smart Chain.