OxPHP is an asynchronous PHP application server written in Rust β
built for production workloads that demand low latency, high concurrency, and zero-config observability.
Documentation: English Β· Π ΡΡΡΠΊΠΈΠΉ Β· δΈζ Β· FranΓ§ais Β· Polski Β· ζ₯ζ¬θͺ
Quick Start Β· Why OxPHP Β· Migration Β· Features Β· Configuration Β· Roadmap
Warning
OxPHP is not production-ready yet. The project is under active development β APIs may change, edge cases are still being uncovered, and there is no SLA. It is ready for evaluation, staging environments, and early adopters who want to test it on real workloads and report what breaks. Feedback, bug reports, and benchmarks against your stack are exactly what we need right now β open an issue or start a discussion on GitHub.
Two lines. That's it.
FROM ghcr.io/oxphp/oxphp:0.14.0
COPY --chown=www-data:www-data . /var/www/html/publicNote: By default,
DOCUMENT_ROOTis/var/www/html/publicβ the snippet above copies your app directly into the document root. For Laravel, Symfony, Slim, or any project that already ships apublic/subdirectory, useCOPY --chown=www-data:www-data . /var/www/htmlinstead: the framework's ownpublic/lines up with the defaultDOCUMENT_ROOT.
docker build -t my-app . && docker run -p 80:80 my-app
curl http://localhost/No nginx config. No PHP-FPM pool tuning. No process manager. Just your app.
See the full Quick Start guide for more details.
OxPHP replaces nginx + PHP-FPM with a single container. The server works out of the box β TLS, compression, rate limiting, Prometheus metrics, health checks, and structured JSON logs are configured via environment variables.
- One process instead of a stack. HTTP/1.1, HTTP/2, TLS, static files, compression and PHP execution live in one binary. There are no FastCGI sockets, pool files or process managers to keep in sync between containers.
- Threads, not processes. PHP workers are OS threads of a single process (PHP ZTS) and share one OPcache: one worker compiles a file, every worker runs the cached bytecode β see OPcache and JIT.
- Persistent workers when you want them. Worker mode keeps the autoloader, service container and DB connections alive between requests, and fiber multiplexing lets one worker carry many requests while each waits on I/O. It is opt-in: the default mode starts every request from a clean PHP state, as PHP-FPM does.
- Concurrency primitives built in. Async promises for parallel work, and
Shared\*in-process counters, maps, channels and mutexes that cover single-host coordination without Redis or APCu. - Defined behaviour under overload. Requests wait in a bounded queue; one that waits longer than
QUEUE_WAIT_TIMEOUT_MSis refused with529andRetry-Afterrather than queuing without limit. - Observability without sidecars. Prometheus
/metrics, liveness/readiness/startup probes, JSON access logs, W3C Trace Context, OpenTelemetry export, APM auto-instrumentation of PDO, mysqli, cURL and Redis, and a per-request profiler all ship in the binary. - Safe defaults. Hidden files (
.env,.git/) return 404, symlink escapes are blocked, a deny-list stops.phpexecution in upload directories,X-Forwarded-*is honoured only from trusted proxies, and the process drops from root towww-databefore serving a request. - Familiar routing. Three of the four routing modes mirror an nginx
try_filessetup for a front-controller framework, a classic multi-entry app and a SPA. - Rust where it matters. The HTTP layer (Tokio, rustls) is Rust; PHP is the stock engine from the official
php:*-ztsimages, so the extensions and OPcache are the ones you already know.
See the full documentation for details.
Most PHP applications move from nginx + PHP-FPM without code changes: the default mode runs each request from a clean PHP state, so the work is translating configuration. The migration guide covers:
- picking a routing mode from your
try_filesand building the image; - an nginx / PHP-FPM β OxPHP configuration mapping, including where
php.inisettings go; - behaviour differences to check after the move: wall-clock
max_execution_time,php_sapi_name(), default frame headers; - porting FrankenPHP and RoadRunner workers, and tracking memory instead of restarting on a request count;
- what does not carry over: reverse proxy and WebSocket, HTTP/3, one protocol per port, Linux only.
Formal benchmarks are coming soon. We are working on a reproducible test suite covering req/s, latency (p50/p99), memory usage, and worker throughput under concurrent load.
- Native PHP execution β PHP runs directly inside the server process, in a dedicated thread pool
- Full superglobals support:
$_SERVER,$_GET,$_POST,$_COOKIE,$_FILES,php://inputβ see Superglobals - HTTP Object API β
oxphp_http_request()returns a typed, lazy-loading request object with built-in JSON body parsing, content-detected MIME types for uploads, and a mutable attributes container for middleware β see HTTP Request API - Worker Runtime API β
OxPHP\Server\Worker::current()exposes per-thread introspection (id,requestCount,startTime,memoryUsage,rss,maxMemoryBytes) and the worker entry point (serve) β see Worker class - Shared OPcache across all workers β one worker compiles a file, every worker uses the cached bytecode β see OPcache and JIT
- PHP extension functions β
oxphp_*()helpers for streaming, early response, async, tracing, and request access β see PHP functions reference - Plugin system with typed event dispatch, priority ordering, and PHP function registration
- Attribute-based decorators β intercept function/method calls via PHP 8+ attributes with zero overhead on undecorated code; supports
TARGET_FUNCTION,TARGET_METHOD,TARGET_CLASSβ see Decorators - Fatal-error isolation β a fatal error in one request does not take down the server. The exception is PHP's hard memory limit, on PHP 8.4.27 / 8.5.12 and later: an allocation past it ends the whole process β see Memory limits. A native crash, such as a segmentation fault in PHP or in an extension, is not a fatal error and ends the whole process as well
- Worker mode β persistent PHP workers that stay alive across requests; autoloaders, service containers, and DB connections are initialized once and reused β see Worker mode
- Fiber multiplexing β each worker handles multiple concurrent requests via PHP Fibers;
oxphp_sleep()andoxphp_async_await()yield the current fiber instead of blocking the worker thread β see Fiber multiplexing - Runtime hooks β
RUNTIME_HOOKS=sleep,streams,netmakes nativesleep()/usleep(), blocking TCP reads,stream_select(), connects, TLS waits and reads on local sockets suspend the fiber instead of the worker thread, so unmodified PDO MySQL, mysqli and phpredis code benefits β see Runtime hooks - Automatic recycling β in worker mode a worker is recycled when it passes
WORKER_MAX_MEMORY_MIB, when the application callsWorker::scheduleExit(), or after three consecutive requests come apart, a fatal error being the usual one β see Recycling - Worker health monitoring β workers that die unexpectedly are automatically detected and replaced; a static pool refills to its configured count, a dynamic one to its minimum
- Early response via
oxphp_finish_request()β send the response and keep running background work β see Early response
See the full Async promises guide.
oxphp_async()/oxphp_async_await()β dispatch closures to a dedicated thread pool for true parallel execution- Portable serialization for
usevariables, arguments, and return values β safe cross-thread binary transfer - Supported types: scalars, strings, arrays (nested), and
Shared\*/OxPHP\Shared\Shareableobjects. Resources and plain objects are rejected β see Limitations - Exception & die() safety β exceptions,
die(), andexit()are caught and re-thrown asOxPHP\Async\AsyncException - Timeout support β per-task timeouts with
OxPHP\Async\TimeoutException oxphp_async_await_all()/oxphp_async_await_race()/oxphp_async_await_any()β batch, race (first settled), and any (first fulfilled, JSPromise.anystyle) primitives
Process-wide concurrent primitives that let PHP workers coordinate mutable state without Redis, Memcached, or APCu. Everything lives in-process β per-op cost is microseconds, not network round-trips. See the full Shared state guide and observability reference.
Shared\Counterβ atomic int64 accumulator (get,set,add,compareAndSet) β see CounterShared\Atomicβ full lock-free int64 primitive (load,store,swap,compareAndSet,fetchAdd/Sub/And/Or/Xor) with explicit memory ordering β see AtomicShared\Flagβ atomic bool withcompareAndSetfor one-shot transitions β see FlagShared\Onceβ run-once container with reentrancy-safe factory β see OnceShared\Mutexβ poisoning mutex over a stored value, with reentrancy and cross-thread deadlock detection β see MutexShared\Channelβ bounded MPMC queue, fiber-aware (blocking recv yields the current fiber) β see ChannelShared\Mapβ concurrentint|string-keyed store with batchedsetMany/getManyand cycle-checked nested values β see MapShared\Poolβ bounded object pool with strict per-thread affinity, idle-timeout eviction, and chaos-reclaim on worker death β see PoolShared\Registryβ name-keyed handles (Registry::counter('hits', fn() => ...)) so every worker and every request converges on the same entry without external stores β see Registry- Built-in observability β
oxphp_shared_*Prometheus counters and/__ox_shared/{summary,entries,entry,preview,types,graph}JSON endpoints on the internal port - Refcount + lifecycle safety β handles cannot outlive the registry entry; cycle detector rejects graphs that would leak memory
- When you outgrow it, see Migrating to an external store
- HTTP/1.1 + HTTP/2 on one port β the protocol is auto-detected per connection: prior-knowledge h2c over cleartext, or
h2via ALPN under TLS, with transparent HTTP/1.1 fallback. Flow-control windows are tuned for typical PHP response sizes β see HTTP/2 - TLS 1.3 with ALPN β both HTTP/2 and HTTP/1.1 over TLS β see TLS
- 4 routing modes β Traditional (file mapping + always-on PATH_INFO), Framework (every request to
index.php; the original path is inREQUEST_URI,PATH_INFOonly for/index.php/extra), SPA (index.htmlfor no-extension paths, hard 404 for missing assets), Worker (static assets from disk, everything else to the persistent worker entry). The first three mirror a familiar nginxtry_filesconfiguration β see Routing - SSE streaming via
Content-Type: text/event-streamauto-detection oroxphp_stream_flush()β cooperative with fiber multiplexing β see Server-Sent Events - Timeouts β header read (
HEADER_TIMEOUT_SECONDS, slowloris protection); script execution is bounded by PHP's ownmax_execution_time/set_time_limit(), answered with 504 β see Timeouts
- LRU file cache for static files (in-memory β€1 MiB, streaming for larger) β see Static files
- HTTP caching with ETag, Last-Modified, and 304 Not Modified
- Compression for text responses (256 B β 3 MiB range) β Brotli, Zstandard and gzip, negotiated per client β see Compression
- mimalloc allocator for lower allocation latency under contention
- Configurable HTTP server threads β CPU/2 worker threads by default (single-threaded on hosts with fewer than 4 CPUs), tunable via
TOKIO_WORKERS
Full guide: Distributed tracing.
- W3C Trace Context β automatic
traceparent/tracestatepropagation,$_SERVER['OXPHP_TRACE_ID']for PHP log correlation - OpenTelemetry β OTLP span export (gRPC/HTTP) with semantic conventions, configurable sampling, batch processing
- APM auto-instrumentation β internal PHP functions across PDO, mysqli, cURL, Redis, Memcached, and file I/O hooked at the engine level; every call becomes a span with zero code changes
#[OxPHP\Apm\Trace]decorator β annotate any function or method with a PHP 8 attribute to create spans automatically- PHP tracing SDK β 10
oxphp_apm_*()functions (start,end,attribute,event,error,status,header,trace,trace_id,span_id) for manual span creation, attributes, events, error recording, and trace context propagation - Prometheus metrics at
/metricsβ per-worker, zero dependencies β see Metrics - Health checks at
/health/liveness,/health/readinessand/health/startup, with/healthaggregating them for dashboards β see Health checks - Internal server on a separate port for health, metrics, and runtime config β see Internal server
- Structured error logging β PHP errors appear in the server log with
php_error_type,php_file,php_linefields - JSON access logging with optional
trace_id/span_idfields (levels:all,error, off viaACCESS_LOG) β see Access logging - Request ID generation + pass-through (
X-Request-ID); trace-derived when OTel enabled β see Request IDs
Full guide: Profiling.
- Per-request profile capture β triggered by cookie (
OXPROF), header (X-OxPHP-Profile), query (?__oxprof=), or statistical sampling (PROFILER_SAMPLE_RATE); constant-time token compare - Four export formats β xhprof (for xhgui), speedscope (for speedscope.app), pprof (Go tools / Pyroscope), collapsed (FlameGraph)
- Rich per-span data β wall-time, CPU time, memory (start/end), events, attributes β nanosecond precision throughout
- PHP SDK β 7 functions (
OxPHP\Profile\{start, stop, pause, resume, mark, metric, is_active}) + 7 attributes (4 observer-filter:#[Profile]/#[Exclude]/#[Sample]/#[Tag]; 3 decorators:#[Mark]/#[SlowThreshold]/#[MemoryThreshold]) - Shared tree with APM β both plugins read one
Arc<SpanTree>; no double collection; APM continues to export only explicit spans to OTel while the profiler keeps the full tree - In-memory LRU + disk retention β last
PROFILER_RETENTION_COUNTruns always retrievable, token-bucket rate-limited writes, 5 s atomic-rename background trimmer - HTTP push β ship profiles to xhgui or any collector; 3Γ exponential backoff (100/200/400 ms) with 5 s wallclock cap; xhgui envelope auto-detect
- Internal HTTP routes at
/__profiler/β 8 endpoints (list / metadata / raw / speedscope redirect / DELETE / config / stats / landing) with optional bearer-token auth and path-traversal validation - Prometheus metrics β 8 counters + 1 gauge (runs, spans, bytes, disk drops, disk/HTTP saturation drops, push failures, truncated, in-memory runs) via
/metrics
- Admission control β a request waits up to
QUEUE_WAIT_TIMEOUT_MSfor a PHP worker and is refused with529+Retry-Afterpast it; the waiting set itself is bounded β see Configuration - Per-IP rate limiting with
X-RateLimit-*headers and 429 responses β see Rate limiting - Custom error pages β pre-loaded at startup, zero I/O on the hot path β see Error pages
- Graceful shutdown β on SIGTERM/SIGINT in-flight requests get up to
DRAIN_TIMEOUT_SECONDSto finish, then are cancelled β see Graceful shutdown - Path traversal protection β symlink escape detection β see Symlink allow paths
- Trusted proxy support β real client IP extraction from
Forwarded(RFC 7239),X-Forwarded-*and, behind Cloudflare,CF-Connecting-IPheaders with CIDR-based trust β see Trusted proxies - Dot-path blocking β returns 404 for hidden files (
.env,.git/) with.well-knownexception (RFC 8615) β see Dot-path blocking - Privilege drop β the container starts as root so it can bind port 80, and
oxphpdrops towww-data(UID 82; 33 in the Debian image) before handling any request;--useroverrides the target
flowchart TD
Client([Client])
HTTP["Async HTTP server<br/>single- or multi-threaded"]
Route{Route dispatch}
Static["Static file<br/>LRU cache"]
Queue[("Bounded queue<br/>529 on wait timeout")]
NF["404 Not Found"]
Pool["Async pool<br/>oxphp_async / oxphp_async_await"]
Client --> HTTP
HTTP --> Route
Route -->|static| Static
Route -->|miss| NF
Route -->|PHP| Queue
Queue --> PhpWorkers
PhpWorkers -.-> Pool
Pool --> AsyncWorkers
subgraph PhpWorkers [PHP workers β dedicated OS threads]
direction BT
W1[Worker]
W2[Worker]
W3[Worker]
end
subgraph AsyncWorkers [Async workers β dedicated OS threads]
direction BT
A1[Worker]
A2[Worker]
A3[Worker]
end
- Async HTTP server β multi-threaded by default, tunable via
TOKIO_WORKERS - PHP worker pool β each worker is a dedicated OS thread; a fatal error in one worker does not affect the others, except an allocation past PHP's hard memory limit on PHP 8.4.27 / 8.5.12 and later, which ends the whole process β see Memory limits
- Requests wait in a bounded queue between the HTTP server and the PHP workers; a request that waits longer than
QUEUE_WAIT_TIMEOUT_MSfor a worker is refused with 529 - Async pool β separate threads for
oxphp_async()tasks, preventing slowdowns in the main worker pool - Worker mode β persistent PHP workers that stay alive between requests; autoloaders and DB connections are shared across all requests handled by that worker
When INTERNAL_ADDR is set, a lightweight HTTP server starts on a separate port:
| Endpoint | Description |
|---|---|
GET /health |
Aggregate JSON health status (uptime, requests, connections); 503 when a plugin fails, no worker thread is alive, or the pool is stalled |
GET /health/liveness, /health/readiness, /health/startup |
Orchestrator probes (aliases /healthz, /readyz, /startupz) β see Health checks |
GET /metrics |
Prometheus text format metrics |
GET /config |
JSON runtime configuration (TLS paths redacted; internal_addr and error_pages_dir omitted) |
A port-only INTERNAL_ADDR (e.g. :9090) binds loopback; bind 0.0.0.0:9090 only to expose it. When the listener is reachable off-host without INTERNAL_ALLOW_IPS, the server warns at startup. Access control is by network isolation plus the INTERNAL_ALLOW_IPS CIDR allow-list β there is no bearer token by design, since a token invites exposing the port "because it's protected." Health probes are always reachable so orchestrator liveness/readiness checks never break.
APM depends on OTel and shares its TracerProvider via the plugin service registry. Span collection happens on the PHP worker thread; OTLP export runs off the hot path.
flowchart LR
subgraph Tokio1 ["Tokio thread β request start"]
TC["Trace context handler<br/>(priority -95)<br/>generates trace_id / span_id"]
OTR["OtelRequestHandler (-80)<br/>records start_us,<br/>sets X-Request-ID"]
end
subgraph PHP ["PHP worker thread"]
SDK["PHP tracing SDK<br/>oxphp_apm_*()"]
DEC["#[OxPHP\\Apm\\Trace]<br/>decorator"]
HOOKS["APM hooks (34 fn)<br/>PDO Β· mysqli Β· cURL<br/>Redis Β· Memcached Β· file I/O"]
STACK[("SpanTree<br/>per request")]
PHPERR["PHP errors"]
end
subgraph Tokio2 ["Tokio thread β request end"]
OTC["OtelCompleteHandler<br/>builds root server span"]
APC["ApmCompleteHandler (-70)<br/>reads child spans,<br/>links to root span"]
end
subgraph Export ["Background export"]
BATCH["BatchSpanProcessor<br/>(shared TracerProvider)"]
OTLP["OTLP exporter<br/>gRPC :4317 / HTTP :4318"]
end
TC --> OTR
OTR --> SDK
OTR --> DEC
OTR --> HOOKS
SDK --> STACK
DEC --> STACK
HOOKS --> STACK
STACK -->|Arc<SpanTree> via profile_tree| APC
PHPERR -->|structured log| APC
OTR --> OTC
OTC --> BATCH
APC --> BATCH
BATCH --> OTLP
- Trace context is generated first (priority
-95) whenTRACE_CONTEXT=true(auto-enabled by OTel). OTel's request handler at-80recordsstart_us; APM's handler runs at-70. - One span tree per request β APM hooks, the
#[Trace]decorator, and theoxphp_apm_*()SDK record into the same per-request span tree, handed to the complete handler asArc<SpanTree>. - Shared
TracerProviderβ OTel registersotel.provideras a plugin service; APM fetches the sameArc<OnceLock<TracerProvider>>so both plugins export to the same batch processor. - Off-hot-path export β OTel enqueues the root span into the
BatchSpanProcessor, which exports on its own thread, and APM exports child spans from atokio::spawntask; the HTTP response is returned to the client before spans are sent. - Provider lifecycle β OTel initializes the
BatchSpanProcessorinon_ready()(after the Tokio runtime starts). On shutdown,force_flush()+shutdown()drain pending spans.
All settings are via environment variables β no config files required.
The essentials β what most deployments need to get a service up:
| Variable | Default | Description |
|---|---|---|
LISTEN_ADDR |
0.0.0.0:80 |
Address and port to bind |
DOCUMENT_ROOT |
/var/www/html/public |
Filesystem path to serve files from. false switches it off: every request goes to ENTRY_FILE β see No Document Root |
ENTRY_FILE |
(unset) | Single canonical entry script. Unset or without an extension = Traditional, *.php = Framework, any other extension = SPA. Resolved against DOCUMENT_ROOT; must be absolute when it is switched off |
WORKER_MODE_ENABLED |
false |
Enable persistent worker mode. Requires ENTRY_FILE to point at a .php script |
INTERNAL_ADDR |
(unset) | Internal server for health/metrics/config. A port-only value like :9090 binds 127.0.0.1; use 0.0.0.0:9090 to expose it off-host |
INTERNAL_ALLOW_IPS |
(unset) | Comma-separated CIDRs allowed to reach /metrics, /config and other internal paths. Health endpoints (/health, /healthz, /readyz, /startupz, β¦) are always allowed. Empty = allow all. Loopback is not implicit β list 127.0.0.1/32 to keep localhost access |
TLS_CERT |
(unset) | Path to TLS certificate PEM file |
TLS_KEY |
(unset) | Path to TLS private key PEM file |
SUPERGLOBALS_ENABLED |
true |
Build $_SERVER and $_GET; set false to skip that and read the request through oxphp_http_request(). $_POST, $_FILES and $_COOKIE are built either way |
ASYNC_WORKERS |
0 (disabled) |
Dedicated async worker threads for oxphp_async() |
Worker pool, queue, rate limiting, timeouts, TLS tuning, static file caching, compression, access logs, trusted proxies, PHP-execution deny rules, and every plugin-scoped variable live in the consolidated reference β see Configuration for the full table.
Boolean values (case-insensitive, trimmed): truthy =
on/true/1/yes; falsy =off/false/0/no. Any non-empty value outside that set β typos liketureβ fails fast at startup with an error naming the variable. An unset variable or empty assignment (FOO=) falls back to the default, so Docker Compose / Kubernetes substitutions likeFOO=${FOO}work cleanly when the host variable is missing.
Plugin-scoped env vars (the OTEL_*, OTEL_APM_*, and SHARED_* families) live in the consolidated configuration reference so there is one source of truth:
- OpenTelemetry (
plugin-otel): Configuration β OpenTelemetry. For the export pipeline end-to-end, see the Distributed tracing guide. - APM (
plugin-apm): Configuration β APM. RequiresOTEL_ENABLED=true. - Shared State (
plugin-shared): Configuration β Shared State. Concept-level walkthrough lives in the Shared state guide.
# Host (without PHP β stub executor, no PHP execution)
cargo build --release --no-default-features
# Docker (with PHP β full functionality)
docker compose buildLISTEN_ADDR=127.0.0.1:8080 DOCUMENT_ROOT=./www/public ./target/release/oxphpItems are not ordered by priority. Presence on this list does not guarantee implementation.
| Feature | Description |
|---|---|
β
Implemented β automatic propagation of traceparent / tracestate headers (W3C spec), enabled via TRACE_CONTEXT=true |
|
β
Implemented β OTLP trace export via plugin-otel feature, W3C context propagation, per-request spans with standard semantic conventions |
|
β
Implemented β plugin-apm feature: automatic tracing of internal PHP functions across PDO, mysqli, cURL, Redis, Memcached, and file I/O, #[OxPHP\Apm\Trace] decorator, 10 oxphp_apm_*() SDK functions, PHP error capture |
|
| Custom Metrics | PHP API for registering application-defined Prometheus metrics from userland code |
β
Implemented β plugin-profiler feature: per-request profiling with xhprof/speedscope/pprof/collapsed formats, PHP SDK, attribute triggers, in-memory LRU + disk retention, HTTP push to xhgui, /__profiler/ internal routes, Prometheus metrics β see Profiling |
|
β
Implemented β every release from 0.13.0 on is also published on Debian trixie (glibc) as :trixie, :php8.5-trixie and the release's other tags with a -trixie suffix, an alternative to the default Alpine image β see Debian (glibc) Image |
|
| Non-Docker Install | (speculative) Native installation via system package managers (apt, brew, etc.) |
| HTTP/3 | QUIC-based HTTP/3 support |
| HTTP 103 Early Hints | Send 103 Early Hints responses to allow clients to preload resources before the final response |
| Ecosystem Plugins | Expanded plugin system: more lifecycle hooks, richer PHP API, and documentation for third-party plugin authors |
β
Implemented β the same async runtime powers both the HTTP server and oxphp_async() / oxphp_async_await() with timeouts, result delivery, and race coordination |
|
β
Implemented β oxphp_async() / oxphp_async_await() with dedicated thread pool, portable serialization, and exception safety |
|
β
Implemented β each worker handles multiple concurrent requests via PHP Fibers; oxphp_sleep() / oxphp_usleep() and oxphp_async_await() yield the fiber cooperatively |
|
| Diagnostics | Production doctor: checks OS limits (ulimit, TCP backlog, epoll/kqueue, container settings), identifies performance bottlenecks (worker queue depth, lock contention, GC/alloc pressure, ZTS stats), and gives specific actionable recommendations |
| TLS hot-reload | Reload TLS certificate and key without restart β compatible with cert-manager / SPIRE / istiod short-lived rotation, removes the rolling-restart-per-rotation workaround |
| SPIFFE Workload API | Native client for SPIFFE/SPIRE workload identity: streaming SVIDs over Unix socket with cryptographic node attestation, as an opt-in alternative to file-mount cert distribution |
| FIPS-validated TLS | Cargo-feature switch from rustls + ring to rustls + aws-lc-rs with the fips feature for FIPS 140-2 / 140-3 compliance in regulated deployments |
oxphp.dev β English Β· Π ΡΡΡΠΊΠΈΠΉ Β· δΈζ Β· FranΓ§ais Β· Polski Β· ζ₯ζ¬θͺ
The English source of the documentation also lives in this repository under docs/.
Built and evolved with AI under careful human guidance.