Self-hosted file transfer that doesn't suck. Multi-GB packages, expiring magic links, per-recipient isolation, your storage, your rules.
Not a shrunken-down Dropbox clone. Not an enterprise sales pitch. The features you need for sending files to customers and partners — and nothing in the way.
Upload one or many files, set an expiry, hit Send. Your recipient gets a magic-link email — no signup required on their side.
Ask a customer to send you files. They get a link to a private upload page. You see the files as they arrive.
Magic-link tokens are scoped to a single package. Tokens are SHA-256-hashed in the DB — a database dump leaks nothing useful.
Per-file progress bars + speed, plus authoritative "Transferred 47.7 MB in 509 ms (93.7 MB/s)" stats logged server-side.
Any SMTP server: Gmail, Postmark, SES, your own Postfix. Configure in the admin UI with a Test Send button. DKIM/SPF/DMARC compatible.
Default: files on disk under /srv/files. Switch to S3
anytime — presigned URLs mean bytes never flow through your app.
Every magic-link hit, login, file download, upload, revocation, and admin action is logged with IP and user-agent. Survives package deletion.
Programmatic access to packages, files, tokens. Token-authenticated. Self-documenting via auto-generated Swagger UI.
Fire HTTP POSTs to your Slack/Discord/internal-ops when a package is created, downloaded, uploaded, or expired.
Two ways to look at it: versus other self-hosted file-transfer tools, and versus the cloud-drive products people stretch to do file transfer.
| Feature | SpeedyFiles | Pingvin Share | FileBrowser | WeTransfer |
|---|---|---|---|---|
| Open source / self-hosted | ✓ MIT | ✓ MIT | ✓ Apache | ✗ SaaS |
| Inbound upload requests | ✓ First-class | ~ via link | ✗ | ✓ |
| Per-recipient magic links | ✓ | ✓ | ✗ | ✓ |
| Multi-user with roles | ✓ Admin + regular | ✓ | ✓ | ✓ |
| S3 backend | ✓ Built-in | ~ via env | ✓ | ✓ |
| Server-side DKIM email | ✓ Any SMTP | ✓ SMTP | ✗ | ✓ |
| Per-file transfer stats logged | ✓ Persisted | ✗ | ✗ | ✗ |
| REST API + OpenAPI | ✓ | ~ NestJS | ✓ | ~ paid |
| Webhooks | ✓ | ✗ | ✗ | ✗ |
| Per-seat pricing | $0 | $0 | $0 | $$$ |
Cloud drives are great collaboration tools. They're awkward external-transfer tools — shares leak permissions, files persist forever, every recipient seems to need an account, and your customer's data lives on someone else's servers. Here's what changes when you use a purpose-built tool.
| Feature | SpeedyFiles | OneDrive | Google Drive | Box |
|---|---|---|---|---|
| Files live on your servers / storage | ✓ Your S3 or disk | ✗ Microsoft | ✗ Box | |
| Recipient needs no account | ✓ Magic link only | ~ admin policy | ~ link-share | ~ link-share |
| One-shot per-recipient links | ✓ Per package | ✗ Folder-share model | ✗ Folder-share model | ✗ Folder-share model |
| Auto-expire + auto-delete files | ✓ Files removed at TTL | ~ link expires, file persists | ~ link expires, file persists | ~ Business+ only |
| Inbound upload requests | ✓ First-class | ✓ Request files | ✗ (workspace forms only) | ✓ Box Request |
| No risk of over-sharing your drive | ✓ Nothing else to share | ✗ One wrong click | ✗ One wrong click | ✗ One wrong click |
| No background sync to recipient's cloud | ✓ No sync | ✗ Copies on every device | ✗ Copies on every device | ✗ Copies on every device |
| Audit log of every recipient access | ✓ Free + permanent | ~ E3/E5 only | ~ Workspace Audit | ~ Business+ |
| Max single-file size | ∞ (filesystem-bound) | 250 GB | 5 TB | 50 GB (Business) |
| Self-hostable / air-gappable | ✓ On-prem OK | ✗ | ✗ | ✗ |
| Webhooks + REST API on free tier | ✓ Built-in | ~ Graph API | ~ Drive API | ~ Box API |
| Per-seat licensing | $0 (OSS) | ~$5–$23/user/mo | ~$6–$18/user/mo | ~$15–$35/user/mo |
Where the cloud drives still win: document co-editing, mature mobile apps, org-wide search, sync clients for working-offline. If those are your primary need, keep using them — and use SpeedyFiles alongside for the specific job of moving big files to people outside your org.
From zero to running in under five minutes. The Docker path is the friendliest, but a bare-metal install is one shell script.
docker pull ghcr.io/bokelleher/speedyfiles:latest
/setup
The first-run wizard creates your admin account, asks for site
name & URL, and tests your mail config.
# docker-compose.yml
services:
speedyfiles:
image: ghcr.io/bokelleher/speedyfiles:latest
ports:
- "5300:5300"
volumes:
- ./data:/data
- ./files:/srv/files
environment:
SESSION_SECRET: ${SESSION_SECRET}
PUBLIC_BASE_URL: https://files.example.com
LOCAL_STORAGE_ROOT: /srv/files
restart: unless-stopped
# .env
SESSION_SECRET=$(openssl rand -hex 32)
# run it
docker compose up -d
open http://localhost:5300/setup
MIT licensed. Documented. Tested. Contributions welcome.