Skip to content

bokelleher/speedyfiles

Repository files navigation

SpeedyFiles

Self-hosted file transfer that doesn't suck.

License: MIT Python 3.12+ FastAPI Docker pulls

Send 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.

🌐 Website: https://speedyfiles.app πŸ“– Docs: https://speedyfiles.app/docs/ βš™οΈ API: https://speedyfiles.app/api/


Why?

Sending big files to customers is harder than it should be:

  • Dropbox / Google Drive expose your whole shared drive; over-share-by-accident is one click away.
  • WeTransfer is great but per-seat fees, no audit trail, and your customers' files live on their servers.
  • FTP/SFTP works but the UX is medieval and credentials get reused forever.
  • Email attachments cap out at 25 MB.

SpeedyFiles 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.

Features

  • πŸ“€ Outbound packages β€” upload files, set TTL, send magic link to recipient.
  • πŸ“₯ Inbound requests β€” invite a customer to upload to a private page.
  • πŸ” Per-recipient isolation β€” magic-link tokens scoped to a single package; SHA-256 hashed in DB.
  • πŸ“Š Live transfer stats β€” per-file progress bars + speed + persisted Transferred 47.7 MB in 509 ms (93.7 MB/s) data.
  • πŸ“§ BYO-SMTP β€” any mail server: Gmail, Postmark, SES, your own. Configure in the UI.
  • πŸ’Ύ Local or S3 storage β€” toggle globally or per-package.
  • πŸ“œ Full audit log β€” every login, magic-link hit, file download, upload, revocation.
  • βš™οΈ REST API β€” token-authenticated, OpenAPI 3 documented, Swagger UI bundled at /api/v1/docs.
  • πŸͺ Webhooks β€” HMAC-signed HTTP POSTs to your URLs on every event.
  • πŸ‘₯ Multi-user with roles β€” admin + regular; admin sees everything.
  • πŸ”‘ Password reset by email β€” forgot-password flow built in.
  • πŸš€ 5-minute install β€” Docker compose + first-run wizard; no config files needed.

Quick start

curl -O https://speedyfiles.app/quickstart/docker-compose.yml
echo "SESSION_SECRET=$(openssl rand -hex 32)" > .env
docker compose up -d
open http://localhost:5300/setup

That's it. The first-run wizard collects your admin email, site name, and (optional) SMTP settings β€” you're sending files in 5 minutes.

For production deployments with TLS, a real domain, and proper email deliverability, see the full install guide.

Stack

  • Backend: Python 3.12 + FastAPI + SQLAlchemy 2 (async) + SQLite (default) or any SQLAlchemy-supported DB
  • Frontend: server-rendered Jinja2 + HTMX + vanilla JS (no Node/npm build step at runtime)
  • Storage: local filesystem or S3-compatible (AWS S3, MinIO, R2, B2, Wasabi, Spaces…)
  • Mail: stdlib smtplib β†’ any SMTP server (no vendor lock-in)
  • Auth: argon2id passwords + signed-cookie sessions + double-submit CSRF + Bearer-token API
  • Security: HMAC-signed webhooks, Fernet-encrypted secrets at rest, audit log per action

Architecture

                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚     Recipient                        β”‚
                  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
                  β”‚  β”‚ Magic link inβ”‚                    β”‚
                  β”‚  β”‚ their email  β”‚                    β”‚
                  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
                  β”‚         β”‚                            β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚ HTTPS
                            β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  nginx (TLS termination)   β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚ proxy_pass
                            β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  SpeedyFiles (FastAPI)     β”‚
              β”‚  - Web UI (/dash, /p/...)  β”‚
              β”‚  - REST API (/api/v1/*)    β”‚
              β”‚  - Background webhooks     β”‚
              β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚           β”‚
                 β”‚ SQLite    β”‚ Local FS or S3
                 β–Ό           β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ DB   β”‚   β”‚ /srv/    β”‚
              β”‚      β”‚   β”‚  files/  β”‚
              β””β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

REST API

Every instance auto-publishes its OpenAPI 3 spec + Swagger UI:

  • GET /api/v1/openapi.json β€” machine-readable spec
  • GET /api/v1/docs β€” try-it-in-browser Swagger UI
  • GET /api/v1/redoc β€” clean reference style

Example: create a package, upload a file, send the notification β€” entirely from a script:

TOKEN="sf_..."  # create in the web UI under Account β†’ API tokens
HOST="https://files.example.com"

PKG=$(curl -s -X POST $HOST/api/v1/packages \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"title":"Q4 financials","recipient_email":"cfo@acme.com",
       "recipient_name":"Acme CFO","direction":"outbound","ttl_days":14}' | jq -r .id)

curl -X POST $HOST/api/v1/packages/$PKG/files \
  -H "Authorization: Bearer $TOKEN" -F "file=@./Q4-report.pdf"

curl -X POST $HOST/api/v1/packages/$PKG/finalize \
  -H "Authorization: Bearer $TOKEN"
# β†’ response includes the magic link emailed to the recipient

Webhooks

Subscribe 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.

POST /your/webhook HTTP/1.1
Content-Type: application/json
X-SpeedyFiles-Event: package.finalized
X-SpeedyFiles-Signature: sha256=...

{"event":"package.finalized","timestamp":"...","package_id":"abc...",
 "title":"Q4 financials","recipient_email":"cfo@acme.com",...}

After 10 consecutive failures the hook auto-disables. Configure under Settings β†’ Webhooks in the admin UI.

Development

git clone https://github.com/bokelleher/speedyfiles
cd speedyfiles
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt  # pytest, ruff, mypy
cp .env.example .env
python -m app.cli init-db
uvicorn app.main:app --reload --port 5300

Run tests:

pytest -v

Lint:

ruff check .
mypy app/

Roadmap

  • OIDC / SSO support (Authelia / Authentik / Keycloak / Google Workspace)
  • tus.io resumable upload protocol
  • Per-package storage backend (mix local + S3 in the same instance)
  • Browser-direct presigned S3 uploads (skip the app server)
  • Migration tooling: import from Pingvin Share / WeTransfer

SpeedyFiles Cloud

For teams that want UDP-accelerated global transfers, a signed CLI that works on customer machines without IT help, multi-region edge nodes, managed email reputation, and zero-ops operation β€” we're building SpeedyFiles Cloud, a hosted SaaS layered on top of this same open-source core.

The OSS will always include everything you need to run SpeedyFiles yourself. Cloud adds the operationally-expensive bits (UDP edge network, signed clients, abuse mitigation, deliverability-as-a-service) for teams that would rather pay than build.

πŸ‘‰ Join the Cloud waitlist β€” early access + a generous free tier for OSS contributors.

Contributing

PRs welcome. See CONTRIBUTING.md. Vulnerability reports go to SECURITY.md.

License

MIT. Commercial use, modification, redistribution all permitted.

Acknowledgments

Built with FastAPI, SQLAlchemy, HTMX, and argon2-cffi.

About

Self-hosted file transfer that doesn't suck. Multi-GB packages, magic-link sharing, REST API, webhooks, audit log. MIT.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors