Environment variables

Env is the contract between the image, CI, and Bunny. The same image runs dev, CI, and prod — only the env file changes. Set these in .env.docker.dev / .env.docker.prod; never bake secrets into the image.

Always set

Var Value
APP_NAME Public product name (Filament brandName, mail from-name, HTML title). PHP fallback is "Qcentic Edge Template".
APP_KEY Stable forever. Generate: php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;"
APP_URL App origin, no trailing slash.
APP_ENV / APP_DEBUG production / false on Magic Containers.

Database (libSQL)

Var Value
DB_CONNECTION libsql
DB_URL libsql://[id].lite.bunnydb.net (or Turso / self-hosted sqld). Empty in dev defaults to the local sqld sidecar.
DB_AUTH_TOKEN Required for remote libSQL.

Session, cache, and queue all use the database driver on libSQL — zero extra services.

Object storage (Bunny S3 map)

Bunny Storage speaks the S3 API. Map the zone fields precisely:

Bunny field Env var
Zone name AWS_ACCESS_KEY_ID + AWS_BUCKET
Zone password AWS_SECRET_ACCESS_KEY
Region code (de / ny / …) AWS_DEFAULT_REGION (never a URL)
S3 API host AWS_ENDPOINT=https://{region}-s3.storage.bunnycdn.com
Pull zone hostname AWS_URL

AWS_ENDPOINT is the S3 API host; AWS_URL is the public/CDN base. Storage::url() uses AWS_URL; Storage::temporaryUrl() signs against AWS_ENDPOINT. Set retain_visibility=false on the disk — Bunny has no object ACLs, so copies must not call GetObjectAcl.

Assets

Var Value
ASSET_URL Prefixes asset() / Vite build URLs for a static-asset CDN. Empty = app origin.

Applied at PHP runtime, so one image serves many CDN origins. Do not set Vite base to a CDN in vite.config.js — that bakes the origin into the build.

Livewire

Var Value
LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK s3 on multi-replica Magic Containers; local is OK in single-container compose.

On multiple pods the upload request and the form submit can land on different replicas — only the shared S3 disk is visible to both.

Passport / API

Var Value
PASSPORT_PRIVATE_KEY / PASSPORT_PUBLIC_KEY PEM in env, one-line \n-escaped for Magic Containers. Same class of secret as APP_KEY.
API_KEY Content API Bearer key, if the Content API plugin is enabled.

Generate with php artisan passport:keys, paste the \n-escaped PEM, then delete storage/oauth-*.key — Magic Containers have no persistent disk.

Realtime

Var Value
BROADCAST_CONNECTION reverb (default) points at a Reverb process or remote Reverb host. pusher = Pusher Cloud (clone option). log = broadcasts off.
REVERB_HOST Reverb hostname clients connect to.
REVERB_SCALING_ENABLED Off by default (in-memory fan-out). On only with Redis, typically when replica count > 1.

CDN WebSockets (Bunny pull-zone feature) stay off until enabled — it sits in front of Reverb, not instead of it. On a CaaS HTTP-only deploy (Magic Containers, Cloud Run, Cloudflare Containers/Workers) there is no Reverb in the pod: either run Reverb on a self-hosted host and point REVERB_HOST, or set BROADCAST_CONNECTION=pusher (Pusher Cloud) or log (off). See Laravel broadcasting docs.

Queue

Var Value
QUEUE_CONNECTION database (default, libSQL) on self-hosted compose/k8s/VPS — a queue:work daemon must run there. sync = no worker, jobs run inline. redis / sqs / … via Laravel queue docs.

The queue worker is a self-hosted always-on process (ADR 0009), not a CaaS sidecar. On a CaaS HTTP-only deploy, leave QUEUE_CONNECTION=sync (no daemon) or point at a vendor queue (redis / sqs) per Laravel queue docs.

Installer

Var Value
INSTALLER_ENABLED true on first deploy; false after the DB lock is set.

The env var opens the app; the installer_locks row records that setup ran. See the first-run installer page for the two-gate flow.

See also:

Built by Qcentic