A stupid simple file upload application that provides a clean, modern interface for dragging and dropping files. Built with Node.js and vanilla JavaScript.
No auth (unless you want it now!), no storage, no nothing. Just a simple file uploader to drop dumb files into a dumb folder.
- Quick Start
- Production Deployment with Docker
- Local Development (Recommended Quick Start)
- Features
- Configuration
- Security
- Technical Details
- Demo Mode
- Contributing
- License
# Pull and run with one command
docker run -p 3000:3000 -v ./uploads:/app/uploads dumbwareio/dumbdrop:latest
- Go to https://localhost:3000
- Upload a File - It'll show up in ./uploads
- Celebrate on how dumb easy this was
Create a docker-compose.yml
file:
services:
dumbdrop:
image: dumbwareio/dumbdrop:latest
ports:
- 3000:3000
volumes:
# Where your uploaded files will land
- ./uploads:/app/uploads
environment:
# Explicitly set upload directory inside the container
UPLOAD_DIR: /app/uploads
# The title shown in the web interface
DUMBDROP_TITLE: DumbDrop
# Maximum file size in MB
MAX_FILE_SIZE: 1024
# Optional PIN protection (leave empty to disable)
DUMBDROP_PIN: 123456
# Upload without clicking button
AUTO_UPLOAD: false
# The base URL for the application
# You must update this to the url you use to access your site
BASE_URL: https://localhost:3000
Then run:
docker compose up -d
- Go to https://localhost:3000
- Upload a File - It'll show up in ./uploads
- Rejoice in the glory of your dumb uploads
Note: The
UPLOAD_DIR
environment variable is now explicitly set to/app/uploads
in the container. The Dockerfile only creates theuploads
directory, notlocal_uploads
. The host directory./uploads
is mounted to/app/uploads
for persistent storage.
For local development setup, troubleshooting, and advanced usage, see the dedicated guide:
- π Drag and drop file uploads
- π Multiple file selection
- π¨ Clean, responsive UI with Dark Mode
- π¦ Docker support with easy configuration
- π Directory upload support (maintains structure)
- π Optional PIN protection
- π± Mobile-friendly interface
- π Configurable notifications via Apprise
- β‘ Zero dependencies on client-side
- π‘οΈ Built-in security features
- πΎ Configurable file size limits
- π― File extension filtering
Variable | Description | Default | Required |
---|---|---|---|
PORT | Server port | 3000 | No |
BASE_URL | Base URL for the application | https://localhost:PORT | No |
MAX_FILE_SIZE | Maximum file size in MB | 1024 | No |
DUMBDROP_PIN | PIN protection (4-10 digits) | None | No |
DUMBDROP_TITLE | Site title displayed in header | DumbDrop | No |
APPRISE_URL | Apprise URL for notifications | None | No |
APPRISE_MESSAGE | Notification message template | New file uploaded {filename} ({size}), Storage used {storage} | No |
APPRISE_SIZE_UNIT | Size unit for notifications (B, KB, MB, GB, TB, or Auto) | Auto | No |
AUTO_UPLOAD | Enable automatic upload on file selection | false | No |
ALLOWED_EXTENSIONS | Comma-separated list of allowed file extensions | None | No |
ALLOWED_IFRAME_ORIGINS (deprecated: see ALLOWED_ORIGINS) | Comma-separated list of origins allowed to embed the app in an iframe | None | No |
ALLOWED_ORIGINS | You can restrict CORS to your BASE_URL or a comma-separated list of specified origins, which will automatically include your base_url | '*' | No |
UPLOAD_DIR | Directory for uploads (Docker/production; should be /app/uploads in container) |
None (see LOCAL_UPLOAD_DIR fallback) | No |
LOCAL_UPLOAD_DIR | Directory for uploads (local dev, fallback: './local_uploads') | ./local_uploads | No |
- UPLOAD_DIR is used in Docker/production. If not set, LOCAL_UPLOAD_DIR is used for local development. If neither is set, the default is
./local_uploads
. - Docker Note: The Dockerfile now only creates the
uploads
directory inside the container. The host's./local_uploads
is mounted to/app/uploads
and should be managed on the host system. - BASE_URL: If you are deploying DumbDrop under a subpath (e.g.,
https://example.com/watchfolder/
), you must setBASE_URL
to the full path including the trailing slash (e.g.,https://example.com/watchfolder/
). All API and asset requests will be prefixed with this value. If you deploy at the root, usehttps://example.com/
. - BASE_URL must end with a trailing slash. The app will fail to start if this is not the case.
See .env.example
for a template and more details.
ALLOWED_IFRAME_ORIGINS (DEPRECATED: see ALLOWED_ORIGINS)
- This is now deprecated but still works for backwards compatibility
- ALLOWED_IFRAME_ORIGINS will be used as a fallback if ALLOWED_ORIGINS is not set
- Please update to ALLOWED_ORIGINS for future compatibility
To allow this app to be embedded in an iframe on specific origins (such as Organizr), set the ALLOWED_IFRAME_ORIGINS
environment variable. For example:
ALLOWED_IFRAME_ORIGINS=https://organizr.example.com,https://myportal.com
If not set, the app will only allow itself to be embedded in an iframe on the same origin (default security).If set, the app will allow embedding in iframes on the specified origins and itself.Security Note: Only add trusted origins. Allowing arbitrary origins can expose your app to clickjacking and other attacks.
ALLOWED_ORIGINS
By default ALLOWED_ORIGINS
is set to '*'
ALLOWED_ORIGINS=https://organizr.example.com,https://myportal.com,https://internalip:port
- If you would like to restrict CORS to your BASE_URL, you can set it like this:
ALLOWED_ORIGINS=https://localhost:3000
- If you would like to allow multiple origins, you can set it like this:
ALLOWED_ORIGINS=https://internalip:port,https://subdomain.domain.tld
- This will automatically include your BASE_URL in the list of allowed origins.
File Extension Filtering
To restrict which file types can be uploaded, set the ALLOWED_EXTENSIONS
environment variable. For example:
ALLOWED_EXTENSIONS=.jpg,.jpeg,.png,.pdf,.doc,.docx,.txt
If not set, all file extensions will be allowed.
Notification Setup
The notification message supports the following placeholders:
{filename}
: Name of the uploaded file{size}
: Size of the file (formatted according to APPRISE_SIZE_UNIT){storage}
: Total size of all files in upload directory
Example message template:
APPRISE_MESSAGE: New file uploaded {filename} ({size}), Storage used {storage}
Size formatting examples:
- Auto (default): Chooses nearest unit (e.g., "1.44MB", "256KB")
- Fixed unit: Set APPRISE_SIZE_UNIT to B, KB, MB, GB, or TB
Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UNIT.
- Integration with Apprise for flexible notifications
- Support for all Apprise notification services
- Customizable notification messages with filename templating
- Optional - disabled if no APPRISE_URL is set
- Variable-length PIN support (4-10 digits)
- Constant-time PIN comparison
- Input sanitization
- Rate limiting
- File extension filtering
- No client-side PIN storage
- Secure file handling
- Backend: Node.js (>=20.0.0) with Express
- Frontend: Vanilla JavaScript (ES6+)
- Container: Docker with multi-stage builds
- Security: Express security middleware
- Upload: Chunked file handling via Multer
- Notifications: Apprise integration
- express: Web framework
- multer: File upload handling
- apprise: Notification system
- cors: Cross-origin resource sharing
- dotenv: Environment configuration
- express-rate-limit: Rate limiting
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes using conventional commits
- Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
See Local Development (Recommended Quick Start) for local setup and guidelines.
Made with β€οΈ by DumbWare.io
- Camera Upload for Mobile
Got an idea? Open an issue or submit a PR