From 25e9c5a23dbb388160ce416ea93240c5afb2ced0 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Mon, 12 Oct 2026 21:12:34 +0200 Subject: [PATCH] fix(catalog): catch up with the web catalog and point at a wrong-shaped key in the form The vendored catalog was missing the Storj Chapter 11 caution, the Repocket API key pattern, Noderr and Sia hostd. The sync refused to run because Sia hostd ships a floating image with no digest pin here, so the pin comes first and the README lists the two new services with the counts the tests check. The web app's #428 taught the deploy form to hand a catalog pattern to the browser and refuse a wrong-shaped value before anything is sent. The backend here already enforced the pattern on every deploy; now the wizard renders it on the input, asks the browser for a new secret rather than a saved password, and reports the first invalid field before Save or Deploy. The render checks cover the attribute and were watched failing without it. --- README.md | 6 +- catalog-overlay/image-pins.yml | 3 + frontend/scripts/fields_check.mjs | 10 ++ frontend/scripts/wizard_render_check.mjs | 23 ++++ frontend/src/main.ts | 17 +++ frontend/src/render/fields.ts | 1 + frontend/src/render/wizard.ts | 2 +- frontend/src/wails.d.ts | 3 + services/bandwidth/repocket.yml | 3 +- services/depin/noderr.yml | 110 ++++++++++++++++ services/storage/sia-hostd.yml | 157 +++++++++++++++++++++++ services/storage/storj.yml | 28 ++-- 12 files changed, 349 insertions(+), 14 deletions(-) create mode 100644 services/depin/noderr.yml create mode 100644 services/storage/sia-hostd.yml diff --git a/README.md b/README.md index 0b94654..a727182 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ Platform notes, system requirements and the full walkthrough are in [Getting sta ## Supported services -CashPilot bundles a catalog of 39 active passive-income services across multiple categories (the catalog also carries 11 retired entries, which the app hides and refuses to deploy). Some links below are affiliate/referral links -- see the [disclosure](docs/services.md#disclosure). Read [how bandwidth-sharing works](docs/services.md#before-you-start-how-bandwidth-sharing-works) before you opt in; per-service limits, payouts and caveats are in [docs/services.md](docs/services.md). +CashPilot bundles a catalog of 41 active passive-income services across multiple categories (the catalog also carries 11 retired entries, which the app hides and refuses to deploy). Some links below are affiliate/referral links -- see the [disclosure](docs/services.md#disclosure). Read [how bandwidth-sharing works](docs/services.md#before-you-start-how-bandwidth-sharing-works) before you opt in; per-service limits, payouts and caveats are in [docs/services.md](docs/services.md). -- **Docker-deployable:** [Anyone Protocol](https://anyone.io), [Bitping](https://app.bitping.com), [Earn.fm](https://earn.fm/ref/GEISYB91), [EarnApp](https://earnapp.com/i/TSMD9wSm), [Honeygain](https://dashboard.honeygain.com/ref/SERGIB4014), [IPRoyal Pawns](https://pawns.app?r=19266874), [MystNodes](https://mystnodes.co/?referral_code=do7v7YOoBBpbOstKQovX2pUvZYKia4ZhH3QIdNtE), [PacketStream](https://packetstream.io/?psr=7xgZ), [ProxyBase](https://peer.proxybase.org?referral=nXzS3c6iTO), [ProxyBase Markets](https://proxybase.xyz?referral=nXzS3c6iTO), [ProxyLite](https://proxylite.ru/?r=KMUPRZIZ), [ProxyRack](https://peer.proxyrack.com/ref/mpwiok3xlaxeycnn5znqlg7ipjeutxyxr6xl7vmn), [Repocket](https://repocket.com/), [Storj](https://storj.dev/node/get-started/setup), [Traffmonetizer](https://traffmonetizer.com/?aff=2111758), [URnetwork](https://ur.io/?referral_code=1Q3G19) -- **Browser extension / desktop only:** [Bytebenefit](https://bytebenefit.io/invited?ref=Brl4z3), [Bytelixir](https://bytelixir.com/r/OYEIRE0VSZBZ), [Dawn Internet](https://dawninternet.com/?code=2QLQV97F), [Deeper Network](https://deeper.network), [Ebesucher](https://www.ebesucher.com/?ref=geiserx), [Gradient Network](https://app.gradient.network/signup?referralCode=YSKMY7), [Grass](https://app.grass.io/register?referralCode=kn8FNEPnUr2tMqE), [Helium](https://helium.com), [Nodepay](https://app.nodepay.ai/register?ref=0wzzyznen64j9zx), [Nodle](https://nodle.com), [PassiveApp](https://passiveapp.com/i/bqpC4M), [Sentinel dVPN](https://sentinel.co), [Spide](https://spide.network/register.html?f3bc51), [Teneo Protocol](https://dashboard.teneo.pro/?code=CAqef), [Theta Edge Node](https://thetatoken.org), [Titan Network](https://edge.titannet.info/signup?inviteCode=2GKKJ495), [Uprock](https://link.uprock.com/i/33e8492e) +- **Docker-deployable:** [Anyone Protocol](https://anyone.io), [Bitping](https://app.bitping.com), [Earn.fm](https://earn.fm/ref/GEISYB91), [EarnApp](https://earnapp.com/i/TSMD9wSm), [Honeygain](https://dashboard.honeygain.com/ref/SERGIB4014), [IPRoyal Pawns](https://pawns.app?r=19266874), [MystNodes](https://mystnodes.co/?referral_code=do7v7YOoBBpbOstKQovX2pUvZYKia4ZhH3QIdNtE), [PacketStream](https://packetstream.io/?psr=7xgZ), [ProxyBase](https://peer.proxybase.org?referral=nXzS3c6iTO), [ProxyBase Markets](https://proxybase.xyz?referral=nXzS3c6iTO), [ProxyLite](https://proxylite.ru/?r=KMUPRZIZ), [ProxyRack](https://peer.proxyrack.com/ref/mpwiok3xlaxeycnn5znqlg7ipjeutxyxr6xl7vmn), [Repocket](https://repocket.com/), [Sia hostd](https://docs.sia.tech/provide-storage/setting-up-hostd/docker), [Storj](https://storj.dev/node/get-started/setup), [Traffmonetizer](https://traffmonetizer.com/?aff=2111758), [URnetwork](https://ur.io/?referral_code=1Q3G19) +- **Browser extension / desktop only:** [Bytebenefit](https://bytebenefit.io/invited?ref=Brl4z3), [Bytelixir](https://bytelixir.com/r/OYEIRE0VSZBZ), [Dawn Internet](https://dawninternet.com/?code=2QLQV97F), [Deeper Network](https://deeper.network), [Ebesucher](https://www.ebesucher.com/?ref=geiserx), [Gradient Network](https://app.gradient.network/signup?referralCode=YSKMY7), [Grass](https://app.grass.io/register?referralCode=kn8FNEPnUr2tMqE), [Helium](https://helium.com), [Nodepay](https://app.nodepay.ai/register?ref=0wzzyznen64j9zx), [Noderr Micronodes](https://micronodes.noderr.xyz/), [Nodle](https://nodle.com), [PassiveApp](https://passiveapp.com/i/bqpC4M), [Sentinel dVPN](https://sentinel.co), [Spide](https://spide.network/register.html?f3bc51), [Teneo Protocol](https://dashboard.teneo.pro/?code=CAqef), [Theta Edge Node](https://thetatoken.org), [Titan Network](https://edge.titannet.info/signup?inviteCode=2GKKJ495), [Uprock](https://link.uprock.com/i/33e8492e) - **GPU compute:** [Flux](https://runonflux.io), [Golem Network](https://golem.network), [io.net](https://io.net), [Nosana](https://nosana.io), [Salad](https://salad.io), [Vast.ai](https://cloud.vast.ai/?ref_id=452772) ## Documentation diff --git a/catalog-overlay/image-pins.yml b/catalog-overlay/image-pins.yml index 34c9903..74c849e 100644 --- a/catalog-overlay/image-pins.yml +++ b/catalog-overlay/image-pins.yml @@ -56,6 +56,9 @@ pins: repocket: image: "repocket/repocket@sha256:5888d756de7e0e74b95b5eb08bb93f4240a0ce840c910a7e528d1143ad0c502b" why: "Upstream ships no tag at all on this entry." + sia-hostd: + image: "ghcr.io/siafoundation/hostd@sha256:2f27742e103cf79cf1bc818820af936fb342ee435e7bd5ee4f0193f7cd03e2cd" + why: "Upstream ships no tag at all on this entry." storj: image: "storjlabs/storagenode@sha256:21ca0ac819d1d66240830d28097eeb693923e51383aa3bb07bf823f9fad1f6e9" why: "Upstream ships no tag at all on this entry." diff --git a/frontend/scripts/fields_check.mjs b/frontend/scripts/fields_check.mjs index 347aa76..e18af49 100644 --- a/frontend/scripts/fields_check.mjs +++ b/frontend/scripts/fields_check.mjs @@ -125,5 +125,15 @@ check( check("stripHtml leaves plain text alone", stripHtml("no markup here") === "no markup here"); +// A catalog pattern must survive into the field, or the wizard cannot render it. +check( + "a docker.env pattern reaches the rendered field", + serviceFormFields(service("s", [envVar("K", { pattern: "[a-f0-9-]+" })]), {})[0].pattern === "[a-f0-9-]+", +); +check( + "a field without a pattern carries none", + serviceFormFields(service("s", [envVar("K")]), {})[0].pattern === undefined, +); + console.log(`${checks - failures}/${checks} checks passed`); if (failures > 0) process.exit(1); diff --git a/frontend/scripts/wizard_render_check.mjs b/frontend/scripts/wizard_render_check.mjs index 1530d45..c1d9d29 100644 --- a/frontend/scripts/wizard_render_check.mjs +++ b/frontend/scripts/wizard_render_check.mjs @@ -48,6 +48,8 @@ function inputs(html) { type: attr("type"), value: attr("value"), placeholder: attr("placeholder"), + pattern: attr("pattern"), + autocomplete: attr("autocomplete"), }; }); } @@ -121,6 +123,7 @@ const repocket = service({ label: "API Key", secret: true, description: 'Your Repocket API key — log in at app.repocket.com and copy it', + pattern: "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}", }), ], }, @@ -314,6 +317,26 @@ const manual = renderWizardServiceSetup( check("a manual-only service still renders its collector input", inputs(manual)[0]?.env === "PAWNS_EMAIL", manual); check("its Deploy button is disabled", manual.includes('data-wizard-action="deploy" data-slug="pawns" disabled'), manual); +// --------------------------------------------------------------------------- +// RULE 6: a catalog pattern reaches the input, so the browser can point at a +// value of the wrong shape (a password pasted where a UUID API key belongs) +// before anything is saved. The backend check stays the gate. +// --------------------------------------------------------------------------- +const field = (html, key) => inputs(html).find((input) => input.env === key); +check( + "RULE 6: a docker.env field with a pattern renders it on the input", + field(rp, "RP_API_KEY")?.pattern === "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}", + field(rp, "RP_API_KEY")?.tag, +); +check("RULE 6: a field without a pattern renders none", field(rp, "RP_EMAIL")?.pattern === undefined, field(rp, "RP_EMAIL")?.tag); +check("RULE 6: nor does a collector field", field(rp, "REPOCKET_PASSWORD")?.pattern === undefined, field(rp, "REPOCKET_PASSWORD")?.tag); +check( + "RULE 6: a secret asks the browser for a new value, never a saved password", + field(rp, "RP_API_KEY")?.autocomplete === "new-password" && field(hg, "HONEYGAIN_PASSWORD")?.autocomplete === "new-password", + rp, +); +check("RULE 6: a non-secret field carries no autocomplete hint", field(rp, "RP_EMAIL")?.autocomplete === undefined, field(rp, "RP_EMAIL")?.tag); + // Nothing to ask for must say so rather than render an empty grid. const none = renderWizardServiceSetup(service({ slug: "quiet", docker: { env: [] } }), {}, "macmini"); check("a service with no credentials renders none", inputs(none).length === 0, none); diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 143a7e8..47b82ab 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -1229,8 +1229,25 @@ function readWizardForm(slug: string): Record { return values; } +// A typed value the catalog constrains (the input carries its pattern) is checked +// in the browser first, so a password pasted where a UUID API key belongs is +// pointed at in the form instead of coming back as a backend error after a save. +// The backend check stays authoritative: this is the early warning, not the gate. +function firstInvalidWizardInput(slug: string): HTMLInputElement | null { + for (const input of document.querySelectorAll(`[data-form-slug="${slug}"] [data-wizard-env]`)) { + if (input.pattern && input.value.trim() && !input.checkValidity()) return input; + } + return null; +} + async function runWizardAction(slug: string, action: string) { const output = document.querySelector(`[data-output-slug="${slug}"]`); + const invalid = firstInvalidWizardInput(slug); + if (invalid && (action === "save" || action === "deploy")) { + invalid.reportValidity(); + if (output) output.textContent = `${invalid.dataset.wizardEnv} does not have the shape this provider expects.`; + return; + } const values = readWizardForm(slug); try { if (action === "save") { diff --git a/frontend/src/render/fields.ts b/frontend/src/render/fields.ts index 89bc4d5..76b621d 100644 --- a/frontend/src/render/fields.ts +++ b/frontend/src/render/fields.ts @@ -44,6 +44,7 @@ export function serviceFormFields( secret: item.secret, required: item.required, default: item.default, + pattern: item.pattern, })); const envKeys = new Set(env.map((item) => item.key)); const collector = (collectorFields || {})[service.slug] || []; diff --git a/frontend/src/render/wizard.ts b/frontend/src/render/wizard.ts index 0f6d59b..d1ba755 100644 --- a/frontend/src/render/wizard.ts +++ b/frontend/src/render/wizard.ts @@ -59,7 +59,7 @@ export function renderWizardServiceSetup( ${fields.map((item) => ` `).join("") || `

No credentials are required by the catalog for this service.

`} diff --git a/frontend/src/wails.d.ts b/frontend/src/wails.d.ts index 033a682..78cdf5a 100644 --- a/frontend/src/wails.d.ts +++ b/frontend/src/wails.d.ts @@ -376,6 +376,8 @@ export interface CollectorField { description: string; secret?: boolean; required?: boolean; + /** A regular expression the whole value must match (catalog docker.env pattern). */ + pattern?: string; } export interface EnvVar { @@ -385,6 +387,7 @@ export interface EnvVar { secret: boolean; description: string; default: string; + pattern?: string; } // PreflightFinding is one thing that could stop a service earning on this machine, diff --git a/services/bandwidth/repocket.yml b/services/bandwidth/repocket.yml index 1b34c66..1e1fa2f 100644 --- a/services/bandwidth/repocket.yml +++ b/services/bandwidth/repocket.yml @@ -28,9 +28,10 @@ docker: secret: false description: "Your Repocket account email" - key: RP_API_KEY - label: "API Key" + label: "API Key (UUIDv4, not your password)" required: true secret: true + pattern: '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}' description: "Your Repocket API key — log in at app.repocket.com and copy the API key shown on the bandwidth-earnings page (this is NOT your account password)" ports: [] volumes: [] diff --git a/services/depin/noderr.yml b/services/depin/noderr.yml new file mode 100644 index 0000000..10af126 --- /dev/null +++ b/services/depin/noderr.yml @@ -0,0 +1,110 @@ +name: Noderr Micronodes +slug: noderr +category: depin +status: beta +# Listed on request of the project (issue #409). Link-only: CashPilot does not +# deploy, run or collect anything for it. Everything below comes from +# micronodes.noderr.xyz and docs.noderr.xyz as read on 2026-10-07. +website: https://micronodes.noderr.xyz +description: > + Noderr Micronodes is the free entry tier of the Noderr Protocol, a DeFi + project on Base L2. A micronode is a small agent on a spare Android phone, + a Windows PC, a Mac or a Chromium browser. On Android it shares the phone's + mobile connection: other Noderr traffic exits through the phone's carrier + IP, so it needs a SIM with mobile data. On a PC or in the browser it runs + automation tasks for the protocol with spare compute. Rewards are designed + to be paid in NODR, scaled by an on-chain uptime and reliability score, but + the network is on the Base Sepolia testnet during its beta: node rewards + are unfunded and none have been paid yet. +short_description: Free micronode (Android connection sharing, Windows, Mac, browser) - testnet, rewards unfunded so far + +referral: + signup_url: "https://micronodes.noderr.xyz/" + # The project confirmed on 2026-10-07 that there is no referral programme + # and no invite parameter on the download page (issue #409). + program: false + +docker: + image: "" + platforms: [] + env: [] + ports: [] + volumes: [] + command: "" + network_mode: "" + +disclosure: + sells: >- + Depends on the device. An Android phone sells its mobile connection: other + Noderr traffic exits through the phone's carrier IP address and counts + against its data plan. A Windows PC, a Mac or a browser sells spare compute + for what the provider calls social media and content automation tasks. + third_party_traffic: >- + Yes. On Android, other Noderr traffic exits through your phone's mobile IP + address; the app asks for a recorded consent before it starts and you can + stop sharing from the same screen. For the Windows, Mac and browser + clients the provider describes automation tasks and does not say whether + those carry traffic for other people. + data_collected: >- + The node's wallet address and its uptime and task-completion figures go + on-chain as a reputation score (the TrustFingerprint). The provider says + tasks are anonymised, run in a sandbox and that wallet keys never leave + the device. Nothing more specific is published. + isp_risk: >- + On Android the shared connection is a carrier mobile plan: the provider's + own docs warn that sharing may not be allowed under some carriers' + acceptable-use policies, and shared traffic uses the plan's allowance. For + the desktop and browser clients the provider says nothing about ISP terms. + account_rules: >- + One node per device, each with its own soulbound Utility NFT; running + several devices is allowed and encouraged. No per-IP limit is published. + There is no account in the usual sense: the identity is a wallet the app + generates on first launch. + +requirements: + # Android: a SIM with mobile data is required (Wi-Fi alone shares nothing). + # Desktop and browser: the provider publishes no IP requirement, so neither + # residential_ip nor vps_ip is asserted here. + devices_per_account: 0 + min_bandwidth: "" + gpu: false + min_storage: "" + note: "Android needs a SIM with mobile data; the desktop and browser clients publish no IP requirement." + +payment: + methods: [crypto] + crypto_token: NODR + minimum_payout: "" + currency: NODR + frequency: "On request" + +earnings: + # Not an estimate: the provider's own docs state that node rewards are + # unfunded on testnet and none have been paid (2026-10-07). The 5-10% APY + # the site mentions is a design target, not observed earnings. + monthly_low: 0 + monthly_high: 0 + currency: USD + per: "device" + notes: "Testnet beta: node rewards are unfunded and none have been paid yet. The 5-10% APY on the site is a design target. Revisit when the network leaves Base Sepolia." + +cashout: + method: manual + dashboard_url: "https://dapp.noderr.xyz/nodes" + # Undocumented: the provider publishes no minimum. NOT 0, which would mean + # "no minimum, cash out anything". + min_amount: null + currency: NODR + notes: "Rewards accrue to the node's own wallet and are claimed from the app or the dApp. During the beta they are Base Sepolia testnet tokens with no market value." + +payout: + model: minted + chain: base + address_source: app + notes: "The app creates the node wallet on first launch and mints a free soulbound Utility NFT to it. Back up the wallet from the app: losing the device loses the node identity. Rewards are on Base Sepolia (testnet) during the beta." + +platforms: [android, windows, macos, browser-extension] + +collector: + type: manual + notes: "No public API found. The dashboard at dapp.noderr.xyz/nodes sits behind a wallet signature. Nothing to collect while rewards are unfunded on testnet." diff --git a/services/storage/sia-hostd.yml b/services/storage/sia-hostd.yml new file mode 100644 index 0000000..9e4135e --- /dev/null +++ b/services/storage/sia-hostd.yml @@ -0,0 +1,157 @@ +name: Sia (hostd) +slug: sia-hostd +category: storage +status: active +website: https://sia.tech +description: > + Sia is a decentralized storage marketplace run by the Sia Foundation (a Swiss + non-profit) that has operated since 2015. Run the Foundation's official hostd + node to rent out spare disk space and earn Siacoin from storage and bandwidth + contracts. You must buy some Siacoin before the node can earn: hosts lock + collateral against every contract and pay a fee for each storage proof. The + collateral comes back when a contract completes and is burned if the node + goes offline or loses data, so it needs an always-on machine (Sia says 95% + uptime at least). Earnings depend on how much data renters actually store; + Sia recommends pricing storage at $1 per TB per month, so it suits machines + with large spare disks rather than small VPS slices. +short_description: Sia Foundation storage node - official Docker image, earn Siacoin + +referral: + signup_url: "https://docs.sia.tech/provide-storage/setting-up-hostd/docker" + # Permissionless: no account to sign up for, and the Sia Foundation runs no + # referral programme for hosts (checked on sia.tech and docs.sia.tech). + program: false + +docker: + image: "ghcr.io/siafoundation/hostd@sha256:2f27742e103cf79cf1bc818820af936fb342ee435e7bd5ee4f0193f7cd03e2cd" + platforms: [linux/amd64, linux/arm64] + resources: + # Measured on hostd 2.11.0: 1.9 GiB within four minutes of the initial + # sync, so a 2g limit would OOM-kill it mid-sync. + mem_limit: "4g" + # A storage node the network dials back into; keep it weighted above the + # default so a contended host does not make it answer slowly (see the + # cpu_shares note in _schema.yml). + cpu_shares: 4096 + env: + - key: HOSTD_WALLET_SEED + label: "Wallet seed phrase" + required: true + secret: true + description: "BIP-39 seed phrase that controls the host's Siacoin wallet. Generate one with `docker run --rm ghcr.io/siafoundation/hostd seed` and back it up -- it is the ONLY way to reach the earnings" + - key: HOSTD_API_PASSWORD + label: "Dashboard password" + required: true + secret: true + description: "Password for the hostd web UI and local API (BasicAuth). Any long passphrase" + - key: SIA_STORAGE_DIR + label: "Storage directory" + required: true + secret: false + description: "Host path on your largest disk where renter data is stored (e.g. /srv/sia). Needs at least 256GB free" + ports: + # Dashboard/API. Its API can spend the wallet, so it binds to loopback as + # Sia's own Docker guide does; reach it with an SSH tunnel (see the guide). + - "127.0.0.1:9980:9980" + # Sia consensus: peer-to-peer sync with the rest of the network. + - "9981:9981" + # RHP4, the renter-host protocol: SiaMux on TCP, QUIC on UDP. + - "9984:9984/tcp" + - "9984:9984/udp" + volumes: + # Consensus + host databases (named volume; recreated nodes re-sync). + - "sia-hostd-data:/data" + # Where renter data is actually stored. Point it at the largest disk. + - "${SIA_STORAGE_DIR}:/storage" + critical_volumes: + - target: "/data" + holds: >- + Wallet database, host settings and contract state. Losing it loses the + node's identity and contract revenue tracking; the seed phrase remains + the only recovery path for funds. + - target: "/storage" + holds: >- + Stored renter data. Losing it fails storage proofs and forfeits the + collateral locked against those contracts. + command: "" + network_mode: "" + setup: > + Before first run, generate a seed with + `docker run --rm ghcr.io/siafoundation/hostd seed` and back it up. After + the deploy, send some Siacoin to the node's wallet for collateral and + fees, then add the storage folder (/storage), set prices and announce the + host in the dashboard. + +requirements: + residential_ip: false + vps_ip: true + min_storage: "256GB" + gpu: false + note: "A stable public address with ports 9981 (TCP, consensus) and 9984 (TCP and UDP, renter contracts) forwarded. Datacenter/VPS hosting is common on Sia. The wallet needs Siacoin before the node can take contracts." + +payment: + methods: [crypto] + crypto_token: "SC" + minimum_payout: "$0" + currency: USD + frequency: "On request" + +earnings: + monthly_low: 0 + monthly_high: 2 + currency: USD + per: "TB" + notes: > + Hosts set their own prices. Sia recommends $1 per TB stored per month and + over $5 per TB downloaded, and 3.9% of every contract payout goes to + Siafund holders. Income scales with how much renter data lands on the + node, which starts at zero and grows with uptime and price. Collateral + (Sia suggests 2x the storage price) is locked per contract and returned on + successful completion. + +cashout: + method: manual + dashboard_url: "http://localhost:9980" + min_amount: 0 + currency: USD + notes: > + Earnings accrue in the host's own Siacoin wallet (seed-controlled). Convert + SC on an exchange and withdraw to bank/card from there; there is no + provider-side payout request. + +platforms: [docker, linux, windows, macos] + +collector: + type: manual + notes: > + hostd exposes a local REST API on port 9980 (BasicAuth with the API + password): GET /api/wallet returns the wallet balance, GET /api/metrics and + GET /api/settings return host revenue and configuration. A future collector can + read those endpoints the same way the Storj collector reads the local + storagenode API -- but adding it requires an app-side change + (app/collectors), so it is proposed upstream rather than shipped here. + +payout: + model: external + chain: sia + address_source: app + notes: > + Funds live in the seed-controlled Sia wallet inside the node. CashPilot + never holds the key; the seed phrase is the only recovery path and must be + backed up before first deploy. + +disclosure: + sells: >- + Disk space and the bandwidth to serve it. + third_party_traffic: >- + No. Renters store encrypted file fragments on your disk and fetch them + back. Other people do not route arbitrary traffic through your IP. + data_collected: >- + Your Sia wallet address, host public key, and the public IP:port the node + announces so renters can reach it. + isp_risk: >- + Sustained upload/download traffic on the line, similar to running any + storage server; no anonymised third-party web traffic is attributed to you. + account_rules: >- + Permissionless: no signup or account. Collateral is burned if the node + misses storage proofs, by going offline or losing data. diff --git a/services/storage/storj.yml b/services/storage/storj.yml index f8518e0..bc65051 100644 --- a/services/storage/storj.yml +++ b/services/storage/storj.yml @@ -5,14 +5,24 @@ status: active website: https://www.storj.io description: > Storj is a decentralized cloud storage network where you earn by renting out - your unused disk space. Run the storage node via Docker and get paid approximately - $1.50/TB stored per month plus $2/TB egress. Payouts are monthly in USDC, a - US-dollar stablecoin, on Ethereum mainnet to a wallet you control, once the - balance clears a fee-based minimum (STORJ token until the September 2026 - payout). Requires at least 550GB of available disk space and a stable internet - connection. One of the most mature and truly passive storage income services. - No account or signup needed -- nodes are permissionless since mid-2025. -short_description: Decentralized storage node - ~$1.50/TB stored + $2/TB egress + your unused disk space. Run the storage node via Docker and get paid + $1.35/TB stored per month plus $1/TB egress (rates since 1 September 2026). + Payouts are monthly in USDC, a US-dollar stablecoin, on Ethereum mainnet to + a wallet you control, once the balance clears a fee-based minimum (STORJ + token until the September 2026 payout). Requires at least 550GB of available + disk space and a stable internet connection. No account or signup needed -- + nodes are permissionless since mid-2025. + CAUTION (October 2026): Storj Labs filed for Chapter 11 on 26 July 2026 (US + Bankruptcy Court, Northern District of West Virginia, case 5:26-bk-00512) to + restructure legacy debt. The network keeps running and Storj keeps paying + active nodes, but node earnings from before the filing are frozen until the + court rules on them. The STORJ token is down about 98% from its 2021 peak. + Binance delisted it on 3 September 2026, and Coinbase suspended trading in + it on 28 September 2026. A new node withholds part of its earnings during + its first nine months and fills only as customer demand allows, so starting + one now ties a long payback to a company in restructuring that could still + wind down. +short_description: Decentralized storage node - $1.35/TB stored + $1/TB egress referral: signup_url: "https://storj.dev/node/get-started/setup" @@ -154,7 +164,7 @@ earnings: monthly_high: 15 currency: USD per: "TB" - notes: "~$1.50/TB stored + $2/TB egress + $2.74/TB audit/repair. Earnings scale with disk allocated and node age. First 9 months have held-back escrow. Port 28967 must be forwarded." + notes: "$1.35/TB stored + $1/TB egress + $1/TB audit/repair since 1 September 2026. Earnings scale with data stored and node age. The first 9 months withhold 75%, then 50%, then 25% of earnings; half the held amount returns in month 16 and the rest on graceful exit. Port 28967 must be forwarded." cashout: method: redirect