Skip to content(if available)orjump to list(if available)

Simple Web Server

Simple Web Server

126 comments

·April 14, 2025

elcritch

Cool project! Setting up a quick local HTML server can be annoying.

Alas it looks like it's web/electron based. :/ Downloading it and yep, 443.8 MB on MacOS. The Linux one is a bit better at 183.3 MB.

Electron really should get a kickback from disk manufacturers! ;)

Shameless plug, I've been working on a HTML inspired lightweight UI toolkit because I'm convinced we can make these sort of apps and they should only be ~10-20 MB [1] with nice syntax, animation, theming, etc. I'm finally making a suite of widgets. Maybe I can make a basic clone of this! Bet I could get in < 10MB. :)

1: https://github.com/elcritch/figuro

tyzoid

My usual go-to for a quick static server is:

python -m http.server

But variations exist for a lot of languages. Php has one built-in too

zikduruqe

Don't forget bash.

    #!/bin/bash

    while :; do nc -l 80 < index.html; done

xmodem

I was about to down-vote you, but that would be unfair, as this has roughly the typical level of correctness of most bash scripts.

vFunct

This is hilarious

blacksmith_tb

There are some nice compilations of those, like

https://gist.github.com/willurd/5720255

red_admiral

Python is my go-to method too, altough the config file approach from this project looks exciting.

(I'm sure if I dug in the http.server documentation I could find all those options too.)

nodesocket

I use python for serving my local static site development with this custom little bash wrapper script I wrote:

    #!/usr/bin/env bash
    set -e; [[ $TRACE ]] && set -x

    port=8080
    dir="."

    if [[ "$1" == "-h" || "$1" == "--help" ]]; then
        echo "usage: http-server [PORT] [DIRECTORY]"
        echo "  PORT      Port to listen on (default: 8080)"
        echo "  DIRECTORY Directory to serve (default: .)"
        exit 0
    fi

    if [ -n "$1" ]; then
        port=$1
    fi

    if [[ -n "$2" ]]; then
        dir=$2
    fi

    python3 -m http.server --directory "$dir" --protocol HTTP/1.1 "$port"

Y_Y

From the people who brought you Useless Use of Cat, here's our newest innovation: Useless Use of Bash!

That whole script could just be the last line! Maybe you could add defaults like

    "${port:-8080}"

shakna

Random tangent: It appears that most of Electron's funding is actually the German government.

The Sovereign Tech Agency, under the Federal Ministry for Economic Affairs and Climate Action, fund OpenJS, specifically for improving the state of open source in JavaScript.

Electron is now part of OpenJS.

Y_Y

Is wasting cycles considered "climate action" now?

lmz

It's an action alright. The direction, however...

netsharc

I wonder if I can get an LLM to act as a webserver, and connect it to a TCP port...

8-prime

I like and understand the paradigm of using web technologies to build GUI apps. I have yet to find any desktop framework that even comes close to the DX of using web tech.

I recently explored both Tauri [1] and Wails [2]. Especially Wails is lots of fun. The simplicity of go paired with the fast iteration I get from using React just feels awesome. And the final application is ~10 MB in size!

[1] https://v2.tauri.app/ [2] https://wails.io/

onli

Did you try Flutter? That one worked for me at least as well as using the web approach. Definitely from a DX side.

8-prime

I have tried Flutter and liked it for mobile development. Maybe I should give it a shot for desktop. Though I believe those that dislike Electron and the likes for not being native would also have a bone to pick with Flutter.

brulard

With flutter you give up all the standard web components, accessibility defaults etc. If you don't mind, then it's definitely an option.

fake-name

OTOH, I have yet to see any web framework that comes even close to the UX of native tech.

It's almost as if web crap is optimizing for developer experience at the expense of users.

8-prime

I have thought about this and I'm not sure that Electron really is to blame here. It makes building an application accessibile, which means that there will be lots of apps built with it, many of which won't be any good.

Just like many native apps will also be horrible in terms of UX. Good apps are good. And I believe that it's entire possible to build an amazing app with Electron.

Although not everyone might agree, IMO VSCode is a great example of that.

brulard

In SW development you need to make compromises. You can not have all of: quality, performance, memory/cpu/disk efficiency, security, development speed, low effort, cross-platform app, accessibility, all the business features, etc. Which corners would you cut? You mention native tech but you seem to ignore the enormous tax in development time/knowledge, etc. So let's say you aim for the best UX. Are you ready to sacrifice business features, or any other aspect? I'm not advocating for crappy UI/UX, but I would rather use an electron app that has all the features I need, than native app that doesn't.

chabska

Could you list out your native GUI stack, for Windows, OSX and Linux?

jasonlotito

You say that, and I hear the arguments, but numbers don't lie.

https://x.com/daniel_nguyenx/status/1734495508746702936

Further discussion can be found here: https://www.macstories.net/linked/is-electron-really-that-ba... and in the linked video.

You say at the expense of users. But when even Apple does't go all native, it's telling.

thomas-mc-work

> Alas it looks like it's web/electron based.

For me this contradicts the claim of being simple. As opposed to this:

    python -m http.server 8080

drcongo

I use miniserve (< 5mb) just because I can never remember the python incantation. https://github.com/svenstaro/miniserve

1vuio0pswjnm7

"Bet I could get in < 10MB."

I use one that is 99K static binary.

Even the full-featured TLS/HTTPS forward proxy I use, linked with bloated OpenSSL, is still less than 10MB static binary: 8.7MB. When linked to WolfSSL it's only 4.6MB static binary. The proxy can serve small, static HTML pages, preloading them into memory at startup.

elcritch

For a GUI app though?

sgarland

WinRAR is 3.7 MB.

cosmotic

Funny the bulk of the server is vestigial client code.

elcritch

Figures, though I suspect that code only makes up a fraction of the binary size. Assuming it’s electron most of that bulk is chromium bits.

tredre3

Figuro is like Sciter but for Nim?

elcritch

Sorta! It didn’t start out that way but I’ve been building more from HTML overtime but keeping it fast and lightweight. I’ve cherry picked a subset of HTML like CSS grids which add a lot of layout power without tons of normal HTML hacks.

I want to try adding a JavaScript runtime with simple DOM built on Figuro nodes instead. But there’s some issues with Nim’s memory management and QuickJs.

nickpsecurity

lighttpd is awesome for a quick, local server on Ubuntu. One command installs it. You tell the firewall to allow it. Then, just move your files into the directory. Use a CDN, like BunnyCDN, for HTTPS and caching.

It's not only easy: it runs (or ran) huge sites in production.

vince14

Because projects like these were missing back then, I got creative with nginx and do not need any config changes to serve new projects:

  server {
    listen 80;
    server_name ~^(?<sub>\w+)(\.|-)(?<port>\d+).*; # projectx-20201-127-0-0-1.nip.io
    root sites/$sub/public_html;
    try_files $uri @backend;
    location @backend {
      proxy_pass http://127.0.0.1:$port;
      access_log logs/$sub.access;
    }
  }
Configuration is done via the domain name like projectx-20205-127-0-0-1.nip.io which specifies the directory and port.

All you need to do is create a junction (mklink /J domain folder_path). This maps the domain to a folder.

gizmo

Am I reading this wrong or does this almost open up any server bound to localhost to the outside?

I think proxy_pass will forward traffic even when the root and try_files directives fail because the junction/symlink don't exist? And "listen 80" binds on all interfaces doesn't it, not just on localhost?

Is this clever? Sure. But this is also the thing you forget about in 6 months and then when you install any app that has a localhost web management interface (like syncthing) you've accidentally exposed your entire computer including your ssh keys to the internet.

merpkz

Nothing is preventing you to add an IP whitelist and/or basic auth to same configuration. That is what I do to all my nginx configurations to be extra careful, so nothing slips by accident.

lmz

Will just any request even pass the host matching?

merpkz

I got something similar running with nginx myself with purpose of getting access to my internal services from outside. The main idea here is that internal services are not on same machine this nginx is running on, so it will pass around to needed server in internal network. It goes like this:

  server_name ~^(?<service>(?:lubelogger|wiki|kibana|zabbix|mail|grafana|git|books|zm))\.domain\.example$;
  location / {
        resolver 127.0.0.1;
        include proxy.conf;
        proxy_set_header Authorization "";
        proxy_set_header Host $service.internal;
        proxy_set_header Origin http://$service.internal;
        proxy_redirect http://$proxy_host/ /;
        proxy_pass http://$service.internal;
  }
Basically any regex matched subdomain is extracted and resolved as $service.internal and proxy passed to it. For this to work, of course any new service has to be registered in internal DNS. Adding whitelisted IPs and basic auth is also a good idea ( which I have, just removed from example ).

miroljub

That's why I switched to Caddy for most of my needs. I create one Caddy server template, and then instantiate it as a new host with one line per server.

Hyperlisk

This looks nice with a friendly UI. I've been very happy with Caddy[1], but this seems like something I might recommend to someone that is new to the web environment.

[1] https://caddyserver.com/docs/quick-starts/static-files

lukan

Or someone who has chromeOS not in dev mode.

I use SimpleWebServer there since 6 years or something and it just works.

overfeed

Caddy works just fine in ChromeOS' OOTB Linux VM. Crostini has chipped away at most dev mode use-cases.

nipperkinfeet

Electron? It's unfortunate how bad programming has become. Over 100MB for a program that could be written with native code under 1MB.

8-prime

I think the popularity of Electron is merely a testament to the fact that native UI libraries need to step up their game in terms of approachability.

LeonM

> native UI libraries need to step up their game in terms of approachability.

Gnome does this, you can develop apps in Typescript.

But, they started to migrate some of their own apps to Typescript and immediately received backlash from the community [0]. Although granted, the Phoronix forums can be quite toxic.

My observation is that there is just a big disconnect between younger devs who just want to get the job done, and the more old-school community that care about resource efficients. Both are good intentions that I can understand, but they clash badly. This unfortunately hinders progress on this point.

[0] https://www.phoronix.com/forums/forum/phoronix/latest-phoron...

8-prime

Cool, I didn't know that.

I agree that this is, at least often, a case of where your roots lie. Whats most shocking to me is that the likes of Apple and Mircosoft don't seem to be interested in/capable of building an actually good framework.

I feel like Microsoft tried with .NET Maui, but that really isn't a viable choice if you go by developer sentiment.

pjmlp

It is more a side effect of JavaScript bootcamp programming wihtout learning anything else.

I have been coding since 1986, nowadays most of the UIs I get paid to work on are Web based, yet when I want to have fun in side projects I only code for native UIs, if a GUI is needed.

Want to code like VB and Delphi? Plenty of options available, and yes they do scalable layouts, just like they used to do already back in the 1990's for anyone that actually bothered to read the programming manuals.

red_admiral

Yes, I've dabbled in gtk, wxWidgets and several other systems. All of them are meh.

The big player these days seems to be web-based (Electron and friends), though the JVM stack with a native theme for Win/Mac is certainly usable in an environment where you can rely on Java being around.

I think the best option would be some kind of cross-application client-side HTML etc. renderer that apps could use for their user interaction. We could call it a "browser". That avoids the problem of 10 copies of the whole electron stack for 10 apps.

Years ago, Microsoft had their own version of this called HTA (HTml Application) where you could delegate UI to the built-in browser (IE) and get native-looking controls. Something like that but cross-platfom would be nice, especially as one motivation for this project is that Chrome apps are no longer supported so "Web Server for Chrome" is going away. So the "like electron but most of the overhead is handled by Chrome" option is actively being discontinued.

brulard

> I think the best option would be some kind of cross-application client-side HTML etc...

I think Tauri is trying to go for this - a web app without the whole chromium bundled, but using a native web view

0x073

Funny to ship a web browser for a webserver.

nottorp

I suppose that's why people run multi socket machines for "home labs".

dheera

The real problem is that frontend work with anything else is such a pain in the ass.

You want to write separate versions for MacOS, Linux, and Windows Visual .NET#++ and maintain 3 separate source trees in 3 languages and sync all their features and deal with every bug 3 times?

flessner

It looks nice and friendly, but for developers I can recommend exploring caddy[1] or nginx[2]. It's a useful technology to have worked with, even if they're ultimately only used for proxying analytics.

[1] https://caddyserver.com/ [2] https://nginx.org/

ozim

Second that, I don't really see reason not to run proper web server actually especially if one does web development and would use it for multiple projects anyway.

dpz

em-bee

a more comprehensive list of one liner webservers is here: https://github.com/imgarylai/awesome-webservers

p4bl0

I was going to mention busybox httpd and php -S, but this list has them already :).

bangaladore

Should support self-signed HTTPs ideally. IIRC there a quite a few (some?) web features that do not function unless the page is served over HTTPs.

That would certainly make this more useful than `python3 -m http.server`.

zamadatix

It does. It also includes a dozen other things beyond what that one liner would do. Keep in mind, if it fits with what you're trying to test/how you're trying to develop, just doing things on http://localhost will be treated as a secure origin in most browsers these days.

There does seem to be a weird limitation that you can't enable both HTTP and HTTPS on the same port for some reason. That should be easy enough to code a fix for though.

bangaladore

> HTTP and HTTPS on the same port

Do any real web servers support this?

Its the same transport (TCP assuming something like HTTP 1.1) and trying to mix HTTP and HTTPS seems like a difficult thing to do correctly and securely.

dextercd

NGINX detects attempts to use http for server blocks configured to handle https traffic and returns an unencrypted http error: "400 The plain HTTP request was sent to HTTPS port".

Doing anything other than disconnecting or returning an error seems like a bad idea though.

woleium

You can in fact run http, https (and ssh and many others) on the same port with SSLH (its in debian repos) SSLH will forward incoming connections based on the protocol detected in the initial packets. Probes for HTTP, TLS/SSL (including SNI and ALPN), SSH, OpenVPN, tinc, XMPP, SOCKS5, are implemented, and any other protocol that can be tested using a regular expression, can be recognised

https://github.com/yrutschle/sslh

p4bl0

Theoretically it would be feasible with something like STARTTLS that allows to upgrade a connection (part of SMTP and maybe IMAP) but browsers do not support this as it is not part of standard HTTP.

zamadatix

I think what I had seen before was replacing the http variant of the "bad request" page with a redirect to the HTTPS base URL something akin to https://serverfault.com/a/1063031. Looking at it now this is probably more "hacky" than it'd be worth and, as you note, probably comes with some security risks (though for a local development app like this maybe that's acceptable just as using plain HTTP otherwise is), so it does sense that's not an included feature after all.

rhardih

This particular shortcoming of is why I wrote https://github.com/rhardih/serve back when.

These days just using `caddy` might be easier though.

smusamashah

I use voidtools Everything on windows for instant file lookup. It has an Http server built in. Whenever browser complains about a feature only available via webserver url, not local file, it comes handy. Open everything webserver, enter name of the file and click.

starik36

I've been using Everything forever and never knew about this feature. Thanks!

danpalmer

Tailscale does this, you can serve a port on your Tailnet, or you can serve a directory of files, or you can expose it to the internet. Comes with HTTPS. It's pretty neat.

https://tailscale.com/kb/1312/serve

nasso_dev

For those who have Rust, I like miniserve[1]:

    cargo install --locked miniserve
    miniserve path/to/directory
[1]: https://github.com/svenstaro/miniserve

Svenstaro

Thanks for posting miniserve <3

kakuri

npx http-server (keep the "r" at the end, it's more up-to-date than the http-serve package)

https://github.com/http-party/http-server

null

[deleted]

Ingon

For a second there, I read it as static web server [1], which is actually pretty cool itself

1: https://static-web-server.net/