servery
A zero-dependency, pure-Python HTTP file server — a batteries-included python -m http.server.
Run it right now — no install:
# with uv — fetches a matching Python and runs servery, nothing to install:
uvx servery ./public --port 8000
# …or one self-contained file, straight from a pipe (latest release):
curl -fsSL https://github.com/mjbommar/servery/releases/latest/download/servery.py | python3 - ./public -p 8000
uvx (from uv) is the
easiest path — it even fetches a matching Python for you. The piped servery.py is the
released package amalgamated into one auditable file (pure stdlib). It runs code, so
inspect it first if you like (curl -fsSL <url> | less), pin a version
(…/releases/download/v1.6.0/servery.py), or grab the servery.pyz zipapp — both are
attached to every release.
Serve or share a directory over HTTP with the niceties people expect from tools like
miniserve or npx serve — rich sortable
directory listings, file upload, HTTP Basic Auth, HTTPS, range/resumable downloads,
on-the-fly archive download, even HTTP/2 and opt-in HTTP/3 — while the core
depends on nothing but the Python standard library.
$ servery # serve the current directory on http://127.0.0.1:8000
$ python -m servery ./public --port 9000
$ servery --upload --auth me:secret # password-protected drop box
$ servery --tls-cert cert.pem --tls-key key.pem --http2 # HTTPS + HTTP/2
$ servery ./docs --preview --metadata # render Markdown/code; index by title
Features
- Rich directory listings — sizes, modified times, directories first, fully escaped; sortable
columns (
?C=&O=, Apache convention), a?q=name filter, a?ext=file-type facet, a breadcrumb trail, per-type icons, relative timestamps, inline size bars, an aggregate metrics strip, a pure-SVG modification timeline, per-file download (?download=1), pagination, and a cookie-backed light/dark/auto theme — all server-side with no JavaScript. - File preview, opt-in —
--previewadds?preview=1: Markdown rendered to HTML, source code syntax-highlighted (Python via the stdlib's owntokenize, plus ~35 more — C/Rust/Go/JS/TS, LaTeX, SQL, YAML, HTML…), notebooks, JSON re-indented, CSV as a table, and images/audio/video inline.?preview=sourcereads any of them as highlighted source instead. Zero dependencies, no JavaScript, raw HTML always escaped. - Document metadata, opt-in —
--metadatareads inside files (bounded, nothing executed): front matter, Python docstrings +__version__, LaTeX\title{}, HTML<title>, PEP 621 fields, image dimensions, ID3, PDF Info. Adds a Title/Author column,?meta=author:ada/?meta=tag:draftfilters, title/author sorting, and?metadata=1JSON for a file or a whole directory (curl … | jq). - Correct downloads — RFC 9110
Range/206(resumable), strongETags, the full conditional-request ladder (If-None-Match/If-Modified-Since/If-Range→304/412), and zero-copysendfile. Opt-in RFC 9530 integrity digests — sendWant-Repr-Digestand get aRepr-Digest: sha-256=:…:over the whole file (even for a ranged/parallel download), a standardized replacement for a.sha256sidecar. - HTTPS — bring your own cert (
--tls-cert/--tls-key) or get an ad-hoc self-signed one with--tls-self-signed(zero-dependency, generated at startup — handy for a quick encrypted LAN share). ALPN + HSTS over TLS. - Automatic HTTPS (Let's Encrypt), zero-dependency —
--acme example.comobtains a browser-trusted certificate over ACME HTTP-01 (RFC 8555) and serves it. The JWS + CSR are built from servery's own RSA/DER primitives, so trusted auto-TLS needs no third-party crypto. Staging by default;--acme-productionfor real certs. - HTTP Basic Auth — single credential or a pre-hashed
user:sha256:…, constant-time compare. - Upload — opt-in
--upload, streamingmultipart/form-data(nocgi), atomic writes, bounded size, overwrite off by default. Resumable uploads too:PUTwithContent-Rangeappends a chunk and survives an interrupted transfer (the Google/S3 convention — works from barecurl,308+Rangeto resume). Same-target writes are serialized across upload, WebDAV, archive extraction, and TFTP. - Archive download — stream any directory as
tar.gzorzip(?archive=tar.gz), or tick the per-entry checkboxes and zip just the selected files/folders — all with no JavaScript.--max-archive-streamsadds per-worker admission before headers. - Access logging —
--access-log PATHwrites HTTP/1 file-serving responses in Common Log Format (clf/combined/json). Synchronous writes remain the measured default; setting--access-log-queueopts into a count- and byte-bounded batched writer. Backpressure versus drop, batching, and drain are configurable; the diagnostic stderr log remains separate. - WebDAV —
--davlets macOS Finder / Windows Explorer / Linux mount the share as a network drive (read-only);--dav-writeadds write (PUT/DELETE/MKCOL/MOVE/COPY). Pure stdlib, same path-safety as everything else; writes honor--auth. Writable DAV defaults to enforced exclusive locks, with explicitclass1and compatibility modes. - CORS, SPA fallback, cache control, security headers —
--cors,--spa,--cache, withnosniffeverywhere and a scoped CSP on generated pages (off via--no-security-headers). - On-the-fly compression — text-like responses (and the directory listing) are compressed
when the client accepts it (RFC 9110: q-value negotiation,
Vary, distinct ETag, ranges served identity). Preferszstdwhen the interpreter has it (Python 3.14+,compression.zstd) and the client accepts it, elsegzip. Already-compressed media is left alone (keepssendfile). Off via--no-compress. - Frictionless LAN sharing —
--qrprints a scannable QR of the LAN URL (pure-stdlib QR encoder, with auto-detected LAN IP even on a0.0.0.0bind), and--discoverableadvertises over mDNS/DNS-SD so the share shows up in Finder / file managers and at<host>.local. - HTTP/2 —
--http2enables a pure-stdlib HTTP/2 server (ALPNh2over TLS, or h2c prior-knowledge). The HPACK and frame codecs are implemented against the RFCs with no third-party package. - HTTP/3 — optional, via
pip install servery[http3](theaioquicQUIC stack); the core stays zero-dependency. It runs beside the TCP fallback and advertises its live UDP port viaAlt-Svc; large HTTP/2/3 files stream above a configurable buffering threshold. - TFTP — opt-in
--tftpalso serves the directory over TFTP (UDP, RFC 1350) for PXE boot and network gear, withblksize/tsize/timeoutoptions; read-only unless--tftp-write. Pure stdlib. No auth or encryption — trusted LAN / lab networks only (off by default). - Safe by default — binds
127.0.0.1, path-traversal + symlink-escape protection, a default socket timeout, a 256-connection/session ceiling, distinct HTTP/2/TFTP budgets, optional HTTP/1 idle/request-count reuse limits, an opt-in cross-transport stalled-write deadline, and loud warnings when you expose it or run auth without TLS. - Free-threading ready — runs under the no-GIL builds (3.13t/3.14t); immutable config, no module-level mutable state.
Install
With uv (recommended — manages Python for you):
uvx servery # run ad-hoc, nothing installed
uv tool install servery # …or install the `servery` command
Or with pip:
pip install servery # core: zero dependencies
pip install servery[http3] # optional HTTP/3 (aioquic)
Python 3.13+ (free-threaded builds supported).
Library use
from servery import Config, serve
serve(Config.create("./public", host="127.0.0.1", port=8000))
A note on dependencies
The core has zero third-party runtime dependencies — enforced by a CI gate that fails the
build if the wheel ever declares one. HTTP/3 is the single, opt-in exception: it requires a real
QUIC + crypto stack the standard library does not provide, so it lives behind the
servery[http3] extra and never burdens the core. (For the curious, servery._oscrypto proves
the standard library can reach AEAD crypto with zero PyPI dependencies via ctypes → the OS
OpenSSL — the foundation a future native HTTP/3 could build on.)
It lives in the file-server lane (share a folder), not the web-framework lane — there is no routing or app-building here. It is a dev / LAN / ad-hoc sharing tool, not a hardened public-internet server.
Documentation
📖 Full documentation site → mjbommar.github.io/servery — getting started, task-oriented guides with examples, recipes, how to extend it, and a full CLI reference.
The deep-dive design docs (also rendered on the site):
| Document | What it covers |
|---|---|
| docs/VISION.md | The gap, positioning, target users, non-goals |
| docs/PRINCIPLES.md | Zero-dependency mandate and the scope rubric |
| docs/TRANSPORTS.md | The tiered HTTP/1.1→2→3 transport model and crypto policy |
| docs/STANDARDS.md | RFC 9110/9111/9112 compliance map (MUST/SHOULD + tests) |
| docs/ARCHITECTURE.md | Module layout, request lifecycle, security design |
| docs/BEST-PRACTICES.md | 2026 stdlib-only implementation best practices |
| docs/REQUIREMENTS.md | Testable requirements and the CLI surface |
| docs/ROADMAP.md | How it was built, milestone by milestone |
| docs/DYNAMIC.md | Phased roadmap for opt-in CGI / WSGI / ASGI (stdlib-only) |
| docs/REFERENCES.md | Prior art and stdlib feasibility map |
Development
Requires uv. All gates run locally exactly as in CI:
uv sync # dev tooling (never ships in the wheel)
uv run pre-commit install # local commit gates
make check # lint (ruff) + type (ty) + security (bandit) + tests
make build # build + zero-dependency gate
CI runs the suite on Linux/macOS/Windows × CPython 3.13/3.14, the free-threaded 3.13t/3.14t builds, and 3.15. See CONTRIBUTING.md.
A reproducible per-transport benchmark suite (pytest-benchmark) lives in benchmarks/:
uv run --group bench pytest benchmarks/ # HTTP/1.1, TLS, HTTP/2, WSGI, CGI, ASGI, proxy, …
See BENCHMARKS.md for reference numbers, the HTTP/3 case, the regression workflow, and the controlled static/WSGI/ASGI comparisons against nginx, Caddy, Gunicorn, and Uvicorn.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file servery-1.7.0.tar.gz.
File metadata
- Download URL: servery-1.7.0.tar.gz
- Upload date:
- Size: 824.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25133fd29e1bd724c51f14b44e276536a9cf10e4369a737e74ae82a21fc98305
|
|
| MD5 |
ad04beaa08239b17b2ea5580fe34d25d
|
|
| BLAKE2b-256 |
29e8e8d8afca5c9b5b7056d29e8a916076a936739db0fee53d8a938fd43aae4a
|
Provenance
The following attestation bundles were made for servery-1.7.0.tar.gz:
Publisher:
release.yml on mjbommar/servery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servery-1.7.0.tar.gz -
Subject digest:
25133fd29e1bd724c51f14b44e276536a9cf10e4369a737e74ae82a21fc98305 - Sigstore transparency entry: 2438110783
- Sigstore integration time:
-
Permalink:
mjbommar/servery@2c40ad54eaf976eef056d84f0e3aa74ec469be6e -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/mjbommar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2c40ad54eaf976eef056d84f0e3aa74ec469be6e -
Trigger Event:
push
-
Statement type:
File details
Details for the file servery-1.7.0-py3-none-any.whl.
File metadata
- Download URL: servery-1.7.0-py3-none-any.whl
- Upload date:
- Size: 238.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8cb9ad80c9d91595b55d47b82ebc85896258951d97c485b0572b81bcf1a41aa
|
|
| MD5 |
fb5ec37efb6bc4b44114bcd907239bce
|
|
| BLAKE2b-256 |
d34c5e85af37ec0464d4462f2425fc24751adbccedccab0dacf18c5950ea8a43
|
Provenance
The following attestation bundles were made for servery-1.7.0-py3-none-any.whl:
Publisher:
release.yml on mjbommar/servery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servery-1.7.0-py3-none-any.whl -
Subject digest:
c8cb9ad80c9d91595b55d47b82ebc85896258951d97c485b0572b81bcf1a41aa - Sigstore transparency entry: 2438110812
- Sigstore integration time:
-
Permalink:
mjbommar/servery@2c40ad54eaf976eef056d84f0e3aa74ec469be6e -
Branch / Tag:
refs/tags/v1.7.0 - Owner: https://github.com/mjbommar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2c40ad54eaf976eef056d84f0e3aa74ec469be6e -
Trigger Event:
push
-
Statement type: