FireCloud
Private, encrypted, distributed storage across machines you own.
Files are chunked and encrypted on the client before anything touches the network, so storage nodes only ever hold ciphertext. With five or more nodes a file is erasure coded and survives losing a third of the cluster. S3 means renting someone else's disks, Syncthing has no erasure coding, and IPFS announces content on a public DHT. FireCloud is for a LAN of machines you already run yourself.
Install
pip install git+https://github.com/rajashekharsunkara/firecloud.git
# optional extras
pip install "firecloud-devnet[rag]" # local RAG pipeline
pip install "firecloud-devnet[mlops]" # ML artifact store
Quickstart with containers
Works with podman (rootless is fine) or docker; swap the command name.
git clone https://github.com/rajashekharsunkara/firecloud.git
cd firecloud
cp .env.example .env # set FIRECLOUD_PASSPHRASE in .env
# create the network keystore the containers share
podman build -t firecloud .
mkdir -p test_config/.firecloud
podman run --rm --env-file .env \
-v "$PWD/test_config/.firecloud:/root/.firecloud:z" firecloud init
# bootstrap node + 3 storage nodes
podman compose build
podman compose up -d
Note for podman: podman compose up reuses service images if they already
exist, so run podman compose build after pulling changes.
Upload from one node, download from another:
podman exec firecloud-bootstrap sh -c 'echo "hello cluster" > /data/hello.txt'
podman exec firecloud-bootstrap firecloud upload /data/hello.txt \
--bootstrap 127.0.0.1:7474 --storage /tmp/cli
podman exec firecloud-node-1 firecloud download <file_id> /tmp/hello.txt \
--bootstrap 127.0.0.1:7475 --storage /tmp/cli
podman exec firecloud-bootstrap firecloud verify \
--bootstrap 127.0.0.1:7474 --storage /tmp/cli
--storage /tmp/cli gives the one-shot command its own scratch directory so
it doesn't share state with the daemon in the same container. Stop a
container (podman stop firecloud-node-3) and the download still works;
verify reports the file as degraded until the node returns.
Run it on real machines
Install the package on each machine. The network key is the network: nodes holding the same key can talk, everyone else fails the handshake.
# machine A
firecloud init # writes ~/.firecloud/network.key
firecloud start --port 7474
# every other machine: copy the key over first
scp userA@machine-a:~/.firecloud/network.key ~/.firecloud/
firecloud start --port 7474 --bootstrap <machine-a-ip>:7474
One --bootstrap peer is enough; a joining node asks it for the rest of the
cluster, connects to them, and pulls the file catalog. Nodes listen on all
interfaces, so the only thing to check is the firewall on each machine
(sudo firewall-cmd --add-port=7474/tcp on Fedora, sudo ufw allow 7474/tcp
on Ubuntu).
Then from any machine on the network:
firecloud upload ./photos.zip --bootstrap <machine-a-ip>:7474
firecloud list --bootstrap <machine-a-ip>:7474
firecloud download <file_id> ./out --bootstrap <machine-a-ip>:7474
firecloud verify --bootstrap <machine-a-ip>:7474
To try multiple nodes on a single machine, give each its own port and storage directory:
export FIRECLOUD_PASSPHRASE=test-pass
firecloud init
firecloud start --port 7474 --storage /tmp/fc/n0 &
for i in 1 2 3 4; do
firecloud start --port $((7474 + i)) --storage /tmp/fc/n$i \
--bootstrap 127.0.0.1:7474 &
done
CLI reference
firecloud init # create a network keystore
firecloud start # run a node
firecloud upload <path> # chunk, encrypt, distribute
firecloud download <id> <out> # retrieve, verify, reassemble
firecloud verify [<id>] # healthy / degraded / unrecoverable
firecloud list # file catalog across the network
firecloud sync <folder> # two-way folder sync
firecloud status / peers / delete <id>
Environment variables, all optional: FIRECLOUD_PASSPHRASE (skip the
prompt), FIRECLOUD_DATA_DIR (storage directory), FIRECLOUD_MAX_STORAGE_GB
(chunk store quota), FIRECLOUD_BOOTSTRAP (comma-separated peers to join on
start), FC_RAG_MODEL (Ollama model for the RAG layer).
Architecture
┌─────────────────────────────────────────┐
│ fc-rag (private RAG, opt-in) │
│ fc-mlops (artifact store, opt-in) │
│ containers + GitHub Actions CI │
│ core: storage, crypto, P2P transport │
└─────────────────────────────────────────┘
The core does XChaCha20-Poly1305 chunk encryption, FastCDC content-defined chunking, zfec erasure coding, and mDNS peer discovery. Manifests use Lamport timestamps with last-writer-wins merges. Nodes talk a small binary RPC protocol over TLS.
fc-mlops stores version-tracked ML artifacts through the Node API and
ships a FastAPI telemetry endpoint with IsolationForest anomaly detection.
fc-rag indexes documents with fastembed, searches them in an embedded
Qdrant, and generates answers with a local Ollama model.
Security
Chunk IDs are HMAC-SHA-256 under a key derived from the network key rather than a plain content hash. Someone who suspects you store a particular file can't confirm it by hashing the plaintext themselves, because valid chunk addresses require the network key.
Chunks are encrypted before they leave the client, so storage nodes hold authenticated ciphertext only. The transport caps frame sizes, times out handshakes and requests, and compares auth tokens in constant time.
Devnet limitations to know about: node TLS certificates are self-signed and clients skip verification, so the TLS layer stops passive snooping but not an active man-in-the-middle on your LAN. The chunk payloads stay end-to-end encrypted either way. Run this on networks you control.
Private RAG (fc-rag)
Index documents and ask questions against a local model. Embeddings (fastembed), vector search (embedded Qdrant), and generation (Ollama) all run on your machine.
pip install "firecloud-devnet[rag]"
ollama pull llama3.2:3b # any local model; set FC_RAG_MODEL to change
fc-rag index ./docs
fc-rag query "How does FireCloud handle node departure?"
If Ollama isn't running, the query still prints the retrieved passages and sources; only the generated answer is skipped.
MLOps artifact store (fc-ml)
pip install "firecloud-devnet[mlops]"
fc-ml save ./model.pt --name resnet --version 1.0.0 --type model --metric accuracy=0.94
fc-ml simulate-failure
Development
git clone https://github.com/rajashekharsunkara/firecloud.git
cd firecloud
pip install -e ".[dev]"
pytest tests/ -v
ruff check firecloud fc_rag fc_mlops
License
MIT, see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file firecloud_devnet-0.2.1.tar.gz.
File metadata
- Download URL: firecloud_devnet-0.2.1.tar.gz
- Upload date:
- Size: 70.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf640f5364847654c3ddd16954f6099377cccd8b791c2560d74142726235e82e
|
|
| MD5 |
e329afc46bd83619a09c1663ccd4d8a3
|
|
| BLAKE2b-256 |
29314a0ec04f57a83079e223e36cda6d3c77f92835fcabc58f452e351a98701e
|
Provenance
The following attestation bundles were made for firecloud_devnet-0.2.1.tar.gz:
Publisher:
publish.yml on rajashekharsunkara/firecloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
firecloud_devnet-0.2.1.tar.gz -
Subject digest:
bf640f5364847654c3ddd16954f6099377cccd8b791c2560d74142726235e82e - Sigstore transparency entry: 2062989380
- Sigstore integration time:
-
Permalink:
rajashekharsunkara/firecloud@76e5cdb8e9712dcd87d94dd42416b594c34034fa -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/rajashekharsunkara
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76e5cdb8e9712dcd87d94dd42416b594c34034fa -
Trigger Event:
push
-
Statement type:
File details
Details for the file firecloud_devnet-0.2.1-py3-none-any.whl.
File metadata
- Download URL: firecloud_devnet-0.2.1-py3-none-any.whl
- Upload date:
- Size: 56.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d9ac2af6c11db8529867a84d497defe8d40c25fa56e9d44f276e0783d98ad34
|
|
| MD5 |
c964756e9101be9473e783960f0db8b5
|
|
| BLAKE2b-256 |
97605ddb54f22c674b56d52ce0b8c7be99006d301f919c58b1614b73da4f8077
|
Provenance
The following attestation bundles were made for firecloud_devnet-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on rajashekharsunkara/firecloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
firecloud_devnet-0.2.1-py3-none-any.whl -
Subject digest:
7d9ac2af6c11db8529867a84d497defe8d40c25fa56e9d44f276e0783d98ad34 - Sigstore transparency entry: 2062989532
- Sigstore integration time:
-
Permalink:
rajashekharsunkara/firecloud@76e5cdb8e9712dcd87d94dd42416b594c34034fa -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/rajashekharsunkara
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@76e5cdb8e9712dcd87d94dd42416b594c34034fa -
Trigger Event:
push
-
Statement type: