# ipfstr

ipfstr is a small service that makes IPFS uploads easy and adds Blossom endpoints for Nostr clients. It includes a simple admin UI to check health and manage pins.

## What it does

- Upload files to IPFS and return shareable URLs.
- Serve Blossom endpoints for Nostr clients.
- Discover and pin content from Nostr relays.
- Provide a local admin UI for status and maintenance.

## Requirements

- Docker + Docker Compose

## Quick start (Docker)

1. Copy `.env.example` to `.env` and update the few basics (domain/IP, NPUB).
2. `cp docker-compose.dev.yml docker-compose.yml`
3. `sudo docker compose up -d --build`

Most defaults are fine for local testing.

## Where to open it

- Public endpoint: `http://<host>:3334` (or your domain).
- Admin UI (local/LAN): `http://<host>:3335/` or `http://<host>:3335/admin.html`.

Tip: if you expose a public domain, keep the admin UI on a local-only port (do not expose 3335 and that is all).

## Configuration tips (.env.example)

Common settings:

- `SERVICE_URL`: public base URL for Blossom (what Nostr clients use).
- `IPFS_GATEWAY_URL`: URL that clients use to fetch content.
- `IPFS_GATEWAY_FALLBACK_URL`: optional backup gateway (for example `https://dweb.link/ipfs/`).
- `IPFS_API_URL`: where ipfstr talks to the IPFS API (Docker: `http://ipfs:5001`).
- `PIN_UPLOADS`: set to `true` to pin on upload.
- `NPUB`, `NOSTR_RELAYS`: enable the Nostr discovery worker.
- `ADMIN_BIND_ADDR`, `ADMIN_PORT`: where the admin UI listens.

## Cloudflare Worker fallback (optional)

Use this if you want `https://ipfstr.example.com/ipfs/<cid>` to fall back to `dweb.link` when your server is down.

1) Create an origin hostname (no Worker)

Zero Trust -> Tunnels -> your tunnel -> Public Hostnames:

- Hostname: `ipfstr-origin.example.com`
- Service: `http://192.168.1.10:3334`

2) Create Worker (UI)

Workers & Pages -> Create application -> Start with Hello World -> Deploy -> Edit code.
Paste the content from `cloudflare/worker-ipfs-fallback.js`, then Save & Deploy.

3) Worker variables

Workers & Pages -> your Worker -> Settings -> Variables and Secrets:

- `ORIGIN_GATEWAY_BASE` = `https://ipfstr-origin.example.com`
- `FALLBACK_GATEWAY_BASE` = `https://dweb.link`

4) Route

Workers & Pages -> your Worker -> Domains & Routes:

- Zone: `example.com`
- Route: `ipfstr.example.com/ipfs/*`
- Mode: **Fail open (proceed)**.

5) Test

```
sudo docker compose stop ipfstr
```

Visit an uploaded file:

```
https://ipfstr.example.com/ipfs/<CID>
```

It should redirect to `https://dweb.link/ipfs/<CID>`.

## Endpoints (mostly for the admin UI)

- `GET /health`, `GET /status`, `GET /nostr`
- `GET /api/ipfs`
- `POST /api/ipfs/gc`
- `GET /api/ipfs/pins?type=recursive&cid=<cid>`
- `POST /api/ipfs/pin/add` (JSON: `{ "cid": "<cid>", "recursive": true }`)
- `POST /api/ipfs/pin/rm` (JSON: `{ "cid": "<cid>", "recursive": true }`)
- `GET /api/ipfs/swarm/peers`
- `POST /api/ipfs/swarm/connect` (JSON: `{ "addr": "<multiaddr>" }`)
- `POST /api/ipfs/swarm/disconnect` (JSON: `{ "addr": "<multiaddr>" }`)
- `POST /api/pins/ignore` (JSON: `{ "cid": "<cid>" }`)
- `POST /api/pins/unignore` (JSON: `{ "cid": "<cid>" }`)
- `POST /upload` (multipart) or `PUT /upload` (raw)
- Blossom: `POST /blossom`, `GET /list/<pubkey>`, `GET /<sha256>.<ext>`
