Skip to content

toggio/PocketWebServer

Repository files navigation

PocketWebServer

A portable, single-file web server for Windows. Drop the executable in a folder, put your files in www\, and serve them over HTTP or HTTPS — from a console window or as a native Windows service. No installer, no runtime, no dependencies.

Features

  • Truly portable — configuration, logs and content all live next to the executable. Copy the folder anywhere (USB stick included) and it works.
  • Windows service built in — install, start, stop and remove the service from the same executable. Talks to the Service Control Manager directly via the Win32 API; pywin32, NSSM or srvany are not needed.
  • Least privilege by default — the service runs under the NT SERVICE\PocketWebServer virtual account, not LocalSystem. File permissions are granted on install and revoked on removal.
  • HTTPS — point it to a PEM certificate and key and it serves TLS.
  • Optional CGI — run batch, PowerShell, Python or PHP scripts from a cgi-bin folder. Interpreters are detected automatically; custom ones can be mapped in the config.
  • Safe by default — no directory listing, path traversal blocked, CGI disabled unless requested, runaway scripts killed with their whole process tree.
  • Friendly CLI — colored output, plain-language errors instead of stack traces, --help with practical examples.

Quick start

:: Serve the www\ folder next to the exe on port 8080 (Ctrl+C to stop)
PocketWebServer.exe run

:: Serve an arbitrary folder on another port
PocketWebServer.exe run --port 9000 --root C:\path\to\site

run serves index.html for / and for any sub-folder that contains one; everything else maps to files inside the root. /healthz answers OK, handy for monitoring.

Running as a Windows service

Service commands need an elevated (Administrator) prompt:

:: Install: --auto starts at boot, --manual (default) starts on demand,
:: --start also starts it right now
PocketWebServer.exe install --root C:\path\to\site --auto --start

:: Day-to-day management
PocketWebServer.exe start
PocketWebServer.exe stop
PocketWebServer.exe restart
PocketWebServer.exe status
PocketWebServer.exe remove

The service runs under the NT SERVICE\PocketWebServer virtual account: a per-service identity that Windows creates and removes together with the service, with no password to manage. On install the account is granted read/execute on the program and content folders and write access to logs\; remove revokes the grants. Pass install --system if you specifically need the service to run as LocalSystem.

If the served folder lies outside the program folder, permissions are granted there as well — avoid pointing --root at system locations.

Note for onefile builds: the service account must be able to unpack the onefile bundle on first start. If the service will not start under the virtual account, reinstall with --system or build with --standalone.

Configuration

Settings are stored in config.json next to the executable, created by install or config. Command-line options always win over the file for a single run; with config they are saved permanently. A ready-to-edit template ships as config.example.json — copy it to config.json and adjust the paths if you prefer editing by hand.

:: Show current configuration and service state
PocketWebServer.exe config

:: Change something, then restart to apply
PocketWebServer.exe config --port 9000
PocketWebServer.exe restart
Key Default Meaning
host 0.0.0.0 Address to bind (0.0.0.0 = all interfaces)
port 8080 TCP port
root_dir www\ next to the exe Folder served over HTTP
log_path logs\server.log Rotating log file (2 MB × 5)
cert_file / key_file empty PEM pair; set both to enable HTTPS
cgi_enabled false Master switch for CGI
cgi_dir cgi-bin\ next to the exe Folder with CGI scripts
cgi_timeout 30 Seconds before a CGI script is killed
cgi_handlers {} Extra interpreters by extension (see CGI)

Invalid values in config.json fall back to their defaults instead of crashing the server.

HTTPS

PocketWebServer.exe run --port 8443 --cert C:\certs\cert.pem --key C:\certs\key.pem

Both files must be in PEM format (the usual fullchain.pem / privkey.pem pair works as-is). To go back to plain HTTP use config --http, or run --http to ignore the certificate for one run. For quick internal tests a self-signed certificate does the job:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"

CGI

Disabled by default. Enable it with --cgi (uses cgi-bin\ next to the executable, created if missing) or --cgi-dir C:\path\to\scripts; turn it off again with --no-cgi. While enabled, http://host:port/cgi-bin/<script> executes the script and returns its output; everything else is still served statically.

Supported script types:

  • .exe, .bat, .cmd — run natively, always available.
  • .ps1 — runs through PowerShell 7 (pwsh) when installed, otherwise the built-in Windows PowerShell 5.1.
  • .py — available when a Python interpreter is found in PATH.
  • .php — available when php-cgi.exe is found in PATH or in a common install folder.
  • Anything else can be mapped in config.json; use a list when the interpreter needs arguments:
"cgi_handlers": {
  ".pl": "C:\\perl\\bin\\perl.exe",
  ".rb": ["C:\\ruby\\bin\\ruby.exe", "-W0"]
}

Scripts receive the standard CGI/1.1 environment (REQUEST_METHOD, QUERY_STRING, CONTENT_LENGTH, REMOTE_ADDR, HTTP_*, ...), read POST bodies from stdin, and must print headers, a blank line, then the body:

@echo off
echo Content-Type: text/html
echo.
echo ^<h1^>Hello CGI^</h1^>

Commented examples ship in cgi-bin\:

Script Language Shows
hello.cmd batch minimal HTML response
time.cmd batch dynamic output (server date/time)
env.cmd batch every CGI variable received (debugging aid)
echo.cmd batch reading the query string safely (delayed expansion)
hello.ps1 PowerShell environment variables and dynamic HTML
info.py Python query parsing and POST body from stdin
info.php PHP $_GET / $_POST handling via php-cgi

The examples are harmless but talkative (env.cmd prints the whole environment): in production keep only the scripts you actually use.

A script that exceeds cgi_timeout is killed together with its whole process tree, so a hung script cannot pile up orphan processes. Unknown extensions return 404; traversal attempts return 403.

Security note: CGI is remote code execution by design. The least-privilege service account limits the blast radius, but a vulnerable script still exposes whatever that account can reach. In batch scripts always expand request data with delayed expansion (!QUERY_STRING!), never %QUERY_STRING%, or a crafted query string can inject commands.

Known limitations

Built for LAN and small-scale use. Keep these in mind before exposing it any wider:

  • No cap on concurrent CGI processes; a request flood can spawn many interpreters (each still dies at cgi_timeout).
  • HEAD on a CGI URL executes the script and discards the body (Apache does the same).
  • /healthz is reserved and shadows a www\healthz file; /cgi-bin/ is reserved while CGI is enabled.
  • No Range / download-resume support for static files.

Building from source

Requirements:

  • Windows 10/11
  • Python 3.11 or newer (developed and tested on 3.12)
  • Nuitka: pip install nuitka
  • A C compiler. Nuitka offers to download a suitable MinGW toolchain on the first build (the script passes --assume-yes-for-downloads), or it will use Visual Studio if present.

Then:

build.bat

This produces dist\PocketWebServer.exe as a self-contained onefile binary. The bundle is unpacked once per version into %LOCALAPPDATA% and reused on later starts. To change the release number, update VERSION in build.bat and in pocketwebserver.py.

No compilation is required during development — the script runs directly:

python pocketwebserver.py run --port 8080

Help us

If you find this project useful and would like to support its development, consider making a donation. Any contribution is greatly appreciated!

Bitcoin (BTC) Addresses:

  • 1LToggiof3rNUTCemJZSsxd1qubTYoSde6
  • 3LToggio7Xx8qMsjCFfiarV4U2ZR9iU9ob

License

Licensed under the Apache License 2.0. You are free to use, modify and redistribute this software, provided the copyright notice and license are preserved — see the LICENSE and NOTICE files.

Copyright (C) 2026 Luca Soltoggio - Edptech S.r.l.

About

Portable HTTP/HTTPS server for Windows: single executable, service mode, optional CGI

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors