podman:generate/podman:setup only render files — they never touch the podman binary, so they run anywhere PHP does. The output is a build artifact: don't commit it, and feel free to delete and regenerate it any time.
Normal workflow: render on your dev machine as usual (php artisan podman:setup), then copy the generated podman/ folder to production and install it there with lpod. Production needs no PHP, and lpod doesn't need this package installed either.
What if there's no PHP on the rendering machine either? Install dependencies and render inside disposable containers, using the same composer/php:8.5-cli images lpod-setup defaults to:
# vendor/ has to exist before "podman:setup" can boot at all
podman run --rm --userns=keep-id -u "$(id -u):$(id -g)" \
-v "$PWD":/app:Z -w /app docker.io/library/composer:2 \
install --no-dev --optimize-autoloader --no-interaction
podman run --rm --userns=keep-id -u "$(id -u):$(id -g)" \
-e PODMAN_WORKING_PATH="$PWD" \
-v "$PWD":/var/www/html:Z -w /var/www/html docker.io/library/php:8.5-cli \
php artisan podman:setup --preset=frankenphp-octane
# On the host: install, then set secrets
lpod install frankenphp-octane/pgsql.quadlets --replace
lpod pgsql secrets
Example output for an app named acme — podman/frankenphp-octane/valkey.quadlets:
# FileName=acme-valkey
[Unit]
Description=Valkey container
[Container]
Image=docker.io/valkey/valkey:latest
AutoUpdate=registry
Exec=valkey-server --save --loglevel warning
Volume=acme-valkey:/data:rw,Z,U
Network=acme.network
ExposeHostPort=6379
[Service]
Restart=always
RestartSec=5
TimeoutStartSec=120
TimeoutStopSec=60
---
# FileName=acme-valkey
[Volume]
Label=acme-valkey
VolumeName=systemd-acme-valkey
lpod install frankenphp-octane/valkey.quadlets --replace
A few things worth knowing about this approach:
PODMAN_WORKING_PATH/--working-path= only change the host paths baked into the rendered files — rendering itself always happens from /var/www/html here.--userns=keep-id -u "$(id -u):$(id -g)" keeps the generated files owned by you, not root. Keep :Z on SELinux hosts.lpod setup wraps the podman run command above, once lpod (which also ships lpod-setup) is on the host. Add --install to install immediately, or --secrets to also set secrets.lpod needs nothing else from this project — that's what makes a production install truly standalone. lpod-setup itself still shells out to php artisan podman:setup, which needs this project's vendor/. That's why copying already-rendered output is the normal path for production.See lpod CLI for the full command reference.