The environment file
Every variable read from .env, its default, and which ones to set before the first boot.
Everything that changes between machines lives in .env. Anything that belongs to the product itself is a committed value in config/. This guide walks the whole file, group by group, so you can see in one place what the application reads. The variables that belong to a feature are named here too, with a link to the guide that explains the feature.
Set these before the first boot
.env.example is a copy of a server configuration, with placeholders where the secrets go. Before the first request, decide these:
| Variable | Why it cannot wait |
|---|---|
APP_KEY |
php artisan key:generate writes it; without it nothing encrypts |
APP_NAME |
names the site, the emails, the PWA and the session cookie |
APP_URL |
every absolute link, the PWA scope and the SMTP hello domain come from it |
DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD |
the migration needs them |
FILESYSTEM_DISK |
ships as s3 with fake AWS keys; set public until you have a bucket |
MAIL_MAILER |
ships as failover, which needs Mailgun or SES credentials; set log locally |
MAIL_FROM_ADDRESS |
the sender of every email; the example value is not yours |
SESSION_DRIVER |
keep database: the device list in the account reads the sessions table |
Everything else has a default that lets the application boot. The placeholders left in .env.example for AWS_*, TELNYX_*, STRIPE_* and AUTH_VALIDATION_PROVIDER are harmless until the feature that reads them is turned on; delete them or replace them when you get there.
Values with spaces need quotes: APP_NAME="Your Project". A variable that is present but empty is read as an empty string, not as absent, so remove a line rather than blanking it when you want the default back.
Application
Read by config/app.php.
| Variable | Default | Purpose |
|---|---|---|
APP_NAME |
Laravel |
Shown in the interface, the emails, the manifest; also seeds the default cookie, cache and Redis prefixes |
APP_ENV |
production |
local on your machine. php artisan env prints what the application believes |
APP_KEY |
none | Encryption key, written by key:generate |
APP_PREVIOUS_KEYS |
empty | Comma-separated older keys, so values encrypted with them still decrypt after a rotation |
APP_DEBUG |
false |
Detailed error pages and the Debugbar. Never true in production; it also loosens the session cookie, see below |
APP_URL |
http://localhost |
Root URL for links built outside a request, the public disk URL, the PWA scope and VAPID_SUBJECT |
ASSET_URL |
none | Serve compiled assets from another host or CDN |
APP_LOCALE |
es |
Language before anyone chooses one; also the lang of the PWA manifest. Must be a key of languages in config/app.php. The fallback locale is committed as es |
APP_MAINTENANCE_DRIVER |
file |
file or cache; cache lets several servers share maintenance mode |
APP_MAINTENANCE_STORE |
database |
Cache store used when the driver is cache |
APP_PWA |
false |
Turns on the service worker and the manifest. See Web push and the PWA |
COUNTRY_CODE_FALLBACK |
US |
Country assumed when the IP cannot be resolved, such as on 127.0.0.1. See Detect the visitor's country |
Database
Read by config/database.php. DB_CONNECTION picks one of sqlite, mysql, mariadb, pgsql or sqlsrv; the other variables are shared by all of them. The queue's failed_jobs and job_batches tables use the same connection.
| Variable | Default | Purpose |
|---|---|---|
DB_CONNECTION |
mysql |
Which connection block is the default |
DB_URL |
none | A single connection URL that replaces host, port, database, username and password |
DB_HOST |
127.0.0.1 (localhost for SQL Server) |
Server address |
DB_PORT |
3306 MySQL and MariaDB, 5432 PostgreSQL, 1433 SQL Server |
Server port |
DB_DATABASE |
laravel; for SQLite database/database.sqlite |
Database name, or the SQLite file path |
DB_USERNAME |
root |
Database user |
DB_PASSWORD |
empty | Database password |
DB_SOCKET |
empty | Unix socket for MySQL and MariaDB instead of host and port |
DB_CHARSET |
utf8mb4 MySQL and MariaDB, utf8 others |
Connection charset |
DB_COLLATION |
utf8mb4_unicode_ci |
Collation for MySQL and MariaDB |
DB_FOREIGN_KEYS |
true |
Enforce foreign keys on SQLite |
MYSQL_ATTR_SSL_CA |
none | Path to a CA certificate for TLS to MySQL or MariaDB |
DB_ENCRYPT, DB_TRUST_SERVER_CERTIFICATE |
none | Listed in the SQL Server block but commented out; nothing reads them until you uncomment those lines |
Read by config/mail.php, with the provider credentials in config/services.php. The kit sends verification codes, password resets, notifications and billing emails, so a working mailer is not optional once real people sign up. How each transport is set up end to end, SMS included, is in Email and SMS delivery.
MAIL_MAILER chooses the transport. The mailers defined are smtp, ses, mailgun, postmark, resend, sendmail, log, array, failover and roundrobin. The two composite ones are committed in config/mail.php:
failovertriesmailgun, thenses, and waits 60 seconds before retrying a transport that failed. It is the value shipped in.env.example.roundrobinalternates betweensesandpostmark.
Verification emails have one more safety net: after the default mailer fails, the code is sent again through each mailer in mail_fallbacks in config/auth.php, which ships as ['mailgun'].
| Variable | Default | Purpose |
|---|---|---|
MAIL_MAILER |
smtp in config, failover in .env.example |
Transport to use |
MAIL_FROM_ADDRESS |
[email protected] |
Sender address of every email |
MAIL_FROM_NAME |
APP_NAME |
Sender name |
MAIL_SCHEME |
none | smtp or smtps for the SMTP transport |
MAIL_URL |
none | A single SMTP URL that replaces host, port, username and password |
MAIL_HOST |
127.0.0.1 |
SMTP server |
MAIL_PORT |
2525 |
SMTP port |
MAIL_USERNAME |
none | SMTP user |
MAIL_PASSWORD |
none | SMTP password |
MAIL_EHLO_DOMAIN |
host of APP_URL |
Domain announced in the SMTP EHLO |
MAIL_SENDMAIL_PATH |
/usr/sbin/sendmail -bs -i |
Binary for the sendmail transport |
MAIL_LOG_CHANNEL |
none | Log channel the log transport writes to; the default channel when empty |
MAILGUN_DOMAIN |
mg.weblabor.mx |
Your Mailgun sending domain. Change it: the default is Weblabor's |
MAILGUN_SECRET |
none | Mailgun API key |
MAILGUN_ENDPOINT |
api.mailgun.net |
api.eu.mailgun.net for the EU region |
POSTMARK_TOKEN |
none | Postmark server token |
POSTMARK_MESSAGE_STREAM_ID |
none | Postmark message stream |
RESEND_KEY |
none | Resend API key |
Amazon SES reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION from the files group below; the region defaults to us-east-1 for SES when the variable is missing.
Files and storage
Read by config/filesystems.php. Three disks exist: local in storage/app/private, public in storage/app/public served at APP_URL/storage through the link that php artisan storage:link creates, and s3. Uploads and image handling are in Files, images and storage.
| Variable | Default | Purpose |
|---|---|---|
FILESYSTEM_DISK |
s3 |
Disk used when none is named. Set public for files people can see, local for files they cannot |
AWS_ACCESS_KEY_ID |
none | AWS key. Shared by S3, SES, SQS, DynamoDB, Bedrock and the SNS phone codes |
AWS_SECRET_ACCESS_KEY |
none | AWS secret, shared the same way |
AWS_DEFAULT_REGION |
none for S3 | Bucket region. SES, SQS and DynamoDB fall back to us-east-1; the SNS phone codes fall back to us-west-1 |
AWS_BUCKET |
none | Bucket name |
AWS_URL |
none | Public URL of the bucket when it is not the AWS default, such as a CDN in front of it |
AWS_ENDPOINT |
none | Custom endpoint for an S3-compatible service such as MinIO or DigitalOcean Spaces |
AWS_USE_PATH_STYLE_ENDPOINT |
false |
true for services that put the bucket in the path instead of the host |
LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK |
the default disk | Where Livewire parks a file while a form is still open |
Queues
Read by config/queue.php. Notifications, web push and billing all run through the queue, so a worker has to be running in every environment; see Queues and scheduled work. The database driver needs no extra service.
| Variable | Default | Purpose |
|---|---|---|
QUEUE_CONNECTION |
database |
sync, database, beanstalkd, sqs, redis or null. sync runs jobs inline, useful only in tests |
QUEUE_FAILED_DRIVER |
database-uuids |
Where failed jobs are kept: database-uuids, dynamodb, file or null |
DB_QUEUE_CONNECTION |
the default connection | Database connection for the database driver |
DB_QUEUE_TABLE |
jobs |
Table for the database driver |
DB_QUEUE |
default |
Queue name for the database driver |
DB_QUEUE_RETRY_AFTER |
10 |
Seconds before a job still running is retried. Raise it above your longest job |
BEANSTALKD_QUEUE_HOST |
localhost |
Beanstalkd server |
BEANSTALKD_QUEUE |
default |
Beanstalkd tube |
BEANSTALKD_QUEUE_RETRY_AFTER |
90 |
Retry seconds for Beanstalkd |
SQS_PREFIX |
an AWS placeholder URL | Your SQS queue URL prefix, https://sqs.<region>.amazonaws.com/<account id> |
SQS_QUEUE |
default |
SQS queue name |
SQS_SUFFIX |
none | Suffix appended to the queue name, used with FIFO queues |
REDIS_QUEUE_CONNECTION |
default |
Redis connection for the redis driver |
REDIS_QUEUE |
default |
Redis queue name |
REDIS_QUEUE_RETRY_AFTER |
90 |
Retry seconds for Redis |
SQS also reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION.
Session
Read by config/session.php. Two defaults differ from a stock Laravel install: the lifetime is a year, and the cookie flags follow APP_DEBUG and APP_PWA.
| Variable | Default | Purpose |
|---|---|---|
SESSION_DRIVER |
file in config, database in .env.example |
Keep database: the devices list at /account and the "disconnect" buttons read the sessions table |
SESSION_LIFETIME |
525600 |
Idle minutes before a session expires; the default is one year. The devices list only shows sessions inside this window |
SESSION_EXPIRE_ON_CLOSE |
false |
Expire when the browser closes |
SESSION_ENCRYPT |
false |
Encrypt the stored session payload |
SESSION_CONNECTION |
the default connection | Database or Redis connection for the session |
SESSION_TABLE |
sessions |
Table for the database driver |
SESSION_STORE |
none | Cache store for the memcached, redis and dynamodb drivers |
SESSION_COOKIE |
slug of APP_NAME plus -session |
Cookie name |
SESSION_PATH |
/ |
Cookie path |
SESSION_DOMAIN |
none | Cookie domain; set it to share the session across subdomains |
SESSION_SECURE_COOKIE |
false when APP_DEBUG is on, otherwise the value of APP_PWA |
Send the cookie only over HTTPS. An installed PWA needs it |
SESSION_HTTP_ONLY |
true |
Hide the cookie from JavaScript |
SESSION_SAME_SITE |
lax when APP_DEBUG is on; otherwise none if APP_PWA is on, else lax |
none is what lets the installed PWA keep its session; it requires the secure flag |
SESSION_PARTITIONED_COOKIE |
false |
Partition the cookie by top-level site; needs secure and same_site=none |
Cache
Read by config/cache.php. The database store needs no extra service and is the default.
| Variable | Default | Purpose |
|---|---|---|
CACHE_STORE |
database |
array, database, file, memcached, redis, dynamodb, octane or null. Also the store for embedding caches in config/ai.php |
CACHE_PREFIX |
slug of APP_NAME plus -cache- |
Prefix that keeps two applications apart in a shared cache |
DB_CACHE_CONNECTION |
the default connection | Connection for the database store |
DB_CACHE_TABLE |
cache |
Table for the database store |
DB_CACHE_LOCK_CONNECTION |
same as the cache connection | Connection for atomic locks |
DB_CACHE_LOCK_TABLE |
cache_locks |
Table for atomic locks |
MEMCACHED_HOST |
127.0.0.1 |
Memcached server |
MEMCACHED_PORT |
11211 |
Memcached port |
MEMCACHED_PERSISTENT_ID |
none | Reuse the connection between requests |
MEMCACHED_USERNAME, MEMCACHED_PASSWORD |
none | SASL credentials |
REDIS_CACHE_CONNECTION |
cache |
Redis connection for the redis store |
REDIS_CACHE_LOCK_CONNECTION |
default |
Redis connection for locks |
DYNAMODB_CACHE_TABLE |
cache |
Table for the dynamodb store, with the AWS_* credentials |
DYNAMODB_ENDPOINT |
none | Local DynamoDB endpoint |
Redis
Read by config/database.php. Only needed when the queue, the cache or the session points at redis. Two connections exist: default on database 0 and cache on database 1, sharing host and credentials.
| Variable | Default | Purpose |
|---|---|---|
REDIS_CLIENT |
phpredis |
phpredis extension or predis package |
REDIS_URL |
none | A single URL that replaces host, port, username and password |
REDIS_HOST |
127.0.0.1 |
Server |
REDIS_PORT |
6379 |
Port |
REDIS_USERNAME, REDIS_PASSWORD |
none | Credentials |
REDIS_DB |
0 |
Database number of the default connection |
REDIS_CACHE_DB |
1 |
Database number of the cache connection |
REDIS_CLUSTER |
redis |
Cluster mode |
REDIS_PREFIX |
slug of APP_NAME plus -database- |
Key prefix |
REDIS_PERSISTENT |
false |
Keep the connection open between requests |
Logging
Read by config/logging.php. The default channel is daily, which rotates storage/logs/laravel.log and keeps fourteen days. Whatever you log is readable in the browser at /logs; as shipped that route has no sign-in in front of it, so restrict it before the site is public. Two channels ship for sending errors elsewhere: slack posts through an incoming webhook, and slack_api posts through a bot token; papertrail sends syslog over TLS. See Logs and debugging.
| Variable | Default | Purpose |
|---|---|---|
LOG_CHANNEL |
daily |
Channel that receives everything. Use stack to fan out to several |
LOG_STACK |
daily |
Comma-separated channels the stack channel writes to, such as daily,slack_api |
LOG_LEVEL |
debug; critical for slack |
Lowest level written. slack_api is fixed at error |
LOG_DAILY_DAYS |
14 |
Days of daily files to keep |
LOG_DEPRECATIONS_CHANNEL |
null |
Where PHP and package deprecations go; null discards them |
LOG_DEPRECATIONS_TRACE |
false |
Include a stack trace with each deprecation |
LOG_SLACK_WEBHOOK_URL |
none | Incoming webhook for the slack channel |
LOG_SLACK_USERNAME |
Laravel Log |
Sender name in Slack |
LOG_SLACK_EMOJI |
:boom: |
Sender icon in Slack |
SLACK_BOT_TOKEN |
none | Bot token for the slack_api channel |
SLACK_LOG_CHANNEL |
#errores |
Slack channel the slack_api channel posts to |
PAPERTRAIL_URL |
none | Papertrail host |
PAPERTRAIL_PORT |
none | Papertrail port |
LOG_PAPERTRAIL_HANDLER |
Monolog SyslogUdpHandler |
Handler class for the papertrail channel |
LOG_STDERR_FORMATTER |
none | Formatter class for the stderr channel, used in containers |
LOG_SYSLOG_FACILITY |
LOG_USER |
Facility for the syslog channel |
Development tools
Read by config/debugbar.php and config/querydetector.php. Both packages are development dependencies and switch themselves on when APP_DEBUG is true; these variables override that.
| Variable | Default | Purpose |
|---|---|---|
DEBUGBAR_ENABLED |
follows APP_DEBUG |
Force the Debugbar on or off |
DEBUGBAR_OPEN_STORAGE |
false |
Let anyone open stored requests |
DEBUGBAR_EDITOR |
phpstorm |
Editor that file links open in |
DEBUGBAR_REMOTE_SITES_PATH, DEBUGBAR_LOCAL_SITES_PATH |
empty | Map container paths to your machine so file links resolve |
DEBUGBAR_THEME |
auto |
auto, light or dark |
QUERY_DETECTOR_ENABLED |
follows APP_DEBUG |
Force the N+1 detector on or off |
QUERY_DETECTOR_THRESHOLD |
1 |
Repeated queries before it reports |
QUERY_DETECTOR_LOG_CHANNEL |
daily |
Where it writes when it outputs to the log |
More in Working on the code.
Variables that belong to a feature
These are read by config/ too, so they belong in this file, but the meaning of each value is explained in the feature's own guide.
Sign-in and verification, read by config/auth.php and config/services.php. See Configure sign-in and registration, Verify email and phone and The security PIN.
| Variable | Default |
|---|---|
AUTH_APPROACH |
CreationValidation |
AUTH_LOGIN_STEPS |
one |
AUTH_ENABLE_REGISTER |
true |
AUTH_ENABLE_VALIDATION |
true |
AUTH_ENABLE_PIN |
false |
LOGIN_IDENTITIES |
email |
AUTH_VALIDATION_PROVIDER |
aws |
TELNYX_API_KEY |
none; falls back to the older name TELNYX_TOKEN |
TELNYX_VERIFY_PROFILE_ID |
none |
AUTH_PASSWORD_TIMEOUT |
10800 seconds before a password confirmation expires |
AUTH_GUARD, AUTH_PASSWORD_BROKER, AUTH_MODEL, AUTH_PASSWORD_RESET_TOKEN_TABLE |
web, users, App\Models\User, password_reset_tokens: standard Laravel, no reason to change them |
Feature flags, read by config/features.php. See Configure your project; the referral values are explained in Referrals, and the ticket values in Support tickets.
| Variable | Default |
|---|---|
FEATURE_PLANS_ENABLED |
false |
FEATURE_ADDONS_ENABLED |
false |
FEATURE_ANNOUNCEMENTS |
false |
FEATURE_TRACKING_ENABLED |
false |
FEATURE_REFERRALS_ENABLED |
false |
FEATURE_REFERRALS_REGISTRATION_REWARD |
10 |
FEATURE_REFERRALS_SUBSCRIPTION_REWARD_PERCENT |
10 |
FEATURE_REFERRALS_CURRENCY |
mxn |
FEATURE_REFERRALS_COOKIE_DAYS |
30 |
FEATURE_TICKETS_ENABLED |
false |
FEATURE_TICKETS_PRIORITY_RESPONSE_DAYS, FEATURE_TICKETS_STANDARD_RESPONSE_DAYS |
1, 5 business days |
FEATURE_TICKETS_NEAR_DUE_FRACTION |
0.25 |
FEATURE_TICKETS_AUTO_CLOSE_DAYS, FEATURE_TICKETS_AUTO_CLOSE_WARNING_DAYS |
5, 4 |
FEATURE_TICKETS_CHAT_ENABLED |
false; the chat also needs tickets on and real time running |
FEATURE_TICKETS_CHAT_IDLE_MINUTES |
5 |
Stripe and billing, read by config/services.php, config/pricing.php, the billing package's billing-core.php and Laravel Cashier's own configuration. See Turn on plans and billing and Free trials and coupons.
| Variable | Default |
|---|---|
STRIPE_KEY |
none |
STRIPE_SECRET |
none |
STRIPE_WEBHOOK_SECRET |
none |
BILLING_CORE_ENABLED |
true |
BILLING_USER_ENABLED |
true |
BILLING_SUITE_ENABLED |
named in a commented-out adapter block of billing-core.php; nothing reads it until you uncomment that block and write the adapter class |
BILLING_COUPONS_ENABLED |
true |
BILLING_FREE_TRIAL_ENABLED |
false |
BILLING_FREE_TRIAL_DAYS |
14 |
CASHIER_CURRENCY |
usd, read by Cashier itself; the billing package's own currency is the committed primary_currency in config/pricing.php, mxn |
CASHIER_CURRENCY_LOCALE, CASHIER_PATH, CASHIER_WEBHOOK_TOLERANCE, CASHIER_LOGGER |
Cashier's own, en, stripe, 300, none |
Web push and the PWA, read by config/webpush.php and config/app.php. See Web push and the PWA.
| Variable | Default |
|---|---|
APP_PWA |
false |
VAPID_SUBJECT |
APP_URL |
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY |
none; php artisan webpush:vapid prints them |
VAPID_PEM_FILE |
none; an alternative to the two keys |
WEBPUSH_DB_TABLE |
push_subscriptions |
WEBPUSH_DB_CONNECTION |
DB_CONNECTION |
WEBPUSH_AUTOMATIC_PADDING |
true |
Real time, read by Laravel's broadcasting configuration and by Reverb's own. It is on only when BROADCAST_CONNECTION is reverb. See Real time with Reverb.
| Variable | Default |
|---|---|
BROADCAST_CONNECTION |
null, real time off |
REVERB_APP_ID, REVERB_APP_KEY, REVERB_APP_SECRET |
none |
REVERB_HOST |
none; the public address browsers connect to |
REVERB_PORT |
443; .env.example writes 8080 for local work |
REVERB_SCHEME |
https |
AI providers, read by config/ai.php. The translator uses the provider named in the committed default, which is openai, so OPENAI_API_KEY is the one that matters unless you change that key. See Connect an AI provider.
| Variable | Default |
|---|---|
OPENAI_API_KEY |
none |
OPENAI_URL |
https://api.openai.com/v1 |
ANTHROPIC_API_KEY |
none |
ANTHROPIC_URL |
https://api.anthropic.com/v1 |
GEMINI_API_KEY |
none |
GEMINI_URL |
https://generativelanguage.googleapis.com/v1beta/ |
AZURE_OPENAI_API_KEY, AZURE_OPENAI_URL |
none |
AZURE_OPENAI_API_VERSION |
2025-04-01-preview |
AZURE_OPENAI_DEPLOYMENT |
gpt-4o |
AZURE_OPENAI_EMBEDDING_DEPLOYMENT |
text-embedding-3-small |
AZURE_OPENAI_IMAGE_DEPLOYMENT |
gpt-image-1 |
AWS_BEDROCK_REGION |
us-east-1 |
AWS_BEARER_TOKEN_BEDROCK, AWS_SESSION_TOKEN |
none |
AWS_USE_DEFAULT_CREDENTIALS |
true |
COHERE_API_KEY, DEEPSEEK_API_KEY, ELEVENLABS_API_KEY, GROQ_API_KEY, JINA_API_KEY, MISTRAL_API_KEY, OPENROUTER_API_KEY, VOYAGEAI_API_KEY, XAI_API_KEY |
none |
OLLAMA_API_KEY |
empty; Ollama needs no key |
OLLAMA_URL |
http://localhost:11434 |
Country detection, read by config/services.php and config/app.php. See Detect the visitor's country.
| Variable | Default |
|---|---|
WEBLABOR_WORLD_TOKEN |
none; without it the country is still detected from the IP, but nothing is looked up in Weblabor World |
WEBLABOR_WORLD_ENDPOINT |
https://world.weblabor.mx/api, read by the World UI package rather than by config/ |
WEBLABOR_WORLD_TIMEOUT |
3, the seconds each call to Weblabor World may wait, read by config/worldui.php |
COUNTRY_CODE_FALLBACK |
US |
Tracking, read by config/services.php and config/features.php. See Tracking and analytics.
| Variable | Default |
|---|---|
FEATURE_TRACKING_ENABLED |
false |
FACEBOOK_ACCESS_TOKEN, FACEBOOK_PIXEL_ID |
none; both are needed before an event is sent to Facebook |
FACEBOOK_TEST_EVENT_CODE |
none |
Activity log, read by config/activitylog.php. See Activity log.
| Variable | Default |
|---|---|
ACTIVITY_LOGGER_ENABLED |
true |
ACTIVITY_LOGGER_DB_CONNECTION |
the default connection |
The DevZone deploy button, the one place where a variable is read straight from .env instead of through config/. See The DevZone.
| Variable | Default |
|---|---|
GIT_USER, GIT_PASSWORD |
none; the deploy in /admin/dev refuses to pull until both are set, and uses them as the Git credentials for git pull |
After you change a value
A running application reads .env on every request only while the configuration is not cached. After php artisan config:cache, which every deploy should run, a change in .env does nothing until you run it again or clear it with php artisan config:clear. The queue worker holds its own copy too: restart it with php artisan queue:restart after any change it should see.