summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorJason McCormick <jason@mfamily.org>2026-10-16 16:57:47 -0400
committerJason McCormick <jason@mfamily.org>2026-10-16 16:57:47 -0400
commit98119d8fb55e1633d7bdd79db30fd5caea9ee641 (patch)
tree370d5aefedfc3eba4d69a6682f7d6139701a2539 /README.md
feat: add private image upload serviceHEADmain
Diffstat (limited to 'README.md')
-rw-r--r--README.md78
1 files changed, 78 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..473b078
--- /dev/null
+++ b/README.md
@@ -0,0 +1,78 @@
+# Private Drop
+
+A small, dependency-free web application for anonymous single-image submissions. It accepts JPG, PNG, and HEIC files up to 10 MiB, verifies the file signature, replaces the original filename, and stores the image outside the HTTP-served directory.
+
+Upload forms are available only at named, single-segment targets such as `/logo-contest` or `/911u19jasdl`. The bare `/` path is rejected with HTTP 418. Each target stores its submissions in a separate private directory beneath the configured upload directory.
+
+## Run locally
+
+```bash
+python3 server.py
+```
+
+Open a target such as <http://127.0.0.1:8000/logo-contest>. By default, its uploads are written to `data/uploads/logo-contest/`, while the server only exposes allow-listed frontend assets. Uploaded files therefore have no HTTP route.
+
+For production, choose a private directory on a persistent disk and bind to the needed interface:
+
+```bash
+UPLOAD_DIR=/var/lib/blind-uploader/uploads HOST=0.0.0.0 PORT=8000 python3 server.py
+```
+
+The service creates the upload directory with mode `0700` and each image with mode `0600`. The process user needs write access to `UPLOAD_DIR`.
+
+## Test
+
+```bash
+python3 -m unittest discover -s tests -v
+```
+
+## Production notes
+
+- Put the service behind an HTTPS reverse proxy and set its request-body limit to at least 11 MiB.
+- Do not configure the reverse proxy, CDN, or another static server to expose `UPLOAD_DIR`.
+- Add rate limiting at the reverse proxy before exposing anonymous uploads to the public internet.
+- Back up, retain, and delete submissions according to your review and privacy policy.
+- Malware scanning and image re-encoding are recommended before a reviewer opens untrusted files.
+
+## systemd and nginx
+
+Example deployment files are provided in `deploy/`. They assume the application is installed at `/opt/blind-uploader`, nginx proxies to `127.0.0.1:8000`, and images are stored under `/var/lib/blind-uploader/uploads`.
+
+To install the application, systemd unit, and nginx configuration in one step, run:
+
+```bash
+sudo make install DOMAIN=upload.example.com
+```
+
+This validates the nginx configuration before starting the service and reloading nginx. It requires Python 3, systemd, nginx, `make`, and standard Unix installation tools to already be installed. The generated nginx configuration is `/etc/nginx/conf.d/blind-uploader.conf`.
+
+To run the test suite without installing anything:
+
+```bash
+make check
+```
+
+Install and start the service:
+
+```bash
+sudo cp deploy/blind-uploader.service /etc/systemd/system/
+sudo systemctl daemon-reload
+sudo systemctl enable --now blind-uploader.service
+sudo systemctl status blind-uploader.service
+```
+
+The unit uses systemd's `DynamicUser` and `StateDirectory` features, so no permanent application user or manual data-directory setup is needed. Optional overrides can be placed in Debian's standard `/etc/default/blind-uploader` environment file, for example:
+
+```ini
+PORT=8080
+UPLOAD_DIR=/var/lib/blind-uploader/uploads
+```
+
+Install the nginx configuration after replacing `upload.example.com` and adding the TLS configuration appropriate for your server:
+
+```bash
+sudo cp deploy/nginx-blind-uploader.conf /etc/nginx/sites-available/blind-uploader
+sudo ln -s /etc/nginx/sites-available/blind-uploader /etc/nginx/sites-enabled/blind-uploader
+sudo nginx -t
+sudo systemctl reload nginx
+```