Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- `status` now reports execution peer count, matching the README.
- Management commands now sanitize service state and tolerate missing local RPC cleanly before the node is installed.
- Follow-mode endpoints now use the v0.7.1 CLI format and let Arc derive matching WebSocket URLs.
- Systemd service flags now include upstream Arc `--full` pruning presets and consensus execution-persistence backpressure.
- Snapshot guidance now matches the upstream Arc node repo: fresh nodes need snapshots and should not be described as syncing from genesis.
- Keypair-only VPS sudo handling now fails with root/cloud-init instructions when sudo cannot already elevate, instead of attempting an impossible self-escalation.

### Added
Expand All @@ -40,7 +42,7 @@ Initial public release.
- **Live monitor dashboard** — `monitor` command refreshes every 5 s with service status, sync lag, peer count, resource usage, and recent log lines
- **Auto-detect update** — `update` queries the GitHub Releases API (falls back to tags) to find the latest `circlefin/arc-node` version; supports pinning with `update vX.Y.Z`
- **Atomic update with rollback** — backs up current binaries before recompiling; automatically restores them and restarts services if any build step fails
- **Guided uninstall** — removes services, binaries, and optionally chain data (~120 GB) and source; each destructive step requires separate confirmation
- **Guided uninstall** — removes services, binaries, and optionally chain data (~139+ GB with current snapshots) and source; each destructive step requires separate confirmation
- **Firewall configuration** — `--with-firewall` auto-configures `ufw` with SSH, EL P2P (30303 TCP+UDP), CL P2P (31001 TCP), and optionally JSON-RPC (8545 TCP)
- **MetaMask / LAN RPC** — `--expose-rpc` binds JSON-RPC on `0.0.0.0:8545` and prints the server's public IP at setup completion
- **Colour-safe output** — ANSI colour codes are stripped automatically when stdout is not a TTY (piped / CI logs)
Expand All @@ -50,4 +52,4 @@ Initial public release.

- Ubuntu 22.04 LTS and later
- Debian 12 and later
- Arc Testnet **v0.6.0** (`circlefin/arc-node`)
- Arc Testnet **v0.7.1** (`circlefin/arc-node`)
34 changes: 18 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
|---|---|
| Installs system packages, Rust, and Foundry | `apt-get` + `rustup` + `foundryup` |
| Builds 3 Arc binaries from source | `cargo install` from `circlefin/arc-node` |
| Downloads blockchain snapshots (~60 GB) | `arc-snapshots download` |
| Downloads blockchain snapshots (~84 GB compressed) | `arc-snapshots download` |
| Initialises your node's P2P identity key | `arc-node-consensus init` |
| Registers auto-start + crash-restart services | `systemd` unit files |
| Provides live monitoring, logging, and updates | Built-in subcommands |
Expand All @@ -74,7 +74,7 @@ Setup takes **20–60 minutes** on a fast machine (dominated by Rust compilation
| **OS** | Ubuntu 22.04 or Debian 12 | Ubuntu 22.04 LTS |
| **CPU** | 8 cores | 16+ cores |
| **RAM** | 64 GB | 128 GB |
| **Disk** | 150 GB free SSD | 500 GB+ NVMe SSD |
| **Disk** | 200 GB free SSD | 1 TB+ NVMe SSD |
| **Network** | Stable broadband | 1 Gbps unmetered |
| **User** | Non-root with `sudo` | — |
| **Init** | systemd | — |
Expand All @@ -87,13 +87,13 @@ Setup takes **20–60 minutes** on a fast machine (dominated by Rust compilation

```bash
# One command to setup
curl -fsSL https://raw.githubusercontent.com/candyburst/arc-node-setup/main/setup.sh | bash -s -- --yes
curl -fsSL https://raw.githubusercontent.com/candyburst/arc-node-setup/main/setup.sh | bash -s -- setup --yes
```

Or equivalently:

```bash
curl -fsSL https://raw.githubusercontent.com/candyburst/arc-node-setup/main/setup.sh | bash -s -- -y
curl -fsSL https://raw.githubusercontent.com/candyburst/arc-node-setup/main/setup.sh | bash -s -- setup -y
```

```bash
Expand Down Expand Up @@ -142,7 +142,7 @@ All options apply to the `setup` command:
| Flag | Description |
|---|---|
| `-y`, `--yes` | Skip all yes/no prompts (non-interactive / CI mode) |
| `--skip-snap` | Skip snapshot download — syncs from genesis (very slow, not recommended) |
| `--skip-snap` | Skip snapshot download — only for existing compatible data |
| `--expose-rpc` | Bind JSON-RPC on `0.0.0.0` — needed for MetaMask over LAN/WAN |
| `--with-firewall` | Auto-configure `ufw` firewall rules |
| `--swap SIZE` | Create a swap file, e.g. `--swap 16G` |
Expand All @@ -168,7 +168,7 @@ All options apply to the `setup` command:
Displays a banner, then checks:

- **RAM** ≥ 64 GB (warns, does not block)
- **Disk** ≥ 150 GB free (warns, does not block)
- **Disk** ≥ 200 GB free (warns, does not block)
- **OS** is Ubuntu 22.04+ or Debian 12+
- **User** is not root (root execution is blocked)
- **systemd** is present
Expand Down Expand Up @@ -212,9 +212,9 @@ Creates:
/run/arc/ ← IPC socket directory
```

Then offers to download the **testnet snapshot** (~60 GB download, ~120 GB on disk). This lets your node start near the chain tip in 1–2 hours rather than syncing from genesis (which would take many days).
Then offers to download the **testnet snapshots**. The upstream Arc repo currently lists the latest snapshots as roughly **68 GB EL + 16 GB CL compressed**, expanding to roughly **103 GB EL + 36 GB CL**. The script requires 200 GB free before starting so the compressed archives and extracted data both have room.

The free disk space is checked before downloading. Snapshot download is given a 4-hour timeout.
The Arc node docs say a fresh node needs a snapshot to bootstrap; syncing a new node from genesis is currently not supported. Snapshot download is given a 4-hour timeout.

### Phase 5 — Initialise Consensus Layer

Expand All @@ -232,15 +232,17 @@ Writes two systemd unit files:

| Service | Binary | Key Behaviour |
|---|---|---|
| `arc-execution` | `arc-node-execution` | Runs Reth EL; exposes JSON-RPC on `localhost:8545` (or `0.0.0.0:8545` with `--expose-rpc`) |
| `arc-consensus` | `arc-node-consensus` | Runs the BFT consensus layer; connects to EL via IPC socket |
| `arc-execution` | `arc-node-execution` | Runs Reth EL with Arc's `--full` pruning preset; exposes JSON-RPC on `localhost:8545` (or `0.0.0.0:8545` with `--expose-rpc`) |
| `arc-consensus` | `arc-node-consensus` | Runs the BFT consensus layer in follow mode with `--full` and execution-persistence backpressure; connects to EL via IPC socket |

Both services:
- Start automatically on boot (`WantedBy=multi-user.target`)
- Restart automatically on crash (`Restart=on-failure`, 10-second delay)
- Log to `journald`
- Have `LimitNOFILE=1048576`

The service flags follow the upstream Arc node binary guide: both layers start with `--full`, and the consensus layer adds `--execution-persistence-backpressure --execution-persistence-backpressure-threshold=50`.

The script waits up to 120 seconds for the execution-layer IPC socket (`/run/arc/reth.ipc`) to appear before starting the consensus layer.

If `--with-firewall` was passed, `ufw` is configured automatically (see [Firewall](#firewall-ufw)).
Expand Down Expand Up @@ -339,7 +341,7 @@ The ordering (consensus before execution on stop, execution before consensus on
Guided removal. You are asked separately (with a danger prompt) about:

1. Services and binaries — removed automatically after confirmation
2. Chain data at `~/.arc` (~120+ GB) — separate `yes`-to-confirm prompt
2. Chain data at `~/.arc` (~139+ GB with current snapshots) — separate `yes`-to-confirm prompt
3. Source code at `~/arc-node-src` — optional
4. Passwordless sudo drop-in (if present)

Expand Down Expand Up @@ -404,13 +406,13 @@ Configures `ufw` with these rules:
./setup.sh setup --skip-snap
```

Skips the snapshot download entirely. The node will sync from genesis block 0, which can take **many days**. Not recommended unless you have a specific reason.
Skips only the script-managed snapshot download. Use this only if compatible execution and consensus data already exists, or if you will bootstrap it manually before expecting the services to sync. The current Arc node docs say a fresh node cannot bootstrap from genesis.

### Pin a Specific Arc Version

```bash
./setup.sh setup --version v0.7.1
./setup.sh setup --version v0.6.0 --yes
./setup.sh setup --version v0.7.1 --yes
```

Version strings must match `v<MAJOR>.<MINOR>.<PATCH>` exactly. The tag must exist in `circlefin/arc-node`.
Expand Down Expand Up @@ -471,8 +473,8 @@ After a successful install:
├── arc-setup.log ← Full setup log (all output)
├── arc-node-src/ ← Cloned + compiled source (circlefin/arc-node)
├── .arc/
│ ├── execution/ ← Reth execution-layer data (~120 GB with snapshots)
│ └── consensus/
│ ├── execution/ ← Reth execution-layer data (~103 GB with current snapshots)
│ └── consensus/ ← Consensus-layer data (~36 GB with current snapshots)
│ └── config/
│ └── priv_validator_key.json ← Your P2P identity key
└── .arc-key-backup/
Expand Down Expand Up @@ -544,7 +546,7 @@ cat ~/arc-setup.log

| Resource | URL |
|---|---|
| Arc Docs | https://docs.arc.network |
| Arc Docs | https://docs.arc.io |
| Block Explorer | https://testnet.arcscan.app |
| Testnet Faucet | https://faucet.circle.com |
| Arc Discord | https://discord.com/invite/buildonarc |
Expand Down
42 changes: 23 additions & 19 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#
# SETUP OPTIONS:
# -y, --yes Skip all yes/no prompts (non-interactive / CI)
# --skip-snap Skip snapshot download (sync from genesis — very slow)
# --skip-snap Skip snapshot download (requires existing data)
# --expose-rpc Bind JSON-RPC on 0.0.0.0 (needed for MetaMask over LAN)
# --with-firewall Auto-configure ufw firewall rules
# --swap SIZE Create swap file, e.g. --swap 16G
Expand Down Expand Up @@ -65,7 +65,7 @@ STATE_FILE="${HOME}/.arc-setup-state"
BACKUP_DIR="${HOME}/.arc-key-backup"

MIN_RAM_GB=64
MIN_DISK_GB=150
MIN_DISK_GB=200
MONITOR_INTERVAL=5
EL_RPC_PORT=8545
EL_P2P_PORT=30303
Expand Down Expand Up @@ -179,7 +179,7 @@ ${BOLD}COMMANDS${NC}

${BOLD}SETUP OPTIONS${NC}
${YELLOW}-y, --yes${NC} Skip all yes/no prompts (non-interactive)
${YELLOW}--skip-snap${NC} Skip snapshot download (sync from genesis — very slow)
${YELLOW}--skip-snap${NC} Skip snapshot download (requires existing data)
${YELLOW}--expose-rpc${NC} Bind JSON-RPC on 0.0.0.0 (needed for MetaMask over LAN/WAN)
${YELLOW}--with-firewall${NC} Auto-configure ufw firewall rules
${YELLOW}--swap SIZE${NC} Create swap file, e.g. --swap 16G (use if RAM < ${MIN_RAM_GB} GB)
Expand All @@ -199,7 +199,7 @@ ${BOLD}EXAMPLES${NC}
./setup.sh rollback-sudo Remove the passwordless sudo drop-in

${BOLD}RESOURCES${NC}
Docs https://docs.arc.network
Docs https://docs.arc.io
Explorer https://testnet.arcscan.app
Faucet https://faucet.circle.com
Discord https://discord.com/invite/buildonarc
Expand Down Expand Up @@ -377,8 +377,8 @@ phase_welcome() {
echo -e "${YELLOW}⚠ Requirements at a glance:${NC}"
echo " OS : Ubuntu 22.04+ or Debian 12+"
echo " RAM : 64 GB+ (Reth spikes during initial sync)"
echo " Storage : 1 TB+ NVMe SSD (150 GB free minimum)"
echo " Network : Stable 24 Mbps+ (snapshots ≈ 60 GB)"
echo " Storage : 1 TB+ NVMe SSD (${MIN_DISK_GB} GB free minimum)"
echo " Network : Stable 24 Mbps+ (snapshots ≈ 84 GB compressed)"
echo " Time : 1–3 hours total (compile + snapshot download)"
echo ""
[[ -n "$FLAG_SWAP" ]] && info "--swap ${FLAG_SWAP}: will create a swap file."
Expand Down Expand Up @@ -774,15 +774,15 @@ phase_setup_data() {
echo ""

if $FLAG_SKIP_SNAP; then
warn "--skip-snap: Skipping snapshots. Node will sync from genesis (very slow)."
warn "--skip-snap: Skipping snapshot download. Arc docs do not support bootstrapping a fresh node from genesis."
else
echo -e "${DIM} Snapshots let you start near the chain tip instead of syncing${NC}"
echo -e "${DIM} from block 0 (genesis), which would take many days.${NC}"
echo -e "${DIM} Arc docs require snapshots to bootstrap a fresh node.${NC}"
echo -e "${DIM} This downloads the latest EL and CL pruned snapshots.${NC}"
echo ""
warn "~60 GB download → ~120 GB on disk. Typically 1–2 hours."
warn "~84 GB compressed → ~139 GB extracted. Download time depends on connection speed."
echo ""
if confirm "Download blockchain snapshots? (strongly recommended)"; then
local required_gb=130
local required_gb=200
local free_gb; free_gb=$(df -BG "$ARC_DATA_DIR" | awk 'NR==2{gsub("G",""); print $4}')
if [[ -z "$free_gb" ]]; then
warn "Could not parse free disk space for ${ARC_DATA_DIR} — assuming 0 GB."
Expand All @@ -798,7 +798,7 @@ phase_setup_data() {
|| fatal "Snapshot download failed or timed out after 4 hours. Check ${LOG_FILE}"
success "Snapshots downloaded and extracted!"
else
warn "Skipped — node will sync from genesis (very slow)."
warn "Skipped — setup will continue, but a fresh node needs compatible snapshot data before it can bootstrap."
fi
fi

Expand Down Expand Up @@ -899,7 +899,7 @@ phase_install_services() {
sudo tee /etc/systemd/system/arc-execution.service > /dev/null <<EOF
[Unit]
Description=Arc Node — Execution Layer (Reth)
Documentation=https://docs.arc.network
Documentation=https://docs.arc.io
After=network-online.target
Wants=network-online.target

Expand All @@ -913,6 +913,7 @@ WorkingDirectory=${ARC_DATA_DIR}
ExecStart=${bin_path}/arc-node-execution node \\
--chain arc-testnet \\
--datadir ${ARC_EXECUTION_DIR} \\
--full \\
--disable-discovery \\
--ipcpath /run/arc/reth.ipc \\
--auth-ipc \\
Expand Down Expand Up @@ -944,7 +945,7 @@ EOF
sudo tee /etc/systemd/system/arc-consensus.service > /dev/null <<EOF
[Unit]
Description=Arc Node — Consensus Layer (Malachite)
Documentation=https://docs.arc.network
Documentation=https://docs.arc.io
After=arc-execution.service
Requires=arc-execution.service

Expand All @@ -957,14 +958,17 @@ WorkingDirectory=${ARC_DATA_DIR}
ExecStart=${bin_path}/arc-node-consensus start \\
--home ${ARC_CONSENSUS_DIR} \\
--private-key ${ARC_CONSENSUS_DIR}/config/${CONSENSUS_KEY_BASENAME} \\
--full \\
--p2p.addr /ip4/0.0.0.0/tcp/${CL_P2P_PORT} \\
--eth-socket /run/arc/reth.ipc \\
--execution-socket /run/arc/auth.ipc \\
--rpc.addr 127.0.0.1:${CL_RPC_PORT} \\
--follow \\
--follow.endpoint https://rpc.drpc.testnet.arc.network \\
--follow.endpoint https://rpc.quicknode.testnet.arc.network \\
--follow.endpoint https://rpc.blockdaemon.testnet.arc.network \\
--follow.endpoint https://rpc.drpc.testnet.arc.network,wss=rpc.drpc.testnet.arc.network \\
--follow.endpoint https://rpc.quicknode.testnet.arc.network,wss=rpc.quicknode.testnet.arc.network \\
--follow.endpoint https://rpc.blockdaemon.testnet.arc.network,wss=rpc.blockdaemon.testnet.arc.network/websocket \\
--execution-persistence-backpressure \\
--execution-persistence-backpressure-threshold=50 \\
--metrics 127.0.0.1:${CL_METRICS_PORT}

Restart=on-failure
Expand Down Expand Up @@ -1121,7 +1125,7 @@ print_summary() {
echo ""

echo -e "${BOLD}Resources:${NC}"
echo " Docs : https://docs.arc.network"
echo " Docs : https://docs.arc.io"
echo " Explorer : https://testnet.arcscan.app"
echo " Faucet : https://faucet.circle.com"
echo " Discord : https://discord.com/invite/buildonarc"
Expand Down Expand Up @@ -1717,7 +1721,7 @@ cmd_uninstall() {
echo " • Passwordless sudo drop-in (/etc/sudoers.d/${USER}-nopasswd)"
echo ""
echo "Optionally (asked separately):"
echo " • Chain data at ${ARC_DATA_DIR} (~120+ GB)"
echo " • Chain data at ${ARC_DATA_DIR} (~139+ GB with current snapshots)"
echo " • Source code at ${BUILD_DIR}"
echo ""

Expand Down
15 changes: 14 additions & 1 deletion tests/smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,30 @@ assert_output_contains "$help_output" 'Arc Node Setup & Manager'
assert_output_contains "$help_output" 'Testnet v0\.7\.1'
assert_output_contains "$help_output" '\./setup\.sh update v0\.7\.1'
assert_output_contains "$help_output" '--version VER[[:space:]]+Arc version to install[[:space:]]+\(default: v0\.7\.1\)'
assert_output_contains "$help_output" 'https://docs\.arc\.io'
assert_file_contains README.md 'bash -s -- setup --yes'
assert_file_contains README.md 'bash -s -- setup -y'

assert_file_contains setup.sh '^ARC_VERSION_DEFAULT="v0\.7\.1"$'
assert_file_contains setup.sh '^CONSENSUS_KEY_BASENAME="priv_validator_key\.json"$'
assert_file_contains setup.sh '^EL_RPC_PORT=8545$'
assert_file_contains setup.sh '^EL_P2P_PORT=30303$'
assert_file_contains setup.sh '^CL_RPC_PORT=31000$'
assert_file_contains setup.sh '^CL_P2P_PORT=31001$'
assert_file_contains setup.sh '^MIN_DISK_GB=200$'
assert_file_contains setup.sh 'systemctl show "\$svc" --property=LoadState --value'
assert_file_contains setup.sh '--private-key \$\{ARC_CONSENSUS_DIR\}/config/\$\{CONSENSUS_KEY_BASENAME\}'
assert_file_contains setup.sh '--full[[:space:]]*\\\\'
assert_file_contains setup.sh '--p2p\.addr /ip4/0\.0\.0\.0/tcp/\$\{CL_P2P_PORT\}'
assert_file_contains setup.sh '--follow\.endpoint https://rpc\.drpc\.testnet\.arc\.network'
assert_file_contains setup.sh '--follow\.endpoint https://rpc\.drpc\.testnet\.arc\.network,wss=rpc\.drpc\.testnet\.arc\.network'
assert_file_contains setup.sh '--follow\.endpoint https://rpc\.blockdaemon\.testnet\.arc\.network,wss=rpc\.blockdaemon\.testnet\.arc\.network/websocket'
assert_file_contains setup.sh '--execution-persistence-backpressure[[:space:]]*\\\\'
assert_file_contains setup.sh '--execution-persistence-backpressure-threshold=50'
assert_file_contains setup.sh 'sudo ufw allow "\$\{EL_P2P_PORT\}/tcp"'
assert_file_contains setup.sh 'sudo ufw allow "\$\{EL_P2P_PORT\}/udp"'
assert_file_contains setup.sh 'sudo ufw allow "\$\{CL_P2P_PORT\}/tcp"'
assert_file_contains setup.sh 'printf " %-36s\$\{CYAN\}%s\$\{NC\}\\n" "Execution peers" "\$peers"'
assert_file_contains README.md 'fresh node cannot bootstrap from genesis'

if grep -Eq 'node_key\.json|node_key_<timestamp>' setup.sh README.md; then
fail 'stale node_key.json documentation or script reference found'
Expand All @@ -52,6 +61,10 @@ if grep -Eq 'sudo -n bash -c|auto-accepting sudo drop-in|Allow setup\.sh to writ
fail 'sudo bootstrap still claims it can self-write a sudoers drop-in'
fi

if grep -Eq 'will sync from genesis|syncs from genesis|sync from genesis \(very slow\)' setup.sh README.md; then
fail 'snapshot skip guidance still claims a fresh genesis sync is supported'
fi

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
mkdir -p "$tmp_dir/bin" "$tmp_dir/home"
Expand Down
Loading