Title: How to setup your own IPFS private network
       Author: Solène
       Date: 21 August 2026
       Tags: linux network ipfs
       Description: In this article, you will learn how to set up your own
       IPFS private network.
       
       # Introduction
       
       In this blog post, you will learn how to make a private IPFS network
       that will allow private peers to exchange data between each other. 
       This is in opposition to the default setup in which you use the default
       configuration connecting to the whole IPFS network.  The incentive to
       have your own network is mostly speed, because this does not have any
       extra access control, any peer can potentially access to any content
       you have in your IPFS network.
       
       If you do not know about IPFS, I wrote some blog posts, but otherwise
       IPFS website may give you some clue.  It is not easy to grasp, but you
       can see it as a network service providing content addressed object
       storage.  The base blocks provide features to manage data in the
       network but also cache it or provide it through a web gateway.
       
 (HTM) IPFS project official website
       
       Kubo is the reference implementation of IPFS.
       
       The setup I explain in this article is pretty much useless for most
       people.  Depending on your needs, you will have a better experience
       with Nextcloud/Seafile for central file sharing, Peergos for encrypted
       storage, syncthing for directory synchronization between peers, or even
       magic wormhole for one-shot transfers.  I am still not sure which
       purpose an IPFS private swarm serves correctly, but none of the use
       cases I just listed, maybe it is useful if you need to keep some
       dataset synchronized and quickly available in multiple areas, but then
       an hyperscaler may be more suited.
       
       # Setup
       
       In this setup, you will have various nodes that can speak to each other
       (through a VPN, LAN or directly over the Internet) and potentially but
       not mandatory, a node that is up 24/7.
       
       They must all share the same `swarm.key` to create a swarm (a group of
       nodes, that is private until you get access to the key).
       
       The setup itself will allow nodes to publish data and give it access to
       other nodes for caching, downloading or relaying, but also give the
       opportunity to publish on a web gateway.
       
       # Too Long Didn't Read
       
       IPFS daemon will hold data until it reaches its maximum allowed size,
       then will run a garbage collector to reclaim disk space by removing
       unused data.  Data which was pinned on the server will never be garbage
       collected.  A directory or file is content addressed, this mean is has
       a unique address derived from its content, which mean the URL of a
       resource depends on its content, if you update a directory, it will get
       a new URL because its content changed.
       
       IPFS has a mechanism called IPNS which allows to publish a content hash
       under a fixed hash, which is published to other peers under some
       conditions, this is the only way to provide an address that never
       change but in which you can change the content.  An IPNS address
       requires an associated cryptographic key that is managed by kubo, if
       you want to pin a resource for each people you share data with, you
       will need a dedicated key for each.
       
       Data do not propagate magically over IPFS, if you add data to your
       node, it remains local until another node pulls in the content, then it
       will be able to distribute the data too, but there is a high chance it
       gets garbage collected one day if the node owner do not pin your data.
       
       IPFS has no at rest encryption or access control available, it is a
       method to publish data.
       
       # Configuring a node
       
       First, you need to install Kubo, make sure to not install kubo-desktop
       which is unfortunately incompatible with a private swarm.
       
       I personally prefer to use it in a container version for sandboxing
       reasons.
       
       Generate the swarm.key with this code:
       
       ```
       echo -e "/key/swarm/psk/1.0.0/\n/base16/\n$(openssl rand -hex 32)" > swarm.key
       ```
       
       Download the ipfs-webui which is normally downloaded by kubo from the
       IPFS network, but as you are not connecting to it, you need to inject
       the webui in your kubo.  On the following URL, download the "car" file
       that matches your kubo version.
       
       => https://github.com/ipfs/ipfs-webui/releases
       
       Now, create and init your IPFS daemon using this script, if you do not
       use podman and prefer to use `ipfs` binary, replace the long podman
       command by just `ipfs`.
       
       The script takes `swarm.key` as the first parameter and the web-ui car
       file as a second parameter:
       
       ```
       #!/bin/sh
       
       set -xe
       
       if ! test -f "$1"
       then
           echo "You must give the swarm.key file in parameter"
           exit 1
       fi
       
       if ! test -f "$2"
       then
           echo "You must give the ipfs-webui@v4.13.0.car file in parameter (version should match your kubo version)"
           echo "You can download it from https://github.com/ipfs/ipfs-webui/releases"
           exit 1
       fi
       
       # execute commands with ipfs
       run() {
        podman run --replace --name kubo \
          -e LIBP2P_FORCE_PNET=1 -e IPFS_PROFILE=lowpower \
          --userns=keep-id \
          -v $HOME/.ipfs/:/data/ipfs:Z \
          docker.io/ipfs/kubo:release $*
       }
       
       # import webui, requires stdin
       import_webui() {
        podman run --replace -i --name kubo \
          -e LIBP2P_FORCE_PNET=1 -e IPFS_PROFILE=lowpower \
          --userns=keep-id \
          -v $HOME/.ipfs/:/data/ipfs:Z \
          docker.io/ipfs/kubo:release dag import < "$1"
       }
       
       # make sure the directory exist
       # you can adjust if you want to store it elsewhere
       mkdir -p ~/.ipfs
       
       # copy the swarm key
       cp "$1" ~/.ipfs/swarm.key
       
       # uncomment this if you do not use the container version which does it automatically
       #run init
       
       # allow server to give other peers address
       run config Routing.Type dht
       
       # allow other peers to relay if a peer is not directly reachable by us but another peer can
       run config --json Swarm.RelayClient.Enabled true
       
       # remove all the default stuff
       run bootstrap rm --all
       run config --json Routing.DelegatedRouters '[]'
       run config --json Bootstrap '[]'
       
       # private swarm key = TLS can not be used but it is still encrypted
       run config --json AutoTLS.Enabled false
       run config --json AutoConf.Enabled false
       
       # allow to use IPNS through pubsub and advertise often
       run config --json Ipns.UsePubsub true
       run config Ipns.RecordLifetime 240h
       run config Ipns.RepublishPeriod 1m
       run config Ipns.MaxCacheTTL 1m
       
       import_webui "$2"
       
       echo "Setup successful"
       echo "You can visit http://localhost:5001/webui/ after starting the server"
       ```
       
       Now, start the server (use `ipfs daemon` and the environment variables
       if not using the container):
       
       ```
       podman run --replace --name kubo --restart=always \
         -e LIBP2P_FORCE_PNET=1 \
         -e IPFS_PROFILE=lowpower \
         -p 8080:8080 -p 127.0.0.1:5001:5001 -p 4001:4001 -p 4001:4001/udp \
         --userns=keep-id \
         -v $HOME/.ipfs/:/data/ipfs:z docker.io/ipfs/kubo:release
       ```
       
       On the webui, in the Peers menu, add your other peers.
       
       # 24/7 server specific setup
       
       The snippet above will work for a server, but you want to change a few
       things:
       
       If you use a container with restricted network, you need to give a
       reachable IP address to announce to your other peers:
       
       ```
       ipfs config --json Addresses.Announce '["/ip4/192.168.1.166/tcp/4001"]'
       ```
       
       You may also want it to be the DHT server to allow peers to discover
       each others through it, and maybe relay data between peers which could
       not connect directly:
       
       ```
       # allow to give other peers address for mesh networking
       ipfs config Routing.Type dhtserver
       
       # allow to relay data between two peers that could not connect to each other
       ipfs config --json Swarm.RelayService.Enabled true
       ```
       
       You may also want to limit the amount of storage allowed in your Kubo
       server before the garbage collector free some space:
       
       ```
       ipfs config Datastore.StorageMax "50GB"
       ```
       
       # Networking
       
       There are 4 differents ports in use that you need to be aware of:
       
       * Port 4001 TCP and port 4001 UDP are used by peers to exchange data
       between each other
       * Port 5001 TCP is used to reach the admin API and the webui, do not
       expose it publicly
       * Port 8080 TCP is used for the gateway, it allows to expose your IPFS
       private network content to people able to reach the gateway, without
       them installing kubo at all
       
       # Conclusion
       
       In my use case, I have a script regularly pinning a list of IPNS
       addresses on the server running the HTTPS gateway, so it always
       download the latest version of the IPNS published resources and make
       them available through the gateway even if the computers owning the
       file is offline.
       
       This is actually not super useful as I could have done the same thing
       using Nextcloud, or with a script copying the files to a static HTTPS
       server.
       
       # Going further
       
       This infrastructure got more useful after adding a single
       `ipfs-cluster` service near my gateway running 24/7 allowing the nodes
       to use it as a remote pinning service.  Now, a node can pin a CID on
       the gateway which make sure the data will be available locally there.