Host a PHP website

Run PHP on Falix's PHP Web Server application — nginx and PHP-FPM under supervisord, pretty URLs through a front controller, and how to bring in Composer packages.

Skip the setup This guide has a one-click starter template that installs everything below onto your server.

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_PORT baked into its config, and a fresh PHP Web Server's default config doesn't do that substitution — so it crash-loops with host 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.
  • .php files 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 to index.php and keeps the query string. That means one index.php can 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 install for you — a composer.json sitting 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 (public by 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 set display_errors on 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 in php-fpm.conf and 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.

Next steps

Was this guide helpful?