Masquerade Mode
Masquerade mode makes bext a full drop-in replacement for nginx. External tools — certbot, logrotate, monitoring, deployment scripts — see nginx and interact with it normally, but bext handles all traffic.
How It Works#
Masquerade mode has three components:
- Shim binary — installed at
/usr/sbin/nginx, intercepts all CLI invocations - systemd drop-in — overrides the
nginx.serviceto run bext instead - PID file — written at
/run/nginx.pidfor signal-based management
Installation#
sudo bext nginx masquerade install
This performs four steps:
- Backs up the real nginx binary to
/usr/sbin/nginx.real - Installs the bext-nginx-shim at
/usr/sbin/nginx - Writes a systemd drop-in at
/etc/systemd/system/nginx.service.d/bext-masquerade.conf - Runs
systemctl daemon-reload
Custom Paths#
sudo bext nginx masquerade install \
--bext-bin /usr/local/bin/bext-server \
--shim-bin /usr/sbin/nginx \
--pid-file /run/nginx.pid
Uninstallation#
sudo bext nginx masquerade uninstall
This restores the original nginx binary, removes the systemd drop-in, and runs daemon-reload.
The Shim Binary#
The shim at /usr/sbin/nginx handles all standard nginx CLI flags:
| Flag | Behavior |
|---|---|
-t, -T |
Tests config syntax via bext-server nginx check |
-v, -V |
Prints nginx/1.28.2 (bext-masquerade) |
-s reload |
Sends SIGHUP to bext (config + TLS reload) |
-s stop |
Sends SIGTERM to bext (graceful shutdown) |
-s quit |
Sends SIGQUIT to bext (immediate shutdown) |
-s reopen |
Sends SIGUSR1 to bext (log file reopen) |
-c /path |
Specifies config file path |
-g, -p |
Accepted but ignored (compatibility) |
Combined flags work too: nginx -tc /etc/nginx/nginx.conf
The shim reads the PID file (default /run/nginx.pid, override with BEXT_PID_FILE) to find the running bext process for signal delivery.
systemd Drop-In#
The generated override file:
# /etc/systemd/system/nginx.service.d/bext-masquerade.conf
[Service]
Type=exec
PIDFile=/run/nginx.pid
ExecStartPre=
ExecStart=/usr/local/bin/bext-server --nginx-masquerade
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
ExecStopPost=/bin/rm -f /run/nginx.pid
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
This means:
systemctl start nginxstarts bextsystemctl stop nginxstops bextsystemctl reload nginxsends SIGHUP (config + TLS reload)systemctl status nginxshows bext's status- Automatic restart on failure with 5-second delay
Signal Handling#
SIGHUP — Config Reload#
When bext receives SIGHUP (via nginx -s reload or systemctl reload nginx):
- Re-parses the nginx config file from disk
- Logs any new conversion warnings
- Rebuilds the complete routing state (vhosts, upstreams, rate limiters)
- Reloads all TLS certificates from disk into the SNI resolver
- Performs an atomic state swap using
ArcSwap
In-flight requests continue with the old config. New requests immediately use the new config. If the config parse fails, the old config continues serving and the error is logged.
This is critical for certbot integration — after Let's Encrypt renews a certificate, nginx -s reload (or the certbot deploy hook) reloads the new cert without downtime.
SIGUSR1 — Log Reopen#
When bext receives SIGUSR1 (via nginx -s reopen):
- Reopens the access log file in append mode
- Updates the internal file handle
This enables standard logrotate workflows:
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
rotate 14
compress
postrotate
/usr/sbin/nginx -s reopen
endscript
}
SIGTERM — Graceful Shutdown#
Finishes in-flight requests, then exits. The PID file is cleaned up by the ExecStopPost directive.
Listening Configuration#
In masquerade mode, bext:
- Extracts all unique ports from the nginx vhost
listendirectives - Binds HTTP on every detected port
- Binds HTTPS on port 443 with SNI resolution using all nginx TLS certificates
- Sets the first certificate as the default fallback
- Writes the PID file before accepting connections
Certbot Integration#
Certbot works unchanged after masquerade installation:
# Initial certificate issuance
sudo certbot --nginx -d example.com
# The certbot nginx plugin interacts with the shim
# Renewal hooks call nginx -s reload, which sends SIGHUP to bext
The SIGHUP handler reloads certificates from disk, so the standard certbot renewal flow works without modification.
Monitoring Compatibility#
Tools that check nginx status continue to work:
- systemctl status nginx — shows bext process status
- PID file —
/run/nginx.pidcontains bext's PID - nginx -t — validates config syntax via bext
- nginx -V — reports version (bext-masquerade)
- Process name — visible in
psasbun run server.tsorbext-server
After bext nginx masquerade install, the -V flag reports nginx/1.28.2 (bext-masquerade) — not your previous nginx version. If any tool parses the exact version string from -V, update it accordingly.
Related#
- Takeover Process — the alternative migration path with an atomic rollback UI
- Migration Guide — full step-by-step walkthrough, including masquerade as Option A
- nginx Compatibility Overview — the three-stage parse → convert → serve pipeline
- TLS and HTTPS — how SIGHUP reloads new certificates from disk
- Operations: Invalidation and Restarts — reload vs. restart semantics