Takeover Process
The takeover process atomically migrates traffic from nginx to bext. It stops nginx, binds bext to ports 80/443, and provides automatic rollback if anything fails.
State Machine
The takeover follows a strict state machine:
Preflight ──→ TakingOver ──→ Active
│ │
▼ ▼
Failed ←── RollingBack ──→ RolledBack
| Phase | Description |
|---|---|
| Preflight | Checks running, no changes made. Take Over button enabled. |
| TakingOver | Stopping nginx, binding ports. Loading overlay shown. |
| Active | bext serving on 80/443. Rollback button visible. |
| RollingBack | Stopping bext listeners, restoring nginx. Loading overlay. |
| RolledBack | nginx restored. Dashboard still accessible on preflight port. |
| Failed | Error occurred. Rollback button always available. |
Takeover Sequence
When you click "Take Over" (or POST to /api/takeover):
1. Verify preconditions — phase must be Preflight, no critical check failures
2. Set phase = TakingOver — UI shows loading overlay
3. Record nginx state — whether nginx was enabled for boot start
4. Stop nginx — systemctl stop nginx
5. Wait for ports — poll ports 80/443 for up to 3 seconds
- If ports are still busy → auto-rollback, phase = Failed
6. Disable nginx — systemctl disable nginx (non-fatal if it fails)
7. Bind bext — start serving on ports 80/443 with nginx config
8. Set phase = Active
Rollback Sequence
When you click "Rollback" (or POST to /api/rollback):
1. Verify phase — must be Active or Failed
2. Set phase = RollingBack
3. Re-enable nginx — systemctl enable nginx (if it was enabled before)
4. Start nginx — systemctl start nginx
5. Verify — wait 500ms and check nginx is running
- If nginx fails to start → phase = Failed with error message 6. Set phase = RolledBack
Automatic Rollback
If the takeover fails after nginx has been stopped (e.g., ports still occupied by another process), bext immediately runs:
systemctl start nginx
This ensures traffic is never left without a server. The phase is set to Failed, and the error is displayed in the dashboard.
Prerequisites
- Root access — needed to stop/start services and bind to ports < 1024
- systemd — the takeover uses systemctl for all service management
- nginx.service — the nginx systemd unit must be named "nginx"
Safety Guarantees
1. Read-only during preflight — no system changes until you explicitly trigger takeover 2. Confirmation required — both takeover and rollback require user confirmation 3. Atomic transitions — if any step fails, auto-rollback restores nginx immediately 4. Boot-start preserved — nginx's enabled/disabled state is recorded and restored on rollback 5. Dashboard stays up — the preflight server remains accessible on its port for rollback access even after takeover 6. No data loss — the takeover only manages process lifecycle, not configuration files
Usage via CLI
# Launch with auto-detected config
sudo bext nginx-takeover
# Specify config and port
sudo bext nginx-takeover --nginx-config /etc/nginx/nginx.conf --port 9999
# Non-interactive (for scripted migrations)
sudo bext nginx-takeover --auto-takeover --timeout 30
Preflight Checks Reference
| # | Check | Critical | What it verifies |
|---|---|---|---|
| 1 | Config Parsed | Yes | nginx.conf parses without errors |
| 2 | SSL Certs Accessible | Yes | All certificate/key files are readable |
| 3 | nginx Running | No | Whether nginx is currently serving |
| 4 | Port Availability | Yes | 80/443 will be free after nginx stops |
| 5 | Root Directories | No | Document root paths exist |
| 6 | Upstream Backends | No | Backend servers are reachable |
| 7 | Process Permissions | Yes | Running as root or has CAP_NET_BIND_SERVICE |
| 8 | systemd Available | Yes | systemctl is present and functional |
All critical checks must pass before takeover is allowed. Non-critical warnings are informational — they highlight potential issues but don't block the migration.