Run a Logos storage node
Get started running a Logos storage node and uploading your first file to the Logos network.
This procedure covers how to build and run the Logos Storage Module, connect it to the testnet bootstrap nodes, publish a file, and verify that the file can be downloaded. It is intended for node operators on testnet v0.2 who want to contribute storage capacity to the Logos network.
Before you start, make sure you have the following:
-
Linux (tested on Ubuntu 22.04)
-
Nix with flakes enabled. Install from nixos.org, then enable flakes:
mkdir -p ~/.config/nixecho 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf -
logoscore, andlgpminstalled. To install these tools, use theinstall-node-tools.shhelper script:curl -fsSL https://raw.githubusercontent.com/logos-co/logos-docs/main/resources/scripts/install-node-tools.sh | shexport PATH="$PWD/bin:$PATH" -
jqon yourPATH— used to pull the uploaded CID out of the manifests JSON. Verify:jq --version
What to expect
- You can connect a Logos Storage node to the testnet and have it listed among the bootstrap peers.
- You can publish a file to the network and retrieve a content address to share with other nodes.
- You can download the file back from the network and confirm it lands on disk.
Build and install the storage module
-
Build the module package with Nix:
nix build 'github:logos-co/logos-storage-module/v2.1.0#lgx-portable' -o storage-lgx- This produces a
.lgxpackage in./storage-lgx/.
infoUse the
#lgx-portableoutput: it declares the standard platform variant (e.g.linux-amd64) that the release build oflgpmaccepts. The plain#lgxoutput produces a-devvariant that only a source-builtlgpmcan install.infoThe initial Nix build takes 15–20 minutes on first run. Subsequent builds use the Nix cache and complete in seconds.
- This produces a
-
Install the package into a local modules directory using
lgpm. The package is a local build and is unsigned, so pass--allow-unsigned:mkdir -p moduleslgpm --modules-dir ./modules --allow-unsigned install --file storage-lgx/*.lgx -
Confirm the module landed:
lgpm --modules-dir ./modules list# storage_module appears in the listing
Start the daemon and load the storage module
Run logoscore with the modules directory, then load and initialise the storage module against the testnet config.
Several module calls in this procedure are asynchronous: the call returns "result":true as soon as the command is accepted, and the real outcome is delivered later as an event (storageStart, storageUploadDone, storageDownloadDone, storageRemoveDone, storageDownloadManifestDone). These events are emitted to event subscribers (such as the Storage UI); the logoscore call client does not subscribe to them, so they do not appear in logs.txt. Each step below instead waits briefly and confirms the outcome with a follow-up query (for example manifests or exists).
-
Start the
logoscoredaemon in background mode, capturing its output:logoscore -D -m ./modules > logs.txt 2>&1 &- The client subcommands below connect to this running process via the config written under
~/.logoscore/.
- The client subcommands below connect to this running process via the config written under
-
Verify the daemon is running:
logoscore status# Logoscore Daemon# Status: running# PID: 148188# Uptime: 0s# Version: v1.0.0## Modules: 1 loaded, 0 crashed, 1 not loaded# storage_modulev not_loaded -# capability_modulev loaded - -
Load the storage module and confirm it reports
loaded:logoscore load-module storage_module# Loaded module: storage_module (v)logoscore status# Logoscore Daemon# Status: running# PID: 148188# Uptime: 0s# Version: v1.0.0# Modules: 2 loaded, 0 crashed, 0 not loaded# storage_modulev loaded -# capability_modulev loaded -- To see every method the module exposes (the same methods you can
call), runlogoscore module-info storage_module.
- To see every method the module exposes (the same methods you can
-
Create the storage config. Use absolute paths: in daemon mode the module runs as its own process, whose working directory is not the one you are typing in, so relative paths resolve to the wrong place. Replace
your-public-IPby your public external IP. The$(pwd)in the heredoc takes care of it:mkdir -p "$(pwd)/storage-data"cat > config.json <<EOF{"data-dir": "$(pwd)/storage-data","log-level": "INFO","log-file": "$(pwd)/storage-data/storage.log","listen-ip": "0.0.0.0","listen-port": 8091,"disc-port": 8090,"network": "logos.test","nat": "extip:<your-public-IP>"}EOF-
With
"nat": "extip:<your-public-IP>"the node announces the machine's own IP as-is. If it is reachable from other peers over Internet (with ports forwarded for example), the node will be able to upload and download from other peers. Otherwise, it can only download from the network but other peers will not be able to download from this node. To know more about node reachable state: see Connectivity. -
config.jsonincludes the following fields:
Field Purpose data-dirStorage repository path (absolute) log-levelLog verbosity log-fileNode log destination (absolute) listen-ipLocal TCP bind address listen-portPublic TCP libp2p port disc-portPublic UDP discovery port networkStorage network preset natPublic IP advertisement mode — see Connectivity - Every omitted key keeps its default: the node joins the
logos.testnetwork preset (which provides the testnet bootstrap settings), binds discovery to the default UDP port8090, and picks a random TCPlisten-port. - For a public, reachable node, set fixed
listen-port(TCP) anddisc-port(UDP) values: see Connectivity.
-
-
Initialise the storage module with the testnet configuration.
initis synchronous and returnstrueon success (the@config.jsonsyntax loads the file's contents as the argument):logoscore call storage_module init @config.json -
Start the node.
startis asynchronous: the return value only confirms the command was accepted; completion is signalled later by thestorageStartevent (delivered to event subscribers, not written tologs.txt):logoscore call storage_module start# Wait few seconds to start -
Inspect the running node with
debug. It returns the node's identity: itsid(peer ID) and itsspr, the signed record other nodes use to connect to you (see Connectivity):logoscore call storage_module debug
Publish and download a file
Once the node is running and connected to the testnet, publish a file and verify the round-trip.
-
Create a file to publish:
echo "Hello world from Logos Storage" > "$(pwd)/hello.txt" -
Upload the file to the network with
uploadUrl. It takes an absolute path and a chunk size in bytes, and returns immediately; the upload runs in the background and completes with astorageUploadDoneevent:logoscore call storage_module uploadUrl "$(pwd)/hello.txt" 65536infoThe default chunk size is 65536.
-
Extract the content ID (CID) from the first
manifestsentry:# Wait a second for the upload to complete firstlogoscore call storage_module manifests \| jq -er '.result.value[0].cid' > cid.txt -
Download the file back from local storage with
downloadToUrl. It takes the CID, an absolute destination path, alocalflag, and a chunk size in bytes. Withlocalset totrue, the download reads the blocks straight back out of this node's own repository. LikeuploadUrlit runs in the background and completes with astorageDownloadDoneevent:logoscore call storage_module downloadToUrl "$(cat cid.txt)" "$(pwd)/hello-destination.txt" true 65536- The
localflag reads only from locally cached data when set totrue;falsefetches from the network.
- The
-
Confirm the downloaded file is present at the destination path and matches the original. You can also check the content is in local storage by CID:
# Confirm the download is a byte-for-byte copy of the original (both files are static):diff "$(pwd)/hello.txt" "$(pwd)/hello-destination.txt" && echo "match"# And confirm the content is in local storage by CID:logoscore call storage_module exists "$(cat cid.txt)"# returns true
Remove content and shut everything down
To clear your local storage, destroy the storage node, and stop the daemon, follow the steps below.
-
Remove content from local storage by its CID.
removereturns immediately; the outcome arrives as astorageRemoveDoneevent:logoscore call storage_module remove "$(cat cid.txt)" -
Confirm the content is gone:
# Wait a second for the removal to complete firstlogoscore call storage_module exists "$(cat cid.txt)" | jq '.result.value'# false -
Stop the storage node.
stopis asynchronous likestart; completion is signalled by astorageStopevent (delivered to event subscribers, not written tologs.txt). The node can be started and stopped multiple times:logoscore call storage_module stop# Wait a few seconds for the node to stop before destroying it -
Destroy the storage context.
destroyis synchronous and must be called after the node is stopped:logoscore call storage_module destroy -
Stop the daemon and confirm it has exited:
logoscore stop# Wait 5 secondslogoscore status# Logoscore Daemon# Status: not_running
Troubleshooting Logos Storage
Connectivity problems (downloads timing out from another machine, no peers, unreachable node) are covered in the Troubleshooting and Connectivity pages.