selfhost.directory

The index of self-hostable projects — ranked, categorized and served with live updates.
Own your data and stop giving it to big tech.

ADAMANT IPFS Node logo

Self-host ADAMANT IPFS Node

v0.1.0

IPFS storage node for app file delivery

ReleaseOpen SourceGPL-3.0
Updated4 weeks ago
LanguageTypescript
Setup difficultyAdvanced
Stars
307
Ports
4000 (HTTP REST API), 4001 (libp2p TCP listener for peer connections)
Docker
ghcr.io/adamant-im/ipfs-node
Install with Docker

What is ADAMANT IPFS Node?

ADAMANT IPFS Node is a self-hosted content-addressed file storage service for application file delivery. It runs as a standalone Node.js service embedding Helia and libp2p with an Express REST API. It avoids the public DHT and Kubo API. Instead, it forms a controlled peer mesh over TCP using Noise and Yamux, where nodes exchange blocks and health data only with configured peers. Features include bounded disk usage with watermark garbage collection, deterministic replica placement via rendezvous hashing with age-based tiering, cross-node repair cycles, health checkpoints with monotonic height, and rate limits with admission control. Configured via a single JSON5 file. Deployable via Docker, Docker Compose, or source on Node.js 24. Requires a TLS reverse proxy and admin API key for production. Used by ADAMANT Messenger for attachment delivery.

Should you self-host ADAMANT IPFS Node?

ADAMANT IPFS Node scores 48/100 on selfhost.directory (how scoring works) and ranks #8 of 15 in File Storage. It has 307 GitHub stars.

It shipped 1 stable release in the past year. The latest, v0.1.0, came out on 30 September 2026.

Setup is advanced: plan for several services and some ongoing maintenance. An official Docker image is available. It is GPL-3.0-licensed and written mostly in Typescript.

Its closest alternative on selfhost.directory is juicefs (73/100, 14 582 stars). It scores higher overall, so compare the two before you pick. See ADAMANT IPFS Node vs juicefs side by side.

Features

  • Administrative API key authentication
  • Bounded disk usage
  • Controlled peer mesh
  • CORS Configuration
  • Cross-node repair
  • Deterministic replication
  • Graceful Shutdown
  • Health checkpoints
  • Health monitoring endpoint
  • Rate limits and admission control
  • REST API for file upload/download
  • Storage metrics and policy API
  • Structured JSON logging
  • Trusted proxy support

ADAMANT IPFS Node README

How to install ADAMANT IPFS Node

Install ADAMANT IPFS Node with Docker

Docker Engine, a TLS-terminating reverse proxy for public deployments
Environment variables
IPFS_NODE_CONFIG (optional, selects config.<name>.json5)

docker volume create ipfs-node-data

docker run -d
--name ipfs-node
--restart unless-stopped
--stop-timeout 20
--security-opt no-new-privileges:true
-v ipfs-node-data:/data
-v "$PWD/config.json5:/app/config.json5:ro"
-p 127.0.0.1:4000:4000
-p 4001:4001
ghcr.io/adamant-im/ipfs-node:

Requires a mounted config.json5 at /app/config.json5. The image ships no configuration. Take <version> from the releases page.

How to configure ADAMANT IPFS Node

  • adminApiKey''Secret required in the x-api-key header on administrative routes

    Secret required in the x-api-key header on administrative routes

    values: string (empty or >= 32 chars)

  • cors.allowedOriginsBrowser origins accepted by the API

    Browser origins accepted by the API

    values: array of strings (exact origins, subdomain wildcards, or app:// desktop origins)

  • diskUsageScanPeriodHow often the storage scan that feeds the metrics runs

    How often the storage scan that feeds the metrics runs

    values: cron string

  • downloadIdleTimeoutfindFileTimeoutMaximum pause between download chunks, in milliseconds

    Maximum pause between download chunks, in milliseconds

    values: integer >= 1

  • downloadMaxDurationMsmax(14400000, size-derived)Absolute ceiling for one download response, in milliseconds

    Absolute ceiling for one download response, in milliseconds

    values: integer >= 1

  • downloadMinBytesPerSecond32768Rate used to derive a size-aware complete-transfer deadline

    Rate used to derive a size-aware complete-transfer deadline

    values: integer >= 1

  • enableDebugApifalseMounts /api/debug/*, which still requires the key

    Mounts /api/debug/*, which still requires the key

    values: true|false

  • findFileTimeoutMilliseconds allowed for locating a file before a download fails

    Milliseconds allowed for locating a file before a download fails

    values: integer >= 1

  • health.checkpointIntervalMs60000Length of one checkpoint round

    Length of one checkpoint round

    values: integer >= 1000

  • health.clockSkewToleranceMs10000Allowed clock difference between two attesting peers

    Allowed clock difference between two attesting peers

    values: integer >= 0

  • health.maxCheckpointAgeMscheckpointIntervalMs * 3Age at which the last completed checkpoint becomes stale

    Age at which the last completed checkpoint becomes stale

    values: integer >= checkpointIntervalMs

  • health.peerAttestationTimeoutMs5000Bound for one peer attestation call

    Bound for one peer attestation call

    values: integer >= 1

  • health.repairBacklogGraceCycles0Consecutive complete unsuccessful repair cycles with backlog during which repairFresh remains true

    Consecutive complete unsuccessful repair cycles with backlog during which repairFresh remains true

    values: integer >= 0

  • health.repairMaxAgeMs3600000Maximum age of a completed full repair sweep

    Maximum age of a completed full repair sweep

    values: integer >= checkpointIntervalMs

  • health.requiredPeerCount1 when more than one node is configured, otherwise 0Configured remote peers that must attest a round

    Configured remote peers that must attest a round

    values: integer >= 0

  • health.storageMaxAgeMscheckpointIntervalMs * 2Maximum age of the cached storage scan a checkpoint accepts

    Maximum age of the cached storage scan a checkpoint accepts

    values: integer >= checkpointIntervalMs

  • IPFS_NODE_CONFIGEnvironment variable to select config file (config.<name>.json5)

    Environment variable to select config file (config.<name>.json5)

    values: string

  • logLevelOne of fatal, error, warn, info, debug, trace, silent

    One of fatal, error, warn, info, debug, trace, silent

    values: fatal|error|warn|info|debug|trace|silent

  • maxFileCountMaximum number of files in one upload request

    Maximum number of files in one upload request

    values: integer 1-100

  • nodesPeer nodes this node replicates with and keeps connections to. May be empty for a standalone node.

    Peer nodes this node replicates with and keeps connections to. May be empty for a standalone node.

    values: array of objects with name and multiAddr

  • peerDiscovery.bootstrapMultiaddrs dialled once at startup. May be empty.

    Multiaddrs dialled once at startup. May be empty.

    values: array of strings

  • peerDiscovery.listenlibp2p listen multiaddrs, at least one

    libp2p listen multiaddrs, at least one

    values: array of strings

  • peeringSchedule*/30 * * * * *How often connected entries of nodes are pinged and missing entries are redialled

    How often connected entries of nodes are pinged and missing entries are redialled

    values: cron string

  • prettyLogsfalseRoutes logs through pino-pretty. Leave false in production

    Routes logs through pino-pretty. Leave false in production

    values: true|false

  • rateLimits.pin{ windowMs: 900000, limit: 10 }Applies to POST /api/helia/pin/:cid

    Applies to POST /api/helia/pin/:cid

    values: policy object

  • rateLimits.read{ windowMs: 60000, limit: 100 }Applies to public read routes and administrative read routes

    Applies to public read routes and administrative read routes

    values: policy object

  • rateLimits.upload{ windowMs: 900000, limit: 10 }Applies to POST /api/file/upload

    Applies to POST /api/file/upload

    values: policy object

  • replication.ackQuorum1Acknowledgements counted before an upload is reported durable

    Acknowledgements counted before an upload is reported durable

    values: integer >= 1

  • replication.enabledtrueWhether this node places copies of its own content on its peers

    Whether this node places copies of its own content on its peers

    values: true|false

  • replication.placement[{ minAgeMs: 0, copies: 4 }, { minAgeMs: 15552000000, copies: 3 }, { minAgeMs: 31536000000, copies: 2 }]Target copy count by file age, including this node

    Target copy count by file age, including this node

    values: array of tiers

  • replication.repairBatchDelayMs1000Pause between bounded passes inside one full repair cycle

    Pause between bounded passes inside one full repair cycle

    values: integer >= 0

  • replication.repairEnabledtrueRuns the scheduled repair job

    Runs the scheduled repair job

    values: true|false

  • replication.repairProbeConcurrency4Released records probed concurrently during one pass

    Released records probed concurrently during one pass

    values: integer >= 1

  • replication.repairSchedule0 */30 * * * *Repair schedule

    Repair schedule

    values: cron string

  • replication.requestTimeoutMs30000Timeout of one replication request to a peer

    Timeout of one replication request to a peer

    values: integer >= 1

  • replication.requireQuorumOnUploadfalseFails an upload with 503 when the quorum is not reached

    Fails an upload with 503 when the quorum is not reached

    values: true|false

  • serverPortHTTP API port

    HTTP API port

    values: integer >= 1

  • storage.confirmationRequiredfalseKeeps an upload temporary until POST /api/file/:cid/confirm

    Keeps an upload temporary until POST /api/file/:cid/confirm

    values: true|false

  • storage.diskReserveBytes5368709120Free space on the blockstore filesystem that uploads must never consume

    Free space on the blockstore filesystem that uploads must never consume

    values: integer >= 0

  • storage.gc.enabledtrueRuns the scheduled collector

    Runs the scheduled collector

    values: true|false

  • storage.gc.highWatermarkBytes53687091200Blockstore size above which collection starts

    Blockstore size above which collection starts

    values: integer >= 1

  • storage.gc.lowWatermarkBytes42949672960Blockstore size collection reclaims down to

    Blockstore size collection reclaims down to

    values: integer >= 1

  • storage.gc.schedule0 */15 * * * *Collector schedule

    Collector schedule

    values: cron string

  • storage.maxConcurrentDownloads64File responses retrieving content at once

    File responses retrieving content at once

    values: integer >= 1

  • storage.maxConcurrentDownloadsPerClient8Share of the global download slots one client address may hold

    Share of the global download slots one client address may hold

    values: integer >= 1

  • storage.maxConcurrentUploads32Upload requests writing into the blockstore at once

    Upload requests writing into the blockstore at once

    values: integer >= 1

  • storage.maxRequestSizeBytes536870912Combined size of all files in one upload request

    Combined size of all files in one upload request

    values: integer >= 1

  • storage.temporaryTtlMs86400000Lifetime of an unconfirmed upload before it becomes reclaimable

    Lifetime of an unconfirmed upload before it becomes reclaimable

    values: integer >= 1

  • storeFolderDirectory name resolved against the home directory of the process user

    Directory name resolved against the home directory of the process user

    values: string

  • trustProxyfalseVerified proxy hop count, or exact proxy addresses and CIDR ranges

    Verified proxy hop count, or exact proxy addresses and CIDR ranges

    values: false|integer >= 1|string|array of strings

  • uploadLimitSizeBytesMaximum size of one uploaded file

    Maximum size of one uploaded file

    values: integer >= 1

ADAMANT IPFS Node releases & version history

More in File Storage

Rate this project

Click to rate — no account needed.

0 comments

Posting as guest
Loading comments…