apps/blobs/README.md 3.5 K raw
1
# blobs
2
3
Self-hosted browser, CLI, and TUI for S3-compatible blob storage. Built for Cloudflare R2 but works with any S3-compatible endpoint (AWS S3, MinIO, Backblaze B2, etc).
4
5
Single binary, three modes:
6
7
- `blobs server` — web UI (password-protected, session cookies)
8
- `blobs` (no args) — Yazi-style TUI for browsing buckets, copying URLs, opening files, previewing images inline
9
- `blobs <file>` — one-shot upload that prints the resulting URL to stdout
10
11
Features:
12
13
- Lists every bucket the credentials can see
14
- Folder/file navigation with breadcrumbs (web) or two-pane preview (TUI)
15
- Inline image previews via Kitty/Ghostty/iTerm2 graphics protocols (or `chafa` fallback)
16
- Presigned download URLs + optional permanent public URL map
17
- Upload (multi-file in web, single-file in CLI), replace, delete, create folder
18
19
## Quick start (server)
20
21
```sh
22
cp .env.example .env
23
# edit .env — set BLOBS_PASSWORD and either:
24
#   S3_ENDPOINT + S3_ACCESS_KEY_ID + S3_SECRET_ACCESS_KEY  (generic)
25
#   R2_ACCOUNT_ID + S3_ACCESS_KEY_ID + S3_SECRET_ACCESS_KEY  (R2)
26
go run . server
27
```
28
29
Visit `http://127.0.0.1:3000` and log in.
30
31
## CLI / TUI
32
33
The same binary also speaks directly to S3 (no server required):
34
35
```sh
36
blobs auth                          # interactive: writes ~/.config/blobs/config.toml
37
blobs                               # TUI — bucket picker then folder browse
38
blobs -b my-bucket                  # TUI — jump straight into my-bucket
39
blobs ./photo.png                   # upload to BLOBS_DEFAULT_BUCKET, print URL
40
blobs -b my-bucket --prefix imgs/ ./photo.png
41
```
42
43
The TUI auto-detects Kitty/Ghostty/iTerm2 graphics protocols for inline image previews and falls back to `chafa` when available. Override with `BLOBS_PREVIEW={kitty|iterm|chafa|none}`.
44
45
Key bindings in browse view: `enter`/`l` open, `h`/`esc` back, `y` copy URL (public if mapped, else presigned), `Y` force public, `K` copy S3 key, `o` open in browser, `u` upload, `d` delete, `r` refresh, `b` jump to buckets, `space` toggle preview, `?` help, `q` quit.
46
47
## Configuration
48
49
See `.env.example` for the full list. Notable knobs:
50
51
- `BLOBS_MAX_UPLOAD_MB` — single-shot upload cap (default 100MB)
52
- `BLOBS_PRESIGN_TTL_SECONDS` — presigned download URL lifetime (default 3600)
53
- `BLOBS_PUBLIC_URLS` — `bucket=url,bucket=url` map; when a file's bucket appears here, the detail page also surfaces a permanent public URL (e.g. an R2 public dev URL or custom domain)
54
55
## R2 setup
56
57
1. In the Cloudflare dashboard, create an R2 API token with read+write access to your bucket(s).
58
2. Set in `.env`:
59
   ```
60
   R2_ACCOUNT_ID=<your account id>
61
   S3_ACCESS_KEY_ID=<token id>
62
   S3_SECRET_ACCESS_KEY=<token secret>
63
   ```
64
3. (Optional) Enable a public dev URL or custom domain on the bucket and add it to `BLOBS_PUBLIC_URLS`.
65
66
## Generic S3 setup (e.g. MinIO)
67
68
```
69
S3_ENDPOINT=http://localhost:9000
70
S3_REGION=us-east-1
71
S3_ACCESS_KEY_ID=minioadmin
72
S3_SECRET_ACCESS_KEY=minioadmin
73
```
74
75
## Routes
76
77
| Method | Path | Notes |
78
| --- | --- | --- |
79
| GET | `/login`, POST `/login` | password form |
80
| POST | `/logout` | clear session |
81
| GET | `/buckets` | list buckets |
82
| GET | `/b/{bucket}/browse/{prefix...}` | folder listing |
83
| GET | `/b/{bucket}/object/{key...}` | file detail |
84
| GET | `/b/{bucket}/preview/{key...}` | proxied file stream (for inline images) |
85
| POST | `/b/{bucket}/upload` | multipart file upload |
86
| POST | `/b/{bucket}/replace` | overwrite existing key |
87
| POST | `/b/{bucket}/delete` | delete by key |
88
| POST | `/b/{bucket}/mkdir` | create zero-byte `prefix/name/` marker |