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:
1. Shim binary — installed at /usr/sbin/nginx, intercepts all CLI invocations
2. systemd drop-in — overrides the nginx.service to run bext instead
3. PID file — written at /run/nginx.pid for signal-based management
Installation
sudo bext nginx masquerade install
This performs four steps:
1. Backs up the real nginx binary to /usr/sbin/nginx.real
2. Installs the bext-nginx-shim at /usr/sbin/nginx
3. Writes a systemd drop-in at /etc/systemd/system/nginx.service.d/bext-masquerade.conf
4. 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 nginx starts bext
- systemctl stop nginx stops bext
- systemctl reload nginx sends SIGHUP (config + TLS reload)
- systemctl status nginx shows 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):
1. Re-parses the nginx config file from disk
2. Logs any new conversion warnings
3. Rebuilds the complete routing state (vhosts, upstreams, rate limiters)
4. Reloads all TLS certificates from disk into the SNI resolver
5. 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):
1. Reopens the access log file in append mode 2. 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:
1. Extracts all unique ports from the nginx vhost listen directives
2. Binds HTTP on every detected port
3. Binds HTTPS on port 443 with SNI resolution using all nginx TLS certificates
4. Sets the first certificate as the default fallback
5. 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.pid contains bext's PID
- nginx -t — validates config syntax via bext
- nginx -V — reports version (bext-masquerade)
- Process name — visible in ps as bun run server.ts or bext-server