No description
  • Python 53.7%
  • JavaScript 33.4%
  • HTML 12.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-09 22:28:58 -04:00
static Init Commit 2026-10-09 22:28:58 -04:00
templates Init Commit 2026-10-09 22:28:58 -04:00
.gitignore Init Commit 2026-10-09 22:28:58 -04:00
app.py Init Commit 2026-10-09 22:28:58 -04:00
README.md Init Commit 2026-10-09 22:28:58 -04:00
requirements.txt Init Commit 2026-10-09 22:28:58 -04:00

P7MJ Drive™ (v0.1 starter)

A self-hosted, Flask + SQLite file drive designed for Debian/Linux and a plain HTML/CSS/JavaScript frontend.

Included

  • Admin-created accounts by default; public registration is disabled initially.
  • Passwords hashed with Werkzeug's scrypt password hash implementation.
  • SQLite user database and per-user storage roots.
  • Session cookies, CSRF tokens, and authenticated API endpoints.
  • Uploads in chunks of at most 25 MiB, with a 1 GiB per-file cap and a server-side limit of 10 concurrent chunk requests.
  • File and folder upload, including browser folder selection and drag-and-drop folder traversal where supported by the browser.
  • Folder creation, rename, delete, download, image/audio/video preview, and basic UTF-8 text editing.
  • Text is previewed as text, not executed as HTML/JavaScript.

Important status

This is a v0.1 starter, not yet a hardened internet-facing service. Keep it LAN-only while testing. It does not yet include per-user storage quotas, audit logs, antivirus scanning, resumable uploads after server restart, or a backup/restore command. Folder drag-and-drop uses browser-specific File System Entry APIs and can vary by browser. Large media previews currently fetch the media into browser memory; the upload path is chunked, but preview playback should be improved to use a dedicated range-capable media endpoint before relying on very large videos.

Install on Debian 13

sudo apt update
sudo apt install -y python3 python3-venv
mkdir -p ~/src
# Copy/extract this project to ~/src/p7mj-drive
cd ~/src/p7mj-drive
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt

Generate an app secret without printing it into the terminal output:

umask 077
python3 -c 'import secrets; print(secrets.token_urlsafe(48))' > .secret

Set the environment when running (replace the example path with the actual project path):

export P7MJ_DRIVE_SECRET="$(cat .secret)"
export P7MJ_DRIVE_DATA="$HOME/p7mj-drive-data"

Create the first account:

flask --app app create-user

Start the app on loopback for the first test:

waitress-serve --listen=127.0.0.1:8080 app:app

For a LAN-only test, stop it and bind to the M73's LAN address instead:

waitress-serve --listen=192.168.1.202:8080 --threads=12 app:app

Then visit http://192.168.1.202:8080 from a device on your home LAN. Do not port-forward this port to the public internet yet. For remote use later, put it behind a properly configured HTTPS reverse proxy and set P7MJ_DRIVE_HTTPS=1.

Public registration toggle

Registration is stored in SQLite and is off by default:

flask --app app registration on
flask --app app registration off

The toggle takes effect immediately. Account creation remains available with flask --app app create-user.

Upload design

The browser sends each file sequentially as slices of up to 25 MiB. The server reads each request in 1 MiB reads and writes it to a private temporary file; a bounded semaphore limits simultaneous chunk requests to 10. A file is atomically moved into the user's drive only after its expected size has arrived. The web UI currently uploads one file at a time per browser session to keep client/server memory use predictable.

Notes / next hardening tasks

Before wider use: add per-user quotas and disk-space checks, rate limiting, stronger login throttling, upload cleanup on startup, a persistent upload table for resumability, range-enabled media streaming without full-file buffering, a safe server-side backup tool, and tests for path isolation and race conditions. Back up both the SQLite DB and users/ together.