Skip to content

Servers: CLI and Docker

necter-miner is one binary: CLI, background daemon, local HTTP API and dashboard. Mining needs no inbound port: everything is outbound HTTPS plus one outbound WebSocket.

Terminal window
cargo build --release -p necter-miner && sudo install target/release/necter-miner /usr/local/bin/
necter-miner init # asks "Open the web dashboard on this server's IP? [y/N]" on servers
necter-miner join --project 0x<project_id> --payout 0x<payout address>
sudo necter-miner service install # systemd unit (User=necter-miner, ProtectSystem=strict, data in /var/lib/necter-miner)

On a headless host without a keyring, the embedded wallet’s encryption key lives in <data_dir>/wallet.key (0600) unless you pass --wallet-key-file. Data: ~/.local/share/necter-miner (service: /var/lib/necter-miner).

necter-miner join --project <id> does init + bind (embedded wallet) + faucet + subscribe + run:

Flag
--project <id> the project to mine (its id from the store)
--collateral <NECTA> decimal, e.g. 10 or 12.5; default: the project’s minimum
--payout 0x… where rewards go (default: the owner wallet)
--no-run do not start the daemon afterwards

Find project ids in the store, or: curl -s https://testnet-rpc.necter.network/v1/projects.

A fresh init prints:

Data dir: /home/miner/.local/share/necter-miner
Node ID: ndsr-f7f67866c5cfe55c
Wallet: 0x0414cceceab0d06f76db18c923afca75c672ceb4 (embedded)
Dashboard: ssh -L 7878:127.0.0.1:7878 <user>@<host> then open http://127.0.0.1:7878

and status:

State: stopped
node: ndsr-f7f67866c5cfe55c
owner: (unbound)
relay: disconnected
engine: native
leases: 0 active, 0 today (0 units)
(daemon not running; start it with `necter-miner start`)
Terminal window
necter-miner status [--json] # state, owner, relay, engine, leases
necter-miner start | stop [--daemon] # stop mining; --daemon also exits the daemon
necter-miner subscriptions [--json]
necter-miner claims [--submit] # show / claim rewards (gasless)
necter-miner faucet # test NECTA for the owner wallet
necter-miner leave --project <id> # unbond this device's subscription
necter-miner withdraw --project <id> # withdraw released collateral after unbonding
necter-miner payout set 0x… # change the payout address (gasless)
necter-miner policy show | policy set max_cpu_pct=50 networks='["ethernet"]'
necter-miner logs [-f] [--level warn]
necter-miner bench # run the benchmark suite
necter-miner update [--check]

Full list: necter-miner CLI.

By default the dashboard listens only on 127.0.0.1:7878. Reach it through SSH:

Terminal window
ssh -L 7878:127.0.0.1:7878 user@host # then open http://127.0.0.1:7878

To open it on the server’s IP (opt-in; password and TLS are mandatory):

  1. Enable it interactively:

    Terminal window
    necter-miner ui enable-remote # prompts for a password twice (min 12 chars)
    necter-miner ui enable-remote --domain miner.example.org # Let's Encrypt instead of self-signed

    or non-interactively:

    Terminal window
    install -m 600 /dev/stdin /root/ui-pass <<< 'a-long-unique-password'
    necter-miner --ui-public --ui-password-file /root/ui-pass run
  2. Allow TCP 7878 in your firewall or security group.

  3. Open https://<server-ip>:7878. With the self-signed certificate, compare the SHA-256 fingerprint the CLI printed with the one your browser shows before accepting it.

How it is protected:

  • The password is stored only as an argon2id hash in miner.toml. The daemon refuses to start (exit 78) if the dashboard is bound to a non-loopback address without a password or without TLS.
  • TLS: a self-signed ECDSA P-256 certificate (397 days, renewed 30 days before expiry), or Let’s Encrypt with --ui-domain (HTTP-01 on port 80, or TLS-ALPN-01 when the dashboard uses port 443).
  • 5 failed sign-ins per IP in 15 minutes → 15-minute lockout, doubling up to 24 hours; 60 attempts per minute globally. Sessions are Secure; HttpOnly; SameSite=Strict cookies (12 h, 1 h idle) with CSRF protection.
  • Payout changes, unbond, withdraw, wallet create/unlock and dashboard settings ask for the password again. Wallet import and export are never available remotely.
  • necter-miner ui status | disable-remote [--forget-password] | set-password | rotate-token work on a running daemon.
Code Meaning
0 ok
1 runtime error
2 usage error
73 cannot create the data directory or key
75 another instance holds miner.lock
78 configuration refused (e.g. remote dashboard without password/TLS)

If the Hub is unreachable, the daemon keeps running, serves the dashboard, raises a hub_unreachable alert and retries with backoff (1 s to 60 s).