Self-hosted service
svenstaro/miniserve avatar
svenstaro/miniserve

miniserve: a single-binary HTTP file server for when you just need to share a directory

🌟 For when you really just want to serve some files over HTTP right now!

7,881 stars397 forksRustMIT

At a glance

What is it?
miniserve is a Rust CLI that serves files and directories over HTTP from one binary. It is built for the quick share, not for running a permanent file portal, and that distinction decides most of its limits.
Who is it for?
Adopt miniserve when you need to hand a directory to someone over HTTP in one command, on a machine where installing nothing is the point. Do not adopt it as a multi-user file portal with per-user permissions, since the README documents only a single auth credential set and no account model.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What miniserve solves, and who it is actually for

The README opens with the sentence that defines the project: "For when you really just want to serve some files over HTTP right now!" That is a narrower goal than it sounds. miniserve is not a file manager you host for a team. It is a replacement for the moment when you would otherwise run `python3 -m http.server` and then discover you need authentication, a QR code, or a folder download.

The people this fits are developers moving a build artifact between machines, someone handing a directory of photos to a phone on the same LAN, or a CI job that needs to expose a report for a few minutes. The README even gives the smartphone case directly: `miniserve -u -m image -q`, where `--media-type` sends a hint so that a mobile browser such as Firefox on Android offers the camera app.

The people it does not fit are teams that want accounts, quotas, audit logs, or a web UI for administration. Nothing in the README describes a user database, roles, or per-path permissions. The auth options take one username and one password, or a file of logins separated by new lines. That is a door lock, not an access control system.

How the serving model works: one process, one path, actix-web underneath

miniserve is a single Rust binary built on actix-web, with `actix-files` handling static file responses and `dav-server` with the `actix-compat` feature providing WebDAV. The release profile in Cargo.toml sets `lto = true`, `codegen-units = 1`, `opt-level = 'z'`, `panic = "abort"` and `strip = true`, which explains why the distributed binary is small enough to be described as a drop-in with no extra dependencies.

The data flow is deliberately flat. You give it one path, or a single file, and it maps the request path onto that root. Directory listings are generated when there is no index file; `--index` swaps the listing for a named file such as `index.html`. `--spa` goes further and forwards non-existent paths to the SPA router, which is the behaviour a client-side routed app needs.

Two details show how much of the work is done at the HTTP layer rather than in an application layer. Custom headers are inserted with `--header`, and the README notes that if a header is already set or previously inserted, it will not be overwritten. Range requests are supported, so partial downloads and resumable transfers work. A healthcheck route lives at `/__miniserve_internal/healthcheck`, which is the one endpoint you would point a container probe at.

Installing miniserve and serving a directory with auth and uploads

The README does not give a package-manager install line. The project's stated model is to grab the binary from the releases page, and the Makefile shows how the maintainers build it: `cargo build --release` for a local build, or cross-compiled targets such as `x86_64-unknown-linux-musl` for Linux. If you have a Rust toolchain, the source build is the path the repository itself uses.

bash
cargo build --release

After that build finishes, the binary is at `target/release/miniserve`. The simplest real use is serving a directory on the default port 8080.

bash
miniserve linux-distro-collection/

The README shows this exact form. You should see a directory listing in the browser, with correct MIME types handled for you.

Adding a password is one flag. The README's example uses the plaintext form, and there is a hashed variant using SHA-256.

bash
miniserve --auth joe:123 unreleased-linux-distros/

For uploads, the README is explicit that you need `--` to disambiguate the argument to `-u`, because `-u` can also take a path. Without a path, uploads are possible to every path.

bash
miniserve -u -- .

From another terminal, the matching curl form sends a multipart field named `path`, and the README shows the target directory in the query string.

bash
curl -F "path=@$FILE" http://localhost:8080/upload\?path\=/

One consequence the README spells out: because of that ambiguity you cannot combine flags as `-uv` when `-u` is used. You need `-u -v`.

Where miniserve is the wrong tool

The upload path is the sharpest limitation. The README describes `--temp-directory` as the place where uploads are written before being moved into position, and warns that it is wise to make sure that directory is written to disk and not into memory. That is a direct hint about the failure mode: large uploads buffered in a RAM-backed temp directory can exhaust memory before the move happens. If you enable uploads on a host with a small tmpfs, you have configured a way to take the process down.

The second limitation is the missing multi-user model. A file of logins gives you several credentials, but the README describes nothing about scoping them to paths. Anyone who can authenticate sees the whole served root. For a shared drop box that is probably fine. For anything resembling a departmental file server it is not.

TLS is qualified. The README lists TLS as a feature "(for supported architectures)" and the Cargo.toml marks `rustls` and `rustls-pemfile` as optional dependencies. If you need HTTPS and your target architecture is not among the supported ones, you are expected to terminate TLS elsewhere. The README's own note about reaching an A+ rating at the SSL Labs test says that fullchain TLS and HSTS together are necessary, which means the plain `--tls-cert` and `--tls-key` pair alone is not the hardened configuration.

Finally, miniserve has no persistence layer. There is no database, no state beyond the filesystem, and no documented rollback of an upload. If you need history or recovery, this is not the component for it.

How miniserve differs from FileBrowser and from a plain web server

FileBrowser is the comparison people search for, and the difference is architectural rather than cosmetic. FileBrowser is a file management application with its own user accounts, its own database of users and settings, and a persistent web UI you log into. miniserve has none of that. It reads a path, serves it, and exits when you stop it. The trade is that FileBrowser can answer "who uploaded this and when" while miniserve cannot, and miniserve can be started in one command on a machine with nothing installed while FileBrowser cannot.

Against a general web server such as nginx or Caddy, the difference is the configuration surface. A static web server is built to be configured once and left running, with virtual hosts, rewrites and a config file. miniserve is built to be typed. Flags like `--random-route`, which the README shows generating a random 6-hexdigit URL such as `http://192.168.0.1/c789b6`, exist because the intended lifetime of an instance is short. You do not put a random route on a permanent service; you put it on a share you will kill in an hour.

The `--spa` flag sits between the two. It makes miniserve usable as the preview server for a client-side routed app, which is the one case where the tool outlives a single session.

Maintenance, releases and what the MIT licence lets you do

The repository is not archived, and the last push was on 2026-09-18, four days before this writing. Releases are frequent and numbered: v0.33.0 on 2026-02-16, then v0.34.0 and v0.35.0 within a day of each other in April 2026. That cadence matters for upgrades, because a CLI with this many flags can change behaviour between minor versions. The CHANGELOG.md at the repository root is the file to read before moving a pinned version. The Cargo.toml also pins `edition = "2024"`, so building from source requires a toolchain recent enough to accept that edition.

The licence is MIT, which is permissive: you can use, modify and redistribute it, including in closed products, provided the copyright notice and permission notice are kept. This article is not legal advice, and if you redistribute the binary inside a product you should read the LICENSE file at the repository root rather than take a summary.

One packaging detail worth knowing before you containerise it: the repository carries both `Containerfile` and `Containerfile.alpine`, so there are two documented image builds with different base images. The Docker Hub badge in the README points at `svenstaro/miniserve`, which is where the published images live.

Editorial conclusion

Adopt miniserve when you need to hand a directory to someone over HTTP in one command, on a machine where installing nothing is the point. Do not adopt it as a multi-user file portal with per-user permissions, since the README documents only a single auth credential set and no account model. Before relying on it, verify that your target architecture has TLS support (the README qualifies TLS as available for supported architectures), decide whether uploads are enabled at all, and check the CHANGELOG for the upgrade cost between v0.33.0 and v0.35.0.

Frequently asked questions

How do I install miniserve?

The README does not document a package-manager install. The project's stated model is to grab the binary, and the Makefile shows a source build with `cargo build --release`, which produces `target/release/miniserve`.

How do I use miniserve to serve a directory?

Pass the path as the argument, for example `miniserve linux-distro-collection/`, and it serves that directory on port 8080. Add `--index test.html` to serve a specific file instead of a directory listing.

Can I upload files to miniserve?

Yes, with `-u`. The README notes you must use `--` to disambiguate the argument to `-u`, and that because of this you cannot combine flags as `-uv`; use `-u -v` instead.

Does miniserve support TLS?

It does, through `--tls-cert` and `--tls-key`, but the README qualifies TLS as available for supported architectures. The README also notes that fullchain TLS plus an HSTS header is what is needed for an A+ rating at the SSL Labs test.

Does miniserve support multiple user accounts?

The README documents `--auth` for a single username and password, and `--auth-file` for a file of logins separated by new lines. It describes no per-path permissions or account roles.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. svenstaro/miniserve on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/svenstaro-miniserve.svg)](https://hysenlabs.com/projects/svenstaro-miniserve)