PHP still runs a huge share of the web, and Falix has an application built for it: the PHP Web Server. Unlike the plain PHP CLI, this one puts a real nginx and PHP-FPM in front of your code, so you serve a proper website — static assets, .php pages, and clean URLs — not just a script. This guide covers how it fits together and how to bring in Composer libraries.
| At a glance | |
|---|---|
| You need | A server running the PHP Web Server application, and comfort editing files |
| Plan | Any plan |
| Time | Twenty minutes |
If servers are new to you, read Create your first app server first.
How it runs
The application's startup command is supervisord -c /home/container/supervisord.conf. supervisord is a small process manager; here it keeps two things alive together: PHP-FPM (which executes your PHP) and nginx (which serves files and hands .php requests to PHP-FPM). Your site lives in the folder named by the Web Root variable — public by default.
⚠️ Heads up: nginx needs your assigned
SERVER_PORTbaked into its config, and a fresh PHP Web Server's default config doesn't do that substitution — so it crash-loops withhost not found in "SERVER_PORT"and nothing serves. The fix isn't to hand-patch config files; it's to deploy the template first.
Step 1 — Deploy the template
Use the PHP website template on this page. It ships the working stack: a supervisord.conf, an nginx.template.conf that gets your real port and web root filled in at boot, a php-fpm.conf, and a sample public/index.php. Deploying it onto a fresh PHP Web Server is what turns "crash-loop" into "serving."
(A template only overwrites same-named files. Deploying it onto a server running a different application switches that server to PHP Web Server first — a reinstall that wipes files, which the panel warns about. On a fresh PHP Web Server there's nothing to lose.)
Press Start, then open your server's address (from the Network page). The sample page loads and prints the PHP version — proof that nginx, PHP-FPM, and your port are all wired correctly.
How pages are served
Everything lives in public/:
- Static files (
.css,.js, images,.html) are served directly by nginx, fast, with no PHP involved. .phpfiles are executed by PHP-FPM and their output is returned.- Pretty URLs work through a front controller. nginx's rule is
try_files $uri $uri/ /index.php?$query_string: if the requested path isn't a real file or folder, nginx falls back toindex.phpand keeps the query string. That means oneindex.phpcan route your whole site.
A minimal front controller looks like this — save it as public/index.php:
<?php
$path = strtok($_SERVER['REQUEST_URI'], '?');
switch ($path) {
case '/':
echo 'Home page';
break;
case '/about':
echo 'About page';
break;
default:
http_response_code(404);
echo 'Not found';
}
Now /about works even though no about.php file exists — nginx routed it to index.php, which read the path and responded. Query values like /search?q=cats are still available in $_GET as usual.
Composer packages
🎯 Good to know: Unlike the PHP Composer application, the PHP Web Server does not run
composer installfor you — acomposer.jsonsitting in your files does nothing on its own.
You have three ways to get a vendor/ folder onto the server:
| Route | How | Best when |
|---|---|---|
| Packages page | Runs the real composer require in a helper container against your files, writing vendor/ to your disk (restart after) |
You want it done in the panel |
Upload vendor/ |
Run composer install on your own machine, upload the folder via File Manager or SFTP |
You already build locally |
| Git deploy | Add composer install as a post-deploy command, built on the server after each pull — see Add build steps to a deploy |
You deploy from Git |
Whichever you choose, require 'vendor/autoload.php'; at the top of your PHP then works normally.
Uploads and sessions
Two things most PHP sites eventually need — file uploads and sessions — run through PHP's own settings, which the template leaves at PHP's built-in defaults.
File uploads. PHP caps upload and request-body sizes with upload_max_filesize and post_max_size, and the built-in defaults are small — a large upload quietly fails, or the form arrives empty. To raise them, add lines to the [www] pool in php-fpm.conf (the file the template ships) and restart:
php_admin_value[upload_max_filesize] = 20M
php_admin_value[post_max_size] = 24M
Keep post_max_size a little above upload_max_filesize so the whole form fits. Those numbers are just examples — set what suits your app.
Sessions. session_start() works, and PHP writes session data to its default temporary location. If your console shows a failed to write session data warning, that default path isn't writable in the container — point sessions at a folder you own before starting them:
session_save_path(__DIR__ . '/../tmp');
session_start();
The startup already creates a tmp/ folder next to public/, which makes a safe home for session files.
Troubleshooting
host not found in "SERVER_PORT"in the console — the default config never substituted your port. Deploy the PHP website template, which ships the config that does.- 404 on everything — nginx is looking in the wrong folder. Your files must be inside the Web Root folder (
publicby default); confirm the Web Root variable in Settings matches where your files actually are. - Blank white page — usually a PHP fatal error that isn't shown to the browser. Open the File Manager and read
logs/php-fpm.log; the console (nginx/PHP-FPM output) also carries errors. For local debugging you can setdisplay_errorson in your code, but keep it off in anything public. - A file upload fails, or a large form arrives empty — you've hit PHP's default
upload_max_filesize/post_max_size. Raise both inphp-fpm.confand restart (see Uploads and sessions above). - Can't reach it at all — a reachability problem rather than a PHP one: I can't reach my app.