BareProxy Header and Rewrite Rules Plugin: Security Headers, Redirects and URL Rewrites
Status: built, number 3 of 21 in BareProxy’s build order, and out in BareProxy 0.5.0 as headers.wasm on the releases page. Its manual is the README in the code repository.
Every site needs a handful of response headers it rarely thinks about: Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy. Security scanners check for them, and their absence is one of the most common findings on a report. Most apps never set them, and most static sites can’t.
What It Does
- Security headers, on by default. Every response that lacks them gets
X-Content-Type-Options,Referrer-PolicyandX-Frame-Options, and on httpsStrict-Transport-Security. A header the app sets itself is kept, andsecurity offturns the set off. - Any other header. Set, add or remove request and response headers, for the whole site or by path, such as long cache times for
/assets/, a content security policy written once for a whole site, orX-Powered-Bytaken off what an old app sends. - Redirects. Permanent and temporary, by exact path or prefix, with the query kept. BareProxy’s core already has redirect rules; this adds redirects that depend on a request header, such as sending German speakers to
/de/. Those default to a temporary redirect and name the header inVary, so no cache hands them to the wrong visitor. - URL rewrites. Change the path a request is routed on before the core sees it, such as serving
/docs/introfrom/manual/intro.
Rules are exact values and prefixes, never regular expressions. That is BareProxy’s rule for its own routing, and it’s a deliberate one: nginx’s regex rewrite module is where the heap overflow behind NGINX Rift sat from 2008 until 2026.
Here is a config:
plugin headers /etc/bareproxy/plugins/headers.wasm
config /etc/bareproxy/plugins/headers.conf
site example.com
use headers
route /* -> files /var/www/example/public
And the plugin’s own:
# headers.conf
redirect /old-page /new-page
redirect /blog/* https://blog.example.com/* 308
redirect / /de/ when accept-language has de
rewrite /docs/* /manual/*
response set content-security-policy default-src 'self'
response remove x-powered-by
path /assets/
response set cache-control public, max-age=31536000, immutable
Seeing What It Did
A rewrite changes which rule handles a request, so it has to be visible. Every redirect, rewrite and header change is a note in the request’s record, with the line of the config that did it. why shows the path as it arrived, the path after the rewrite, and the rule the core then matched.
Plays Well With the Others
Listed first on a site, its headers go on everything, including a page another plugin answers with. Since 0.5.0, a plugin’s own answer goes back through the plugins before it, the way a backend’s response does, so the maintenance page gets the security headers, and CORS headers too.
The whole program is on the plugins page.