Skip to content

Commit 3b3bf0e

Browse files
authored
Merge pull request #1 from edsu/restructure
Add CLI tool
2 parents dc8c09f + fca0bac commit 3b3bf0e

File tree

11 files changed

+482
-167
lines changed

11 files changed

+482
-167
lines changed

.github/workflows/test.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Test
2+
on:
3+
- push
4+
jobs:
5+
test:
6+
runs-on: ubuntu-latest
7+
strategy:
8+
matrix:
9+
python-version: [3.13]
10+
steps:
11+
12+
- name: checkout
13+
uses: actions/checkout@v3
14+
15+
- name: Set up Python ${{ matrix.python-version }}
16+
uses: actions/setup-python@v4
17+
with:
18+
python-version: ${{ matrix.python-version }}
19+
20+
- name: Lint
21+
uses: astral-sh/ruff-action@v2
22+
with:
23+
args: 'check'
24+
25+
- name: Format
26+
uses: astral-sh/ruff-action@v2
27+
with:
28+
args: 'format --check'
29+
30+
- name: Install uv
31+
run: |
32+
pip install uv
33+
34+
- name: Run tests
35+
run: uv run pytest

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.env
2+
**/__pycache__/

README.md

Lines changed: 58 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
# ⇧📁 shifted-storage
1+
# ⇧📁 shiftedstorage
22

3-
*shifted-storage* is a tailored configuration of [Docker], [IPFS Cluster] and [Tailscale] that allows a trusted network of archives to cooperatively back up each other's data. This work is part of [Shift Collective]'s [Modeling Sustainable Futures: Exploring Decentralized Digital Storage for Community Based Archives] project, which was funded by the [Filecoin Foundation for the Decentralized Web]. For more details you can read reports linked from the project's homepage.
3+
[![Test](https://github.com/edsu/shiftedstorage/actions/workflows/test.yml/badge.svg)](https://github.com/edsu/shiftedstorage/actions/workflows/test.yml)
44

5-
In a nutshell, the goal of *shifted-storage* is to provide an alternative to "big-tech" storage services, that is:
5+
*shiftedstorage* is a tailored configuration of [Docker], [IPFS Cluster] and [Tailscale] that allows a trusted network of archives to cooperatively back up each other's data. This work is part of [Shift Collective]'s [Modeling Sustainable Futures: Exploring Decentralized Digital Storage for Community Based Archives] project, which was funded by the [Filecoin Foundation for the Decentralized Web]. For more details you can read reports linked from the project's homepage.
6+
7+
In a nutshell, the goal of *shiftedstorage* is to provide an alternative to "big-tech" storage services, that is:
68

79
- *Decentralized* instead of *Centralized*: the software is open source and can
810
be deployed on infrastructure that is operated by the members in their data centers,
@@ -15,12 +17,12 @@ In a nutshell, the goal of *shifted-storage* is to provide an alternative to "bi
1517
any time.
1618
- *Private* instead of *Public*: many peer-to-peer and distributed web systems
1719
are built around the idea of data being globally available, and easy to
18-
replicate. Data in *shifted-storage* is not made available to the
20+
replicate. Data in *shiftedstorage* is not made available to the
1921
wider IPFS network. The use of Tailscale allows peers to communicate
2022
directly with each other using a virtual private mesh network, that only they
2123
can see.
2224

23-
*shifted-storage* is really just a Docker Compose configuration for reliably bringing up Docker services that allows a network of shifted-storage instances to talk to each other. The containers are:
25+
*shiftedstorage* is really just a Docker Compose configuration for reliably bringing up Docker services that allows a network of shiftedstorage instances to talk to each other. The containers are:
2426

2527
* *tailscale*: a Tailscale client that establishes your node's connection to other trusted nodes in the mesh network.
2628
* *ipfs*: an IPFS daemon running on the Tailscale network.
@@ -35,63 +37,60 @@ Of course it's not all rainbows and unicorns, there are tradeoffs to this approa
3537
* Tailscale makes establishing a virtual private mesh network easy using the open source Wireguard software and some of their own open source code and infrastructure. Howevver Tailscale are a company and could decide to change how they do things at any time.
3638
* Tailscale doesn't have access to any of the stored data, but they do know the network topology of the IPFS cluster, and could be issued a subpoena in some jurisdictions that forces them to share who is a member of the network. Read more about this [here](https://tailscale.com/blog/tailscale-privacy-anonymity).
3739

38-
## Setup Bootstrap Node
39-
40-
*Note: if you are creating a shifted-storage node in an existing network jump down to the [Let Others Join](#let-others-join) section below.*
41-
42-
The first node in a *shifted-storage* network is known as the bootstrap node. It requires a bit more setup than subsequent nodes because the Tailscale mesh network needs to be created and configured, and a couple secret keys need to be defined. This bootstrap node will be used by subsequent nodes to find the rest of the network when they join.
40+
## Install
4341

44-
### Tailscale
45-
46-
Fill this in! The end goal is to get a `TS_AUTHKEY`.
42+
First, install the `ipfs` and `ipfs-cluster-ctl` command line utilities, and make sure they are in your system path. You don't need to run the cluster on your workstation, however having these utilities available makes it easy to talk to running nodes.
4743

48-
### Keys
44+
* `ipfs`: https://docs.ipfs.tech/install/command-line/#install-official-binary-distributions
45+
* `ipfs-cluster-ctl`: https://dist.ipfs.tech/#ipfs-cluster-ctl
4946

50-
The security and privacy of your shifted-storage network is provided by two keys:
47+
You will need to install the `shiftedstorage` utility which helps create the Docker compose file for the bootstrap node and then clone that for subsequent nodes in your network.
5148

52-
* IPFS Swarm Key
53-
* IPFS Cluster Key
49+
You can install it with:
5450

55-
You will want to keep these in a secure place and only share them with others using a secure, end-to-end encrypted communication channel like Signal or WhatsApp.
51+
```
52+
pip install shiftedstorage
53+
```
5654

57-
To create the keys you can:
55+
or if you have [uv]() installed you can just run it without installing it with `uvx`:
5856

5957
```
60-
$ openssl rand -hex 32 > swarm.key
61-
$ openssl rand -hex 32 > ipfs-cluster.key
58+
uvx shiftedstorage
6259
```
6360

64-
### Cluster Peer Name
61+
## Setup Bootstrap Node
6562

66-
You will need to create a name for your node. This name will be used to create a Tailscale host name in your virtual private network. You could use an abbreviated form of your organization name, or your personal name.
63+
*Note: if you are creating a shiftedstorage node in an existing network jump down to the [Let Others Join](#let-others-join) section below.*
6764

68-
### Get the Docker Configuration
65+
The first node in a *shiftedstorage* network is known as the bootstrap node. It requires a bit more setup than subsequent nodes because the Tailscale mesh network needs to be created and configured, and a couple secret keys need to be defined. This bootstrap node will be used by subsequent nodes to find the rest of the network when they join.
6966

70-
```
71-
$ git clone https://github.com/historypin/shifted-storage
72-
$ cd shifted-storage
73-
```
67+
### Tailscale
7468

75-
### Environment File
69+
TBD! The end goal is to get a `TS_AUTHKEY`.
7670

77-
Create a `.env` file:
71+
Be sure to also mention that any admins should get invited to the Tailscale so they can see it from their workstation.
72+
73+
### Create Compose File
74+
75+
Use your Tailscale token to create your bootstrap node, which here is named `bootstrap` but can be whatever you like. This will be the hostname of the bootstrap node in your Tailscale network.
7876

7977
```
80-
IPFS_SWARM_KEY=<YOUR_SWARM_KEY>
81-
CLUSTER_SECRET=<YOUR_CLUSTER_SECRET>
82-
TS_AUTHKEY=<YOUR_TAILSCALE_AUTHKEY>
83-
CLUSTER_PEERNAME=<YOUR_PEER_NAME>
78+
uvx shiftedstorage create --ts-authkey "YOUR KEY HERE" --cluster-peername bootstrap --output compose.yml
8479
```
8580

86-
### Run
81+
This should write a Docker Compose configuration to `compose.yaml`.
82+
83+
**DANGER: Be careful to not make this compose file public since it contains secret keys!**
84+
85+
### Start Bootstrap
8786

88-
Now we are ready to run!
87+
You can now start up your bootstrap node with:
8988

9089
```bash
9190
$ docker compose up -d
9291
```
9392

94-
If you want to stop the service at any time you can execute this command, as long as you are in the `shifted-storage` directory:
93+
If you want to stop the service at any time you can execute this command, as long as you are in the `shiftedstorage` directory:
9594

9695
```
9796
$ docker compose stop
@@ -101,51 +100,53 @@ $ docker compose stop
101100

102101
In order to let others join the network you will need to share a modified version of the compose file with them via a secure channel (e.g. WhatsApp or Signal).
103102

104-
The provided `bootstrap.py` utility will read your existing `compose.yml` and `.env` file and execute some commands in your running docker containers to determine additional information for new nodes to use when bootstrapping into the network:
105-
106-
- Tailscale IP
107-
- IPFS Peer ID
108-
- IPFS Cluster Peer ID
109-
110-
You need to supply a "node name" for the new node in your cluster. It's good to use a name without spaces or punctuation that will help you identify the node later since this is the hostname that it will appear under in the Tailscale network. For example, if you have are adding a node for "Warrior Women Project" you could:
111-
112103
```
113-
./bootstrap.py warriorwomen > warriorwomen-compose.yml
104+
uvx shiftedstorage clone --input compose.yml --cluster-peername acme --output acme-compose.yml --bootstrap-host boostrap
114105
```
115106

116-
You can then share the compose.yml file with the new member for them to use in their own Docker environment.
117-
118-
**DANGER: Be careful to share this file using a private channel with end-to-end encryption like Signal or WhatsApp. It contains secret keys for the Tailscale network as well as your IPFS Cluster.**
107+
This will write out a `acme-compose.yml` file which you can share via a secure channel with someone running a machine at that organization.
119108

120-
## Joining a Network
109+
You should be able to run this using `docker compose`, but for the original Shift-FFDW project we have been standardizing on partners using a [QNAP NAS](https://www.qnap.com/en-us/product/tbs-h574tx) which makes is easy to set up. You can use whatever device you want as long as you can run Docker on it and it has at least 4GB of memory (more couldn't hurt).
121110

122-
In order to join an existing *shifted-storage* network you will need to be given a `compose.yml` file by one of the other members.
123-
124-
You should be able to run this using Docker, but for our project we have been standardizing on QNAP devices that are running the Container Station application.
111+
For people with a QNAP you can:
125112

126113
1. Install Container Station from Apps if it's not already available.
127114
2. Open Container Station.
128115
3. Click `Applications` option in the menu on the left.
129116
4. Click the `Create` button.
130-
5. In the Application Name box enter `shifted-storage`
117+
5. In the Application Name box enter `shiftedstorage`
131118
6. Paste the contents of the supplied `compose.yml` file into the text box.
132119
7. Click the `create` button.
133120
8. Click the `Containers` option in the menu on the left.
134121
9. Verify that you see three containers running.
135122

136123
## Working With Storage
137124

125+
The shiftedstorage utility offers some functionality to add and remove content from storage. These are really just wrappers around the `ipfs-cluster-ctl` command, which you can choose to use directly of course.
126+
138127
### Adding Content
139128

140-
TODO
129+
```
130+
uvx shiftedstorage add --host acme my-file.pdf
131+
```
132+
133+
or
134+
135+
```
136+
uvx shiftedstorage add --host acme my-directory/
137+
```
141138

142139
### Checking Status
143140

144-
TODO
141+
```
142+
uvx shiftedstorage status --host <cid>
143+
```
145144

146145
### Removing Content
147146

148-
TODO
147+
```
148+
uvx shiftedstorage rm --host <cid>
149+
```
149150

150151
[Docker]: https://www.docker.com/get-started/
151152
[Tailscale]: https://tailscale.com/

bootstrap.py

Lines changed: 0 additions & 84 deletions
This file was deleted.

container-init.d/01-ipfs-bootstrap.sh

Lines changed: 0 additions & 15 deletions
This file was deleted.

pyproject.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[project]
2+
name = "shiftedstorage"
3+
version = "0.1.0"
4+
description = "Distributed community storage using ipfs-cluster, Tailscale and Docker"
5+
readme = "README.md"
6+
requires-python = ">=3.13"
7+
dependencies = [
8+
"click>=8.2.1",
9+
"pyyaml>=6.0.2",
10+
]
11+
packages = ["shiftedstorage"]
12+
13+
[project.scripts]
14+
shiftedstorage = "shiftedstorage:cli"
15+
16+
[dependency-groups]
17+
dev = [
18+
"pytest>=8.4.1",
19+
]
20+
21+
[build-system]
22+
requires = ["uv_build"]
23+
build-backend = "uv_build"

src/shiftedstorage/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .cli import cli
2+
3+
__all__ = [
4+
"cli",
5+
]

0 commit comments

Comments
 (0)