A small web server written in Go that builds HTML pages from YAML and Markdown definitions — no template language, no build step. Virtual hosting, automatic HTTPS, server-side scripts (Python, JavaScript, PHP, Shell), reverse proxying, and rate limiting are all built in. Began as a small webserver with built-in letsencrypt for testing, and then was expanded to HTML generation from structured data files.
Website / live docs: bserver.info
You need Go 1.24+.
git clone https://github.com/stgnet/bserver.git
cd bserver
go build
./bserverOpen the URL it logs at startup (port 80 if available, otherwise
8000-8099). You'll land on the bundled documentation site — which is
itself a bserver site living in www/default/.
mkdir www/example.com# www/example.com/index.yaml
main:
- h1: "Hello World"
- p: "Welcome to my site."That's it. Visit the site and bserver wraps your main: content in a
full HTML document with navigation, footer, Bootstrap 5 styling, and an
auto-generated favicon. Everything outside of main: was inherited from
the shared YAML in www/; override any of it by dropping a same-named
file into your vhost directory.
sudo ./install-service.sh # install + start (systemd or launchd)
sudo ./install-service.sh restart # after `git pull && go build`
sudo ./install-service.sh remove # uninstallEvery page is assembled by following a tree of named references starting
at html:
html.yaml ← <html lang="en"> wrapping head + body
├── head.yaml ← <head> with meta, title, styles
└── body.yaml ← <body> wrapping:
├── header.yaml ← navbar
├── main ← YOUR CONTENT (from index.yaml or .md)
└── footer.yaml ← footer
When bserver sees a name like header, it looks for header.yaml
starting in the request's directory and walking up — so site-specific
files win, shared definitions in www/ are inherited. YAML files are
re-read on every request (with a render cache invalidated by fsnotify),
so there's no restart cycle.
Four prefixes govern every YAML key:
main: # plain key — content
- h1: "Hi"
^card: # ^ — format definition (how a name renders as HTML)
tag: div
params: { class: card }
+headlink: # + — merge into an existing definition
- { rel: stylesheet, href: /extra.css }
$navlinks: # $ — data source (script that produces the value)
script: javascript
code: |
print(JSON.stringify([{key: "/", value: "Home"}]));Everything else — components, layouts, the navbar, error pages, scripts, proxy mode — composes from these four pieces.
- YAML / Markdown page generation with clean indented HTML5 output
- Cascading name resolution — child overrides parent, no inheritance ceremony
- Format definitions (
^name) — reusable HTML templates with variable substitution - Data sources (
$name) — script-backed content with JSON output - Server-side scripts — Python, embedded JavaScript (goja), PHP, and
Shell, plus full PHP-CGI for
.phpfiles - Virtual hosting — one directory per domain,
default/fallback, symlink aliases - Automatic HTTPS — Let's Encrypt for public domains, self-signed
fallback for IPs and
.local/.test/.internal - Reverse proxy mode — one-line
index.yamlturns a vhost into a proxy (with SSRF guards and optional API-key gating) - Passwordless authentication — a per-vhost
_auth.yamlgates the site behind emailed one-time codes, with multi-user approval (inline list, file, or script hook such as a database check), pluggable code delivery, and a sign-in dialog defined entirely in customizable YAML (auth-login.yaml), not server code - Render cache with fsnotify invalidation and RAM-aware sizing
- Security headers, rate limiting, privilege dropping, port-80 fallback
- Path-embedded GET arguments —
/script/name/valueworks like/script?name=value, surviving email scanners that strip query strings - Auto-generated favicons with optional
_favicon.yamlcustomization - Debug mode —
?debugemits HTML-comment traces of name resolution
Once the server is running, the full documentation site is available at
/:
- Getting Started — installation, first page, configuration
- Content Definitions — the four prefixes
- Format Definitions — the
^system - Data Sources — the
$system - Built-in Components — pre-defined layout & navigation pieces
- Server-Side Scripts — Python, JavaScript, PHP, Shell
- Server Features — caching, security, rate limiting, TLS, favicons
- Proxy Mode — reverse proxying with one line
- Error Handling — custom 404/500 templates
- Advanced Features — virtual hosting internals, name resolution, debug mode
- Tips & Recipes — common patterns
Apache 2.0 — see LICENSE.