Self-hosted service
vechain/thor avatar
vechain/thor

thor: building and running a VeChainThor node

A general-purpose blockchain that is highly compatible with the Ethereum ecosystem

813 stars276 forksGoLGPL-3.0

At a glance

What is it?
Thor is the official Go client for VeChainThor, the chain behind the VeChain ecosystem, and it runs as a public full node or a validator. The README is unusually concrete about what a node costs in CPU, RAM, disk and IOPS, but the sync times it quotes come from builds that skipped logs or disabled the pruner, so they are floors rather than typical figures.
Who is it for?
Thor suits an operator who wants to run VeChainThor infrastructure directly, a validator candidate working through the endorsement and voting steps, or a developer who needs a local chain for testing, and who has the disk and IOPS to sync from genesis. It does not suit an application developer who only needs an RPC endpoint, since a node costs hundreds of gigabytes and a day of syncing, and it does not suit anyone who needs a permissive licence.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An official client for a chain that mirrors the Ethereum interface

Thor is the official Golang client for VeChainThor, the public blockchain powering the VeChain ecosystem, which the README describes as designed for real-world adoption with an emphasis on scalable, low-cost and sustainable applications. The repository description is blunter: a general-purpose blockchain that is highly compatible with the Ethereum ecosystem.

Compatibility is the product claim, and it comes with a caveat that the README puts in a blockquote near the top. VeChainThor is currently up to date with the EVM's shanghai hardfork, and if you are using Solidity compiler version 0.8.25 or above you have to set the evmVersion to shanghai in the compiler configuration. That is the kind of detail that turns into a production incident if it is missed, since a contract compiled for a newer EVM version will not behave on a chain that has not adopted it.

The node itself is a Go program with a Go module path of github.com/vechain/thor/v2 and a go directive of 1.26.5. The source tree shows the full anatomy of a chain client: a bft directory for the consensus protocol, block, chain, and consensus directories, a txpool, a vm directory for the EVM, tracers, a scheduler, an api directory served over HTTP and WebSocket through gorilla/mux and gorilla/websocket, a p2p and p2psrv layer for the peer to peer network, state and trie storage, a logdb, and a metrics package that reports through the Prometheus client. There is also a thorclient package for talking to a node, and a disco binary for node discovery.

For an application team, the practical question is whether to run a node at all, and the answer is usually no unless you have a specific reason to trust your own view of the chain.

What a node costs in CPU, RAM, disk and IOPS

The hardware requirements are stated as a table with two columns, one for a validator and one for a public full node.

A validator is specified as 4 cores, 16 GB of RAM, 20 Mbit of bandwidth, and a 500 GB NVMe SSD. A public full node needs 8 cores, 64 GB of RAM, 20 Mbit of bandwidth, and a 1 TB SSD. The disk figure is the one that surprises people, because it is not about what a block contains but about the history of state changes the node keeps locally.

Underneath the table there is the constraint that matters more than the capacity numbers: a minimum of 45,000 IOPS is required for an approximate 30 hour sync time. IOPS is the measure of random read and write operations per second, so this is really a statement about the type of storage. A cheap network attached volume will not do, and a spinning disk will not do, and the difference shows up as a sync that never finishes in a reasonable time.

The README also notes that becoming a validator is not just a matter of running the binary. It requires additional steps, meeting the endorsement criteria and being voted in, and it points to a separate document, Becoming a Validator, for the detail. So the validator hardware row describes a node you are aiming to become, not one you can switch into by changing a flag.

The project also documents three node types and a full list of command line arguments in separate documents, which is where the configuration decisions beyond the defaults are described.

The sync time tables are best case, and the notes say so

The sync time section is the most useful part of the README, because it converts a vague expectation into numbers, with hardware configurations and the AWS instance types they correspond to. The measurements are stated as of August 2025.

For a validator, the fastest listed configuration is 4 CPU, 32 GB, 10 Mbit, a 937 GB NVMe SSD at 45K IOPS, which syncs in 30 hours and 00 minutes on an I8g.xlarge. The slowest listed validator configuration, 4 CPU with 32 GB and a 937 GB NVMe SSD at 10K IOPS, takes 54 hours and 08 minutes on an I4g.xlarge, and a middle configuration at 35K IOPS on an I8g.large takes 38 hours and 41 minutes. The IOPS figure moves the number more than the CPU count does.

For a public full node, the fastest listed setup is 8 CPU, 64 GB, 12 Mbit, a 1875 GB NVMe SSD at 42K IOPS, which syncs in 32 hours and 17 minutes, while the same hardware at 15K IOPS takes 59 hours and 04 minutes.

Now the two notes that change how you should read the tables. The validator figures come from a build that used the --skip-logs command, and the public full node figures come from a build that used the -disable-pruner command. Both of those are ways of leaving data out, which is exactly why the sync is faster. A node that keeps the logs and runs the pruner, which is the configuration the installation section tells you to start, will not reproduce these numbers. Treat the tables as the cost of the cheapest node, and add your own margin for the node you actually intend to run.

Building from source: clone, check out a tag, make, run

The source build is a five command sequence, and the detail that catches people is the third command. The clone and the directory change are obvious.

bash
git clone https://github.com/vechain/thor.git
bash
cd thor

Then the checkout, which resolves the most recent tag rather than taking the branch head.

bash
git checkout $(git describe --tags `git rev-list --tags --max-count=1`)

Building and running follow.

bash
make
bash
bin/thor --network mainnet

Once the node starts syncing, the HTTP interface is served on port 8669 and is reachable at http://localhost:8669/.

Prerequisites are Go, with the version pinned by the module and the Makefile, plus a C compiler, and the README asks that you install both with your preferred package manager before starting.

The Makefile is worth a look before you run it, because it does more than compile. The default goal is the thor executable, there is a separate disco target for the discovery binary, and the version string is assembled at build time from a VERSION file, the git commit, the git tag, and the copyright year, all injected with ldflags. There is a go version check target that compares your toolchain against a required major and minor, with the required minor set to 26, and a test target driven by a configurable fuzz time.

The release tags follow the same numbering as the binary, so a version such as v2.5.0 corresponds to a node release you can check out and rebuild.

Docker, and the two ports that are not the API

The container route is the one most operators will use, and the README gives both a plain docker run invocation and a compose file.

bash
docker run -d \
  -v <local-data-dir>/.org.vechain.thor:/home/thor/.org.vechain.thor \
  -p 127.0.0.1:8669:8669 \
  -p 11235:11235 \
  -p 11235:11235/udp \
  --name thor-node vechain/thor \
    --network mainnet  \
    --api-addr 0.0.0.0:8669

The details here are security decisions rather than boilerplate. The API port is published bound to 127.0.0.1, so it is reachable from the host but not from the network, while the api-addr inside the container is 0.0.0.0. The data directory is mounted so the chain database survives a container replacement.

The compose file does the same thing with the same port set, and publishes the API on all interfaces rather than only on the loopback.

yaml
version: '3'

services:
  thor-node:
    image: vechain/thor
    container_name: thor-node
    command: --network mainnet --api-addr 0.0.0.0:8669
    volumes:
      - thor-data:/home/thor
    ports:
      - "8669:8669"
      - "11235:11235"
      - "11235:11235/udp"

volumes:
  thor-data:

Port 11235 is the peer to peer port and is published for both TCP and UDP, which is why the port appears twice in both configurations. The Dockerfile exposes 8669, 2112, 11235 on TCP and UDP, and 55555 on UDP, and it builds in a Go builder stage before copying two binaries, thor and disco, into an Alpine image that runs as an unprivileged user.

One point to check before you expose anything: the README does not document authentication for the API surface, so binding the API to a routable address is a decision you make with your own network controls, not one the client protects for you.

A client that leans on go-ethereum, at a version from 2018

The dependency list is where Thor's approach to Ethereum compatibility shows most clearly, and it is an unusual choice.

The go.mod includes github.com/ethereum/go-ethereum at version v1.8.14, alongside a separate crypto and address library, decred's secp256k1 implementation, urfave/cli for the command line, the Prometheus client for metrics, gorilla/mux and gorilla/websocket for the API layer, gnark-crypto for the zk and VRF style primitives, and goja as a JavaScript engine, which is how the tracer and the built-in contract environments run scripts. The VeChain team maintains its own go-ecvrf module for the verifiable random function.

Pinning go-ethereum to a release from that era is a deliberate fork point rather than an oversight, and it tells you something about the project: Thor is not a reimplementation of an Ethereum client, it is a chain client that reuses selected pieces of one while running its own consensus, its own state handling, and its own transaction pool. The repository layout agrees, with a bft directory for the consensus protocol that has no counterpart in an Ethereum client, and its own logdb and muxdb storage layers.

The cost of that approach is that the shared surface ages on its own schedule, and the shanghai hardfork note in the README is the visible edge of it. The benefit is that the EVM behaviour you depend on is the behaviour your application developers already know, and the toolchain around it, the ABI handling, the tracing, the JSON RPC surface, is inherited rather than rebuilt.

The acknowledgements section names Ethereum, Go-Ethereum, Swagger, and Stoplight Elements, which is consistent with a client whose API layer is shaped by familiar tooling.

Licence, releases, and the shape of the upgrade path

Thor is released under the LGPL, version 3, as the licence badge and the LICENSE file in the repository indicate. For a client binary that you run as a process on your own infrastructure, an LGPL obligation on the library code is a much lighter matter than it would be for something you link into a distributed product, and the licence file itself is the authority on the terms. The README section on the licence is cut short in the copy available here, so read the file rather than a summary.

On the release side, the project is not archived and the last push was on 2026-10-13. The recent tags are v2.5.0, named Interstellar, published on 2026-09-03, a v2.5.0 release candidate on 2026-09-02, and v2.4.4 on 2026-07-15. The presence of a release candidate in the recent list is a normal pattern and tells you that upgrades are staged rather than cut straight from master.

The upgrade path itself is straightforward because the version is coupled to a git tag. Checking out the tag of the release you want and rebuilding gives you a binary that matches the published release, and the Makefile injects the tag, the commit, and the copyright year into the binary at build time, so a running node reports exactly which source it came from.

What an operator has to plan for is the data, not the binary. A chain database that has been syncing for two days cannot be moved between versions cheaply, and the documentation in the repository covers becoming a validator, the command line arguments, the node types, and a solo mode for local testing, which is the one piece of this project most developers should start with.

Editorial conclusion

Thor suits an operator who wants to run VeChainThor infrastructure directly, a validator candidate working through the endorsement and voting steps, or a developer who needs a local chain for testing, and who has the disk and IOPS to sync from genesis. It does not suit an application developer who only needs an RPC endpoint, since a node costs hundreds of gigabytes and a day of syncing, and it does not suit anyone who needs a permissive licence. Verify first that your storage can sustain the 45,000 IOPS the README calls for, that you are using the EVM version the chain expects for your Solidity compiler version, and that you read the sync time tables for the build you actually intend to run rather than the ones with logs skipped or the pruner disabled.

Frequently asked questions

How do I build the VeChainThor thor client from source?

Clone the repository, change into the thor directory, check out the most recent tag with git checkout and the git describe expression in the README, then run make and start the node with bin/thor --network mainnet. The build needs Go and a C compiler.

What hardware does a VeChainThor full node need?

The README lists a public full node as 8 cores, 64 GB of RAM, 20 Mbit of bandwidth and a 1 TB SSD, and a validator as 4 cores, 16 GB of RAM and a 500 GB NVMe SSD. It also states that a minimum of 45,000 IOPS is required for an approximate 30 hour sync time.

How long does it take to sync a VeChainThor node?

The README gives figures as of August 2025, ranging from 30 hours for a validator configuration at 45K IOPS up to 59 hours for a public full node at 15K IOPS. Those numbers come from builds that used the --skip-logs or -disable-pruner commands, so a node that keeps logs and runs the pruner will take longer.

Which EVM version should I compile Solidity for on VeChainThor?

VeChainThor is currently up to date with the shanghai hardfork, so if you use Solidity compiler version 0.8.25 or above you should set evmVersion to shanghai in the compiler configuration. The README calls this out specifically.

Can I run a VeChainThor node with Docker?

Yes, the README gives both a docker run invocation and a docker-compose.yml, both publishing the API on 8669 and the peer to peer port 11235 on TCP and UDP, with the chain data kept in a mounted volume. The example docker run binds the API to 127.0.0.1 on the host.

Official sources

  1. Issues
  2. License: LGPL-3.0
  3. README
  4. Releases
  5. vechain/thor on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vechain-thor.svg)](https://hysenlabs.com/projects/vechain-thor)

Was this useful?