bserver can act as a reverse proxy for any virtual host. Instead of serving files from disk, all requests to the vhost are forwarded to a backend HTTP server and the responses are relayed back to the client.
Create a vhost directory containing a single index.yaml with an http: key
pointing to the backend address:
www/example.com/index.yaml
http: '192.168.1.2:8080'
That's it. All requests to example.com will be proxied to
http://192.168.1.2:8080.
When a request arrives, bserver checks the vhost's index.yaml before doing
any file serving. If the file contains an http: key, a reverse proxy is
created for that backend and the request is forwarded.
index.yaml, the change is picked up automatically on the
next request (mtime-based cache invalidation).502 Bad Gateway
response and the error is logged.The http: value can be specified with or without a scheme:
| Value | Proxies to |
|---|---|
192.168.1.2:8080 |
http://192.168.1.2:8080 |
http://192.168.1.2:8080 |
http://192.168.1.2:8080 |
http://localhost:3000 |
http://localhost:3000 |
http://10.0.0.5:9090/app |
http://10.0.0.5:9090/app |
If no scheme is provided, http:// is assumed.
Run a Node.js app on port 3000 and expose it as myapp.example.com:
mkdir -p www/myapp.example.com
# www/myapp.example.com/index.yaml
http: 'localhost:3000'
Forward internal.example.com to a machine on the LAN:
mkdir -p www/internal.example.com
# www/internal.example.com/index.yaml
http: '192.168.1.50:8080'
Forward to a backend that serves from a subpath:
# www/api.example.com/index.yaml
http: 'http://10.0.0.5:9090/v2'
A vhost index.yaml is a file on disk — but an attacker who can write to
it could otherwise turn bserver into an SSRF gateway. bserver refuses to
proxy to:
127.0.0.0/8, ::1)169.254.0.0/16, including AWS metadata
169.254.169.254)10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)0.0.0.0, ::)If you legitimately need to proxy to a private backend (the common case on
a LAN), opt in with allow-private: true:
# www/internal.example.com/index.yaml
http: '192.168.1.50:8080'
allow-private: true
Add an api-key to require Bearer-token authorization on every request to
a proxied vhost:
# www/api.example.com/index.yaml
http: 'localhost:9090'
api-key: 'sk-secret-string-here'
Clients must send Authorization: Bearer sk-secret-string-here or the
server returns 401 Unauthorized. The header is then stripped before the
request is forwarded, so the backend never sees the bserver key.
This pairs well with rate limiting (10 wrong attempts blocks the IP).
When a vhost is in proxy mode, all requests to that domain are forwarded to the backend. This includes:
The following bserver features are still applied to proxied requests:
X-Content-Type-Options, X-Frame-Options, and
Referrer-Policy are added to responsesA normal (file-serving) vhost can also proxy a single path prefix to a
backend, reusing the vhost's own certificate — handy for mounting a
companion service such as a web terminal at /terminal/ alongside static
content. Configure it in the vhost's _config.yaml:
# www/example.com/_config.yaml
proxy-path: '/terminal/'
proxy-path-backend: 'localhost:7681'
proxy-path-key-file: '/etc/bserver/terminal.key' # shared secret (preferred)
Only requests under proxy-path are forwarded; everything else is served
normally. Access is gated by proxy-path-key (or proxy-path-key-file):
a request must present that value as a bs_proxy_auth cookie or
Authorization: Bearer <key>. Leaving the key empty makes the path proxy
open to anyone.
Like the vhost http: proxy, a path proxy refuses backends that resolve to
loopback / link-local / private / unspecified / multicast addresses, so an
attacker who can write a vhost _config.yaml cannot use it as an SSRF
gateway. Because a path proxy most often fronts a local service (e.g. a
terminal on localhost), opt in to a private backend with
proxy-path-allow-private: true:
# www/example.com/_config.yaml
proxy-path: '/terminal/'
proxy-path-backend: 'localhost:7681'
proxy-path-key-file: '/etc/bserver/terminal.key'
proxy-path-allow-private: true
Without this flag a private backend is refused and the request receives a
502 (the reason is logged).
To switch a vhost from proxy mode to normal file serving, simply remove or
rename the http: key in index.yaml (or replace it with a main:
definition). The change takes effect on the next request.
To switch from normal mode to proxy mode, add an http: key to index.yaml.
Any other keys in the file are ignored when http: is present.
When a proxy vhost is first detected (or its configuration changes), bserver logs the mapping:
Proxy vhost /path/to/www/example.com -> http://192.168.1.2:8080
Backend errors are logged with the domain and target:
proxy error for example.com -> http://192.168.1.2:8080: dial tcp 192.168.1.2:8080: connect: connection refused