Skip to content

Repository files navigation

Simple HTTP Daemon

simple-httpd is a small C++17 HTTP daemon that serves static files.

One process, one config file (INI, YAML, or JSON), one document root (or several, by Host). It speaks HTTP/1.1 and HTTP/2, optionally HTTPS. Reverse proxy, CGI, FastCGI, and SSI are opt-in extras and stay off unless you set them.

Version 0.8.0 — Apache License 2.0 · SimpleDaemons

./build/simple-httpd --root www --port 8080
# open http://127.0.0.1:8080/

What you get

Area Capability
Protocol HTTP/1.1 and HTTP/2 GET, HEAD, OPTIONS; keep-alive; ETag / Last-Modified / 304; single-range 206; chunked and Content-Length request bodies
Content Document root, index files, MIME types (plus mime_type extras), optional directory listing, gzip / deflate, in-memory file cache
Sites Name-based virtual hosts (Host header)
TLS OpenSSL TLS 1.2+ (optional 1.3 floor), PEM cert + key, ECDHE/PFS ciphers, optional HSTS, ALPN (h2 / http/1.1)
Security Path-traversal rejection, method allow-list, CSP and related headers, HTTP Basic, per-IP request/connection limits, CIDR allow/deny, security audit log
Routing Prefix URL rewrites (/blog/posts); optional HTTP reverse proxy with round-robin
Dynamic Optional CGI, FastCGI (TCP), SSI (include / echo; no exec)
Operations /healthz, Prometheus /metrics, JSON /status, auth-gated admin config/reload, SIGHUP soft reload, privilege drop / daemonize, access / error / security logs
Config INI, YAML, or JSON file; CLI flags; SIMPLE_HTTPD_* environment

It is not nginx or Apache. HTTP/3, HTTPS origin proxy, FastCGI process management, and a framed WebSocket stack are out of scope. See ROADMAP.md if you care about later protocol work.

Documentation

Guide Contents
docs/installation.md Dependencies, CMake, tests, install
docs/configuration.md Every config key, CLI flag, and environment variable
docs/security.md TLS, headers, Basic auth, rate limits, hardening
docs/operations.md Logs, health, metrics, signals, systemd / launchd / Docker
docs/architecture.md How a request moves through the process
docs/troubleshooting.md Bind failures, TLS, 401/429, gzip, CSP
config/README.md Ready-made simple / advanced / production / security profiles

Internal planning lives under project/. Version policy: VERSIONING.md. History: CHANGELOG.md.

Quick start

Build

Needs a C++17 compiler and CMake 3.16+. OpenSSL, zlib, and nghttp2 are used when present (HTTPS, gzip, HTTP/2).

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_PACKAGING=OFF -DENABLE_SSL=ON -DENABLE_HTTP2=ON
cmake --build build
ctest --test-dir build --output-on-failure

make build / make test wrap the same CMake flow.

Run the sample site

The tree includes a tiny site in www/.

./build/simple-httpd --root www --port 8080
curl -i http://127.0.0.1:8080/
curl -I http://127.0.0.1:8080/style.css
curl --http2-prior-knowledge -i http://127.0.0.1:8080/

Stop with SIGINT or SIGTERM (Ctrl+C). Foreground is the default; use -d / --daemonize on Unix if you need a background process (systemd is preferred).

HTTPS

./build/simple-httpd --root www --port 8443 \
  --tls-cert /path/to/fullchain.pem \
  --tls-key  /path/to/privkey.pem \
  --hsts

Both cert and key must be set. The listener is HTTPS-only in that mode (no plaintext on the same port).

A config file

cp config/examples/simple.conf.example simple-httpd.conf
# or: simple.yml.example / simple.json.example
./build/simple-httpd --config simple-httpd.conf --dump-config
./build/simple-httpd --config simple-httpd.conf --root www

If you omit --config, the daemon looks for SIMPLE_HTTPD_CONFIG, then ./simple-httpd.conf, ./config/simple-httpd.conf, and /etc/simple-httpd/simple-httpd.conf.

Configuration at a glance

Precedence, later wins: defaults → config file → environment → CLI.

INI, YAML, and JSON accept the same keys. --config picks the parser from the path (.yml / .yaml, .json, otherwise INI).

listen_address = 127.0.0.1
listen_port = 8080
document_root = ./www
directory_listing = true
compression = true

ssl_cert = /etc/simple-httpd/tls/fullchain.pem
ssl_key  = /etc/simple-httpd/tls/privkey.pem
hsts = true

csp = default-src 'self'; style-src 'self' 'unsafe-inline'
auth_basic_file = /etc/simple-httpd/htpasswd
rate_limit_enabled = true
rewrite = /blog:/posts
# proxy = /api:127.0.0.1:9000
# cgi_prefix = /cgi-bin
# ssi = true

[vhost:app.example]
document_root = /var/www/app.example

Profiles:

Profile File Intent
Simple config/examples/simple.{conf,yml,json}.example HTTP on 127.0.0.1:8080, ./www, terminal logs
Advanced config/examples/advanced.{conf,yml,json}.example Virtual hosts, gzip, cache headers, optional TLS
Production config/examples/production.{conf,yml,json}.example HTTPS on 443, file logs, rate limits, vhosts
Security config/examples/security.{conf,yml,json}.example TLS + HSTS + CSP, tight limits, method filter

Full key list: docs/configuration.md.

Command line

Flag Meaning
-c, --config PATH INI, YAML, or JSON config file
-p, --port PORT Listen port (default 8080)
-a, --address ADDR Listen address (default 0.0.0.0)
-r, --root DIR Document root (default ./www)
--directory-listing Autoindex when no index file exists
--no-keep-alive Close after one response
--tls-cert PATH PEM certificate chain (enables HTTPS)
--tls-key PATH PEM private key
--hsts Send Strict-Transport-Security on HTTPS
--no-compression Disable gzip / deflate
--log-level LEVEL debug, info, warn, error
--access-log PATH Access log file, or - for stdout
--error-log PATH Error log file, or - for stderr
--dump-config Print resolved configuration and exit
-d, --daemonize Double-fork to background (Unix)
-f, --foreground Stay in the foreground (default)
--user NAME Drop privileges to user after bind (Unix)
--group NAME Drop privileges to group after bind (Unix)
--pid-file PATH Write PID after a successful bind
-v, --version Print version
-h, --help Usage

Environment: SIMPLE_HTTPD_CONFIG, SIMPLE_HTTPD_ADDRESS, SIMPLE_HTTPD_PORT, SIMPLE_HTTPD_ROOT, SIMPLE_HTTPD_LOG_LEVEL, SIMPLE_HTTPD_TLS_CERT, SIMPLE_HTTPD_TLS_KEY.

Operations snapshot

curl -s http://127.0.0.1:8080/healthz      # "ok"
curl -s http://127.0.0.1:8080/metrics      # Prometheus text
curl -s http://127.0.0.1:8080/status       # JSON snapshot

/healthz, /metrics, and /status skip HTTP Basic and the rate limiter so probes keep working. Access lines are Apache-style Combined. Details: docs/operations.md.

Project layout

include/simple-httpd/     public headers
src/simple-httpd/         library
src/main.cpp              CLI entry
tests/                    ctest binaries
www/                      sample document root
config/                   example INI, YAML, and JSON profiles
docs/                     user documentation
deployment/               systemd, launchd, logrotate, Docker examples

Versioning and releases

Product version lives in VERSION and is read by CMake. SemVer rules: VERSIONING.md. How to tag: RELEASING.md.

Contributing

See CONTRIBUTING.md. Short version: C++17, match neighboring files, add tests, keep static files as the default product. Extras (proxy, CGI, SSI) stay opt-in.

License

Licensed under the Apache License, Version 2.0. See LICENSE.

Copyright 2024 SimpleDaemons.

About

Simple HTTP Daemon [simple-httpd]

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages