File sharing via access codes. Administrators share server-side folder trees with external users using short-lived access codes that map to fnmatch-style glob patterns.
Tech stack: Python / FastAPI / SQLAlchemy / SQLite / Vue.js 3 / Vite / Tailwind CSS v4 / shadcn-vue
make dev # start dev server on :8000 (user) and :8080 (admin)See CLAUDE.md for full developer documentation.
- Share existing folder tree (read-only, no upload)
- Access code system — trade code for session access
- fnmatch glob pattern-based file/folder visibility
- File download with access control
- Admin authentication — trusted headers (reverse proxy forward_auth)
- Alternate login page (password) if standalone
- Session tracking — records which user session claimed each access code
- Revoke (delete or unbind) individual access codes from the session claims view
- Admin file browser — browse the full server file tree and create access codes from any file or folder
- Forward-auth API endpoint — lets a reverse proxy (Caddy) serve file downloads directly from the filesystem
- Docker — multi-stage image with frontend build
- Caddy production compose — forward-auth offloads file I/O from Python to Caddy
- WAF — Coraza with OWASP CRS rules (blocking mode,
coraza-caddyplugin) - Rate limiting — per-IP limits on brute-force endpoints (
caddy-ratelimitplugin) - Upload size limits — 10 MB max request body (
request_bodydirective)
- WAF — Coraza with OWASP CRS rules (blocking mode,
make docker-buildThe app always listens on port 8000. Admin authentication works in two modes:
docker/docker-compose.prod.yml wires Caddy as a TLS-terminating reverse proxy that serves file downloads directly from the filesystem — Python only handles the authorization check via GET /api/v1/auth. This eliminates Python from the file I/O path. The setup also includes a Coraza WAF (OWASP CRS), rate limiting on brute-force endpoints, and a 10 MB upload size cap, all configured in docker/Caddyfile.
cd docker
docker compose -f docker-compose.prod.yml up -dKey variables for this setup:
| Variable | Description |
|---|---|
SHARETREE_FILES_PATH |
Host path to the shared file tree (default: ../files) |
SHARETREE_SESSION_SECRET |
Required; random secret for encrypted session cookies |
SHARETREE_ADMIN_PASSWORD |
Required; password for the built-in admin login page |
Caddy handles HTTPS automatically (Let's Encrypt). For HTTP-only or custom TLS, edit docker/Caddyfile.
Admin routes are protected by a session-based login page at /admin/login.
Set SHARETREE_ADMIN_PASSWORD to the desired admin password.
Rate limiting and WAF: The production Caddy compose (
docker/docker-compose.prod.yml) includes rate limiting on brute-force endpoints and a Coraza WAF with OWASP CRS rules. If you deploy without Caddy, place sharetree behind a reverse proxy with rate limiting configured there.
services:
sharetree:
image: sharetree
build: .
ports:
- "8000:8000"
volumes:
- sharetree-data:/data
- sharetree-files:/files
environment:
SHARETREE_SESSION_SECRET: <random-secret>
SHARETREE_ADMIN_PASSWORD: <admin-password>
restart: unless-stopped
volumes:
sharetree-data:
sharetree-files:Admin access is controlled by the Remote-Groups: admins header forwarded by your upstream proxy.
Set SHARETREE_TRUST_HEADERS=true to enable header validation (disables the login page).
services:
sharetree:
image: sharetree
build: .
ports:
- "8000:8000"
volumes:
- sharetree-data:/data
- sharetree-files:/files
environment:
SHARETREE_SESSION_SECRET: <random-secret>
SHARETREE_TRUST_HEADERS: "true"
restart: unless-stopped
volumes:
sharetree-data:
sharetree-files:docker compose up -d| Variable | Required | Default | Description |
|---|---|---|---|
SHARETREE_SESSION_SECRET |
yes | — | Secret key for encrypted session cookies (generate with python -c "import secrets; print(secrets.token_urlsafe(32))") |
SHARETREE_ADMIN_PASSWORD |
when TRUST_HEADERS is falsy |
— | Password for the built-in admin login page |
SHARETREE_TRUST_HEADERS |
no | false |
Trust Remote-Groups header from upstream proxy; disables the admin login page |
SHARETREE_SHARE_ROOT |
no | /files |
Path to the folder tree to share (mount a volume here) |
SHARETREE_DATA_PATH |
no | /data |
Path where the SQLite database is stored (mount a volume here) |