Skip to content

Operations

Terminal window
# 1. First machine — installs nauka and founds a systemd-managed cluster:
curl -sSfL https://sh.getnauka.com | sh
# 2. Every next machine, run from the first one:
nauka node add <ip>:7311

That’s it. init (run by the installer) generates the cluster identity and founds the cluster; node add provisions each target over SSH — binary, systemd unit, identity — and takes it through consensus to a voting member. The full flow, including the key-directory alternative to the token, is on the Deploy page.

Firewall — the step that catches everyone out: open the listen port AND the next one over UDP (default: 7311/udp and 7312/udp), as well as the HTTP port over TCP (default 8080/tcp). All inter-node traffic is QUIC, hence UDP. Add 8333/tcp only for a binary built with the s3 feature, and 9100/tcp only if you widened --metrics beyond loopback. Several nodes on the same host: space the ports at least 2 apart (the consensus plane of one node would collide with the data plane of the next).

Global options: --data-dir <dir> (default ./nauka-data), --keys <dir> (cluster key directory), --token (cluster token — prefer the NAUKA_TOKEN environment variable, command lines are visible in ps). Commands run on an initialized machine inherit the identity from /etc/nauka/nauka.env automatically — no re-exporting.

Everywhere a hash is expected, a unique prefix works (≥ 4 characters, git-style), resolved against the local store first, then the cluster.

CommandRole
initfounds the first node on this machine, systemd-managed (root + systemd Linux)
node add <ip:port>provisions a machine over SSH and joins it (learner → voter)
node remove <id>live removal (drained by the scrubs; ids in nauka status)
servestarts a node by hand (options below)
status [--api <url>] [--json]members, leader, liveness, capacities, stored bytes; --json for scripts
list [--full] [--local]the cluster’s files, 16-char hashes (--full for 64; --local for this machine’s own store)
get <hash> -o flocal store first, else downloaded from the cluster and BLAKE3-verified client-side
verify <hash>local check, else the cluster serves the file and the hash is verified end-to-end
put <file>encode into this machine’s LOCAL store (standalone use, no network)
upload <file>client-side AES-256-GCM, then upload — prints a share link with the key in the fragment
download <link> -o fdownload + decrypt + verify a share link
tokengenerate a cluster token (the one string that IS the cluster)
keygen --out <dir>the key-directory alternative to the token (refuses to overwrite)
node-infothis node’s node-id + fingerprint
ban <hash> --reason "…" / unban <hash>block a file cluster-wide without reading it (410 on GET)
update [--check]self-update from the latest release, checksum verified

serve options:

OptionDefaultRole
--listen0.0.0.0:7311QUIC data socket (consensus = port+1)
--advertise--listenaddress advertised to the other nodes — the node’s placement identity. Give it a real, reachable address; a wildcard advertise warns
--http / --no-http0.0.0.0:8080public HTTP API
--metrics / --no-metrics127.0.0.1:9100Prometheus endpoint. Loopback by default on purpose: the exposition describes topology, capacities and peer addresses. Widen it only towards a private scrape network
--scrub-interval30 shealing + GC cadence
--capacitysize of the data-dir’s filesystemweight for weighted placement, in bytes
--joinoffwait to be added by a member instead of founding a cluster on a blank data dir (what node add passes to provisioned machines)
--egress-quotaunmeteredmonthly egress budget (env NAUKA_EGRESS_QUOTA; human sizes like 500GB, 20TB; deprioritized past it, never refused)
--cache-sizeauto: 10% of free disk (1GB floor, 50GB cap)disk budget of the local stripe cache (env NAUKA_CACHE_SIZE; 0 disables; content-addressed so never stale, LRU)
--extent-cache-size128MBRAM budget for verified shards and stripes used by Range reads (env NAUKA_EXTENT_CACHE_SIZE; human sizes accepted; 0 disables). Payload, keys and allocation overhead are charged; 4,096 entries and 32 cold loads max; duplicate reads are fused
NAUKA_SMALL_THRESHOLD131072files at or under this many bytes are replicated (1+m full copies, one-round-trip reads) instead of striped; 0 disables
--dns-zone <name>nonezone served by the built-in authoritative geo-DNS (repeat the flag, or set comma-separated NAUKA_DNS_ZONES); outside names return REFUSED, and DNS stays disabled when no zone is configured
--no-dnsoff without a zonedisables the built-in geo-DNS front door (env NAUKA_NO_DNS=true|false); a failed :53 bind only warns
NAUKA_HTTPS_DOMAINHTTP onlyserve the API over TLS on :443 for this domain, with a Let’s Encrypt certificate the node obtains and renews itself through the cluster’s own DNS

serve pre-binds every socket before founding anything: a busy port fails loudly with nothing written to the data dir. On a blank data dir the first serve founds a single-node cluster.

  • nauka status [--api http://<node>:8080]: has a leader been elected? are all members present and alive (●)? It also warns when two members share an address — the signature of a stale identity left behind by a reinstalled machine. Remote reads require the inherited cluster identity; --json passes through the raw /api/status document for scripts and monitoring. Loopback remains available for local health checks.
  • Prometheus metrics on 127.0.0.1:9100 (unless moved): scrub results, shard fetch sources, degraded writes, egress ledgers.
  • Node logs (journalctl -u nauka): scrub: X checked, Y regenerated, Z unrecoverable (Y > 0 means a real repair happened; a persistent Z means too many dead nodes), gc: N shards released (rebalancing), and peer … unreachable warnings.
  • verify <hash>: can the file be rebuilt — from the local store if it is here, otherwise served by the cluster and hash-checked end-to-end?
  • Authenticated /api/files must return the same list on every node (give or take a few hundred ms of replication lag).
  • Back up the cluster identity above all — the token, or cluster-ca.key for key-directory deployments. Losing it means no new node and no new client machine can ever join; the running cluster keeps running, but it can no longer grow or be administered from a fresh machine.
  • The node.key files are optional. A reinstalled node without its old key takes on a new identity; the stale one is either retired with node remove <id>, or — if the machine comes back at the same address via node add — evicted automatically in the same membership change that admits the new identity.
  • Data-dirs rebuild themselves: a node with a blank disk that rejoins gets its share back through healing. (Do not wipe more than m nodes at a time!)
  • A total cluster shutdown (power cut) is covered: all the state that matters is durable in the data-dirs.
LimitationWorkaround / plan
HTTP API with no authentication and no quotas — public API = public filesreverse proxy in the meantime
No NAT traversal (hole punching/relays)nodes with a public IP or a forwarded port; relays to come
The cluster key is present on every node — one compromised machine is a compromised cluster membershipoffline certificate issuance to come
A full disk is not refused: writes fail late instead of earlywatch disk usage; a safeguard is planned
Unfair bandwidth sharing between concurrent uploads (large streams dominate)harmless to durability — fair queuing is in the backlog