Deployment¶
Loxodontu is built to run on ordinary shared PHP hosting — the kind where a cPanel-style control
panel gives you a document root, mod_rewrite, and a way to schedule one file or one URL, but no
containers, process managers, or persistent workers. This page covers deploying it there, and to
Apache in general.
Requirements on the host¶
- PHP 8.2 or 8.3, with the
mbstring,pdo, andpdo_mysqlextensions enabled. These are the versions and extensions tested in CI. - MySQL 8.0+ or MariaDB 11+, reachable from the host.
- Apache with
mod_rewriteenabled — standard on virtually all shared hosting.
Request lifecycle¶
There's no separate public/ webroot — the document root points at the repository root itself,
where .htaccess and index.php live.
.htaccessforces HTTPS, strips a leadingwww., disables directory listing, hides theX-Powered-Byheader, lets requests underassets/andpublic/through untouched, blocks direct access to every.phpfile exceptindex.php(404), and rewrites everything else toindex.php.index.phploadsbootstrap.php, builds the Erlenmeyer app, requiresroutes/index.php(which itself loads the 404/exception handler first), then dispatches.bootstrap.phpautoloads Composer, loads.env(non-fatal if missing), configures the database connection based onDB_MODE, and — only whenENV=development— turns on verbose PHP error display.
Locally, router.php stands in for .htaccess when using PHP's built-in server
(php -S localhost:8000 router.php); it mirrors the same rewrite behavior minus the
HTTPS/www redirects, which only make sense behind real TLS termination.
Deploy steps¶
- Upload the repository (or
git clone) so the document root is the repo root. composer install --no-dev --optimize-autoloader(drop--no-devif you also want Pest available on the host, e.g. to run tests there).- Create
.envfrom.env.exampleand fill in production values — at minimum theDB_*_PRODvariables andDB_MODE=production(or any value other thandevelopment/testing). SetENV=productionandDEBUG=false. See Configuration for the full list. - Run migrations:
php vendor/bin/fullcrawl --run. See Getting Started for the full migration workflow — this is additive, not--fresh. - Confirm
mod_rewriteis on and.htaccessis being read (some hosts disableAllowOverrideby default — check with your provider if routes 404 unexpectedly). -
Hit
/api/healthto confirm the app is serving:
Shared-hosting specific gotchas¶
EDGE_PHP_BINARY. If you use edge functions, shared hosts frequently
alias PHP_BINARY to something like lsphp or php-cgi, which can't be spawned as a plain CLI
interpreter the way the sandbox needs. Set EDGE_PHP_BINARY to the actual CLI binary path (ask
your host, or check what php -v resolves to over SSH) if edge functions fail to run.
Cron. Shared hosts typically let you schedule exactly one file or one URL — not a
long-running worker. Loxodontu's cron jobs are designed around that: point the
host's cron scheduler at worker.php, either as a CLI command or a URL hit, and set
CRON_WORKER_TOKEN if the URL is reachable from the public internet.
command-type cron jobs are disabled by default (CRON_ALLOW_COMMANDS=false) because they
execute arbitrary shell commands on the host under the web server's user. Only enable this if you
trust every person who can create cron jobs on the instance.
Only MySQL/MariaDB. Schema alterations, error handling, and the REST passthrough layer all assume MySQL-flavored SQL. If your host only offers PostgreSQL, Loxodontu won't work correctly even though a Postgres DSN can technically be built.