Vision & goals¶
A batteries-included
python -m http.server.
servery is a zero-dependency, pure-Python (standard-library-only) HTTP file
server. It serves a directory over HTTP with the niceties people actually expect
in 2026 — a rich, sortable directory listing, optional basic auth, file upload,
and HTTPS — while keeping the single property that makes http.server so
beloved: nothing to install but Python itself.
You can run it three ways: python -m servery, a servery console script, or
import servery from your own code. It is pip install servery away, and it
has zero third-party dependencies, forever.
1. Problem statement¶
Everyone who has Python reaches for the same reflex when they need to share a folder, hand a colleague a build artifact, or sanity-check a static site:
It is glorious because it is already there. But the moment you use it for real work, the gaps show:
- The directory listing (
SimpleHTTPRequestHandler.list_directory) is a bare<ul>of links. No file sizes, no modification dates, no sorting, no search. You cannot tell a 2 KB file from a 2 GB one without clicking. - No authentication. Anyone who can reach the port can read everything.
- No upload. It is download-only; receiving a file means firing up something else.
- No HTTPS without hand-rolling an
sslcontext and wiring it into the server yourself. - No range-request support. As of CPython today, stdlib
http.serverdoes not honor theRangeheader, so large-file resume and media seeking do not work out of the box (see the long-standing CPython issue tracking this). - It carries a permanent, prominent "not for production use" warning — and rightly so.
So people leave Python. They install a Rust binary (miniserve), run a Node
package (npx serve, http-server), or pull in a Flask-based tool (updog).
Each solves the listing/auth/upload problem — by adding a runtime, a toolchain,
or a dependency tree that the original one-liner never had.
2. The gap, and the evidence¶
The polished folder-serving tools fall into two camps, and none of them is both pure-Python and zero-dependency:
| Tool | Language / runtime | Zero deps? | Rich listing | Auth | Upload | HTTPS |
|---|---|---|---|---|---|---|
python -m http.server |
Python stdlib | ✅ | ❌ (plain <ul>) |
❌ | ❌ | ❌ (manual ssl) |
uploadserver (PyPI) |
Python, on stdlib | ✅* | ❌ (inherits plain listing) | basic | ✅ | ✅ |
tiny-http-server |
Python, on stdlib | ✅* | ❌ (inherits plain listing) | basic | ✅ | ✅ |
updog |
Python + Flask | ❌ | ✅ | basic | ✅ | ✅ |
| miniserve | Rust binary | ✅ (single binary) | ✅ | ✅ | ✅ | ✅ |
serve / http-server |
Node.js | ❌ (npm tree) | ✅ | partial | varies | ✅ |
* Pure-stdlib Python tools improve on auth/upload/TLS but inherit
http.server's plain, unsortable listing — they bolt features onto the
handler without replacing the listing UI.
The whitespace is precise:
No existing zero-dependency, pure-Python tool combines a rich sortable directory listing and basic auth and upload and HTTPS.
That is the exact spot servery occupies. We are not "another file server"; we are the Python-native one that finally has the listing the Rust tool has, without leaving the Python you already have installed.
3. Target users & use cases¶
servery is for people who have Python and a folder and a few minutes:
- Developers sharing build output / artifacts with a teammate over the LAN — who want sizes and dates in the listing and maybe a password.
- Anyone doing ad-hoc file transfer between two machines on a trusted network ("send me that file" / "grab this from me") — who needs upload, not just download.
- Static-site authors doing a quick local preview, who want range requests so media and large assets behave, and a listing that does not embarrass them.
- Sysadmins / ops on a locked-down host where installing a Rust binary or a Node toolchain is friction or forbidden, but Python is already present.
- People who write
python -m http.serverreflexively and have wished, once per use, that it were just a little nicer. That is the whole audience.
Representative one-liners we want to feel obvious:
servery # serve cwd, localhost, rich listing
servery ./dist --port 8080 # share a build directory
servery --auth alice:s3cret # gate it behind basic auth
servery --upload # let the other side send files back
servery --tls cert.pem key.pem # serve over HTTPS
4. Positioning: the file-server lane¶
There are two lanes for "small Python web tools," and servery lives firmly in one of them.
- The file-server lane (miniserve,
npx serve,http-server,uploadserver): point me at a folder and serve it. The mental model is a directory, files, and a browser. servery is here. - The web-framework lane (Flask, Bottle, the
quickservePyPI package): help me build an application with routes, handlers, templates, and request dispatch. servery is emphatically NOT here.
If a feature request starts with "I want to add an endpoint that…", it belongs
to the framework lane and is out of scope. If it starts with "when I'm serving a
folder, I wish it also…", it may belong to servery. Keeping this line crisp is
how servery stays small, finishable, and honestly describable as "a
batteries-included http.server" rather than "a worse Flask."
Compared to the neighbors:
- vs.
http.server— same spirit and same zero-install promise, but with the listing/auth/upload/TLS niceties stdlib will likely never grow. - vs.
uploadserver/tiny-http-server— same zero-dependency, pure-Python values, but we replace the listing instead of inheriting the plain one. - vs. miniserve — comparable feature set, but no Rust toolchain or binary to
distribute; you get it through
pipand it is hackable Python. - vs.
serve/updog— no Node runtime, no Flask, no dependency tree.
5. Non-goals (explicit)¶
servery will not:
- Be a web framework: no user-defined routes, no app object, no middleware system, no templating-for-your-app. (Internal templating for our own listing UI is fine; exposing one is not.)
- Be a production-grade public web server. Like
http.server, it is a dev / LAN / ad-hoc-sharing tool. We aim for safe defaults, not hardened internet-facing operation. Put it behind a real reverse proxy if you must expose it. - Issue publicly-trusted, auto-renewed TLS certificates (ACME / Let's
Encrypt). servery's TLS is Tier 0 — zero-dependency: user-provided
cert/key (
--tls-cert/--tls-key, with--tls-helpprinting anopensslrecipe) and an ad-hoc self-signed cert minted at startup in pure stdlib (--tls-self-signed, via_certgen.py) for opportunistic encryption on a dev box / LAN. Self-signed is not a trust anchor — clients see an "untrusted certificate" warning. Going past that to publicly-trusted, auto-renewed certs means the full ACME protocol against a public domain on :80/:443 — the production-public-web-server lane servery deliberately doesn't occupy. If it ever lands, it lands as an optionalservery[acme]extra (mirroring theservery[http3]precedent), never in the zero-dep core; it is not implemented. - Add third-party dependencies for any feature, ever. (See
PRINCIPLES.md.) - Render arbitrary Markdown. The stdlib has no Markdown parser, so README rendering is out of scope beyond, at most, escaped plaintext. We will not vendor a parser to get there.
- Be a WebDAV server, an S3 gateway, a media transcoder, a sync engine, or a general reverse proxy. Those are different products.
- Pursue multi-user accounts, roles, sessions, or a database. Auth is a single shared credential gate, nothing more.
6. What success looks like¶
Success is when a Python developer who today types python -m http.server types
python -m servery instead and never thinks about it again — because it
installed with nothing extra, started just as fast, bound somewhere safe by
default, and showed a listing with sizes, dates, and sorting that they did not
have to apologize for. When they need a password, an upload box, or HTTPS, those
are one flag away rather than a different tool away. servery wins not by being
the most powerful folder server in any language, but by being the one that
finally makes the Python you already have good enough that you stop reaching
past it — while never asking you to install a single thing beyond Python itself.