docs/guide/running-with-frankenphp.md
FrankenPHP is a PHP application server that packages a webserver (Caddy) and the
PHP runtime into a single binary, with automatic HTTPS. Koel ships a Caddyfile.example at the project
root to use with it.
::: tip Want a one-download install instead? The Standalone Binary distribution from koel/franken packages FrankenPHP, Koel, and a launcher into a single archive. This page is for installing FrankenPHP yourself as the runtime for an existing Koel install. :::
FrankenPHP is only the runtime. Install Koel first via Pre-Compiled Archive or Building from Source, then use FrankenPHP as the webserver.
Pre-built binaries are published at frankenphp.dev/docs/#install. On Linux, the one-line installer fetches the right binary for your architecture:
curl https://frankenphp.dev/install.sh | sh
sudo mv frankenphp /usr/local/bin/
From the Koel project root:
cp Caddyfile.example Caddyfile
Edit Caddyfile and replace localhost with the domain you'll serve from. Using a real public domain enables automatic
HTTPS via Let's Encrypt.
frankenphp run
That's it — Koel is now served on port 443 (and 80, redirected to HTTPS).
FrankenPHP ships its own PHP, available via the php-cli subcommand. Any php artisan … from Koel's CLI
documentation becomes:
frankenphp php-cli artisan <command>
For example, frankenphp php-cli artisan migrate runs database migrations and frankenphp php-cli artisan koel:sync triggers a media scan. For convenience: alias artisan='frankenphp php-cli artisan'.
If you also have system PHP installed (e.g. for composer install), running php artisan <command> against
it works the same — both share the same .env and database.
::: warning DB_HOST=localhost gotcha
If your .env has DB_HOST=localhost with MySQL, FrankenPHP's PHP will fail to find the MySQL socket and
you'll see Checking database connection … ERROR when running koel:init, even though HTTP serving works
fine. Fix it one of two ways:
DB_HOST=127.0.0.1 frankenphp php-cli artisan <command>.env to DB_HOST=127.0.0.1.
:::For FrankenPHP CLI options not covered here (worker mode, multi-domain serving, custom PHP flags, etc.), refer to the official FrankenPHP documentation.
For a production deployment, run FrankenPHP under systemd so it starts on boot and restarts on failure. Create
/etc/systemd/system/koel.service:
[Unit]
Description=Koel (FrankenPHP)
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/koel
ExecStart=/usr/local/bin/frankenphp run
Restart=on-failure
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
Adjust WorkingDirectory and User to match where Koel lives on your host. Then enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now koel
sudo journalctl -u koel -f
If you're already running nginx (or another reverse proxy) and want to use FrankenPHP only as the PHP runtime, make two
changes to your Caddyfile:
auto_https off and servers { trusted_proxies … } block at the top — Caddyfile.example ships
it commented and ready for this case. Adjust the trusted-proxies CIDR if the reverse proxy lives on a different
host.localhost { to :8001 { and add bind 127.0.0.1 as
the first line inside the block. Everything else inside the site block stays as-is.Then point your existing reverse proxy at 127.0.0.1:8001 and let it terminate TLS as before.