{"id":50874525,"url":"https://github.com/bokelleher/speedyfiles","last_synced_at":"2026-06-15T08:30:49.204Z","repository":{"id":357731221,"uuid":"1238295672","full_name":"bokelleher/speedyfiles","owner":"bokelleher","description":"Self-hosted file transfer that doesn't suck. Multi-GB packages, magic-link sharing, REST API, webhooks, audit log. MIT.","archived":false,"fork":false,"pushed_at":"2026-05-15T22:48:36.000Z","size":383,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T16:18:58.197Z","etag":null,"topics":["docker","fastapi","file-sharing","magic-links","mit-license","python","self-hosted","wetransfer-alternative"],"latest_commit_sha":null,"homepage":"https://speedyfiles.app","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bokelleher.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T01:59:57.000Z","updated_at":"2026-05-15T22:48:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bokelleher/speedyfiles","commit_stats":null,"previous_names":["bokelleher/speedyfiles"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bokelleher/speedyfiles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bokelleher%2Fspeedyfiles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bokelleher%2Fspeedyfiles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bokelleher%2Fspeedyfiles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bokelleher%2Fspeedyfiles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bokelleher","download_url":"https://codeload.github.com/bokelleher/speedyfiles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bokelleher%2Fspeedyfiles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34355156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","fastapi","file-sharing","magic-links","mit-license","python","self-hosted","wetransfer-alternative"],"created_at":"2026-06-15T08:30:45.575Z","updated_at":"2026-06-15T08:30:49.177Z","avatar_url":"https://github.com/bokelleher.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SpeedyFiles\n\n\u003e Self-hosted file transfer that doesn't suck.\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/)\n[![FastAPI](https://img.shields.io/badge/fastapi-0.115-009688.svg)](https://fastapi.tiangolo.com/)\n[![Docker pulls](https://img.shields.io/badge/docker-ghcr.io-blue.svg)](https://github.com/bokelleher/speedyfiles/pkgs/container/speedyfiles)\n\nSend and receive multi-gigabyte packages with **expiring magic links**, **per-recipient isolation**, **signed-email notifications**, and a **clean admin UI**. Your customers, your storage, your rules.\n\n🌐 **Website**: \u003chttps://speedyfiles.app\u003e\n📖 **Docs**: \u003chttps://speedyfiles.app/docs/\u003e\n⚙️ **API**: \u003chttps://speedyfiles.app/api/\u003e\n\n---\n\n## Why?\n\nSending big files to customers is harder than it should be:\n\n- **Dropbox / Google Drive** expose your whole shared drive; over-share-by-accident is one click away.\n- **WeTransfer** is great but per-seat fees, no audit trail, and your customers' files live on their servers.\n- **FTP/SFTP** works but the UX is medieval and credentials get reused forever.\n- **Email attachments** cap out at 25 MB.\n\nSpeedyFiles is the self-hosted middle path: as easy as WeTransfer to use, but **the files live on your storage**, **the audit trail is yours**, and **you pay $0 per seat**.\n\n## Features\n\n- 📤 **Outbound packages** — upload files, set TTL, send magic link to recipient.\n- 📥 **Inbound requests** — invite a customer to upload to a private page.\n- 🔐 **Per-recipient isolation** — magic-link tokens scoped to a single package; SHA-256 hashed in DB.\n- 📊 **Live transfer stats** — per-file progress bars + speed + persisted `Transferred 47.7 MB in 509 ms (93.7 MB/s)` data.\n- 📧 **BYO-SMTP** — any mail server: Gmail, Postmark, SES, your own. Configure in the UI.\n- 💾 **Local or S3 storage** — toggle globally or per-package.\n- 📜 **Full audit log** — every login, magic-link hit, file download, upload, revocation.\n- ⚙️ **REST API** — token-authenticated, OpenAPI 3 documented, Swagger UI bundled at `/api/v1/docs`.\n- 🪝 **Webhooks** — HMAC-signed HTTP POSTs to your URLs on every event.\n- 👥 **Multi-user with roles** — admin + regular; admin sees everything.\n- 🔑 **Password reset by email** — forgot-password flow built in.\n- 🚀 **5-minute install** — Docker compose + first-run wizard; no config files needed.\n\n## Quick start\n\n```bash\ncurl -O https://speedyfiles.app/quickstart/docker-compose.yml\necho \"SESSION_SECRET=$(openssl rand -hex 32)\" \u003e .env\ndocker compose up -d\nopen http://localhost:5300/setup\n```\n\nThat's it. The first-run wizard collects your admin email, site name, and (optional) SMTP settings — you're sending files in 5 minutes.\n\nFor production deployments with TLS, a real domain, and proper email deliverability, see the [full install guide](https://speedyfiles.app/docs/install.html).\n\n## Stack\n\n- **Backend**: Python 3.12 + FastAPI + SQLAlchemy 2 (async) + SQLite (default) or any SQLAlchemy-supported DB\n- **Frontend**: server-rendered Jinja2 + HTMX + vanilla JS (no Node/npm build step at runtime)\n- **Storage**: local filesystem or S3-compatible (AWS S3, MinIO, R2, B2, Wasabi, Spaces…)\n- **Mail**: stdlib `smtplib` → any SMTP server (no vendor lock-in)\n- **Auth**: argon2id passwords + signed-cookie sessions + double-submit CSRF + Bearer-token API\n- **Security**: HMAC-signed webhooks, Fernet-encrypted secrets at rest, audit log per action\n\n## Architecture\n\n```\n                  ┌──────────────────────────────────────┐\n                  │     Recipient                        │\n                  │  ┌──────────────┐                    │\n                  │  │ Magic link in│                    │\n                  │  │ their email  │                    │\n                  │  └──────┬───────┘                    │\n                  │         │                            │\n                  └─────────┼────────────────────────────┘\n                            │ HTTPS\n                            ▼\n              ┌────────────────────────────┐\n              │  nginx (TLS termination)   │\n              └─────────────┬──────────────┘\n                            │ proxy_pass\n                            ▼\n              ┌────────────────────────────┐\n              │  SpeedyFiles (FastAPI)     │\n              │  - Web UI (/dash, /p/...)  │\n              │  - REST API (/api/v1/*)    │\n              │  - Background webhooks     │\n              └──┬───────────┬─────────────┘\n                 │           │\n                 │ SQLite    │ Local FS or S3\n                 ▼           ▼\n              ┌──────┐   ┌──────────┐\n              │ DB   │   │ /srv/    │\n              │      │   │  files/  │\n              └──────┘   └──────────┘\n```\n\n## REST API\n\nEvery instance auto-publishes its OpenAPI 3 spec + Swagger UI:\n\n- `GET /api/v1/openapi.json` — machine-readable spec\n- `GET /api/v1/docs` — try-it-in-browser Swagger UI\n- `GET /api/v1/redoc` — clean reference style\n\nExample: create a package, upload a file, send the notification — entirely from a script:\n\n```bash\nTOKEN=\"sf_...\"  # create in the web UI under Account → API tokens\nHOST=\"https://files.example.com\"\n\nPKG=$(curl -s -X POST $HOST/api/v1/packages \\\n  -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"title\":\"Q4 financials\",\"recipient_email\":\"cfo@acme.com\",\n       \"recipient_name\":\"Acme CFO\",\"direction\":\"outbound\",\"ttl_days\":14}' | jq -r .id)\n\ncurl -X POST $HOST/api/v1/packages/$PKG/files \\\n  -H \"Authorization: Bearer $TOKEN\" -F \"file=@./Q4-report.pdf\"\n\ncurl -X POST $HOST/api/v1/packages/$PKG/finalize \\\n  -H \"Authorization: Bearer $TOKEN\"\n# → response includes the magic link emailed to the recipient\n```\n\n## Webhooks\n\nSubscribe to `package.created`, `package.finalized`, `package.file_uploaded`, `package.downloaded`, `package.revoked`, `package.deleted`, or `package.expired`. SpeedyFiles will POST a JSON body to your URL with an HMAC-SHA256 signature.\n\n```\nPOST /your/webhook HTTP/1.1\nContent-Type: application/json\nX-SpeedyFiles-Event: package.finalized\nX-SpeedyFiles-Signature: sha256=...\n\n{\"event\":\"package.finalized\",\"timestamp\":\"...\",\"package_id\":\"abc...\",\n \"title\":\"Q4 financials\",\"recipient_email\":\"cfo@acme.com\",...}\n```\n\nAfter 10 consecutive failures the hook auto-disables. Configure under **Settings → Webhooks** in the admin UI.\n\n## Development\n\n```bash\ngit clone https://github.com/bokelleher/speedyfiles\ncd speedyfiles\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\npip install -r requirements-dev.txt  # pytest, ruff, mypy\ncp .env.example .env\npython -m app.cli init-db\nuvicorn app.main:app --reload --port 5300\n```\n\nRun tests:\n\n```bash\npytest -v\n```\n\nLint:\n\n```bash\nruff check .\nmypy app/\n```\n\n## Roadmap\n\n- [ ] OIDC / SSO support (Authelia / Authentik / Keycloak / Google Workspace)\n- [ ] tus.io resumable upload protocol\n- [ ] Per-package storage backend (mix local + S3 in the same instance)\n- [ ] Browser-direct presigned S3 uploads (skip the app server)\n- [ ] Migration tooling: import from Pingvin Share / WeTransfer\n\n## SpeedyFiles Cloud\n\nFor teams that want **UDP-accelerated global transfers**, a **signed CLI** that\nworks on customer machines without IT help, **multi-region edge nodes**,\n**managed email reputation**, and zero-ops operation — we're building\n**SpeedyFiles Cloud**, a hosted SaaS layered on top of this same open-source\ncore.\n\nThe OSS will always include everything you need to run SpeedyFiles yourself.\nCloud adds the operationally-expensive bits (UDP edge network, signed clients,\nabuse mitigation, deliverability-as-a-service) for teams that would rather\npay than build.\n\n👉 [**Join the Cloud waitlist**](https://speedyfiles.app/cloud/) — early\naccess + a generous free tier for OSS contributors.\n\n## Contributing\n\nPRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md). Vulnerability reports go to [SECURITY.md](SECURITY.md).\n\n## License\n\n[MIT](LICENSE). Commercial use, modification, redistribution all permitted.\n\n## Acknowledgments\n\nBuilt with [FastAPI](https://fastapi.tiangolo.com/), [SQLAlchemy](https://www.sqlalchemy.org/), [HTMX](https://htmx.org/), and [argon2-cffi](https://argon2-cffi.readthedocs.io/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbokelleher%2Fspeedyfiles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbokelleher%2Fspeedyfiles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbokelleher%2Fspeedyfiles/lists"}