This guide gets you a Pharos Atlantic full node: a machine that downloads the Atlantic testnet, follows it, and answers RPC queries locally. It does not stake, does not validate, and does not need a domain name.
Read the next paragraph before you spend anything. Pharos publishes exactly one node specification, and it is a large one: 32 CPU cores, 256 GB of RAM and 5 TB of fast SSD. There is no smaller documented tier, and the project's own state snapshot is over 600 GB. This is not a hobby node you park on a $6 VPS, and any guide that tells you otherwise is guessing. We priced the spec at four providers on 2026-08-31: about $660 a month on a dedicated server at the cheap end, and $2,000-2,100 a month if you rent it as a cloud instance. Step 1 has the comparison. Expect the initial sync to take a long time on a chain this size.
Setup itself is about thirty minutes of typing. The waiting is the expensive part.
Hardware requirements
Pharos publishes one spec, on its validator requirements page, and the same table is repeated as the prerequisites for both deployment methods. There is no separate, lighter full-node sizing, so these are the numbers to plan against.
| Component | Published spec | Why it matters |
|---|---|---|
| CPU | 32 cores, 2.8 GHz or faster (AMD Milan EPYC or Intel Xeon Platinum) | Pharos is a parallel-execution chain; the core count is the point of it, not padding. |
| Memory | 256 GB | The largest single line item in your bill. Nothing in the docs suggests a smaller figure works. |
| Storage | 5 TB SSD, at least 350 MiB/s and 30,000 IOPS | The state snapshot alone is over 600 GB and grows. The IOPS floor rules out cheap network volumes. |
| Network | 0.5 Gbps | Initial sync moves a lot of data. A metered connection will hurt. |
| Open files | ulimit -n of at least 10,000,000 | The node opens a very large number of file handles. The default on most distributions is 1024, and the node will not behave until this is raised. |
Two honest notes on those figures. First, they are the validator spec — the docs give no separate number for a full node, so treating them as the full-node spec is the conservative reading, not a documented one. Second, the disk figure is the one to take most seriously: you can under-provision CPU and find out slowly, but you run out of disk all at once.
Step 1: Choose your hardware
Two honest options, and at this size the choice matters more than usual.
Path A: rent a server
A rented machine gives you a static IP, real bandwidth, and a box that stays online when your laptop closes. At the published spec you are renting a dedicated server rather than a small cloud instance — 256 GB of RAM and 5 TB of NVMe is not a VPS tier at most providers, and shared virtual disks rarely hold 30,000 IOPS.
Pay monthly. A testnet is temporary by definition, and annual terms on hardware this size are a large commitment to something that may close. If you later decide to keep the node running, you can switch terms then.
We priced this across the four providers this site has referral relationships
with, on 2026-08-31, against the published spec above. The full working — every
URL, every observed price, and the rejections — is in our provider sourcing
note in the repository, docs/research/pharos-vps-options-2026-08.md.
| Provider | Best product it actually sells | Cores | RAM | Fast storage | Per month |
|---|---|---|---|---|---|
| Contabo | Dedicated Server "AMD Turin 32 Cores", upgraded | 32 physical, 3.55 GHz | 256 GB | 2x1 TB boot + 2x4 TB NVMe | about $660 |
| Vultr | Optimized Cloud Compute, Storage Optimized | 32 vCPU | 256 GB | 5,760 GB NVMe | $2,000 |
| DigitalOcean | Storage-Optimized Droplet, top tier | 32 vCPU | 256 GiB | 4,690 GiB NVMe | $2,096 |
| Hostinger | KVM 8, its largest plan | 8 vCPU | 32 GB | 400 GB | not in range |
Two things in that table decide it. A 32-vCPU cloud plan is not 32 cores — Vultr's own API reports every plan it sells as threads, so 32 vCPUs is roughly 16 physical cores, and DigitalOcean's Droplets are the same shape. Only a dedicated server gives you the 32 real cores Pharos asks for. And here the dedicated server is the cheapest of the three, not the most expensive: about a third of the price of either cloud option.
So the honest pick is Contabo, on a dedicated server rather than a VPS. We earn a commission if you use that link, and we want to be exact about what that did and did not decide: Contabo wins this comparison on 32 real cores at a third of the price, and it would still win if we earned nothing from it. If Vultr or DigitalOcean had been the honest answer, this section would name them instead.
Three things to know before you click, none of which are in our interest to tell you:
- That link lands on Contabo's VPS page, not their dedicated servers. Their affiliate programme does not let us link past it. You want the Dedicated Servers section, then "AMD Turin 32 Cores", then raise the RAM to 256 GB and add NVMe drives. A VPS bought from the landing page will not run this node.
- Pay monthly, not annually. The 12-month term saves about 7%, and Contabo bills the whole term on day one — we were quoted EUR 7,891.56 due immediately against EUR 707.50 for a single month, for the same machine. Atlantic is a testnet and may close before a year is out. Seven percent is not worth prepaying a year to a network that might end. If you are still running the node in six months, switch terms then.
- Nobody publishes the IOPS number. Pharos asks for 30,000 IOPS and none of these four states a per-plan IOPS figure for these tiers, so we cannot tell you the requirement is met. Local NVMe on a dedicated server is the right class of device for it. What we can tell you is what is ruled out: Vultr's network-attached block storage publishes 10,000 IOPS, a third of what the spec asks, so topping a smaller server up with a network volume is not a shortcut.
These are the prices the providers showed on 2026-08-31 and they will move. The Contabo figures are before VAT, which depends on your country.
Path B: use a machine you already own
If you happen to have a workstation or home server at this spec, it will work, and it costs you nothing extra. The tradeoffs are real: you will need to forward ports 18100, 19000 and 20000 if you want the node reachable from outside, home connections drop, and a 600 GB initial download on a domestic line is a long evening at best.
For a full node that you only query locally, port forwarding is optional. You only need inbound reachability if you later pursue validator admission.
Hardware slot. You are choosing the storage to put underneath this — fast NVMe with room for the chain to grow well past its current size.
Step 2: Check the machine can take it
Before downloading anything, confirm the three things that stop this setup dead. Run these on the machine that will host the node.
Check the file handle limit. The node needs a very large one, and the default almost certainly is not it:
ulimit -n1024If you see a small number like the one above, raise it. The Docker Compose file in Step 5 sets the limit for the container itself, which is what the node actually needs, so a low value on the host shell is not fatal — but it is a good sign you have not tuned this machine yet.
Check you have the disk. The chain state is already past 600 GB, and the spec
asks for 5 TB. Pharos puts the node under /data, so create that directory
before you measure it — df cannot report on a path that does not exist, and
asking it to is an error rather than a zero:
sudo mkdir -p /datasudo chown $(id -un) /datadf -h /dataRead that answer carefully, because it is easy to misread as good news.
/data is an ordinary directory unless you deliberately put a filesystem
there. On a single-disk server it lives on the root filesystem, so df is
reporting your root disk and that number is the entire budget — the node will
fill it and then stop. If you bought separate storage for the chain data, mount
the device at /data before running the command above, and df will report the
device instead. The line to check is the one under Mounted on: /data means
you have a dedicated filesystem, / means you do not.
Step 3: Install Docker
Pharos ships as a container image, so Docker is the whole runtime. The project's prerequisites ask for Docker Engine 20.10 or newer and Docker Compose 2.0 or newer, and say nothing about how to get them. A fresh Ubuntu server has neither.
The commands below are Docker's documented apt-repository method, read from Docker's install page on 2026-09-02. Do not paste an install script from a node guide — including this one. Docker's own instructions are the ones that stay current, and this step is transcribed from them rather than invented here.
Start with the tools this guide needs alongside Docker. Step 4 fetches three
files with wget, which a minimal server image does not always carry:
sudo apt updatesudo apt install -y wgetNow Docker's signing key and repository, so apt keeps Docker up to date
afterwards like anything else:
sudo apt install -y ca-certificates curlsudo install -m 0755 -d /etc/apt/keyringssudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.ascsudo chmod a+r /etc/apt/keyrings/docker.ascsudo tee /etc/apt/sources.list.d/docker.sources <<EOFTypes: debURIs: https://download.docker.com/linux/ubuntuSuites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")Components: stableArchitectures: $(dpkg --print-architecture)Signed-By: /etc/apt/keyrings/docker.ascEOFsudo apt updateThe two $( ) substitutions work out your Ubuntu release name and your CPU
architecture, so the same paste is correct on 24.04 and on 26.04. Then the
packages:
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginOn a fresh Ubuntu server those packages start the Docker daemon for you and set
it to start at boot. Confirm it with sudo systemctl status docker --no-pager,
and start it with sudo systemctl start docker if it is not running.
Confirm the versions, which is also how you know the install worked:
docker --versiondocker compose versionIf docker compose version reports "is not a docker command", you have the old
standalone docker-compose binary rather than the plugin, and the install above
is what replaces it.
Step 4: Get the Atlantic configuration files
Create the working directory the docs use, and pull down the three files that
tell the node which network it is on. Every block from here on starts by
returning to /data/pharos, so that each one is correct on its own — if you
reconnect, open a second terminal, or come back tomorrow, you can paste any
single block and get the right result.
mkdir -p /data/pharos/bin && cd /data/pharosThe project's docs put a WORKSPACE variable in front of that path. This guide
writes /data/pharos out in full instead, because the Compose file in Step 5
mounts that exact path and a reader who changed the variable would end up with
the two disagreeing.
Now the genesis file, the network version manifest, and the node configuration.
These are the Atlantic files — the mainnet equivalents are named
mainnet.genesis and mainnet.version:
cd /data/pharoswget -O genesis.conf https://raw.githubusercontent.com/PharosNetwork/resources/main/atlantic.genesiswget -O bin/VERSION https://raw.githubusercontent.com/PharosNetwork/resources/main/atlantic.versionwget -O pharos.conf https://raw.githubusercontent.com/PharosNetwork/resources/main/conf/full.confConfirm you got real files rather than error pages. The genesis file is large, the other two are small:
cd /data/pharosls -l genesis.conf pharos.conf bin/VERSIONStep 5: Write the Docker Compose file
This is the project's own Compose file with one deliberate change: the image tag is the Atlantic build, not the mainnet build the docs paste.
Replace CHANGE_THIS_PASSWORD with a password of your own before you run it.
The node encrypts its consensus keys with it, and you will need it again:
cd /data/pharoscat > docker-compose.yml <<'EOF'services:pharos: image: public.ecr.aws/k2g7b7g1/pharos:pharos_community_v0.14.4_05cffaf0_0729 container_name: pharos-node environment: - CONSENSUS_KEY_PWD=CHANGE_THIS_PASSWORD - PHAROS_CONF=/data/pharos.conf - GENESIS_CONF=/data/genesis.conf - KEYS_DIR=/data/keys volumes: - /data/pharos:/data ports: - "18100:18100" - "18200:18200" - "19000:19000" - "20000:20000" restart: unless-stopped ulimits: nofile: soft: 10000000 hard: 10000000EOFLock the file down and confirm your password actually replaced the placeholder:
cd /data/pharoschmod 600 docker-compose.ymlgrep CONSENSUS_KEY_PWD docker-compose.ymlThe consensus keys that password protects are this node's own identity, not a place to hold funds — Atlantic's tokens carry no real value, so there is nothing at stake in them yet. A hardware wallet is worth the cost once you are holding or signing for something that does:
Hardware wallet
Ledger keeps a private key on a physical device, off the machine running your node, and asks for a button press before it signs anything. That is worth having once the key or address in question holds funds with real value. It is not required for anything on this site: every guide here runs on a testnet, testnet tokens carry no real value, and a fresh software wallet -- a new browser-extension or app wallet, ideally in its own browser profile and separate from anything holding real funds -- is enough for that. See Wallets and exchanges for node runners for the difference and where hardware wallets actually fit.
Step 6: Start the node
The container generates its keys on first start, bootstraps from genesis, and then begins syncing. The first pull is several gigabytes, so this takes a while before anything appears to happen:
cd /data/pharosdocker compose up -dWatch it come up. The startup script prints a fixed sequence of lines, and seeing them in order is how you know each stage completed:
cd /data/pharosdocker compose logs --tail 50 pharosAdd -f to that command to follow the log live instead of printing the last
fifty lines. That keeps running until you press Ctrl-C.
On a first run you should see the node copy its binaries, report that it found no existing data, bootstrap, and then start. The bootstrap line is the one that matters — it only appears on a first run, and if the node restarts later it will say it found existing data instead.
Verify your node
"The container is running" and "the node works" are different claims. Check all three of these.
First, the container is actually up and staying up. A container that is restarting in a loop looks similar to a healthy one if you only glance at it:
cd /data/pharosdocker compose psThe status column should say Up, and the time next to it should keep growing
when you run the command again a minute later. Restarting means the node is
crashing — go to Common errors below.
Second, the node is writing its own log. The node's log lands in the directory you mounted, which means you can read it from the host:
tail -n 50 /data/pharos/log/aldaba.logThird, compare against the public network. This is the check that tells you whether your node is on the right chain and how far behind it is. Start with the public endpoint, which answers immediately and confirms what Atlantic's chain ID should be:
curl -s -X POST https://atlantic.dplabs-internal.com -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'{"jsonrpc":"2.0","id":1,"result":"0xa8231"}That hex value is 688689 in decimal, which is Atlantic's chain ID. If you ever get a different number from an endpoint someone hands you, you are not on Atlantic.
Now ask your own node the same question from inside the container. The node
configuration binds its RPC to 127.0.0.1, so the query has to run in the
container rather than from the host:
cd /data/pharosdocker compose exec pharos curl -s -X POST http://localhost:18100 -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'Your node should answer with the same 0xa8231. A different answer means the
wrong genesis or the wrong version files. No answer at all means the node has
not finished starting, or is not listening yet.
Finally, ask both for a block height and compare. Your node is caught up when its number stops trailing the public one:
cd /data/pharosdocker compose exec pharos curl -s -X POST http://localhost:18100 -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'curl -s -X POST https://atlantic.dplabs-internal.com -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'Both answers are hex. You can also paste your node's height into the Atlantic
explorer at atlantic.pharosscan.xyz to see the same block from the outside.
Common errors
Error: pharos.conf not found at /data/pharos.conf — the container started
without its configuration. This is almost always a working directory mistake in
Step 4: the volume line maps /data/pharos on the host into /data in the
container, so the files must be in /data/pharos on the host. Run ls /data/pharos and confirm pharos.conf and genesis.conf are there. If they
landed in your home directory instead, you pasted a block into a shell that was
not in /data/pharos — which is why every block in this guide now starts by
returning there.
Error: CONSENSUS_KEY_PWD environment variable not set — the container
exits immediately on start. You edited the Compose file but left the environment
line out, or removed it while replacing the placeholder. Check it with grep CONSENSUS_KEY_PWD docker-compose.yml.
400 Bad Request when downloading atlantic.version — you used the
refs/heads/main URL from the project docs. We saw that exact failure on
2026-08-31, repeatedly, while the shorter main form in Step 4 worked. Use the
Step 4 URL.
The node runs but reports the wrong chain ID — you have mainnet files or a
mainnet image. Both project deployment pages hand out v0.15.0, which is the
Pacific mainnet build, on pages that otherwise describe Atlantic. Check the
image tag in your Compose file says v0.14.4, and that you downloaded
atlantic.genesis rather than mainnet.genesis.
Connection refused when you curl port 18100 from the host — expected, not
broken. The full.conf this guide downloads sets the node's host IP to
127.0.0.1, so the RPC listens on loopback inside the container and the
published port does not reach it. Query it with docker compose exec as shown
above, which is what the project's own health check does.
The container is killed shortly after starting — usually memory. The
published spec asks for 256 GB, and a machine with less can get the node killed
by the kernel out-of-memory killer rather than by any error the node prints.
Check with docker compose ps for a status of Restarting, and free -g for
what the machine actually has.
Maintenance
Watch the disk weekly. This is the failure that ends node runs. The chain state is already past 600 GB and grows continuously:
df -h /dataKeep the version manifest in sync when you upgrade. The project is explicit
that a new node version needs the VERSION file re-downloaded alongside it, and
the manifest already lists network upgrades scheduled ahead of the current
release. Re-fetch it, update the image tag in your Compose file to the current
Atlantic build, and restart:
wget -O bin/VERSION https://raw.githubusercontent.com/PharosNetwork/resources/main/atlantic.versiondocker compose pulldocker compose up -dBack up your keys and your password. The node generates its keys on first start into the mounted directory. Without them, and without the password that encrypts them, a rebuilt node is a new node:
tar -czf pharos-keys-backup.tar.gz -C /data/pharos keysStore that archive somewhere other than the server it came from.
If sync falls a long way behind, restore from a snapshot. Pharos publishes state snapshots with SHA-256 checksums. Two warnings before you start: the Atlantic snapshot was over 600 GB when we checked on 2026-08-31, and the snapshot page and the rapid-initialization page disagree about which file is current — the rapid-initialization page still names a file from March. Take the filename from the snapshots page, and verify the checksum it publishes before you use the archive:
sha256sum atlantic-snapshot-2026-08-16-04.tar.gzSnapshots hold only the latest validated state, not full history. If you need history, sync from genesis instead.
FAQ
Will running this node earn me an airdrop? Nothing in the project's documentation says so, and this site does not repeat reward claims it cannot source. What the docs do describe is narrower: validator rewards are tied to consensus participation, and validators with consistent uptime and correct votes are eligible to propose blocks and collect the associated transaction fees. A full node is not a validator and the docs describe no reward for one. Treat anything more specific you read elsewhere as unsourced until the project says it itself.
Can I run this on a cheap VPS? No. The published spec is 32 cores, 256 GB of RAM and 5 TB of fast SSD, and the state snapshot alone is larger than most VPS disks. There is no documented smaller tier. If the cost is the blocker, use the public RPC endpoint in the verify section — it answers immediately and costs nothing.
Can I become a validator? Not on your own. The project's node management page says joining the Atlantic validator set means contacting the team with your node's public keys, and that the staking tokens come from them. It is an application, not a command you run.
Which network am I on, and how do I know? Atlantic, chain ID 688689, if you
followed Step 4. The eth_chainId check in the verify section is the way to
confirm it — hex 0xa8231. Pacific mainnet is a different chain with a
different genesis, and the deployment docs mix the two up.
Do I need to open ports? Not to run a full node you query locally. Ports 18100, 19000 and 20000 matter if you want the node reachable from outside, which is only necessary if you are pursuing validator admission.
Why does this guide still say verification pending? Because nobody has run these commands on a clean machine and captured the output yet. Every command here is traceable to the project's published documentation and every download URL was re-checked against the live host on 2026-08-31, but that is a weaker claim than "this works", and this site does not blur the two.