init: video-share — minimal no-signup file/video share with TTL

This commit is contained in:
2026-05-04 16:09:15 +02:00
commit 4ab1f87c1a
12 changed files with 2165 additions and 0 deletions

79
README.md Normal file
View File

@@ -0,0 +1,79 @@
# share
Minimalist no-signup file/video drop. Upload a file, get a private UUID link, share it. Files self-destruct after a configurable TTL.
- No accounts, no DB. Metadata is a tiny JSON sidecar per upload.
- Streamed uploads (no in-memory buffering).
- HTTP `Range` requests so HTML5 video can seek.
- Background sweeper deletes expired files every 5 min.
- Per-upload `deleteToken` lets the uploader revoke early.
## Local dev
```bash
npm install
npm run dev
# http://127.0.0.1:3000
```
Files land in `./data/uploads`.
## Configuration
| Env | Default | Notes |
|---|---|---|
| `PORT` | `3000` | HTTP port |
| `HOST` | `0.0.0.0` | Bind host |
| `DATA_DIR` | `/data/uploads` | Persisted directory (mount a volume here) |
| `MAX_FILE_SIZE` | `524288000` | 500 MB. Bytes. |
| `LOG_LEVEL` | `info` | Fastify logger level |
TTL options exposed in the UI: 30m / 1h / 6h / 24h. Edit `TTL_OPTIONS` in `src/server.js` to change.
## Deploy on Coolify (montlab.dev)
Two ways. Pick one.
### Option A — Dockerfile build pack (matches existing apps)
1. Push this repo to Gitea: `git.montlab.dev/JosLe/video-share`.
2. In Coolify, create a new app:
- Build pack: **Dockerfile**
- Source: Public Repository → `https://git.montlab.dev/JosLe/video-share.git`
- Branch: `main`
- Port: `3000`
- Domain: `share.montlab.dev` (Caddy + Let's Encrypt is automatic)
3. **Persistent storage** → add a volume:
- Source: `share_data` (named volume, or a host path you prefer)
- Destination: `/data`
4. **Environment variables** (optional override):
- `MAX_FILE_SIZE=524288000`
5. Set up the Gitea webhook exactly like the other apps in `INFRASTRUCTURE.md`.
6. Deploy. First time may need "Force redeploy without cache".
### Option B — Docker Compose build pack
Use the bundled `docker-compose.yaml`. Pick build pack **Docker Compose** in Coolify, point at this repo, set the domain on the `app` service to `share.montlab.dev`, port `3000`. The named volume `share_data` is declared in the compose file.
## Caddy / proxy notes
Coolify's Caddy fronts the app, so HTTPS, HTTP/2 and request body limits are handled there. caddy-docker-proxy v2.9 does **not** cap upload size by default for HTTP/2, but if a future config sets `request_body { max_size ... }`, bump it above `MAX_FILE_SIZE`.
## Endpoints
| Method | Path | Purpose |
|---|---|---|
| `GET` | `/` | Upload page |
| `POST` | `/upload` | multipart form: `file` + `ttl` (`30m`/`1h`/`6h`/`24h`) |
| `GET` | `/v/:id` | Viewer (HTML, video player) |
| `GET` | `/f/:id` | Raw file stream, supports `Range` |
| `GET` | `/f/:id?dl=1` | Force download |
| `GET` | `/api/info/:id` | JSON metadata |
| `DELETE` | `/api/:id?token=...` | Revoke with the delete token |
| `GET` | `/healthz` | Liveness |
Links use UUID v4. They are unguessable but **not authenticated** — anyone with the link can view. Send the link over a private channel.
## Disk usage
A 500 MB upload at 1 h TTL uses ~500 MB until the sweep cycle picks it up (≤5 min after expiry). For peak sizing assume `users × max_concurrent_uploads × MAX_FILE_SIZE × longest_TTL/sweep_interval`. Coolify's CX22 has 40 GB SSD — keep an eye on it or lower `MAX_FILE_SIZE`.