Skip to content

v1.4.0 – Boldly Go

Choose a tag to compare

@github-actions github-actions released this 22 Sep 03:17
· 3 commits to main since this release

Qbix Server v1.4.0 – Boldly Go

Cross-Platform, Single-Binary PHP Apps

This release adds Windows COW fork support, auto-provisioning domains, a watchdog process, single-binary app distribution, and a 12-tab control panel that manages frameworks, packages, workers, domains, certs, and hosts — all from a browser.

Download

Platform Binary Fork Model
Linux x86_64 qbixserver-linux-x86_64 pcntl_fork (COW)
Linux ARM64 qbixserver-linux-aarch64 pcntl_fork (COW)
macOS ARM64 qbixserver-macos-arm64 pcntl_fork (COW)
Windows x64 qbixserver-windows-x64.exe RtlCloneUserProcess (COW)
Windows x64 qbixserver-windows-x64-gui.exe Same, no console window

Place qbix_fork.dll next to the Windows binary for COW fork support. Without it, the server falls back to php-cgi subprocess mode.

What's New

Windows COW Fork

A 165-line C shim (fork_shim.c) calls the Windows kernel's RtlCloneUserProcess from ntdll.dll via PHP FFI. Each forked worker shares the parent's memory as copy-on-write — the same model that makes it fast on Linux. The Q_WebServer_Fork class (147 lines) abstracts this: pcntl_fork() on Unix, FFI+DLL on Windows, automatic fallback if neither is available.

Single-Binary App Distribution

Pack your entire application into the server binary:

./qbixserver --pack=./my-app --output=myapp
./myapp --open

The binary detects the appended zip at startup by scanning for the ZIP End-of-Central-Directory signature. Standard zip tools can list and extract the contents (unzip -l myapp, 7-Zip on Windows). The --open flag opens the system browser when the server is ready. Set Q.webserver.open: "/" in config for auto-open without flags.

The GUI variant (-gui.exe) has its PE subsystem set to WINDOWS via editbin, so double-clicking it opens the app in a browser with no console window.

Autohost — Auto-Provision Domains on First Request

Enable Q.webserver.autohost.enabled: true and point any domain's DNS at your server. On first request, the server validates the hostname, checks DNS (multi-resolver: system + 1.1.1.1 + 8.8.8.8), provisions a Let's Encrypt cert via the built-in ACME client, writes the domain config, and serves your app. Subsequent requests go straight through.

Authorization modes: open (any hostname), allowlist (glob patterns like *.example.com), or a custom PHP hook file. Rate limiting: per-IP and global caps to stay under Let's Encrypt quotas. DNS mismatches cached 5 minutes, cert failures cached 1 hour.

Serves a branded splash page over plain HTTP while provisioning. No HSTS until a valid cert is in place, so the first-visit flow never triggers a browser warning.

Watchdog — Auto-Restart on Crash

The server forks an independent watchdog process at startup (Q.webserver.watchdog: true). It detaches via setsid, monitors the server, and on crash: logs the exit code and signal, waits with exponential backoff (2s → 4s → ... → 60s), and restarts. Gives up after 10 crashes in one hour. On clean exit (SIGTERM, Ctrl+C), the watchdog exits too — the shutdown handler explicitly kills it.

Graceful Worker Recycling

Workers now track their request count. After maxRequests (default 1000), a worker is replaced with a fresh fork. The recycling is graceful: busy workers finish their current request before being replaced. No in-flight requests are dropped.

New panel controls: recycle a single worker by index, or "Recycle All" for a rolling restart of the entire pool. The Workers tab shows a per-worker table with PID, status (idle/busy/recycling), and request count.

Config File Watcher

The server polls local/app.json, local/panel.json, and config/app.json every 3 seconds. When a file changes, the config is re-read and merged. New requests see new values immediately. No restart, no reload signal, no downtime.

Hosts File Management

The Domains tab reads /etc/hosts (or C:\Windows\System32\drivers\etc\hosts on Windows) and cross-references your configured domains. Domains not in the hosts file get an "Add to hosts" button that provides the platform-specific elevation command (macOS osascript dialog, Windows UAC, Linux pkexec). Domains ending in .localhost are marked as resolving natively — no hosts entry needed.

Control Panel — 12 Tabs

Tab What it does
Apps List, create, serve apps. Per-app fork mode toggle.
Domains Manage domains, view cert status, one-click ACME provisioning, hosts file management.
Autohost Toggle auto-provisioning, set authorization mode and allowlist, view provisioning log.
Workers Live pool stats, per-worker table with PID/status/request count, recycle controls.
Logs Real-time access and error log viewer.
Cron Scheduled tasks with "Run Now". Built-in cert renewal (every 12 hours).
Frameworks Auto-detects Laravel, Symfony, WordPress, Drupal, Joomla. Install, update, remove packages. Clone from GitHub.
Plugins Qbix plugin management with three-layer version tracking. npm/composer per plugin.
Scripts Run Qbix installer and other scripts from the panel.
Playground Execute PHP snippets in the server context.
System PHP version, extensions, disk space, phpinfo() iframe.
Docs Browse all 21 markdown docs.

Docs Viewer

Browse all server documentation at /Q/docs. Dark theme, sidebar nav, marked.js bundled locally (39KB, no CDN). Inline fallback parser if marked.js is missing.

Migration Guides

New documentation for switching from another server:

GitHub Actions — 4 Platform Build

Builds static binaries for Linux x86_64, Linux ARM64, macOS ARM64, and Windows x64. Windows uses spc from source (not the nightly binary) for reliability. Each platform has separate steps with proper shell handling. fail-fast: false ensures one platform's failure never blocks the others. The Windows build compiles qbix_fork.dll with MSVC and produces a GUI variant via editbin.

Built-in Cert Renewal

A _certRenewal task runs every 12 hours via the internal scheduler. Scans all certs and renews any expiring within 30 days. No external cron job or systemd timer needed.

Framework-Aware App Roots

When autohost provisions a new domain or --pack bundles an app, the server auto-detects the framework and sets the correct web root: web/ for Qbix, public/ for Laravel and Symfony, root for WordPress and Joomla.

Two Modes

Persistent workers (default) — workers stay alive across requests. 28 PHP functions shimmed via source transformation. Static properties restored in 0.03ms. Best performance.

Fork-per-request — for code with untrackable global state. Each worker costs ~120KB (COW), so you run 100× more workers than php-fpm on the same hardware.

Stats

  • 70 unit tests + 27 end-to-end API tests, 0 failures
  • 21 documentation files
  • Panel: 4,222 lines
  • Server: 5,618 lines
  • Total: ~15,000 lines of PHP + 165 lines of C + 208 lines of watchdog