A Node.js-based backend for secure, privacy-focused file sharing with optional end-to-end encryption support.
Dropgate Server is installable from the TrueNAS Apps Market!
See it here: https://apps.truenas.com/catalog/dropgate-server
Learn more: https://diamonddigital.dev/blog/announcing-dropgate-for-truenas
See Dropgate in action here: dropgate.link
To prevent and monitor for abuse, DEBUG-level logging and strict rate limits are enforced.
Dropgate Server is the official backend and reference implementation for secure, privacy-focused file sharing using the Dropgate protocols: DGUP (Dropgate Upload Protocol) and DGDTP (Dropgate Direct Transfer Protocol).
It can be self-hosted easily on:
- Home servers / NAS boxes
- VPS instances
- Docker containers
- Tunnelled/reverse-proxied setups (Cloudflare Tunnel, Tailscale, etc.)
Dropgate supports two ways to share files:
- Hosted uploads (classic mode) — you upload a file, share a link, and the server holds it temporarily.
- Direct transfer (P2P) — when enabled, files can transfer device-to-device, with the server only helping peers connect.
When running with E2EE, the server acts as a blind data relay — the contents are unreadable without the client-side decryption key.
Out of the box, the server is conservative:
- ✅ Web UI is enabled
- ✅ Direct Transfer (P2P) is enabled
- ❌ Hosted uploads are disabled (you must opt in)
This means you can spin it up, try the Web UI, and choose what features you want to allow.
git clone https://github.com/diamonddigitaldev/Dropgate.git
cd Dropgate/server
npm install
npm startEnable hosted uploads:
ENABLE_UPLOAD=true npm start(Windows PowerShell)
$env:ENABLE_UPLOAD="true"
npm startdocker run -d \
-p 52443:52443 \
-e ENABLE_UPLOAD=true \
-e UPLOAD_ENABLE_E2EE=true \
-e UPLOAD_PRESERVE_UPLOADS=true \
-e UPLOAD_MAX_FILE_SIZE_MB=1000 \
-v /path/to/uploads:/usr/src/app/uploads \
--name dropgate \
willtda/dropgate-server:latestIf you want uploads to persist across restarts, map /usr/src/app/uploads to a path on the host machine and set UPLOAD_PRESERVE_UPLOADS=true.
| Variable | Default | Description |
|---|---|---|
SERVER_PORT |
52443 |
Port to run the server on. |
SERVER_NAME |
Dropgate Server |
Display name used by the Web UI and GET /api/info. |
ENABLE_WEB_UI |
true |
Enables the Web UI at /. |
LOG_LEVEL |
INFO |
NONE, ERROR, WARN, INFO, DEBUG. |
RATE_LIMIT_WINDOW_MS |
60000 |
Rate limit window in milliseconds (0 disables rate limiting). |
RATE_LIMIT_MAX_REQUESTS |
25 |
Requests allowed per window (0 disables rate limiting). |
| Variable | Default | Description |
|---|---|---|
ENABLE_UPLOAD |
false |
Enables the hosted upload protocol and routes. |
UPLOAD_ENABLE_E2EE |
true |
Enables end-to-end encryption for hosted uploads (keys stay client-side). |
UPLOAD_PRESERVE_UPLOADS |
false |
Persist uploads across restarts (uses uploads/db/). |
UPLOAD_MAX_FILE_SIZE_MB |
100 |
Max file size in MB (0 = unlimited). |
UPLOAD_MAX_STORAGE_GB |
10 |
Max total storage in GB (0 = unlimited). |
UPLOAD_MAX_FILE_LIFETIME_HOURS |
24 |
Max file lifetime in hours (0 = unlimited). |
UPLOAD_MAX_FILE_DOWNLOADS |
1 |
Max downloads before file is deleted (0 = unlimited). |
UPLOAD_CHUNK_SIZE_BYTES |
5242880 |
Upload chunk size in bytes (default 5MB). Minimum 65536 (64KB). Smaller values increase per-chunk overhead; larger values may need proxy body-size adjustments. |
UPLOAD_BUNDLE_SIZE_MODE |
total |
How multi-file bundle uploads are size-checked. total enforces the limit against the combined size of all files; per-file enforces it against each file individually. |
UPLOAD_ZOMBIE_CLEANUP_INTERVAL_MS |
300000 |
Cleanup interval for incomplete uploads (0 = disabled). |
| Variable | Default | Description |
|---|---|---|
ENABLE_P2P |
true |
Enables direct transfer (P2P). |
P2P_STUN_SERVERS |
stun:stun.cloudflare.com:3478 |
Comma/space separated STUN servers for WebRTC. |
PEERJS_DEBUG |
false |
Enables verbose PeerJS logs. |
You can sanity-check your server and see what it supports via:
GET /api/info
Example response:
{
"name": "Dropgate Server",
"version": "3.0.13",
"logLevel": "INFO",
"capabilities": {
"upload": {
"enabled": true,
"maxSizeMB": 100,
"maxLifetimeHours": 24,
"maxFileDownloads": 1,
"e2ee": true,
"chunkSize": 5242880,
"bundleSizeMode": "total"
},
"p2p": {
"enabled": true,
"peerjsPath": "/peerjs",
"iceServers": [
{
"urls": [
"stun:stun.cloudflare.com:3478"
]
}
],
"peerjsDebugLogging": false
},
"webUI": {
"enabled": true
}
}
}For E2EE and Direct Transfer (P2P) in browsers, you generally want HTTPS (localhost is the common exception). Run the server behind a reverse proxy that terminates TLS:
- Uploaded files live in
uploads/. - Files can be set to expire after a certain period or after a certain number of downloads.
- Incomplete uploads are cleaned up on an interval.
Dropgate tries to keep logs minimal and transparent. For the full breakdown of what gets logged (and what doesn’t), see:
If you’re debugging a problem, temporarily enable LOG_LEVEL=DEBUG, reproduce the issue, then turn it back down.
Licensed under the AGPL-3.0 License. See the LICENSE file for details.
- Logo designed by TheFuturisticIdiot
- Built with Node.js
- Inspired by the growing need for privacy-respecting, open file transfer tools
This project uses AI tools to aid development.
AI is used to:
- Plan significant changes
- Implement initial passes of new features
- Perform security audits (alongside human review)
- Fix bugs and patch security vulnerabilities
- Review pull requests (alongside human review)
AI is NOT used to:
- Design UI/UX
- Design visual assets (such as bitmap and vector graphics)
- Triage issues
- Decide project direction
- Create release information
AI has a tendency to hallucinate/produce plausible but suboptimal, inaccurate or misleading solutions to delegated tasks.
Every commit is manually reviewed and approved by a member of Diamond Digital Development, and testing is carried out to ensure changes work as intended, do not introduce regressions, and meet reliability and security expectations before being merged into the master branch.
- 💬 Need help or want to chat? Join our Discord Server
- 🐛 Found a bug? Open an issue
- 💡 Have a suggestion? Submit a feature request
