High-load HTTP reverse proxy with disk-backed TTL cache for selected paths and automatic Let's Encrypt TLS (auto-issue + auto-renew).
Developed by Quardexus. Version v1.3.2.
- Runs an HTTP service that proxies requests to a required upstream origin.
- For paths matching configured cache patterns, it stores the response body on disk and serves it from cache until TTL expires.
- On cache HIT, it performs zero requests to the origin.
- Public domain: the hostname clients use to reach ProxyBuff (e.g.
multidex.online). - Origin / upstream: the backend ProxyBuff proxies to (flag
--origin), e.g.https://81.177.139.61:443. - TLS domain: domain name(s) ProxyBuff requests Let's Encrypt certificates for (flag
--tls-domain). This must be the public domain, not the origin.
-
Methods: only
GETis cached.HEADcan be served from an existing cachedGETentry, but does not populate the cache. -
Status codes: only
200 OKresponses are cached. -
Range requests (
Range:header):- If the full file is already cached, ProxyBuff serves a single byte range (
206) from disk. - Otherwise, ProxyBuff proxies the range request and downloads the full file in the background to populate cache for next time.
- Multi-range requests (e.g.
bytes=0-99,200-299) are not supported for cache serving and are proxied.
- If the full file is already cached, ProxyBuff serves a single byte range (
-
Cache key: path only (
/some/file.png). Query string is ignored for the cache key, but is still forwarded to the origin. -
Response headers:
- On HIT, headers come from cached metadata and are sent “as stored”.
- ProxyBuff always adds
X-ProxyBuff-Cache: HIT|MISS. Ageheader is optional (enabled via--age-header) and is computed from the cached entry creation time.
-
Cache cleanup (GC):
- ProxyBuff runs a best-effort garbage collector about once per TTL that removes expired cached entries from disk even without client traffic.
- It scans
meta.jsonfiles and deletes the correspondingmeta.jsonandbodywhenExpiresAtis in the past. - GC stops on shutdown (it is tied to the app's background context).
Patterns match the request path only.
*matches any characters including/(nested paths)./matches only the root request path.
Examples:
/caches onlyGET /*.pngcaches/a.pngand/assets/img/b.png/assets/*caches/assets/anything/inside/here
ProxyBuff can proactively refresh cached entries in the background even when there are no client requests.
How it works:
- You configure
--recachepatterns (same syntax as--cache). - For each cached entry matching
--recache, ProxyBuff schedules a refresh at:expiresAt - recacheAhead
- Refresh is done by a background worker pool (
--recache-workers) and uses non-blocking per-key locking so it does not stall user traffic. - Cached entries survive restarts because the scheduler reads
meta.jsonfrom disk on startup.
Defaults:
--recache-ahead=5m--recache-workers=4
go test ./...
go build -o proxybuff ./cmd/proxybuff./proxybuff \
--origin https://origin.example.com \
--http=3128 \
--ttl 10m \
--cache "/" \
--cache "*.png" \
--recache "/assets/*" \
--recache-ahead 5m \
--recache-workers 4 \
--cache-dir ./cachedocker build -t proxybuff:local .Run the container from the locally built image:
docker run -d --name proxybuff \
--restart unless-stopped \
-p 3128:3128 \
-v proxybuff-cache:/var/lib/proxybuff/cache \
proxybuff:local \
--origin https://origin.example.com \
--ttl 10m \
--cache "/" \
--cache "*.png" \
--recache "/assets/*"You can also pass multiple patterns as a comma-separated list:
docker run -d --name proxybuff \
--restart unless-stopped \
-p 3128:3128 \
-v proxybuff-cache:/var/lib/proxybuff/cache \
proxybuff:local \
--origin https://origin.example.com \
--ttl 10m \
--cache "/,*.png,*.jpg,*.webp,/assets/*"Notes:
- Container entrypoint writes the effective config to
/etc/proxybuff/config.jsonand starts the service.
If you enable HTTPS, ProxyBuff will obtain and renew certificates automatically using ACME (Let's Encrypt).
Requirements:
- Your public domain must point to this server (public DNS).
- Port 80/tcp must be reachable from the Internet for HTTP-01 challenges.
- Port 443/tcp (or your chosen HTTPS port) must be reachable for clients.
Behavior:
- When HTTPS is enabled, the HTTP listener is used for ACME HTTP-01 challenges and redirects all other requests to HTTPS.
- Certificates are cached on disk (under
cache/certsinside the cache dir) and are renewed automatically before expiry.
Example (container):
docker run -d --name proxybuff \
--restart unless-stopped \
-p 443:443 \
-p 80:3128 \
-v proxybuff-cache:/var/lib/proxybuff/cache \
proxybuff:local \
--origin https://origin.example.com \
--https=443 \
--tls-domain public.example.comdocker exec -it <container_name_or_id> proxybuff-clear-cacheOptionally specify a directory:
docker exec -it <container_name_or_id> proxybuff-clear-cache /var/lib/proxybuff/cacheYou can view the current cache status (cached files, size, expiration) without running the server:
# From binary (looks in ./cache by default)
./proxybuff status
# Specify cache directory
./proxybuff status --cache-dir /var/lib/proxybuff/cache
# Or use config file
./proxybuff status --config ./config.json--origin(required): upstream origin URL. You can pass a full URL (https://example.com:443) or omit the scheme.- If scheme is omitted and origin is a hostname, it defaults to
http://(port 80). - If scheme is omitted and origin is an IP, ProxyBuff probes the port once on startup to detect TLS and picks
http://orhttps://. If it detects TLS, it also enables--insecure-skip-verifyby default.
- If scheme is omitted and origin is a hostname, it defaults to
--listen(deprecated): alias for--http--http(required): HTTP listener. Accepts port/address (e.g.8080,:8080,127.0.0.1:8080)--https(defaultfalse): HTTPS listener. Acceptstrue|falseor port/address (e.g.443,:443,127.0.0.1:443)--tls-domain(repeatable): domain(s) to request and renew ACME certificates for when HTTPS is enabled--cache(repeatable, default empty): cache patterns--recache(repeatable, default empty): auto-refresh patterns (also implies caching those patterns)--recache-ahead(default5m): how long before expiry to refresh an entry--recache-workers(default4): max concurrent background refresh workers--ttl(default10m): cache TTL duration--cache-dir(default./cache): cache directory (in Docker defaults to/var/lib/proxybuff/cache)--log-file(default empty): optional log file path (also logs to stdout)--age-header(defaultfalse): add standardAgeheader on cache HIT--use-origin-host(defaultfalse): sendHostfrom--origin(by default forwards the original clientHost)--insecure-skip-verify(defaultfalse): skip TLS certificate verification for https origins (dangerous)
Apache-2.0. See LICENSE.