Security & Deployment

Fast is built with security in mind and ships with sensible defaults, but a safe deployment still needs a few things from you: TLS (either terminated in Fast or at a proxy), careful handling of secrets, and the right OS limits. This page pulls that guidance together.

Fast's threat model

Fast treats every public input, HTTP, WebSocket, SSE, timing, and framing, as untrusted. Your handlers, middleware, route registrations, raw SQL fragments, and server-side publishers are trusted application code. The line is clear: data from the network is hostile until proven otherwise; code you wrote is trusted.

That framing tells you where your responsibility lies. Fast defends the wire; you must not undo that by, say, concatenating request input into raw SQL or emitting unescaped user data into HTML.

Terminating TLS

Fast can terminate TLS itself on every runtime (see TLS & HTTPS): pass serve(tls: Fast\Tls\TlsConfig::certificate(...)), or on POSIX let it obtain and renew a Let's Encrypt certificate with TlsConfig::letsEncrypt(...). TLS is opt-in and only asks for ext-openssl.

You can still run behind a trusted reverse proxy (nginx, Caddy, a load balancer) that terminates HTTPS and forwards to a plaintext Fast listener over the local network. Leave tls unset for that setup.

Whichever you choose, the fronting hop must preserve the original Host header. Fast's default browser-origin policy compares the request's Origin authority against Host while ignoring scheme, which is what lets HTTPS forward to HTTP workers. If a proxy cannot preserve Host, configure explicit WebSocket origins with ws(..., origins: [...]).

Secrets and static roots

The single most important deployment rule concerns secrets and static files:

Your .env.php is executable, secret-bearing PHP. Keep it outside every files() static root and outside any directory writable by untrusted users. Static roots themselves must not be writable by untrusted users; Fast validates resolved paths, but correct ownership is still required to prevent symlink or TOCTOU replacement attacks.

In short: a dedicated assets directory for files(), and everything sensitive kept well away from it.

Cookies and sessions

Set session cookies Secure, HttpOnly, and with an appropriate SameSite policy. Fast defaults to all three (SameSite=Lax), so the safe path is the default path. Only turn off Secure for local HTTP development. Session tokens use authenticated encryption, a sealed expiry, key rotation, and session-id regeneration on login, so as long as you keep your key stable and secret, sessions are tamper-evident out of the box.

Secure defaults you get for free

A lot of hardening is already on, and it is worth knowing it is there:

  • Request framing rejects every Transfer-Encoding, repeated or malformed

Content-Length, folded header, and oversized header or body before ambiguous bytes reach a handler by default. A route-scoped BodyPolicy may opt into one exact chunked coding or a larger body without relaxing duplicate-header, dual-framing, syntax, decoded-size, or trailer defenses.

  • Header and body phases have absolute deadlines (10s and 30s by default) that

trickled bytes cannot extend.

  • Each worker caps concurrent public connections (1,024 by default), closing excess

sockets without a response.

  • WebSocket upgrades reject foreign, malformed, and null origins by default.
  • Live component actions and Live Stream subscriptions both enforce their authority

and authorization boundaries before doing any work.

  • All subsystem IPC frame lengths are bounded before any body is allocated.

The local process boundary

Fast's internal IPC (for KV, sessions, streams, the database) uses uid-owned 0700 directories with 0600 sockets on Unix, or loopback with per-boot secrets on TCP. These controls stop accidental or unauthenticated loopback access.

They are not a sandbox against another compromised process running as the same OS user. Keep unrelated tenants under different OS accounts or hosts. Fast's process boundary protects against outside access, not against a co-resident attacker already running as you.

Sizing for production

Finally, size your OS limits to your configuration. Raise the file-descriptor limit (ulimit -n on POSIX) above your connection budget: roughly maxConnections per worker for prefork and single-process, and about workers × maxConnections × 2 for the proc-pool master. Include memory headroom per slow connection, too, up to 1 MiB of waiting WebSocket payload or SSE mailbox frames each.

To report a vulnerability, use the repository's private security advisory flow rather than a public issue, and do not publish an exploit before a fix is available.

That completes deployment. The last section covers how to test your Fast app, starting with The Test Harness.